Прежде всего, я думаю, что более понятно, если вы храните координаты в отдельных переменных вместо массива (startX, startY, lastX, lastY).
Также вы должны вычесть позицию холста из позиции мыши чтобы получить координату внутри холста, сейчас это своего рода работа, потому что холст находится в верхней части страницы.
Я вижу, вы хотите сохранить старое содержимое, я использовал холст для хранения предыдущего нарисованного содержимого, затем перед тем, как нарисовать текущий прямоугольник, вы должны перерисовать старое содержимое (используя ctx.drawImage).
Вы должны добавить 0,5 к координатам, чтобы линии не становились размытыми, это происходит, только если вы рисуете линия с нечетной шириной (1, 3, 5). это потому, что если вы попытаетесь нарисовать линию в 1 пиксель, скажем, по координате x = 1, вы должны нарисовать половину пикселя в обе стороны (от 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>