Scale image on dragging using famo.us - famo.us

I am new to famo.us, I am trying to scale image on dragging.My code is working fine for one drag after that its not working. How can I make it work fro every drag?
Does setTransform make the scale operation fixed?
define(function(require, exports, module) {
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var StateModifier = require("famous/modifiers/StateModifier");
var Draggable = require("famous/modifiers/Draggable");
var Transform = require("famous/core/Transform");
var ImageSurface = require('famous/surfaces/ImageSurface');
var mainContext = Engine.createContext();
var size_x = 200;
var size_y = 200;
var scale_x =1;
var scale_y =1;
var surface = new ImageSurface({
size: [size_x, size_y],
content: 'img/1.jpg',
properties: {
backgroundColor: 'rgba(200, 200, 200, 0.5)',
cursor: 'pointer'
}
});
var draggable = new Draggable({
xRange: [-100, 1000],
yRange: [-100, 1000]
});
surface.pipe(draggable);
var mod = new StateModifier({
transform: Transform.translate(150, 100, 0)
});
var mod1 = new StateModifier({
});
mainContext.add(mod).add(mod1).add(surface);
draggable.on('update',function(data){
var delta = draggable.getPosition();
var scale_x = (size_x+ delta[0])/size_x;
var scale_y = (size_y+ delta[1])/size_y;
mod1.setTransform(
Transform.scale(scale_x,scale_y, 0)
);
});
});

All you need to do is change how you are using the scale function. You are scaling your 'z' property to 0. It should be 1.
So change this..
Transform.scale(scale_x,scale_y, 0);
To this..
Transform.scale(scale_x,scale_y, 1);
Good Luck!

Related

z-translate is ignored by GridLayout view

