尝试在 canvas 上绘制一个矩形,最好是在 Javascript 上?
Trying to SKETCH a rectangle on canvas, preferably in Javascript?
我正在尝试绘制一个矩形,就像您在“画图”中所做的那样。
But currently when I try to sketch a rectangle, this is what my canvas looks like--double drawings, messy rectangles.
我的整个代码是这样的:
(删除代码)
如何画出如下所示的矩形:like one rectangle?
您 post 的代码有数组:
ctx.rect(x[x1],y[y1]
但我猜你画的不仅仅是矩形...
这是一个示例:
ctx = document.getElementById('c').getContext('2d');
ctx.lineWidth = 2;
x = [5, 30, 90]
y = [5, 50, 30]
for (i = 0; i < x.length; i++) {
ctx.rect(x[i], y[i], 50, 20)
}
ctx.stroke();
<canvas height="100" width="300" id="c">
只是矩形而已,没有双重绘图或混乱,您提供的代码应该不会导致任何问题,如您在图片中显示的那样。
这是基于您的新代码的更新...
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
ctx.lineWidth = 2;
var x = 0;
var y = 0;
draw = false;
function down() {
x = event.clientX;
y = event.clientY;
draw = true;
}
function move() {
if (draw) {
var a = event.clientX;
var b = event.clientY;
ctx.clearRect(0, 0, canvas.width, canvas.height)
addCircles()
ctx.beginPath()
ctx.rect(x, y, a - x, b - y);
ctx.stroke();
}
}
function up() {
draw = false
}
function addCircles() {
ctx.beginPath()
ctx.fillStyle = '#F00';
ctx.arc(50, 50, 30, 0, Math.PI * 2)
ctx.fill();
ctx.beginPath()
ctx.fillStyle = '#0F0';
ctx.arc(100, 100, 30, 0, Math.PI * 2)
ctx.fill();
ctx.beginPath()
ctx.fillStyle = '#00F';
ctx.arc(200, 80, 30, 0, Math.PI * 2)
ctx.fill();
}
addCircles()
<canvas id="myCanvas" width="300" height="160" style="border:1px solid #000000;" onmousedown="down()" onmousemove="move()" onmouseup="up()"> </canvas>
你的变量一团糟,我删除了绘制矩形所不需要的所有内容,以后你可以把它复杂化,无论如何你喜欢绘制多个对象,但我建议你经常测试你的代码,小的增量变化确保它做你想做的。
首先,我认为如果将坐标存储在分隔的变量中而不是数组(startX、startY、lastX、lastY)中会更清楚。
您还应该从鼠标位置减去 canvas 位置以获得 canvas 内的坐标,现在它有点工作,因为 canvas 在顶部页面。
我看到你想保留旧的内容,我用了一个canvas来存储以前绘制的内容,然后在绘制当前矩形之前你必须重绘旧的内容(使用ctx.drawImage ).
您应该将坐标增加 0.5,这样线条才不会变得模糊,只有当您绘制一条宽度为奇数 (1, 3, 5) 的线条时才会发生这种情况。这是因为如果你试图在坐标 x=1 上绘制 1px 的线,你必须在两边绘制半个像素(0.5 到 1.5),所以它看起来很模糊。
但是如果你在 x=0.5 处绘制它,你会绘制从 0 到 1 的线,这恰好是一个像素。
var isDown = false;
var startX, startY;
var lastX, lastY;
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var canvasRect = canvas.getBoundingClientRect();
var backBuffer = canvas.cloneNode(true);
var backBufferCtx = backBuffer.getContext('2d');
canvas.addEventListener('mousedown', function down() {
startX = event.clientX - canvasRect.left;
startY = event.clientY - canvasRect.top;
isDown = true;
});
canvas.addEventListener('mouseup', function up() {
isDown = false;
// Draw Current Canvas Content
updateCanvas();
// Save current content
backBufferCtx.clearRect(0, 0, backBuffer.width, backBuffer.height);
backBufferCtx.drawImage(canvas, 0, 0);
});
canvas.addEventListener('mousemove', function move() {
if (! isDown) return;
lastX = event.clientX - canvasRect.left;
lastY = event.clientY - canvasRect.top;
updateCanvas();
});
function updateCanvas() {
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw Current Canvas Content
ctx.drawImage(backBuffer, 0, 0);
// Draw New Rectangle
ctx.beginPath();
// add 0.5 so the line do not get blurry
ctx.rect(startX + 0.5, startY + 0.5, lastX - startX, lastY - startY);
ctx.stroke();
}
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000; margin-top: 100px"></canvas>
canvas的context是一个非常强大的东西,我建议你在https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
上查看它的所有属性,方法
特别是对于您的用例:上下文提供了直接读写 canvas 数据的方法,getImageData()
-putImageData()
是方法对。使用它们,您可以在用户开始绘制新矩形时存储 canvas 包含的任何内容,并在调整当前矩形大小时恢复它。存储的数据甚至可以作为副产品提供一步 "Undo" 功能:
var cnv=document.getElementById("cnv"),
ctx=cnv.getContext("2d"),
col=document.getElementById("color"),
ubtn=document.getElementById("undo"),
copy,
pick=false;
function mdown(event){
copy=ctx.getImageData(0,0,cnv.width,cnv.height);
pick={
x:event.offsetX,
y:event.offsetY
};
}
function mup(event){
pick=false;
ubtn.disabled=false;
}
function mmove(event){
if(pick){
ctx.putImageData(copy,0,0);
ctx.strokeStyle=col.value;
ctx.lineWidth=2;
ctx.strokeRect(pick.x,pick.y,event.offsetX-pick.x,event.offsetY-pick.y);
}
}
function undo(){
ctx.putImageData(copy,0,0);
ubtn.disabled=true;
}
<input type="color" id="color"><button id="undo" disabled onclick="undo()">Undo</button><br>
<canvas id="cnv" width="300" height="140" style="border:1px solid black;cursor:crosshair" onmousedown="mdown(event)" onmousemove="mmove(event)" onmouseup="mup(event)"></canvas>
我正在尝试绘制一个矩形,就像您在“画图”中所做的那样。 But currently when I try to sketch a rectangle, this is what my canvas looks like--double drawings, messy rectangles.
我的整个代码是这样的:
(删除代码)
如何画出如下所示的矩形:like one rectangle?
您 post 的代码有数组:
ctx.rect(x[x1],y[y1]
但我猜你画的不仅仅是矩形...
这是一个示例:
ctx = document.getElementById('c').getContext('2d');
ctx.lineWidth = 2;
x = [5, 30, 90]
y = [5, 50, 30]
for (i = 0; i < x.length; i++) {
ctx.rect(x[i], y[i], 50, 20)
}
ctx.stroke();
<canvas height="100" width="300" id="c">
只是矩形而已,没有双重绘图或混乱,您提供的代码应该不会导致任何问题,如您在图片中显示的那样。
这是基于您的新代码的更新...
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
ctx.lineWidth = 2;
var x = 0;
var y = 0;
draw = false;
function down() {
x = event.clientX;
y = event.clientY;
draw = true;
}
function move() {
if (draw) {
var a = event.clientX;
var b = event.clientY;
ctx.clearRect(0, 0, canvas.width, canvas.height)
addCircles()
ctx.beginPath()
ctx.rect(x, y, a - x, b - y);
ctx.stroke();
}
}
function up() {
draw = false
}
function addCircles() {
ctx.beginPath()
ctx.fillStyle = '#F00';
ctx.arc(50, 50, 30, 0, Math.PI * 2)
ctx.fill();
ctx.beginPath()
ctx.fillStyle = '#0F0';
ctx.arc(100, 100, 30, 0, Math.PI * 2)
ctx.fill();
ctx.beginPath()
ctx.fillStyle = '#00F';
ctx.arc(200, 80, 30, 0, Math.PI * 2)
ctx.fill();
}
addCircles()
<canvas id="myCanvas" width="300" height="160" style="border:1px solid #000000;" onmousedown="down()" onmousemove="move()" onmouseup="up()"> </canvas>
你的变量一团糟,我删除了绘制矩形所不需要的所有内容,以后你可以把它复杂化,无论如何你喜欢绘制多个对象,但我建议你经常测试你的代码,小的增量变化确保它做你想做的。
首先,我认为如果将坐标存储在分隔的变量中而不是数组(startX、startY、lastX、lastY)中会更清楚。
您还应该从鼠标位置减去 canvas 位置以获得 canvas 内的坐标,现在它有点工作,因为 canvas 在顶部页面。
我看到你想保留旧的内容,我用了一个canvas来存储以前绘制的内容,然后在绘制当前矩形之前你必须重绘旧的内容(使用ctx.drawImage ).
您应该将坐标增加 0.5,这样线条才不会变得模糊,只有当您绘制一条宽度为奇数 (1, 3, 5) 的线条时才会发生这种情况。这是因为如果你试图在坐标 x=1 上绘制 1px 的线,你必须在两边绘制半个像素(0.5 到 1.5),所以它看起来很模糊。
但是如果你在 x=0.5 处绘制它,你会绘制从 0 到 1 的线,这恰好是一个像素。
var isDown = false;
var startX, startY;
var lastX, lastY;
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var canvasRect = canvas.getBoundingClientRect();
var backBuffer = canvas.cloneNode(true);
var backBufferCtx = backBuffer.getContext('2d');
canvas.addEventListener('mousedown', function down() {
startX = event.clientX - canvasRect.left;
startY = event.clientY - canvasRect.top;
isDown = true;
});
canvas.addEventListener('mouseup', function up() {
isDown = false;
// Draw Current Canvas Content
updateCanvas();
// Save current content
backBufferCtx.clearRect(0, 0, backBuffer.width, backBuffer.height);
backBufferCtx.drawImage(canvas, 0, 0);
});
canvas.addEventListener('mousemove', function move() {
if (! isDown) return;
lastX = event.clientX - canvasRect.left;
lastY = event.clientY - canvasRect.top;
updateCanvas();
});
function updateCanvas() {
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw Current Canvas Content
ctx.drawImage(backBuffer, 0, 0);
// Draw New Rectangle
ctx.beginPath();
// add 0.5 so the line do not get blurry
ctx.rect(startX + 0.5, startY + 0.5, lastX - startX, lastY - startY);
ctx.stroke();
}
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000; margin-top: 100px"></canvas>
canvas的context是一个非常强大的东西,我建议你在https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
上查看它的所有属性,方法特别是对于您的用例:上下文提供了直接读写 canvas 数据的方法,getImageData()
-putImageData()
是方法对。使用它们,您可以在用户开始绘制新矩形时存储 canvas 包含的任何内容,并在调整当前矩形大小时恢复它。存储的数据甚至可以作为副产品提供一步 "Undo" 功能:
var cnv=document.getElementById("cnv"),
ctx=cnv.getContext("2d"),
col=document.getElementById("color"),
ubtn=document.getElementById("undo"),
copy,
pick=false;
function mdown(event){
copy=ctx.getImageData(0,0,cnv.width,cnv.height);
pick={
x:event.offsetX,
y:event.offsetY
};
}
function mup(event){
pick=false;
ubtn.disabled=false;
}
function mmove(event){
if(pick){
ctx.putImageData(copy,0,0);
ctx.strokeStyle=col.value;
ctx.lineWidth=2;
ctx.strokeRect(pick.x,pick.y,event.offsetX-pick.x,event.offsetY-pick.y);
}
}
function undo(){
ctx.putImageData(copy,0,0);
ubtn.disabled=true;
}
<input type="color" id="color"><button id="undo" disabled onclick="undo()">Undo</button><br>
<canvas id="cnv" width="300" height="140" style="border:1px solid black;cursor:crosshair" onmousedown="mdown(event)" onmousemove="mmove(event)" onmouseup="mup(event)"></canvas>