I'm using Kineticjs for a rotating pie-chart widget. When I try to draw on a rotated canvas element (the parent node is rotated 60deg using CSS3), the events don't seem to be working properly. For example, the hover event on a 15 deg clockwise rotated canvas is 15 deg off. Any Ideas?
The answer to your question is not trivial---here’s why:
Your DOM container is in transformed space.
Your Kinetic objects react as if they are in non-transformed space.
Your kinetic objects are mis-responding because the browser is feeding them transformed mouse positions.
The simple fix: Leave the DOM container untransformed and do all rotations inside KineticJS
The difficult fix: convert rotated DOM mousepoints into unrotated points for Kinetic to use.
Here's the difficult fix:
The default rotation-point of CSS transforms is 50%,50% (the middle of the element) so find the center of the Kinetic stage
var cx=stage.getWidth()/2;
var cy=stage.getHeight()/2;
Given a mouseX/mouseY in transformed space (DOM space), you need to find the untransformed point (KineticJS space)
var unrotatedPoint = unrotatedXY(cx,cy, mouseX,mouseY, cssDegreeRotation);
Here’s the function that does that calculation:
function unrotatedXY(cx,cy, mouseX,mouseY, cssDegreeRotation) {
var dx=mouseX-cx;
var dy=mouseY-cy;
var r=Math.sqrt(dx*dx+dy*dy);
var cssRadianAngle = cssDegreeRotation * Math.PI/180;
// calc the angle of the mouse position
var rotatedAngle = Math.atan2(dy,dx);
// unrotate the mouse position by the css rotation
var unrotatedAngle = rotatedAngle -= cssRadianAngle;
// normalize the angle
if(unrotatedAngle<0){ unrotatedAngle+=Math.PI*2; }
// calc the unrotated XY
unrotatedX = cx+ r * Math.cos(unrotatedAngle);
unrotatedY = cy+ r * Math.sin(unrotatedAngle);
return({x:unrotatedX,y:unrotatedY});
}
The mouseX/mouseY above are coming from the document, not KineticJS.
This means you must listen for mouse events on the document (or your container element), not in KineticJS itself.
$(document).mousemove(function(e){handleMouseMove(e);});
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// convert the DOM mousepoint to a Kinetic mousepoint
var unrotatedPoint = unrotatedXY(cx,cy, mouseX,mouseY, cssDegreeRotation);
// Now you can check for hovers, etc against your Kinetic nodes …
}
To tie back into KineticJS, you might use node.fire to trigger events using custom event objects containing your converted mouse coordinates.