I want to use GridLayout in ScrollView context and be able to translate surfaces of GridLayout in Z-direction. The problem is that for some reason Z-translate is ignored in GridLayout. Seems like GridLayout has zero perspective because translate in x and y directions just work. How to fix that?
Here is example where z-translate just does nothing :(
define(function(require, exports, module) {
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var Scrollview = require("famous/views/Scrollview");
var View = require("famous/core/View");
var ContainerSurface = require("famous/surfaces/ContainerSurface");
var MouseSync = require("famous/inputs/MouseSync");
var TouchSync = require("famous/inputs/TouchSync");
var GenericSync = require("famous/inputs/GenericSync");
GenericSync.register({ 'mouse': MouseSync, 'touch': TouchSync });
var syncX = new GenericSync(['mouse', 'touch'], { direction: 0 });
var GridLayout = require("famous/views/GridLayout");
var StateModifier = require('famous/modifiers/StateModifier');
var Transform = require("famous/core/Transform");
var mainContext = Engine.createContext();
mainContext.setPerspective(1000);
var grid = new GridLayout({
dimensions: [6, 2]
});
var scrollview = new Scrollview({direction: 0});
syncX.pipe(scrollview);
var surfaces = [];
var mods = [];
var views = [];
for (var i = 0, temp; i < 12; i++) {
view = new View();
mod = new StateModifier();
temp = new Surface({
content: "Surface: " + (i + 1),
size: [200, 200],
properties: {
backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
lineHeight: "200px",
textAlign: "center"
}
});
temp.pipe(syncX);
surfaces.push(temp);
mods.push(mod);
view.add(mod).add(temp);
views.push(view);
}
grid.sequenceFrom(views);
var container = new ContainerSurface({size:[1200,400]});
container.context.setPerspective(1000); ///<----------
container.add(grid);
scrollview.sequenceFrom([container]);
Engine.on('click', function(){
mods[0].setTransform(Transform.translate(2,2,999), {duration:1000});
});
mainContext.add(scrollview);
});
BTW I did test it in Chrome
The GridLayout should not ignore the z-translate as you can see if you run the code below. There are some things missing and extra pieces you do not need in the code you supplied above.
Note: Putting a modifier on the view in the GridLayout the way you are using it may not end up giving you the desired result you want, but the example does show how it works.
Example jsBin
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var Scrollview = require("famous/views/Scrollview");
var View = require("famous/core/View");
var ContainerSurface = require("famous/surfaces/ContainerSurface");
var GridLayout = require("famous/views/GridLayout");
var StateModifier = require('famous/modifiers/StateModifier');
var Transform = require("famous/core/Transform");
var mainContext = Engine.createContext();
mainContext.setPerspective(1000);
var grid = new GridLayout({
dimensions: [6, 2]
});
var scrollview = new Scrollview({direction: 0});
var surfaces = [];
var mods = [];
var views = [];
for (var i = 0; i < 12; i++) {
var view = new View();
var mod = new StateModifier({
size: [200, 200],
transform: Transform.translate(0,0,0.001)
});
var temp = new Surface({
content: "Surface: " + (i + 1),
properties: {
backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
lineHeight: "200px",
textAlign: "center"
}
});
surfaces.push(temp);
mods.push(mod);
temp.pipe(view);
view.add(mod).add(temp);
views.push(view);
temp.on('click', translateOut.bind(temp, i));
}
grid.sequenceFrom(views);
var container = new ContainerSurface({size:[1200,400]});
container.add(grid);
grid.pipe(container);
scrollview.sequenceFrom([container]);
container.pipe(scrollview);
function translateOut(index){
if (!this.moved) {
mods[index].setTransform(Transform.translate(0,0,400), {duration:1000});
} else {
mods[index].setTransform(Transform.translate(0, 0,0.001), {duration:1000});
}
this.moved =!this.moved;
}
mainContext.add(scrollview);
This is due to a newly introduced chrome bug. It looks like Chrome tries to fast path some of its rendering when everything is initially at a z translation of 0. If you add a Surface to the scene at a no zero z with an opacity of 0 you can trick Chrome into drawing correctly.
mainContext
.add(new StateModifier({
transform: Transform.translate(0, 0, 100000000),
size: [1, 1],
opacity: 0
})).add(new Surface({
properties: {backgroundColor: 'chromeHack'}
}));
I will edit this post when I make a simpler example and file as a chrome bug.

How to create empty space between the Surfaces in ScrollView in famo.us?

I've created a horizontal ScrollView and added some Surfaces to it. I want to have an empty space between the Surfaces when I scroll (swipe) the view. I've tried setting the margins, padding, borders, etc.. in the properties of the Surfaces and the ScrollView but the surfaces remain connected together no matter what.
Does anyone know how I can achieve this?
This could be done a few ways. The non-famo.us approach would be to add surfaces and use Content HTML to create margins. For the sake of the example, I will assume you want a list of surfaces that just need some margin!
I knew about itemSpacing in SequntialLayout, and was surprised to not find such a thing in ScrollView as well. So to solve the problem, I simply added all my surfaces to a SequentialLayout, and then add that as the sole item in Scrollview.
Also note I added a background surface, to capture the mouse events that happen between the surfaces!
Here is what I did.. Hope it helps!
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var Scrollview = require("famous/views/Scrollview");
var SequentialLayout = require("famous/views/SequentialLayout");
var mainContext = Engine.createContext();
var bg = new Surface({ size:[undefined,undefined] });
var scrollview = new Scrollview();
var scrollSurfaces = [];
scrollview.sequenceFrom(scrollSurfaces);
var sequentialLayout = new SequentialLayout({itemSpacing:20});
var surfaces = [];
sequentialLayout.sequenceFrom(surfaces);
for (var i = 0; i < 40; i++) {
var surface = new Surface({
content: "Surface: " + (i + 1),
size: [undefined, 200],
properties: {
backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
lineHeight: "200px",
textAlign: "center"
}
});
surface.pipe(scrollview);
surfaces.push(surface);
}
scrollSurfaces.push(sequentialLayout);
bg.pipe(scrollview);
mainContext.add(bg);
mainContext.add(scrollview);
I think using a ContainerSurface is better, use many containsurfaces to contain the surface.You should emulate in Apple iphone 5.In other environment, you should adjust the origin of scrollModifier to fix.
define(function(require, exports, module) {
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var Transform = require("famous/core/Transform");
var View = require('famous/core/View');
var StateModifier = require('famous/modifiers/StateModifier');
var Scrollview = require("famous/views/Scrollview");
var Modifier = require("famous/core/Modifier");
var ContainerSurface = require("famous/surfaces/ContainerSurface");
var mainContext = Engine.createContext();
var scrollview = new Scrollview({
direction: 0,
paginated: 'true',
pageStopSpeed: 2
});
var scrollnodes = [];
scrollview.sequenceFrom(scrollnodes);
for (var i = 0; i < 40; i++) {
var container = new ContainerSurface();
var temp = new Surface({
content: "Surface: " + (i + 1),
size: [window.innerWidth -40, window.innerHeight - 40],
properties: {
backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
lineHeight: "200px",
textAlign: "center"
}
});
// wrong
// will return temp as scrollnode, it will ignore the container
// var scrollnode = container.add(temp)
// this is right
container.add(temp);
var scrollnode = container;
temp.pipe(scrollview);
scrollnodes.push(scrollnode);
}
var scrollModifier = new StateModifier({
origin: [0.07, 0.04]
});
mainContext.add(scrollModifier).add(scrollview);
});
You could also use the FlexScrollView, which supports a spacing option to achieve this:
var scrollView = new FlexScrollView({
layoutOptions: {
spacing: 10
}
});
https://github.com/IjzerenHein/famous-flex/blob/master/tutorials/FlexScrollView.md
https://github.com/IjzerenHein/famous-flex

Famo.us how to make a scrollview be filled from bottom to top (or right to left)?

Assuming I've a scrollview with direction 1 (vertical). While populating the scrollView, the items do appear and are aligned from top to bottom.
I would like to know if there is a way to reverse this ordering i.e. to make the scrollView be populated from the bottom to the top. A good example of usage is a message list. You want the last message to always appear on the bottom of the list. By default, the message would be aligned on top, which is not convenient.
[EDIT]
I just found we can easily set our own transform according to an offset overriding the outputFrom function callback. For example the following will invert the scroll content:
scrollview.outputFrom(function(offset)
{
return Transform.translate(0, -offset)
});
Did it like you suggested, it works just fine while rotating all by 180˚. Example: http://jsfiddle.net/tamtamchik/LA49a/3/
Famous.loaded(function () {
var Engine = Famous.Core.Engine;
var Surface = Famous.Core.Surface;
var Scrollview = Famous.Views.Scrollview;
var Timer = Famous.Utilities.Timer;
var Transform = Famous.Core.Transform;
var StateModifier = Famous.Modifiers.StateModifier;
var ContainerSurface = Famous.Surfaces.ContainerSurface;
var mainContext = Engine.createContext();
var scrollview = new Scrollview();
var surfaces = [];
var i = 0;
var surfaceHeight = 50;
scrollview.sequenceFrom(surfaces);
Timer.setInterval(function () {
var container = new ContainerSurface({
size: [undefined, surfaceHeight]
});
var temp = new Surface({
content: "Surface: " + (i + 1),
size: [undefined, surfaceHeight],
properties: {
backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
lineHeight: "50px",
textAlign: "center"
}
});
var surfaceRotate = new StateModifier({
transform: Transform.rotateZ(Math.PI)
});
var surfacePush = new StateModifier({
transform: Transform.translate(window.innerWidth, surfaceHeight)
});
container.add(surfacePush).add(surfaceRotate).add(temp);
container.pipe(scrollview);
temp.pipe(scrollview);
surfaces.unshift(container);
i++;
}, 400);
var rotate = new StateModifier({
transform: Transform.rotateZ(Math.PI)
});
var push = new StateModifier({
transform: Transform.translate(window.innerWidth, window.innerHeight)
});
mainContext.add(push).add(rotate).add(scrollview);
});
Well as famo.us documentation says: "Scrollview will lay out a collection of renderables sequentially in the specified direction", so it will order the surfaces in the order you provide.
My advice is to add the surfaces to a list and then just add them to the ScrollView in reverse.
What you are looking for is unshift(). You can view the following code run at codefamo.us
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 Easing = require('famous/transitions/Easing');
var Scrollview = require('famous/views/Scrollview');
var mainContext = Engine.createContext();
var items = [];
var scroll = new Scrollview();
mainContext.add(scroll);
var counter=0;
scroll.sequenceFrom(items);
function addOne() {
setTimeout(function() {
var surface = new Surface({
size: [100, 100],
content: 'surf: '+counter++,
properties: {
textAlign: 'center',
lineHeight: '20px'
}
});
items.unshift(surface);
if (counter<10)
addOne();
},2000);
}
addOne();

Dragging related issue famo.us

I am very new to Famo.us I am trying to code the following. There are 4 famous image surface surface,surface2,surface3,surface4. Surface1 has image content other 3 are blank. I want to setContent of the other 3 surface by dragging image at them or by dragging surface1.
There are three problems with it:
1) After first drag I am setting the content and trying to move the imagesurface(surface) back to original location, but it is not moving.
2) When I am setting the imagesurface(surface) at any other location than (0,0,0) then the behavior is changed.
3) When I am changing the imagesurface with inputsurface there is huge time lag.
Here is my code:
define(function(require, exports, module) {
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var Modifier = require("famous/core/Modifier");
var StateModifier = require("famous/modifiers/StateModifier");
var Draggable = require("famous/modifiers/Draggable");
var Transform = require("famous/core/Transform");
var Transitionable = require("famous/transitions/Transitionable");
var ImageSurface = require('famous/surfaces/ImageSurface');
var Timer = require('famous/utilities/Timer');
var EventHandler = require('famous/core/EventHandler');
var InputSurface = require("famous/surfaces/InputSurface");
var SnapTransition = require("famous/transitions/SnapTransition");
Transitionable.registerMethod('snap', SnapTransition);
var mainContext = Engine.createContext();
var eventHandler = new EventHandler();
var surface = new ImageSurface({
size: [200, 200],
content: 'img/1.jpg',
properties: {
cursor: 'pointer'
}
});
var background_surface = new ImageSurface({
size: [200, 200],
content: 'img/1.jpg',
properties: {
cursor: 'pointer'
}
});
var surface2 = new ImageSurface({
size: [200, 200],
// type: 'image'
content: ''
});
var surface3 = new ImageSurface({
size: [200, 200],
content: ''
});
var surface4 = new ImageSurface({
size: [410, 200],
content: ''
});
var mod2 = new Modifier({
transform: Transform.translate(500, 0, 0)
});
mainContext.add(mod2).add(surface2);
var mod3 = new Modifier({
transform: Transform.translate(710, 0, 0)
});
mainContext.add(mod3).add(surface3);
var mod4 = new Modifier({
transform: Transform.translate(500, 210, 0)
});
mainContext.add(mod4).add(surface4);
var draggable = new Draggable({
xRange: [-1000, 1000],
yRange: [-1000, 1000]
});
surface.pipe(draggable);
var mod = new Modifier({
});
var back_mod = new Modifier({
origin: [0,0]
});
var trans = {
method: 'snap',
period: 100,
dampingRatio: 0.3,
velocity: 0
};
var check=0;
draggable.on('start', function()
{ draggable.setPosition([0,0,0], trans);
check=0;
surface._matrix[12] = 0;
console.log(surface._matrix[12]);
});
surface.on('mouseup', function() {
draggable.setPosition([0,0,0], trans);
});
draggable.on('end', function(data){
surface2.on('mouseover', function(){
if(check==0)
{ draggable.setPosition([surface2._matrix[12],surface2._matrix[13],surface2._matrix[14]], trans);
check=1;
mainContext.add(back_mod).add(background_surface);
}
});
surface3.on('mouseover', function(){
if(check==0)
{console.log("Surface3");
draggable.setPosition([surface3._matrix[12],surface3._matrix[13],surface3._matrix[14]], trans);
mainContext.add(back_mod).add(background_surface);
check=1;}
});
surface4.on('mouseover', function(){
if(check==0){
console.log("Surface4");
draggable.setPosition([surface4._matrix[12]-256,surface4._matrix[13],surface4._matrix[14]], undefined);
var scale_factor= 410/200;
mod.setTransform(
Transform.scale(scale_factor,1, 0),
{ duration :0,curve: 'linear' }
);
check=1;
mainContext.add(back_mod).add(background_surface);
}
});
});
mainContext.add(mod).add(draggable).add(surface);
});
I'm a little unsure of what you're going for but... here's a different version where the draggable always returns to 0,0 and can be used again to set content of another image surface. Can you help with more detail on what you're trying to achieve?
define(function(require, exports, module) {
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var Modifier = require("famous/core/Modifier");
var StateModifier = require("famous/modifiers/StateModifier");
var Draggable = require("famous/modifiers/Draggable");
var Transform = require("famous/core/Transform");
var Transitionable = require("famous/transitions/Transitionable");
var ImageSurface = require('famous/surfaces/ImageSurface');
var Timer = require('famous/utilities/Timer');
var EventHandler = require('famous/core/EventHandler');
var InputSurface = require("famous/surfaces/InputSurface");
var SnapTransition = require("famous/transitions/SnapTransition");
Transitionable.registerMethod('snap', SnapTransition);
var mainContext = Engine.createContext();
var surface = new ImageSurface({
size: [200, 200],
content: 'images/1.jpg',
properties: {
cursor: 'pointer'
}
});
var background_surface = new ImageSurface({
size: [200, 200],
content: 'images/1.jpg',
properties: {
cursor: 'pointer'
}
});
var surface2 = new ImageSurface({
size: [200, 200],
content: ''
});
var surface3 = new ImageSurface({
size: [200, 200],
content: ''
});
var surface4 = new ImageSurface({
size: [410, 200],
content: ''
});
var mod2 = new Modifier({
transform: Transform.translate(500, 0, 0)
});
mainContext.add(mod2).add(surface2);
var mod3 = new Modifier({
transform: Transform.translate(710, 0, 0)
});
mainContext.add(mod3).add(surface3);
var mod4 = new Modifier({
transform: Transform.translate(500, 210, 0)
});
mainContext.add(mod4).add(surface4);
var draggable = new Draggable({
xRange: [-1000, 1000],
yRange: [-1000, 1000]
});
draggable.imageSurface = surface;
surface.pipe(draggable);
var mod = new Modifier({
});
var back_mod = new Modifier({
origin: [0,0]
});
var trans = {
method: 'snap',
period: 100,
dampingRatio: 0.3,
velocity: 0
};
var check=0;
draggable.on('start', function()
{
check=0;
surface._matrix[12] = 0;
console.log(surface._matrix[12]);
});
draggable.on('end', function(data){
var theDraggable = this;
surface2.on('mouseover', function(){
if(check==0)
{
console.log("Surface2");
check=1;
this.setContent(theDraggable.imageSurface._imageUrl);
}
});
surface3.on('mouseover', function(){
if(check==0)
{console.log("Surface3");
this.setContent(theDraggable.imageSurface._imageUrl);
check=1;}
});
surface4.on('mouseover', function(){
if(check==0){
console.log("Surface4");
this.setContent(theDraggable.imageSurface._imageUrl);
check=1;
}
});
this.setPosition([0,0,0], trans);
});
mainContext.add(mod).add(draggable).add(surface);
});

