我一直在搜索(仍然很少)关于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已经定义并且在范围内(请参阅redraw函数之前的事件)。
实际上,如果你记录ctxt,你将在两种情况下得到一个2d Canvas上下文。但由于某种原因,在重绘函数中创建的画布上下文与第一次重绘之前的画布上下文不同。
这可以通过插入console.log(ctxt === surface.getContext('2d'))
作为重绘函数的第一行(在重新定义ctxt之前)来证明。它记录错误。我不懂为什么。有人可以解释一下吗?
如果觉得ctxt应该指向正确的东西,并且不需要调整,那么第二次调用getContext应该是不必要的。但是,如果我省略它,画布只会绘制一次。
那为什么呢?
最初,我有一个,但也许相关的问题是关于requestAnimationFrame。从评论我可以用行surface.render = redraw
替换它,并确保我的重绘方法返回表面ID,从而允许Famo.us处理动画同步。感谢Andrew在评论中提出的建议。
答案 0 :(得分:2)
在查看CanvasSurface的代码时,似乎使用了两个上下文。可能是您用来渲染的一个,而另一个则显示。当下一个AnimationFrame开始时,它会翻转上下文。
/**
* Returns the canvas element's context
*
* @method getContext
* @param {string} contextId context identifier
*/
CanvasSurface.prototype.getContext = function getContext(contextId) {
this._contextId = contextId;
return this._currTarget ? this._currTarget.getContext(contextId) : this._backBuffer.getContext(contextId);
};
答案 1 :(得分:1)
我在着名的拉格里奇项目中做了Canvas动画: https://github.com/IjzerenHein/famous-lagometer
基本上我在View.render()中进行画布渲染。 两倍大小的乘法是在视网膜显示器上增加额外的褶皱。
/**
* Renders the view.
*/
MyView.prototype.render = function render() {
var context = this.canvas.getContext('2d');
var size = this.getSize();
var canvasSize = [size[0] * 2, size[1] * 2];
this.canvas.setSize(size, canvasSize);
// Do canvas drawing here...
context.clearRect(0, 0, canvasSize[0], canvasSize[1]);
context.fillStyle = this.options.backgroundColor;
context.fillRect(0, 0, canvasSize[0], canvasSize[1]);
context.lineWidth = 1;
context.strokeStyle = this.options.borderColor;
context.strokeRect(0, 0, canvasSize[0], canvasSize[1]);
...
// Call super
return this._node.render();
};