简体   繁体   中英

Point coordinate translate to specific Surface in Famo.us

We have a pretty complex web app built in meteor. The UI is mainly in nested HTML elements. Now we are trying to rewrite the UI with Famo.us so we can have better performance as well as adding great animation effects. One feature in our app is, when user drag on top of an element A, we need to draw a new element B based on the precise position of the mouse events in B. That is, we need to calculate the coordinate of a point in any elements, even the element has complex transforms. We were using the 'webkitConvertPointFromPageToNode' function in webkit browsers(we only support webkit.) to do the job. Does Famo.us has a similar function so I can calculate a point coordinate in a specific Surface? Or do you have any suggestions on how to accomplish such features with current API?

Thanks

Given that the transforms in Famo.us are all backed by absolute positioning, finding the coordinates in any given surface is pretty straightforward. In the Event object you can grab the offsetX and offsetY of the target surface.

Check out this example..

Hope it helps!

var Engine          = require('famous/core/Engine');
var Surface         = require('famous/core/Surface');
var StateModifier   = require('famous/modifiers/StateModifier');
var Transform       = require('famous/core/Transform');

var context = Engine.createContext();

var surface = new Surface({
    size:[200,200],
    properties: {
        backgroundColor:'green',
        color:'white',
        textAlign:'center',
        lineHeight:'200px'
    }
})

surface.on('mousemove',function(e){
    surface.setContent("x: "+e.offsetX+", y: "+e.offsetY);
})

surface.state = new StateModifier({
    transform: Transform.translate(100,100,0)
})

context.add(surface.state).add(surface);

I have found the right way to do this.

First, I dug into the problem mentioned in my comment that the offsetX/offsetY value is actually based on the child surfaces. Because offsetX/offsetY values are generated by DOM's MouseEvent and copied into famo.us with no modification. DOM doesn't provide the coordinate of the mouse point on the 'currentTarget'. It only provide the value for 'target', which is the element the event occurs. So we can only use the clientX/clientY coordinate in the viewport, then calculate the coordinate of that point on the target element. No official API to do the calculation either. Only webkit provide the 'webkitConvertPointFromPageToNode' api to do it because the layout engine knows all about the position and transforms on a specific element.

But then I realise that with Famo.us, we know the transforms of each surface! In the render tree, all the modifiers on the path from root context to a RenderNode form the transform for that node and the nodes below. We can multiply them to get one transform matrix M. Then we can do a coordinate system transformation to calculate the point's right coordinate in the node's local coordinate system.

But Famo.us doesn't have direct API to get all the modifiers for a node, I did it myself in my code. I would suggest Famo.us to add a 'parent' reference on each RenderNode, then we can get them easily for any node.

It took me a while but this work for me:

var myX=event.clientX;
var myY=event.clientY;
for(var i=0;i<event.path.length;i++)
{
    if(event.path[i].style===undefined)
        continue;
    var matrix=event.path[i].style.transform;
    var matrixPattern = /^\w*\((((\d+)|(\d*\.\d+)),\s*)*((\d+)|(\d*\.\d+))\)/i;
    if (matrixPattern.test(matrix)) {
        var matrixCopy = matrix.replace(/^\w*\(/, '').replace(')', '');
        myX-=matrixCopy.split(/\s*,\s*/)[12];
        myY-=matrixCopy.split(/\s*,\s*/)[13];
    }
}

Tested with align and size modifier

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