2

我正在尝试学习如何使用 HTML5 的画布创建流畅的 JavaScript 动画。由于某种原因,动画并不流畅,而是一种“溅射”。

你可以看到我在这个 jsFiddle上构建的框架,它目前只使用 Webkit 属性。

另一位开发人员能够使用基于Ext.js的 WebViews 源代码创建相同的概念。出于学习目的,我想避免使用任何库来更好地理解 JavaScript。WebViews 概念可以在这个 jsFiddle中查看,它显示了更流畅的动画。

我已经阅读并尝试了各种不同的场景,从将updaterequestAnimationFrame 中的调用拉到它自己的循环中,到将上下文转换为绘制位置,再到绘制到后台缓冲区上下文并将其复制到视口。以下代码代表了我迄今为止的最大努力。

关于如何提高性能以使对象平稳移动而没有外部库的所有开销的任何建议?

先感谢您。

var app;
var now = then = delta = 0;
var viewport = document.createElement( 'canvas' );
var viewportContext = viewport.getContext( '2d' );

function App( )
{
    this.circle = {
        position : viewport.width / 2,
        radius : 10
    };
}

App.prototype.initialize = function( )
{
    app = this;
    document.body.appendChild( viewport );
    viewport.width = 320;
    viewport.height = 200;

    webkitRequestAnimationFrame( app.render, viewport );
};

App.prototype.render = function( )
{
    now = performance.webkitNow( );
    delta = ( now - then ) / 1000.0;
    then = now;

    app.update( delta );
    viewportContext.clearRect( 0, 0, viewport.width, viewport.height );
    app.draw( viewportContext );

    webkitRequestAnimationFrame( app.render, viewport );
};

App.prototype.draw = function( context )
{
    context.fillStyle = "white";
    context.beginPath( );
    context.arc( this.circle.position | 0, viewport.height / 2 | 0, this.circle.radius | 0, 0, Math.PI * 2, true );
    context.closePath( );
    context.fill( );
};

App.prototype.update = function( deltaTime )
{
    this.circle.position += viewport.width / 5 * deltaTime;

    if( this.circle.position >= viewport.width )
    {
        this.circle.position = 0;
    }
};

window.onload = function( )
{
    new App( ).initialize( );
};​
4

2 回答 2

4

有关许多常见优化的信息,请参阅此页面,并详细解释它们为什么以及如何提高性能。

此外,出于某种原因,性能似乎在更“中等大小”的画布上有所提高。我不完全确定这是为什么,但我相信这与浏览器优化有关。

您可以在此处通过一些小调整注意到一些性能提升:http: //jsfiddle.net/3TAVu/1/

具体来说,我在这里删除了对 fillStyle 的多余分配:

App.prototype.draw = function( context )
{
    context.beginPath( );
    context.arc( this.circle.position | 0, viewport.height / 2 | 0, this.circle.radius | 0, 0, Math.PI * 2, true );
    context.closePath( );
    context.fill( );
};

我还通过只清除画布的相关部分而不是整个东西来修改渲染方法:

App.prototype.render = function( )
{
    now = performance.webkitNow( );
    delta = ( now - then ) / 1000.0;
    then = now;

    var cX = app.circle ? (app.circle.position - app.circle.radius) : 0;
    var cY = Math.round(viewport.height/2) - app.circle.radius;
    var w = app.circle ? app.circle.radius * 2 : 0;

    viewportContext.clearRect(cX - 1, cY - 1, w + 2, w + 2);

    app.update( delta );
    app.draw( viewportContext );

    webkitRequestAnimationFrame( app.render, viewport );
};
于 2012-09-25T20:09:54.157 回答
3

嘿,我发现这个关于 requestAnimationFrame 的东西解释得很好,它处理更流畅的动画。如果您或此问题的未来查看者可能会发现这很有用..

于 2013-06-06T15:30:58.917 回答