简体   繁体   English

当我移动鼠标时,如何用 HTML 画布绘制一条简单的直线?

[英]How to draw a simple straight line with HTML canvas as I move the mouse?

I want to draw a straight line along with my mouse movement.我想随着鼠标的移动画一条直线。 I got it working.我让它工作了。 But the issue is the canvas.stroke is redrawing lines over and over as I move the mouse.但问题是canvas.stroke在我移动鼠标时一遍又一遍地重绘线条。 What is the workaround for this?解决方法是什么? I just want one line not overlays of multiple lines.我只想要一条线而不是多条线的叠加。

Here is the mousemove listener:这是mousemove侦听器:

canvasElement.onmousemove = (e) => {
            if (!started) return;
            context.beginPath();

            context.globalCompositeOperation = "multiply"; //<<<<
            context.globalAlpha = 0.05;
            context.lineWidth = size;
            context.strokeStyle = color;
            context.lineJoin = "round";
            context.lineCap = "round";
            context.moveTo(prvX, prvY);
            var dx = e.offsetX - prvX;
            var dy = e.offsetY - prvY;
            if (Math.abs(dx) > Math.abs(dy)) {
                context.lineTo(e.offsetX, prvY);
            } 
            context.stroke();
            context.closePath();
        };

As soon as you drawn something eg a line over something that has previously drawn onto your canvas eg an image, the resulting pixeldata stored for your canvas is a combination of the old and the new data.一旦您在画布上绘制的东西(例如图像)上绘制了一些东西,例如一条线,为您的画布存储的结果像素数据就是旧数据和新数据的组合。 That means you can't simply remove a semi-transparent line from it without destroying what was drawn below as well.这意味着您不能简单地从中删除半透明线而不破坏下面绘制的内容。

One solution would be using two independent canvases of the same size and at the same on-screen position.一种解决方案是使用两个大小相同且屏幕位置相同的独立画布。 The canvas in the background holds your original image data and the canvas on top is used to draw the line.背景中的画布保存您的原始图像数据,顶部的画布用于绘制线条。 That way you can simply erase the top-canvas before drawing a new line.这样,您可以在绘制新线之前简单地擦除顶部画布。

In your case that might not work however as you're using a different globalCompositeOperation to draw the line.但是,在您使用不同的globalCompositeOperation画线时,这可能不起作用。 In this case I'd recommend storing the data of your canvas in a second canvas as soon as you've clicked on the 'painting' canvas for the first time.在这种情况下,我建议您在第一次单击“绘画”画布后立即将画布的数据存储在第二个画布中。 This way you can simply restore the data before drawing the line.这样,您可以在绘制线之前简单地恢复数据。

For example:例如:

 let canvasElement = document.getElementById("canvas"); let context = canvasElement.getContext("2d"); let started = false; let size = 7; let color = "red" let prvX = 0; let prvY = 0; let image = new Image(); let backupCanvas = document.createElement("canvas"); let backupCanvasContext = backupCanvas.getContext("2d"); backupCanvas.width = canvasElement.width; backupCanvas.height = canvasElement.height; let backupCreated = false; image.crossOrigin = "anonymous"; image.onload = () => { context.drawImage(image, 0, 0, canvasElement.width, canvasElement.height); } image.src = `https://api.codetabs.com/v1/proxy?quest=https://picsum.photos/id/237/${canvasElement.width}/${canvasElement.height}`; canvasElement.onmousedown = (e) => { if (!backupCreated) { backupCanvasContext.drawImage(canvasElement, 0, 0, canvasElement.width, canvasElement.height); backupCreated = true; } started = true; prvX = e.offsetX; prvY = e.offsetY; } canvasElement.onmouseup = (e) => { started = false; } canvasElement.onmousemove = (e) => { if (!started) return; context.globalCompositeOperation = "source-over"; context.drawImage(backupCanvas, 0, 0, canvasElement.width, canvasElement.height); context.beginPath(); context.globalCompositeOperation = "multiply"; //<<<< context.globalAlpha = 1; context.lineWidth = size; context.strokeStyle = color; context.lineJoin = "round"; context.lineCap = "round"; context.moveTo(prvX, prvY); var dx = e.offsetX - prvX; var dy = e.offsetY - prvY; if (Math.abs(dx) > Math.abs(dy)) { context.lineTo(e.offsetX, prvY); } context.stroke(); context.closePath(); };
 <canvas id="canvas" width="300" height="200"></canvas>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM