在 Canvas 上绘制一个矩形
Posted
技术标签:
【中文标题】在 Canvas 上绘制一个矩形【英文标题】:Drawing a rectangle on Canvas 【发布时间】:2013-06-21 00:54:49 【问题描述】:我正在尝试创建一个简单的画布程序,用户可以在其中不断地创建新形状。这只是一个基本的矩形创建器(我希望将它更多地扩展到圆形、线条,甚至可能是其他东西)。现在虽然我创造了一些以一种非常奇怪的方式工作的东西。
<html>
<head>
<meta chartset="utf-8">
<title>Dragging a square</title>
<script type="text/javascript">
var canvas, context, startX, endX, startY, endY;
var mouseIsDown = 0;
function init()
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
document.body.addEventListener("mouseup", mouseUp, false);
function mouseUp()
mouseIsDown = 0;
//mouseXY();
function mouseDown()
mouseIsDown = 1;
startX = event.clientX;
startY = event.clientY;
mouseXY();
function mouseXY(eve)
if (!eve)
var eve = event;
endX = event.pageX - canvas.offsetLeft;
endY = event.pageY - canvas.offsetTop;
drawSquare();
function drawSquare()
// creating a square
var width = Math.abs(startX - endX);
var height = Math.abs(startY - endY);
context.beginPath();
context.rect(startX, startY, width, height);
context.fillStyle = "yellow";
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
</script>
</head>
<body onload="init()">
<canvas id="canvas" style="border: 1px solid black; cursor: pointer;"></canvas>
</body>
</html>
抱歉,我复制和粘贴代码时的格式有点奇怪。我认为问题出在我的 mouseXY 函数上。我想要的是用户单击画布上的某个位置并拖动鼠标以创建一个矩形,当用户放手时,这就是该操作的结束,他们可以立即创建一个全新的矩形。此时程序只是让我单击并创建一个新矩形,但如果我放开鼠标按钮它不会停止,实际上我必须再次单击以使其停止,然后创建一个新矩形。我对此仍然很陌生,我遇到了很多麻烦,我会继续努力,如果我弄清楚了,我会告诉网站。谢谢你,祝你有美好的一天!
好吧,我得到了这个工作(感谢@Ken),但现在我正在尝试解决一个新问题。我希望能够在画布上放置多个矩形。我创建了一个代表 Rectangle 的函数,然后在 rectangle 函数中创建了一个 draw 函数来绘制一个矩形。我创建了一个名为 addShape() 的新函数,它理想地创建了矩形对象并将其推入一个名为 square 和 drawShapes() 的数组中,该数组应该擦除画布上的所有内容并重绘所有内容。这是我目前所拥有的:
<html>
<head>
<meta chartset="utf-8">
<title>Dragging a square</title>
<script type="text/javascript">
function Rectangle(canvas, x, y, width, height,color)
//this.context = canvas.getContext("2d");
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.draw = function()
this.context.globalAlpha = 0.85;
this.context.beginPath();
this.context.rect(this.x, this.y, this.width, this.height);
this.context.fillStyle = this.color;
this.context.strokeStyle = "black";
this.context.lineWidth = 1;
this.context.fill();
this.context.stroke();
;
;
// hold the canvas and context variable, as well as the
// starting point of X and Y and the end ones
var canvas, context, startX, endX, startY, endY;
var mouseIsDown = 0;
// An array that holds all the squares
var squares = [];
window.onload = function()
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
canvas.addEventListener("mouseup", mouseUp, false);
function mouseUp(eve)
if (mouseIsDown !== 0)
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
//Square(); //update on mouse-up
addShape(); // Update on mouse-up
function mouseDown(eve)
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
// Square(); //update
addShape();
function mouseXY(eve)
if (mouseIsDown !== 0)
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
//Square();
addShape();
function getMousePos(canvas, evt)
var rect = canvas.getBoundingClientRect();
return
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
;
function addShape()
var w = endX - startX;
var h = endY - startY;
var offsetX = (w < 0) ? w : 0;
var offsetY = (h < 0) ? h : 0;
var width = Math.abs(w);
var height = Math.abs(h);
var s = new Rectangle(startX + offsetX, startY + offsetY, width, height, "yellow");
squares.push(s);
// Update the display
drawShapes();
function drawShapes()
context.clearRect(0,0,canvas.width,canvas.height);
for (var i = 0; i < squares.length; i++)
var shape = squares[i];
shape.draw();
;
function clearCanvas()
squares = [];
drawShapes();
</script>
</head>
<body onload="addShape()">
<canvas id="canvas" style="border: 1px solid black; cursor: pointer;"></canvas><br>
<button onclick="clearCanvas()">Clear Canvas</button>
</body>
</html>
我很确定我破坏了原始代码...感谢您的帮助!
【问题讨论】:
如果将 mouseup 事件侦听器更改为像其他两个一样的画布会发生什么? 问题是你没有利用mouseIsDown
收集的信息
你的意思是我没有正确使用它作为标志?我是否应该将其用作移动的条件……好吧,我要尝试一下。
好的,我在 mouseXY 中添加了一个条件,如果 mouseIsDown == 1 则开始绘制。现在的问题是,如果我创建一个矩形,然后尝试使其变小,它会继续自己绘制,这是一个 JSfiddle,这样你就可以看到它在做什么jsfiddle.net/8nA2x
【参考方案1】:
您需要修改代码中的几处:(编辑:这段代码有很多问题。我在这里内联了其中一些,但尚未测试。如果你把它放在小提琴中,它会更容易供我们检查)..
Fiddle
当鼠标按下时初始化起点和终点。调用一个不依赖于事件本身的通用绘图函数:
function mouseDown(eve)
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
drawSquare(); //update
在鼠标打开时,仅当 isMouseDown 为真时才注册,否则此函数将处理所有传入的向上事件(因为您已将其附加到文档,这是正确的 - 也可以使用窗口):
function mouseUp(eve)
if (mouseIsDown !== 0)
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
drawSquare(); //update on mouse-up
仅当 mouseisdown 为 true 时才绘制:
function mouseXY(eve)
if (mouseIsDown !== 0)
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
drawSquare();
此外,您需要在绘制新矩形之前清除矩形的先前区域,否则当您绘制较大的矩形然后将鼠标移回以绘制较小的矩形时,它不会显示。
为简单起见,您可以这样做:
function drawSquare()
// creating a square
var width = Math.abs(startX - endX);
var height = Math.abs(startY - endY);
context.clearRect(0, 0, context.width, context.height);
//or use fillRect if you use a bg color
context.beginPath();
context.rect(startX, startY, width, height);
context.fillStyle = "yellow";
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
将此用于鼠标位置:
function getMousePos(canvas, evt)
var rect = canvas.getBoundingClientRect();
return
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
;
【讨论】:
嗯,这实际上并不能解决这个问题。尝试将正方形拖动到一定大小,然后将其向后拖动以使其变小,它会一直拖动而留下难看的斑点。我希望能够在不离开它的情况下调整它的大小。 @InsigMath 您需要处理的另一个问题是负宽度/高度矩形(您移动 start -width 等)。 (我也解决了这个问题 - 再次参见小提琴)。 非常感谢。但是......而且我确信这不是一个硬性修复,但我非常想绘制多个矩形。所以,如果我画一个,我希望能够在它上面画一个完整的另一个。但是,这是一个很好的开始 :) 非常感谢! 对一百万个问题和所有事情感到抱歉......这是一次有点令人沮丧的学习经历 啊,好吧,所以我可能应该创建一个数组,然后继续推送它们。以上是关于在 Canvas 上绘制一个矩形的主要内容,如果未能解决你的问题,请参考以下文章