// move the image by the amount of the latest drag
var dx=mouseX-startX;
var dy=mouseY-startY;
imageX+=dx;
imageY+=dy;
imageRight+=dx;
imageBottom+=dy;
// reset the startXY for next time
startX=mouseX;
startY=mouseY;

The mousedown event handler hit-tests if the user is starting to drag the rotation-handle.

This hit-testing is made easier with context.isPointInPath(x,y) which tests whether a specified [x,y] coordinate is inside the most recently drawn path (Conveniently, the rotation-handle is actually a path).

So mousedown activates the drag-handle like this:

Calculate the current mouseX and mouseY.

Redraw the rotation handle (required because isPointInPath hit-tests just the most recent path)

Yes...we could have simply hit-tested a circle on the end of the rotation-handle, but using isPointInPath will allow you to draw whatever fancy rotation handle you desire.

And isPointInPath has another nice benefit. When the context containing the path is rotated, isPointInPath will hit-test the rotated path for you. This means you don't have to code the math to unrotate the mouse coordinates to do the hit testing--it's done for you!

The mousemove handler redraws the rotatable image at the angle specified by the rotation-handle:

If the isDown flag is not set, just return (the user is not dragging the rotation-handle).