根据单选按钮模式在画布上绘制矩形或正方形
我提供这个解释,因为我尊重地认为你的代码有点偏离了正确的方向 :)
一个简短的教程
这段代码使用jQuery,平滑了不同Web浏览器之间的差异。
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
首先,获取对画布元素的引用
// get a reference to the canvas element
var canvas=document.getElementById("canvas");
创建绘图画布上下文(称为ctx):
// create a canvas context to draw stuff with
var ctx=canvas.getContext("2d");
在上下文中设置一些样式
ctx.fillStyle="skyblue";
ctx.strokeStyle="lightgray";
ctx.lineWidth=3;
保存画布在网页上的位置。
这将在计算鼠标位置时后续使用。
// get the canvas's position on the page
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
由于我们将进行拖动操作,因此设置变量来保存拖动的起始XY坐标。
// set up variables to hold the mouse starting X/Y
// when the user drags the mouse
var startX;
var startY;
创建一个变量来指示我们是否正在拖动中。
// indicate whether the user is dragging the mouse
var isDragging=false;
创建一个变量来表示是否应该绘制正方形或矩形:
// set up a variable to determine whether to draw a square or a rectangle
var modeName="square";
当用户单击“正方形”或“矩形”单选按钮时,此代码将设置modeName变量。
如果用户单击“矩形”单选按钮,则modeName将被设置为“矩形”
如果用户单击“正方形”单选按钮,则modeName将被设置为“正方形”
$('input[name=mode]').click(function() {
modeName=$('input[name=mode]:checked').val();
});
监听鼠标事件
使用jQuery监听用户按下/释放鼠标按钮以及移动鼠标的事件。
- 当用户按下鼠标按钮时,将调用handleMouseDown函数。
- 当用户释放鼠标按钮时,将调用handleMouseUp函数。
- 无论用户如何移动鼠标,都会重复调用handleMouseMove函数。
监听鼠标事件:
// listen for mousedown, call handleMouseDown when it’s pressed
$("#canvas").mousedown(function(e){handleMouseDown(e);});
// listen for mouseup, call handleMouseUp when it’s released
$("#canvas").mouseup(function(e){handleMouseUp(e);});
// listen for mouse movements, call handleMouseMove when the mouse moves
$("#canvas").mousemove(function(e){handleMouseMove(e);});
处理用户按下、释放和移动鼠标时的操作——拖动!
当用户按下鼠标时,将调用handleMouseDown函数:
- 在startX和startY中存储起始鼠标位置。
- 将isDragging标志设置为true。
handleMouseDown函数:
function handleMouseDown(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
startX=mouseX;
startY=mouseY;
isDragging=true;
}
当用户释放鼠标按钮时,将调用handleMouseUp函数。
handleMouseUp:
function handleMouseUp(e){
isDragging=false;
}
当用户拖动时,handleMouseMove函数会被重复调用:
- 如果isDragging标志未设置,则退出。
- 清除画布以准备新位置的矩形/正方形。
- 如果用户想要一个矩形,则调用绘制矩形的函数。
- 如果用户想要一个正方形,则调用绘制正方形的函数。
handleMouseMove:
// called repeatedly when the user drags the mouse
function handleMouseMove(e){
// calculate the mouse position relative to the canvas
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// if the user isn’t dragging, just exit
if( !isDragging ){ return; }
// clear the canvas in preparation for drawing a modified square/rectangle
ctx.clearRect(0,0,canvas.width,canvas.height);
// this switch decided if the user selected a rectangle or square for drawing
switch(modeName){
// the user clicked the rectangle radio button and modeName == “rectangle”
case "rectangle":
// call a function that draws a rectangle
drawRectangle(mouseX,mouseY);
break;
// the user clicked the rectangle radio button and modeName == “square”
case "square":
// call a function that draws a square
drawSquare(mouseX,mouseY);
break;
default:
break;
}
}
此函数从startX/startY绘制一个矩形到当前的mouseX/mouseY。
function drawRectangle(mouseX,mouseY){
var width=mouseX-startX;
var height=mouseY-startY;
ctx.beginPath();
ctx.rect(startX,startY,width,height);
ctx.fill();
ctx.stroke();
}
此函数从起始点(startX/startY)向当前鼠标坐标点(mouseX/mouseY)绘制正方形。
正方形的四条边长将由mouseX-startX决定。
由于正方形必须保持四边相等,因此拖动正方形时可能会出现“跳跃”的情况。
function drawSquare(mouseX,mouseY){
var width=Math.abs(mouseX-startX)*(mouseX<startX?-1:1);
var height=Math.abs(width)*(mouseY<startY?-1:1);
ctx.beginPath();
ctx.rect(startX,startY,width,height);
ctx.fill();
ctx.stroke();
}
这里有代码和一个Fiddle链接:
http://jsfiddle.net/m1erickson/myHDW/。
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px;}
#canvas{border:1px solid red;}
input{width:15px;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var startX;
var startY;
var isDown=false;
ctx.fillStyle="skyblue";
ctx.strokeStyle="lightgray";
ctx.lineWidth=3;
var modeName="square";
$('input[name=mode]').click(function() {
modeName=$('input[name=mode]:checked').val();
console.log(modeName);
});
function handleMouseDown(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
startX=mouseX;
startY=mouseY;
isDown=true;
}
function handleMouseUp(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
$("#uplog").html("Up: "+ mouseX + " / " + mouseY);
isDown=false;
}
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
if(!isDown){return;}
ctx.clearRect(0,0,canvas.width,canvas.height);
switch(modeName){
case "rectangle":
drawRectangle(mouseX,mouseY);
break;
case "square":
drawSquare(mouseX,mouseY);
break;
default:
break;
}
}
function drawRectangle(mouseX,mouseY){
var width=mouseX-startX;
var height=mouseY-startY;
ctx.beginPath();
ctx.rect(startX,startY,width,height);
ctx.fill();
ctx.stroke();
}
function drawSquare(mouseX,mouseY){
var width=Math.abs(mouseX-startX)*(mouseX<startX?-1:1);
var height=Math.abs(width)*(mouseY<startY?-1:1);
ctx.beginPath();
ctx.rect(startX,startY,width,height);
ctx.fill();
ctx.stroke();
}
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUp(e);});
});
</script>
</head>
<body>
<p>Note: the square's side length is determined</p>
<p>by mouseX minus startingX.</p>
<p>As a result, the square may "jump" as you</p>
<p>move left or above the starting point.</p>
<canvas id="canvas" width=300 height=300></canvas><br>
<input type="radio" id="rect" name="mode" value="rectangle" />
<label for="rect">Rectangle</label>
<input type="radio" id="sqr" name="mode" value="square" checked="checked" />
<label for="sqr">Square</label>
</body>
</html>
[添加:把正方形的边长设置为 Math.abs(mouseX-startX) 和 Math.abs(mouseY-startY) 中的较大值]
这个备选的 drawSquare() 函数会计算出 x 和 y 方向拖动的距离中更长的那个,并把这个距离作为正方形 4 条边的长度:
function drawSquare(mouseX,mouseY){
var lengthX=Math.abs(mouseX-startX);
var lengthY=Math.abs(mouseY-startY);
if(lengthX>lengthY){
var width=lengthX*(mouseX<startX?-1:1);
var height=lengthX*(mouseY<startY?-1:1);
}else{
var width=lengthY*(mouseX<startX?-1:1);
var height=lengthY*(mouseY<startY?-1:1);
}
ctx.beginPath();
ctx.rect(startX,startY,width,height);
ctx.fill();
ctx.stroke();
}