我想使用 MS 绘画风格线条工具,使用 JS 在 html canvas 元素上使用 UI 绘制直线。
问题是,当在起始位置单击后拖动鼠标时,线条预览必须在画布上可见(线条预览基本上是从起始单击点到当前鼠标位置的直线)。一旦鼠标移动到新位置而不释放,旧的线预览应该消失并显示新的线预览。最后,释放鼠标后,应在画布上绘制最后一条线。相反,我得到了您在下面看到的那种图像。
我尝试了各种方法按此顺序执行以下步骤,但没有成功:
重复直到鼠标松开:
window.onload = function() {
const canvas = document.getElementById('paintCanvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
let painting = false;
let startX, startY;
let canvasState = false;
canvas.addEventListener('mousedown', startPosition);
canvas.addEventListener('mouseup', endPosition);
canvas.addEventListener('mousemove', draw);
ctx.lineWidth = 5;
ctx.lineCap = 'round';
function startPosition(e) {
painting = true;
[startX, startY] = [e.offsetX, e.offsetY];
ctx.save();
ctx.beginPath();
draw(e);
}
function endPosition() {
ctx.closePath();
ctx.restore();
painting = false;
canvasState = false;
}
function draw(e) {
if (!painting) return;
if (selectedTool.id === 'pencil') {
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
} else if (selectedTool.id === 'line') {
// write code that works with a line
if (e.type === 'mousemove') {
// remove old preview line
if (canvasState) {
ctx.putImageData(canvasState, 0, 0);
} else {
canvasState = ctx.getImageData(0,0,canvas.width,canvas.height);
}
// paint straight line from original start to current mouse position
ctx.moveTo(startX, startY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
} else if (selectedTool.id === 'eraser') {
if (e.type === 'mousedown') {
ctx.strokeStyle = ctx.fillStyle;
ctx.lineWidth += 5;
} else {
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
}
}
};
我想,这是因为
canvasState
在道路建筑内恢复了。以下修复解决了我的问题:
// remove old preview line
if (canvasState) {
ctx.putImageData(canvasState, 0, 0);
} else {
canvasState = ctx.getImageData(0,0,canvas.width,canvas.height);
}
// paint straight line from original start to current mouse position
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.closePath();
ctx.stroke();