Drawing on canvas like in paint

I have three arrys:

clickX = [], clickY = [], clickDrag = []; 

this is what happens when you click down:

 $('#canvasCursor').mousedown(function (e) { console.log('down'); mouseX = e.pageX - this.offsetLeft; mouseY = e.pageY - this.offsetTop; paint = true; addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop); redraw(); }); 

here it adds clicks to the array and draws .:

function redraw () {ctx.clearRect (0, 0, ctx.canvas.width, ctx.canvas.height); // Removes the canvas

  ctx.strokeStyle = "green"; ctx.lineJoin = "round"; ctx.lineWidth = brushSize*2; for (var i = 0; i < clickX.length; i++) { ctx.beginPath(); if (clickDrag[i] && i) { ctx.moveTo(clickX[i - 1], clickY[i - 1]); } else { ctx.moveTo(clickX[i] - 1, clickY[i]); } ctx.lineTo(clickX[i], clickY[i]); ctx.closePath(); ctx.stroke(); } } 

I am trying to get rid of the way the array does it now, because when I change var brushSize dynamically with the slider, it redraws the whole image in a new size, not the size that they had at that time. I don't know how to save the size of any particular object in an array, and then draw it separately.

I do not mind if I cannot implement the undo function, which in this way gives me as long as I can fix the brush resizing. Here you can see what I'm chatting about! http://www.taffatech.com/Paint.html

- also seems to be slower and I guess it because its drawing from an array

+1
source share
3 answers

EDIT : Sorry, some typos fixed. Change 2 : And again. This is a little hard to verify.

There is no reason to redraw each point every time. You can change your listener to do this:

 var prevMouseX=null,prevMouseY=null; $('#canvasCursor').mousedown(function (e) { paint = true; console.log('down'); //get current mouse coords mouseX = e.pageX - this.offsetLeft; mouseY = e.pageY - this.offsetTop; if (prevMouseX==null) { //store these coordinates for next time if they haven't been defined yet prevMouseX = mouseX; prevMouseY = mouseY; } }); $('#canvasCursor').mousemove(function (e) { //get current mouse coords mouseX = e.pageX - this.offsetLeft; mouseY = e.pageY - this.offsetTop; if (prevMouseX==null) { //store these coordinates for next time if they haven't been defined yet prevMouseX = mouseX; prevMouseY = mouseY; } if (paint) {drawline(mouseX,mouseY,prevMouseX,prevMouseY);} //store these coordinates for next time prevMouseX = mouseX; prevMouseY = mouseY; }); 

If the drawLine function is defined as:

 function drawline(x1,y1,x2,y2) { ctx.strokeStyle = "green"; ctx.lineJoin = "round"; ctx.lineWidth = brushSize*2; ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); ctx.closePath(); ctx.stroke(); } 
+1
source

Do not save painting to array
This is critically critical. Just draw the last line without cleaning the canvas. Thus, line changes do not affect the drawings. So remove the loop ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); and for . You can also change context styles (lineWidth, etc.) only when changes occur, and not every time you run the redraw() function.

Cancel support
By creating different canvases for each mouse session and combining them, you can easily cancel the function. By clicking the “Cancel” button, it simply merges the last canvas from the canvas array. Google to learn more about painting on temporary canvas.

+1
source

Here's how to use a canvas for painting, like Paint

If you want the undo function, the best option is to record all line segments drawn by the user.

This is done using a point array that contains all the points (polylines) drawn by the user.

To track brush size and brush color, you also need to include this information in your array.

Thus, each element of the array will have this information about each segment of the line:

  • x: end x coordinate of this line segment
  • y: final y coordinate
  • size: brush size (lineWidth)
  • color: brush color (strokeStyle)
  • mode: "begin" indicates the beginning of a new line, "end" indicates the end of this line.

How it works?

When a user drags a line segment, each mousemove event extends the current segment with context.lineTo and context.stroke .

