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);