Question

I'm trying to get a square to change color on click in Famo.us, with a transition. I'm currently using CSS classes:

var square = new Surface({
  size: [200, 200],
  content: 'Hello.',
  properties: {
    lineHeight: '200px',
    textAlign: 'center'
  }
});

square.on('click', function() {
  square.addClass('active');
});

And the styling (written in Stylus):

.famous-container
  .famous-surface
    background: rgba(200, 200, 200, 0.5)

    transition: background 0.3s ease

    &.active
      background: rgba(200, 255, 200, 0.5)

It doesn't feel right, and I can't leverage things like Snap/SpringTransition. Is there a better way?

Was it helpful?

Solution

The best way would be to use a RenderController object.

RenderController allows you to hide and show different renderable items with a transition of your choice.

Check out this example (slightly modified for you) posted under the Famo.us Github account.

https://github.com/Famous/examples/blob/master/src/examples/views/RenderController/example.js

var Engine           = require("famous/core/Engine");
var Modifier         = require("famous/core/Modifier");
var Surface          = require("famous/core/Surface");
var RenderController = require("famous/views/RenderController");

var mainContext = Engine.createContext();
var renderController = new RenderController();
var surfaces = [];
var counter = 0;

surfaces.push(new Surface({
     content: "Surface 1",
     size: [200, 200],
     properties: {
         backgroundColor: "green",
         lineHeight: "200px",
         textAlign: 'center'
     }
}));

surfaces.push(new Surface({
     content: "Surface: 2",
     size: [200, 200],
     properties: {
         backgroundColor: "red",
         lineHeight: "200px",
         textAlign: 'center'
     }
}));

renderController.show(surfaces[0]);

Engine.on("click", function() {
    var next = (counter++ + 1) % surfaces.length;
    this.show(surfaces[next]);
}.bind(renderController));

mainContext.add(new Modifier({origin: [.5, .5]})).add(renderController);

Fixed: Added missing parenthesis at the end of both surfaces.push(...) calls.

OTHER TIPS

The simplest way I could think of is to update backgroundColor using setProperties method of a Surface.

Do that in Surface's render method, which is called on every render tick. Remember to return render spec (spec id).

Instead of using strings or hex values for colors, use rgb() or rgba() which accept number values. Number values are obtained from Transitionable objects using get method.

Toggle number values using Transitionable's set method in "click" event handler.

Remember to pass tween options when setting Transitionable value (duration and easing curve) for a smooth animated effect.

Here's the code:

var bgColorRed = new Transitionable(0);
var bgColorGreen = new Transitionable(255);
var bgColorBlue = new Transitionable(0);

var colorTweenTime = 500;

var clicked = false; 

var square = new Surface({
  size: [200, 200],
  content: 'Hello.',
  properties: {
    lineHeight: '200px',
    textAlign: 'center'
  }
});

square.render = function() {
    var red = Math.ceil(bgColorRed.get()),
        green = Math.ceil(bgColorGreen.get()),
        blue = Math.ceil(bgColorBlue.get());

    this.setProperties({
        backgroundColor: 'rgb(' + red + ', ' + green + ', ' + blue + ')'
    });

    return this.id;
};

square.on('click', function() {
    if (clicked) {
        bgColorRed.set(0, { duration: colorTweenTime, curve: 'easeIn' });
        bgColorGreen.set(255, { duration: colorTweenTime, curve: 'easeIn' });
    } else {
        bgColorRed.set(255, { duration: colorTweenTime, curve: 'easeIn' });
        bgColorGreen.set(0, { duration: colorTweenTime, curve: 'easeIn' });
    }
    clicked = !clicked;
});

jsFiddle available here: http://jsfiddle.net/mcr85/6fx9jo9e/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top