javascript - To drag shapes drawn on canvas same as paint -
i have tool similar paint allow user draw different shapes on canvas using mouse events.i want allow user drag shapes(same paint) once drawn on canvas. did done before? have tried using oopdragging didn't work in case.also tool include kind of shapes line,elbow connector,oval,text,image , not circles , rectangles. can please suggest easy achieve solution need asap. in advance.
a demo: http://jsfiddle.net/m1erickson/jrzm2/
assume you've created triangle in paint program
and points triangle in array this:
[{x:0,y:20},{x:30,y:0},{x:70,y:45}]
to move triangle [20,35], need first offset triangle x:20 & y:35
var mytriangle={ x:20, y:35, points:[{x:0,y:20},{x:30,y:0},{x:70,y:45}] }
then can draw triangle @ [20,35] this:
note offsets (20,35) added each point in triangle's position
function draw(mytriangle){ var x=mytriangle.x; var y=mytriangle.y; var points=mytriangle.points; ctx.beginpath(); ctx.moveto( x+points[0].x, y+points[0].y ); for(var i=1;i<points.length;i++){ ctx.lineto( x+points[i].x, y+points[i].y ); } ctx.closepath(); ctx.fill(); }
to drag triangle, listen mouse events
- in mousedown, check if mouse on triangle. if yes, start drag.
- in mousemove, add distance user dragged since last mousemove triangle's position.
- in mouseup, stop drag
in mousedown
canvas has nice built-in function test if specified point inside path triangle.
this function context.ispointinpath(mousex,mousey) , tests if mousex/mousey inside last drawn path.
if mouse pressed on triangle, set isselected
flag indicate triangle should dragged every mousemove.
so mousedown function looks this:
function handlemousedown(e){ // tell browser we're using mousedown, // don't bother doing browser stuff event e.preventdefault(); // current mousex,mousey position mousex=parseint(e.clientx-offsetx); mousey=parseint(e.clienty-offsety); // test if mousex,mousey inside triangle if(ctx.ispointinpath(startx,starty)){ // if yes, set "isselected" flag // indicates triangle should // move mouse isselected=true; } }
in mousemove
the mousemove event triggered 20-30 times per second user moves mouse.
in mousemove, if triangle isselected, want calculate how far mouse has moved since last mousemove event.
then want change x,y position of triangle distance mouse has moved.
so mousemove function looks this:
function handlemousemove(e){ // if triangle wasn't selected during mousedown // there's nothing do, return if(!isselected){return;} e.preventdefault(); // current mouse position mousex=parseint(e.clientx-offsetx); mousey=parseint(e.clienty-offsety); // calculate how far mouse has moved since last mousemove var dx=mousex-startx; var dy=mousey-starty; // next mousemove, reset starting xy current xy startx=mousex; starty=mousey; // move triangle change in mouse position mytriangle.x+=dx; mytriangle.y+=dy; // clear canvas , // redraw triangle @ new position context.clearrect(0,0,canvas.width,canvas.height); draw(mytriangle); }
in mouseup
in mouseup, isselected
flag cleared since drag over:
function handlemouseup(e){ e.preventdefault(); isselected=false; }
here's code more complex example multiple shapes:
<!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> <style> body{ background-color: ivory; } #canvas{border:1px solid red;} </style> <script> $(function(){ // vars related canvas var canvas=document.getelementbyid("canvas"); var ctx=canvas.getcontext("2d"); var $canvas=$("#canvas"); var canvasoffset=$canvas.offset(); var offsetx=canvasoffset.left; var offsety=canvasoffset.top; var scrollx=$canvas.scrollleft(); var scrolly=$canvas.scrolltop(); var cw=canvas.width; var ch=canvas.height; // vars related dragging var isdown=false; var startx; var starty; // save shape-points in var shapes=[]; var selectedshape=null; // test shapes addshape(50,50,[{x:0,y:20},{x:30,y:0},{x:70,y:45}],"blue","red"); addshape(100,100, [{x:0,y:10},{x:30,y:10},{x:30,y:0}, {x:45,y:15},{x:30,y:30},{x:30,y:20},{x:0,y:20}], "green","red"); // begin... drawall(); function addshape(x,y,points,fill,stroke){ shapes.push({x:x,y:y,points:points,fill:fill,stroke:stroke}); } function define(shape){ var x=shape.x; var y=shape.y; var points=shape.points; ctx.beginpath(); ctx.moveto(x+points[0].x,y+points[0].y); for(var i=1;i<points.length;i++){ ctx.lineto(x+points[i].x,y+points[i].y); } ctx.closepath(); } function draw(shape){ define(shape); ctx.fillstyle=shape.fill; ctx.fill(); ctx.strokestyle=shape.stroke; ctx.stroke(); } function drawall(){ ctx.clearrect(0,0,cw,ch); for(var i=0;i<shapes.length;i++){ draw(shapes[i]); } } function handlemousedown(e){ e.preventdefault(); startx=parseint(e.clientx-offsetx); starty=parseint(e.clienty-offsety); for(var i=0;i<shapes.length;i++){ define(shapes[i]); if(ctx.ispointinpath(startx,starty)){ selectedshape=shapes[i]; isdown=true; } } } function handlemouseup(e){ e.preventdefault(); isdown=false; selectedshape=null; } function handlemouseout(e){ e.preventdefault(); isdown=false; selectedshape=null; } function handlemousemove(e){ if(!isdown){return;} e.preventdefault(); mousex=parseint(e.clientx-offsetx); mousey=parseint(e.clienty-offsety); var dx=mousex-startx; var dy=mousey-starty; startx=mousex; starty=mousey; selectedshape.x+=dx; selectedshape.y+=dy; drawall(); } $("#canvas").mousedown(function(e){handlemousedown(e);}); $("#canvas").mousemove(function(e){handlemousemove(e);}); $("#canvas").mouseup(function(e){handlemouseup(e);}); $("#canvas").mouseout(function(e){handlemouseout(e);}); }); // end $(function(){}); </script> </head> <body> <h4>drag shapes around canvas</h4> <canvas id="canvas" width=300 height=300></canvas> </body> </html>
Comments
Post a Comment