-2

我正在尝试绘制一个矩形,就像您在 Paint 中所做的那样。 但目前,当我尝试绘制一个矩形时,这就是我的画布的样子——双重绘图,凌乱的矩形。

这是我的整个代码的样子:

(删除代码)

如何绘制一个看起来像这样的矩形:像一个矩形?

4

3 回答 3

0

你发布的代码有数组:
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>

你有一堆变量,我删除了绘制矩形并非绝对需要的所有内容,以后无论如何你都可以复杂化你喜欢绘制多个对象,但我建议你经常测试你的代码,小的增量更改确保它做了什么你要。

于 2020-04-03T22:33:25.017 回答
0

首先,我认为将坐标存储在分隔变量而不是数组(startX,startY,lastX,lastY)中会更清楚。

此外,您应该从鼠标位置中减去画布位置以获得画布内的坐标,现在它可以工作,因为画布位于页面顶部。

我看到您想保留旧内容,我使用画布存储以前绘制的内容,然后在绘制当前矩形之前必须重新绘制旧内容(使用 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>

于 2020-04-03T23:29:30.080 回答
0

画布的上下文是一个非常强大的东西,我建议你在https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D上查看它的所有属性、方法

特别是对于您的用例:上下文提供了直接读写画布数据的方法,getImageData()-putImageData()是该方法对。使用它们,您可以在用户开始绘制新矩形时存储画布包含的任何内容,并在调整当前矩形大小时恢复它。存储的数据甚至可以提供一步“撤消”功能作为副产品:

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>

于 2020-04-04T10:39:06.500 回答