Did you ever write code to drag or move shapes using HTML5 Canvas 2d APIs? If you did, then didn't you ever face a situation (an unexpected behaviour) when you drag or move a shape (e.g. circle, rectangle, image, Bezier cubic/quadratic curve, etc.)?
Fore a live example, please test following demo. Drag any shape (from its any corner):
Didn't you face a sudden jerk on the shape?
Test bottom-part of the demo too. It is working smoothly. There is no sudden jerk!
Let us dig into both examples
circleX = e.pageX - canvas.offsetLeft; circleY = e.pageY - canvas.offsetTop; context.arc(circleX, circleY, 50, 0, Math.PI * 2, false);
Each workaround regarding the shape's width/height or radius is inefficient or non-smooth:
- Extraction of the radius (one or two times) to accurately position the circle
- Subtraction of half width/height of the shape (rectangle/image) to position it accordingly
But for second example, I've not used pageX/pageY directly; instead I'm doing following steps:
- Tracking first/previous mouse-down or touch position (x-y coordinates)
- Extracting the dragged distance from those coordinates
- Adding or subtracting the distance from shape's coordinates according to the dragging direction (positive or negative x-y axis)
/* Global Variable */ var previousPoints = [0, 0]; /* Mouse Down event! */ { var x = ( e.pageX - canvas.offsetLeft ), y = ( e.pageY - canvas.offsetTop ); /* Saving last x-y coordinates! - on mousedown */ previousPoints = [x, y]; } /* Mouse Move event! */ { var x = e.pageX - canvas.offsetLeft, y = e.pageY - canvas.offsetTop, /* Previous points: x-y */ prevX = previousPoints[0], prevY = previousPoints[1]; /* Drag direction! */ positiveX = x > prevX, positiveY = y > prevY, /* The dragged distance! */ value; /* This value will be used for x-coordinates */ value = positiveX ? (x - prevX) : (prevX - x); if (positiveX) circleX += value; else circleX -= value; /* This value will be used for y-coordinates */ value = positiveY ? (y - prevY) : (prevY - y); if (positiveY) circleY += value; else circleY -= value; /* Saving last x-y coordinates! - on mousemove */ previousPoints = [x, y]; } /* And to draw the circle! */ context.arc(circleX, circleY, 50, 0, Math.PI * 2, false);