Can halt() stop the animation at the end state?

I want halt() my translate animation and have it instantly end up at its final location. halt() currently stops the animation where it currently is.
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 Easing = require('famous/transitions/Easing');
var mainContext = Engine.createContext();
var surface = new Surface({
size: [100, 100],
content: 'click me to halt',
properties: {
color: 'white',
textAlign: 'center',
backgroundColor: '#FA5C4F'
}
});
var stateModifier = new StateModifier({
origin: [0.5, 0]
});
mainContext.add(stateModifier).add(surface);
stateModifier.setTransform(
Transform.translate(0, 300, 0),
{ duration : 8000, curve: 'linear' }
);
surface.on('click', function() {
stateModifier.halt();
surface.setContent('halted');
});
Your solution does seem very hacky.. why don't you just apply the same transform without a transition..
surface.on('click', function() {
stateModifier.halt();
stateModifier.setTransform(Transform.translate(0, 300, 0));
surface.setContent('halted');
});
EDIT:
Even better you can just get the final transform directly..
surface.on('click', function() {
stateModifier.setTransform(stateModifier.getFinalTransform());
surface.setContent('halted');
});
I discovered a hack for this, at least for pre-0.2.0.
You can set the final state using Translate.set() using a very large number to force the last state of the animation.
It would be nice to see support for this somehow with halt() in future versions of Famo.us
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 Easing = require('famous/transitions/Easing');
var mainContext = Engine.createContext();
var surface = new Surface({
size: [100, 100],
content: 'click me to halt',
properties: {
color: 'white',
textAlign: 'center',
backgroundColor: '#FA5C4F'
}
});
var stateModifier = new StateModifier({
origin: [0.5, 0]
});
mainContext.add(stateModifier).add(surface);
stateModifier.setTransform(
Transform.translate(0, 300, 0),
{ duration : 8000, curve: 'linear' }
);
surface.on('click', function() {
// This forces the translate animation to its end state
var translate = stateModifier._transformState.translate;
translate.set(translate.get(Number.MAX_VALUE));
surface.setContent('halted');
});