断断续续的 canvas 动画 - EaselJS

Choppy canvas animation - EaselJS

我正在尝试使用 EaselJS 模拟 spire's 横幅中的 canvas 元素。但是我的动画在 chrome 和 firefox 上都不稳定。任何帮助表示赞赏。 (第一次使用EaselJS)

我的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>EaselJS</title>
    <style>
        body{
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
        #spire-canvas{
            background: #333;
        }
    </style>
</head>
<body>

    <canvas id="spire-canvas" width="1366" height="768"></canvas>

    <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/EaselJS/0.8.0/easeljs.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
    <script>
        $(document).ready(function(){


            //INITIALIZATIONS
            var stage,
            particles = 10, 
            fps = 30, 
            viewportWidth = window.innerWidth, 
            viewportHeight = window.innerHeight,
            circles = [];

            function init(){
                stage = new createjs.Stage("spire-canvas");
                createjs.Ticker.addEventListener("tick", refresh);
                createjs.Ticker.setFPS(fps);
                console.log("init fired");
            }

            function refresh(){
                for(var i = 0; i < particles; i++){
                    var circle = new createjs.Shape();
                    circle.graphics.beginFill('#' + Math.floor(Math.random() * 16777215).toString(16))
                    .drawCircle(0, 0, (Math.random() * 10));
                    circle.x = circle.x + Math.random() * viewportWidth;
                    circle.y = (Math.random() * viewportHeight) + viewportHeight;
                    circle.alpha = 0.1 + Math.random() * 0.2;
                    stage.addChild(circle);
                    circles.push(circle);
                };
                for(var i = 0; i < circles.length; i++){
                    var item = circles[i];
                    var yy = item.y + Math.floor(Math.random() * (viewportHeight - 300)) * -1;

                    if(item.y < 300){
                        TweenLite.to(item, 1, {alpha: '0', ease: Power4.easeOut, onComplete: function(){
                            stage.removeChild(item);
                        }});
                    }

                    TweenLite.to(item, 10, {y: yy});
                };
                stage.update();
            }

            init();
        });
    </script>
</body>
</html>

您的演示存在很多问题,这些问题都会导致性能问题。主要归结为你没有正确使用补间,也没有清理项目。

  1. 主要的性能问题是您正在为每个圆每个刻度创建一个新补间。在你的第二个循环中,对于每个圈子,你都在调用 TweenLite.to(item, 10, {y: yy});。这将为每个圆圈每次都为该对象创建(最好的情况是覆盖)补间。按照你画圈的粗略速度,在任何给定时间都会有 > 1000 个圈。这里最好的方法是将你的整体移动补间移动到你制作每个圆圈的循环中,这样每个圆圈发生一次。

  2. tweens 的第二个问题是检查圆是否小于 300px,如果是则将其补出 (alpha)。然而,由于圆圈在消失时仍在移动,这意味着您为每个圆圈创建一个新的 alpha 补间的每个刻度。每个圈子你应该一次。您可以通过在它正在淡出的元素上设置一个标志来做到这一点,这样它不会发生不止一次。

  3. 您永远不会从 circles 数组中删除圆圈。这意味着您的阵列每滴答增长 10 个圆圈,所以每秒大约 300 个圆圈。 10 秒后你有 3000 个圆圈,等等。对于形状,你将很快达到性能最大值,即使在解决了我上面概述的补间问题之后也是如此。当你从舞台上移除时,也从阵列中移除。

  4. 图形速度很慢。如果你想要一些超级性能的东西,请使用图像或缓存的形状。您的演示中每个精灵都有随机颜色,但 Spire 演示中没有。如果你想要一些变化,你可以预先缓存一堆颜色,并从图像对象池中绘制,最好是在 SpriteSheet 中。

总的来说,Tweens 的开销是最大的问题。您可能可以在不使用补间的情况下重构它以获得更好的性能,因为动画是非常可预测的。

干杯,