I have three arrys:
clickX = [],
clickY = [],
clickDrag = [];
this is what happens when you click down:
$(\'#canvasCur
Do not store painting to array
It slows down drawing critically. Just draw the latest line without clearing canvas. That way lineWeight changes does not affect to before drawings. So remove ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
and for
loop. You also might want to change context styles (lineWidth etc.) only when changes occur, not every time you run redraw()
function.
Undo support
Making different canvas for every mouse down session and drawing them together you can easily make undo feature. By pressing undo it simply splices latest canvas out of canvases array. Google to learn more about drawing to temporary canvas.
EDIT: Sorry, fixed some typos Edit 2: And again. It's a bit difficult to test.
There's no reason to redraw each of the points each time. You could modify 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;
});
Where the function drawLine 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();
}
Here’s how to use canvas to draw like Paint
If you want an undo feature, your best option is to record all line segments drawn by the user.
This is done with a point array that contains all points (polylines) drawn by the user.
To track the brush size and brush color, you need to include this info in your array also.
So each element of the the array will have this info about each line segment:
How does it work?
When the user is drag-drawing a line segment, each mousemove event is extending the current segment with context.lineTo
and context.stroke
.
When the user selects a new BrushSize or BrushColor, context.beginPath starts context.beginPath
.
When the user holds down the Undo button, the last point in the last line segment is popped off the point array. Then all the surviving line segments are redrawn. The undo button fires every 1/10th of a second when held down.
Here is code and a Fiddle: 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>