简体   繁体   中英

In KineticJS, on a canvas rotated using css3, the events don't seem to be working properly

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.

Update:

As markE suggested, there was no easy fix. The issue can be seen here . It was closed recently.

The original error was apparently caused by jquery's event handling code. It works properly as of the latest version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM