Is it possible to set Surface sizes based on percentages in Famo.us?
Asked Answered
H

4

10

Famo.us Surfaces have a single way to set the size of a surface. They have a "size" property that takes an array of 2 numbers which correspond directly to pixel values. This is not overly useful when dealing with mobile devices given the large number of different screen sizes. This will require the user to do math on the size of the parent container rather than Famo.us doing the math behind the scenes.

If one of the values is not given, it will use 100% available of that dimension, but there is no way that I can see to specify 50% or 33%.

var firstSurface = new Surface({
  size: [100, 400],
  content: 'hello world',
  properties: {
    color: 'white',
    textAlign: 'center',
    backgroundColor: '#FA5C4F',
    width: "200px"
  }
});

The "width" property doesn't do anything whether or not the 0th array element is removed, even though it's claimed that you can use CSS properties in camelCase. I assumed this would be the proper way to use %'s, but it is not.

Hartsock answered 11/4, 2014 at 20:14 Comment(0)
H
11

No, this is not possible. You need to calculate, but this is not hard:

var sizeModifier = new Modifier();
sizeModifier.sizeFrom(function(){
    var size = mainContext.getSize();
    return [0.5 * size[0],0.5 * size[1]];
});

The engine emits a resize event from the main context where you can hook up your modifier.

Using the sizeFrom function, you can dynamically set the size.

You need to use a Modifier because setting the size on a Surface does not affect the DOM, only the size used for internal calculations. (This can be used for spacing, see the layout guide)

Assuming you want a percentage of the viewport, I used the mainContext, which is [100%,100%]. Of course, you can call getSize on any parent surface.

Henden answered 11/4, 2014 at 22:4 Comment(3)
I knew it wasn't hard, it just seemed silly to have to do it this way.Hartsock
How do you get the parent?Dallon
Depends on how you've structured your code. I'm guessing that you don't have a reference of the parent, correct? In that case you could look at ContextualView.js. (Read source and check out commit function). If you need more info, perhaps post another SO question!Henden
A
7

As of famo.us v0.3, proportional sizing has been added. You can now use this kind of notation:

new Modifier({
    size: [undefined, undefined],
    proportions: [0.5, 1/3] // width 50%, height 33%
});

You can also use for instance SizeConstraint to do size-scaling:

var sizeCS = new SizeConstraint({
   scale: [0.5, 1.3]
});
sizeCS.add(new Surface({..}));

https://github.com/IjzerenHein/famous-sizeconstraint

Atman answered 2/11, 2014 at 22:37 Comment(0)
S
5

I used famo.us to make Breezi, Thinglist, and Lumosity capptivate.co examples (neaumusic.github.io)


Surface:

size:[undefined, undefined],

// this is default; size key can be ommited; fills Modifier size

Modifier:

size: [window.innerWidth * 0.5, window.innerHeight * 0.5],

Later, you can use .setTransform() on your Modifier with Transform.scale() or Transform.rotateY() and since your Surface is directly overlapping the Modifier, nothing funky will happen. This is not to say you can't have a 1 pixel by 1 pixel Modifier to position a Surface from the Surface's top left corner, and this leads me to another topic of confusion with positioning...


Positioning With Origin

If you have an origin [0.3, 0.3], the location 30% of the way across the inner box will align to 30% of the way across the outer box.

In other words, using CSS aligning the left edge of inner to left edge of outer:

position: absolute,
left: 30%

Is not equivalent to origin: [0.3, Y] because your inner object will be too far left by 30% of it's width

But is equivalent to shifting:

origin: [0, Y],
transform: Transform.translate(window.innerWidth * 0.3, 0, 0)

I was recommended to use only 9 positions for the origin

The corners, the middle of the edges, and the center (0.5, 0.5) of a box

Suspensor answered 16/4, 2014 at 0:3 Comment(0)
E
0

Famo.us does manage the size of the surface, but you have the ability to set min and max widths and heights on your surfaces to be responsive.

  var firstSurface = new Surface({
    size: [100, 400],
    content: 'hello world',
    properties: {
      color: 'red',
      textAlign: 'center',
      backgroundColor: '#FA5C4F',
      minWidth: '90%',
      maxHeight: '60%'
    }   
  });
Etana answered 5/10, 2014 at 19:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.