简体   繁体   中英

html5 canvas drawing: fast motion with mouse cancels line before it hits the edge of the canvas

The app works fine so far except if the line is drawn really fast and leaves the edge of the canvas, the line is then not drawn to the edge of the canvas. There is a part missing from it.

I'm trying to fix the issue with:

canvasVar.addEventListener ('mouseout', clearPathIfMouseCursorLeavesCanvasFunc);

and

 function clearPathIfMouseCursorLeavesCanvasFunc(e){
 contextVar.beginPath(); // clears the path so buttonpresses dont connect the line
 mouseButtonHeld = false;

I've tried some things like adding a settimeout(); but nothing worked so far. I don't know what causes this and I've been searching if someone else had this problem and a fix for it, but every canvas drawing app I've come across has the same issues.

It's very important that the line is drawn to the edge and that the users mouse motion is recognized, not just a line to the last coordinates where the mouse left the canvas.

It's been days now that I'm stuck with this problem. Help is really appreciated!

Whole Code:

 // Varibale declaration var canvasVar = document.getElementById('canvasHtmlElement'); var contextVar = canvasVar.getContext('2d'); var pointRadiusVar = 0.5; var mouseButtonHeld = false; var pointsArrPosition = 0; //Arrays var pointsArr = []; // Varibale declration end //canvas setup canvasVar.width = window.innerWidth; canvasVar.height = window.innerHeight; //canvas setup end //resize fix window.onresize = function() { var tempImageVar = contextVar.getImageData(0, 0, canvasVar.width, canvasVar.height); canvasVar.width = window.innerWidth; canvasVar.height = window.innerHeight; contextVar.putImageData(tempImageVar, 0, 0); } //resize fix end //functions // Objects function pointObject() { this.x = 0; this.y = 0; this.fill = '#444444'; } function addFilledCircleFunc(x, y) { //alert('works1'); var filledCircle = new pointObject; filledCircle.x = x; filledCircle.y = y; pointsArr.push(filledCircle); contextVar.lineWidth = 10; //pointRadiusVar * 2; // Line Width contextVar.lineTo(pointsArr[pointsArrPosition].x, pointsArr[pointsArrPosition].y); contextVar.stroke(); //contextVar.beginPath(); contextVar.fillRect(filledCircle.x, filledCircle.y, 1, 1); //contextVar.arc(filledCircle.x, filledCircle.y, pointRadiusVar, 0, Math.PI * 2); //contextVar.fill(); //contextVar.lineWidth = 0.5; //contextVar.stroke(); //contextVar.beginPath(); pointsArrPosition++; //contextVar.moveTo(pointsArr[pointsArrPosition].x, pointsArr[pointsArrPosition].y); //alert(pointsArr[0].x); } //Objects end // create circle on mouse clicked point while mousebutton is held var addPointToCanvasVar = function(e) { if (mouseButtonHeld) { //alert('addpointfunc'); addFilledCircleFunc(e.clientX, e.clientY); } }; // MAKE SURE that lines work when drawn over the edge of the canvas function clearPathIfMouseCursorLeavesCanvasFunc(e) { contextVar.beginPath(); // clears the path so buttonpresses dont connect the line mouseButtonHeld = false; } // end // mouse Up/Down functions var mouseDownVar = function(e) { //alert("mouseDown"); addPointToCanvasVar(e); // add point on first click, not just when mousebutton is held mouseButtonHeld = true; } var mouseUpVar = function() { //alert("mouseUp"); mouseButtonHeld = false; contextVar.beginPath(); // clears the path so buttonpresses dont connect the line } // mouse Up/Down Switch end //functions end //listeners canvasVar.addEventListener('mousemove', addPointToCanvasVar); canvasVar.addEventListener('mouseup', mouseUpVar); canvasVar.addEventListener('mousedown', mouseDownVar); canvasVar.addEventListener('mouseout', clearPathIfMouseCursorLeavesCanvasFunc); //listeners end 
 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>Confident Drawing</title> </head> <body style="margin: 0"> <canvas id="canvasHtmlElement" style="display: block;"> Your Browser does not support Canvas! Please update to a newer version. </canvas> <script src="main_0.06.js"></script> </body> </html> 

If you don't get what I mean: Run the snippet and draw a line as fast as you can while exiting the canvas.

The reason the line ends prematurely near the edge when you quickly draw a line across the edge is because the last mousemove event fired when the mouse was still in the canvas and just short of the edge, and the very next mousemove event fired after your mouse left the canvas. To fix that problem, simply draw your line from the last recorded mouse position in the canvas to the one outside of the canvas as soon as the mouseout event fires.

You can add a new global variable mousePosition and initialize it to {x:0,y:0} . Every time mousemove fires (whenever you call addPointToCanvasVar ), record the e.clientX and e.clientY to your mousePosition . Then when mouseout fires (whenever you call clearPathIfMouseCursorLeavesCanvasFunc ), draw the rest of the line from mousePosition to the current e.clientX and e.clientY position. This will complete the line to the end of the canvas edge.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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