Задача: нужно рисовать линии на канвасе когда пользователь ведет курсор с зажатой левой кнопкой.
И как всегда, обычное дело оказалось не без подводных камней!
Проблема возникла с определением позиции мышки над canvas элементом.
По идее все просто, на события mousedown, mousemove и mouseup вешаем обработчики. При этом mousedown и mouseup сохраняют за зажата ли кнопка мыши, а mousemove - рисует.
Проблема: координаты, которые приходят в событие через e.pageX/Y, это текущее положение курсора на экране, а не над canvas элементом::
canvas.addEventListener("mouseup", function(e){
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
...
П осути такой метод будет работать, только если сам canvas находиться в верхнем левом углу сайта Также не учитывается, чт остраница могла быть прокручена.
В итоге, мой вариант:
let ClientRect = this.getBoundingClientRect();
mouse.x = e.clientX - ClientRect.left;
mouse.y = e.clientY - ClientRect.top;
Полный код:
let canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
mouse = { x:0, y:0 },
draw = false
;
context.strokeStyle = "black";
canvas.addEventListener("mousedown", function(e){
let ClientRect = this.getBoundingClientRect();
mouse.x = e.clientX - ClientRect.left;
mouse.y = e.clientY - ClientRect.top;
draw = true;
context.beginPath();
context.moveTo(mouse.x, mouse.y);
});
canvas.addEventListener("mousemove", function(e){
if(draw === true){
let ClientRect = this.getBoundingClientRect();
mouse.x = e.clientX - ClientRect.left;
mouse.y = e.clientY - ClientRect.top;
context.lineTo(mouse.x, mouse.y);
context.stroke();
}
});
canvas.addEventListener("mouseup", function(e){
let ClientRect = this.getBoundingClientRect();
mouse.x = e.clientX - ClientRect.left;
mouse.y = e.clientY - ClientRect.top;
context.lineTo(mouse.x, mouse.y);
context.stroke();
context.closePath();
draw = false;
});
<canvas id="canvas" width="600px" height="600px"></canvas>
Живая демонстрация