When the user selects a new BrushSize or BrushColor, context.beginPath launches context.beginPath .

When the user holds the Cancel button, the last point in the last segment of the line is removed from the points array. Then all remaining segments of the line are redrawn. The Cancel button is triggered every 1/10 second when held.

Here is the code and script: http://jsfiddle.net/m1erickson/AEYYq/

 <!doctype html> <html> <head> <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> <!--[if lt IE 9]><script type="text/javascript" src="../excanvas.js"></script><![endif]--> <style> body{ background-color: ivory; } canvas{border:1px solid red;} </style> <script> $(function(){ var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var lastX; var lastY; var mouseX; var mouseY; var canvasOffset=$("#canvas").offset(); var offsetX=canvasOffset.left; var offsetY=canvasOffset.top; var isMouseDown=false; var brushSize=20; var brushColor="#ff0000"; var points=[]; function handleMouseDown(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); // Put your mousedown stuff here ctx.beginPath(); if(ctx.lineWidth!=brushSize){ctx.lineWidth=brushSize;} if(ctx.strokeStyle!=brushColor){ctx.strokeStyle=brushColor;} ctx.moveTo(mouseX,mouseY); points.push({x:mouseX,y:mouseY,size:brushSize,color:brushColor,mode:"begin"}); lastX=mouseX; lastY=mouseY; isMouseDown=true; } function handleMouseUp(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); // Put your mouseup stuff here isMouseDown=false; points.push({x:mouseX,y:mouseY,size:brushSize,color:brushColor,mode:"end"}); } function handleMouseMove(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); // Put your mousemove stuff here if(isMouseDown){ ctx.lineTo(mouseX,mouseY); ctx.stroke(); lastX=mouseX; lastY=mouseY; // command pattern stuff points.push({x:mouseX,y:mouseY,size:brushSize,color:brushColor,mode:"draw"}); } } function redrawAll(){ if(points.length==0){return;} ctx.clearRect(0,0,canvas.width,canvas.height); for(var i=0;i<points.length;i++){ var pt=points[i]; var begin=false; if(ctx.lineWidth!=pt.size){ ctx.lineWidth=pt.size; begin=true; } if(ctx.strokeStyle!=pt.color){ ctx.strokeStyle=pt.color; begin=true; } if(pt.mode=="begin" || begin){ ctx.beginPath(); ctx.moveTo(pt.x,pt.y); } ctx.lineTo(pt.x,pt.y); if(pt.mode=="end" || (i==points.length-1)){ ctx.stroke(); } } ctx.stroke(); } function undoLast(){ points.pop(); redrawAll(); } ctx.lineJoin = "round"; ctx.fillStyle=brushColor; ctx.lineWidth=brushSize; $("#brush5").click(function(){ brushSize=5; }); $("#brush10").click(function(){ brushSize=10; }); // Important! Brush colors must be defined in 6-digit hex format only $("#brushRed").click(function(){ brushColor="#ff0000"; }); $("#brushBlue").click(function(){ brushColor="#0000ff"; }); $("#canvas").mousedown(function(e){handleMouseDown(e);}); $("#canvas").mousemove(function(e){handleMouseMove(e);}); $("#canvas").mouseup(function(e){handleMouseUp(e);}); // hold down the undo button to erase the last line segment var interval; $("#undo").mousedown(function() { interval = setInterval(undoLast, 100); }).mouseup(function() { clearInterval(interval); }); }); // end $(function(){}); </script> </head> <body> <p>Drag to draw. Use buttons to change lineWidth/color</p> <canvas id="canvas" width=300 height=300></canvas><br> <button id="undo">Hold this button down to Undo</button><br><br> <button id="brush5">5px Brush</button> <button id="brush10">10px Brush</button> <button id="brushRed">Red Brush</button> <button id="brushBlue">Blue Brush</button> </body> </html> 
+1
source

Source: https://habr.com/ru/post/1486645/


All Articles