I've been scouring the (still scant) discussions and documentation of famo.us looking for what I hoped would be an obvious thing: Animate a canvas in a CanvasSurface. I am really surprised that I have found not one single example.
I have made some progress, so I hope this post will help someone get their foot on the ladder.
Here is my bare bones code (previously using window.requestAnimationFrame
but now adjusted to extend the built-in render method), which currently works, but I am puzzled.
My question follows the code:
define(function (require) {
"use strict";
var Engine = require('famous/core/Engine'),
View = require('famous/core/View'),
CanvasSurface = require('famous/surfaces/CanvasSurface'),
context = Engine.createContext(),
//
VividCanvas = function () {
var v = new View(),
cw = 320,
ch = 240,
c = 0,
surface = new CanvasSurface({size: [cw, ch]}),
ctxt = surface.getContext('2d'),
//
redraw = function () {
ctxt = surface.getContext('2d'); // WHY IS THIS LINE NECESSARY?
c += 1;
c = c % 360;
ctxt.fillStyle = "hsl(" + c + ", 100%" + ", 50%)";
ctxt.fillRect(0, 0, cw, ch);
window.requestAnimationFrame(redraw);
return surface.id; // i.e. a valid renderSpec
};
surface.render = redraw;
v.add(surface);
return v;
};
//
context.add(new VividCanvas());
});
What puzzles me is that the line ctxt = surface.getContext('2d')
(the first line in the redraw function) is necessary. I would have thought that ctxt was already defined and in scope (see immediately before the redraw function is declared).
Indeed, if you log ctxt, you will get a 2d Canvas Context in both cases. But for some reason, the canvas context which is made in the redraw function is a different instance to the one made before the first redraw.
This may be demonstrated by inserting console.log(ctxt === surface.getContext('2d'))
as the first line of the redraw function (before ctxt is redefined). It logs false. I do not understand why. Can someone explain?
If feel that ctxt should point to the right thing throughout, and should not need to be adjusted, so this second call to getContext should be unnecessary. However, if I omit it, the canvas draws once only.
So why is that?
Originally, I had a second, but perhaps related question was about requestAnimationFrame. From the comments I was able to replace this with the line surface.render = redraw
, and making sure my redraw method returns the surface id, thus allowing Famo.us to handle the animation sync. Thanks to Andrew for his suggestion in the comments.