【发布时间】:2014-06-30 04:46:46
【问题描述】:
我一直在搜索 famo.us 的(仍然很少)讨论和文档,寻找我希望的显而易见的东西:在 CanvasSurface 中为画布设置动画。我真的很惊讶我没有找到一个例子。
我已经取得了一些进展,所以我希望这篇文章能帮助人们踏上阶梯。
这是我的基本代码(以前使用window.requestAnimationFrame,但现在调整为扩展内置的渲染方法),目前可以工作,但我很困惑。
我的问题跟在代码后面:
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());
});
让我困惑的是ctxt = surface.getContext('2d')这行(重绘函数的第一行)是必须的。我会认为 ctxt 已经定义并在范围内(请参阅重绘函数声明之前的内容)。
确实,如果您记录 ctxt,您将在这两种情况下获得 2d Canvas Context。但是由于某种原因,在重绘函数中创建的画布上下文与第一次重绘之前创建的实例不同。
这可以通过插入console.log(ctxt === surface.getContext('2d')) 作为重绘函数的第一行来证明(在重新定义 ctxt 之前)。它记录为假。我不懂为什么。谁能解释一下?
如果觉得 ctxt 应该始终指向正确的东西,并且不应该需要调整,那么第二次调用 getContext 应该是不必要的。但是,如果我省略它,画布只会绘制一次。
那是为什么呢?
最初,我有第二个问题,但可能相关的问题是关于 requestAnimationFrame。在 cmets 中,我可以将其替换为 surface.render = redraw 行,并确保我的重绘方法返回表面 id,从而允许 Famo.us 处理动画同步。感谢 Andrew 在 cmets 中提出的建议。
【问题讨论】:
-
我将不得不回到这个,但对于初学者来说,我不知道 requestAnimationFrame 是否是正确的方法.. Famo.us 允许您使用 Engine.on('prerender' ,fn) 这似乎是不断更新画布的可靠候选者..
-
从 CanvasSurface 继承,然后实现
render方法,您可以在其中执行所有更新工作。 -
按照 Andrew 的建议,我现在添加了一个渲染方法。棘手的部分是让它返回一个有意义的 renderSpec,但一个有意义的 renderSpec 只是表面的 id。但是,我仍然有一个奇怪的问题,即必须在重绘之前和之后都调用 getContext 未解决。有接受者吗?