Is it possible to set Surface sizes based on percentages in Famo.us?
-
21-12-2019 - |
Question
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.
Solution
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.
OTHER TIPS
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({..}));
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
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%'
}
});