Question

In order to center a scaling or a rotation you need to rely on a modifier using the origin property i.e. {"origin":[0.5,0.5]}

Unfortunately it seems that origin will not only set the reference center point of the surface but also translate it to some place relative to its parent.

Now imagine the following case: I would like to create a button surface and to place it in the upper left corner (default with origin:[0,0]). While triggering an action, the surface should scale (or rotate) from its center and not from this upper left corner (which would be the default behaviour).

Obviously I could make it work by creating a custom transform matrix multiplying a translation and a scaling matrix in order to center the surface.

However I cannot imagine there is no better famo.us way of doing this, I tried to make a container (read a view), add the surface to the view through a centred modifier then add this view to the context through another modifier with origin [0,0] but no way… any advise on the pattern to use ?

Was it helpful?

Solution

[EDIT] Famo.us version > 0.2.0 introduced the "align" property.

var rotation = new StateModifier({
  origin:[0.5,0.5], // Set the origin to the center, this will center the rotation as well
  align:[0,0], // Set the surface's origin to the upper left corner of the parent 
  transform: Transform.rotateZ(1), // a transform (here a rotation)
});

Here below is my previous solution for versions < 0.2.0:

As long as there is no modifier with the "size" property the context one is taken as a fallback. In the same way, a modifier cannot be positioned relatively to its parent if its size property is missing. Here is an example on how to do this

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

var mainContext = Engine.createContext();

var surface = new Surface({
  size: [100, 100],
  properties: {
    backgroundColor: '#FA5C4F' // a silly square surface
  }
});

var rotation = new StateModifier({
  origin:[0.5,0.5], //center for the rotation
  transform: Transform.rotateZ(1),// a transform
});

var stateModifier = new StateModifier({
  origin:[0.0,0.0],//The modifier position according to the parent
  size:[100,100],// The size with which the modifier can be positioned (note that using [1,1] would put the center of the square stuck to the upper left corner)
});


mainContext.add(stateModifier).add(rotation).add(surface);

OTHER TIPS

When you say 'no way', are you saying you do not want to do it like this, or that the View does not work?

I would suggest using the ContainerSurface every time you want to alter the origin. If there are two origins there has to two modifiers.

Here is how I approached the problem..

Hope it helps..

var Engine            = require('famous/core/Engine');
var Surface           = require('famous/core/Surface');
var StateModifier     = require('famous/modifiers/StateModifier');
var ContainerSurface  = require('famous/surfaces/ContainerSurface');
var EventHandler      = require('famous/core/EventHandler')
var Transform         = require('famous/core/Transform')
var Easing            = require('famous/transitions/Easing')

var context = Engine.createContext();

var surface = new Surface({
  size: [200,200],
  properties: { backgroundColor: 'green' }
});

surface.rotateState = new StateModifier({origin:[0.5,0.5]});

surface.translateState = new StateModifier({origin:[0,0]});

surface.container = new ContainerSurface({size:surface.getSize()});

surface.container.add(surface.rotateState).add(surface);

var rotate = 0;
var transition = {duration:400,curve:Easing.inOutQuad};

surface.on('click',function(){
  rotate += Math.PI;
  surface.rotateState.setTransform(Transform.rotate(0,0,rotate),transition);
});

context.add(surface.translateState).add(surface.container);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top