简体   繁体   English

不稳定的画布动画-EaselJS

[英]Choppy canvas animation - EaselJS

I'm trying to emulate the canvas element seen in spire's banner using EaselJS. 我正在尝试使用EaselJS模拟在尖塔横幅中看到的canvas元素。 But my animations are choppy both on chrome and firefox. 但是我的动画在chrome和firefox上都不稳定。 Any help is appreciated. 任何帮助表示赞赏。 (Using EaselJS for the first time) (首次使用EaselJS)

My code: 我的代码:

<!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>

There are a number of issues with your demo, which all will cause performance issues. 演示中存在很多问题,所有这些都会导致性能问题。 The main thing it comes down to is that you are not properly using tweens, and not cleaning up items. 主要原因是您没有正确使用补间,也没有清理物品。

  1. The main performance problem is that you are creating a new tween for each circle every tick . 主要的性能问题是, 每个刻度线都为每个圆创建一个新的补间。 In your second loop, for each circle, you are calling TweenLite.to(item, 10, {y: yy}); 在第二个循环中,对于每个圆圈,您都在调用TweenLite.to(item, 10, {y: yy}); . This will create (and best case override) the tween for that object every single time, for each circle. 这将为每个对象每次为每个圆创建(最好覆盖)补间。 At the rough rate you are making circles, there will be > 1000 circles at any given time. 以您制作圈子的粗略速度,任何给定时间将有> 1000个圈子。 The best approach here is to move your overall move tween inside the loop where you make each circle, so it happens one time per circle. 最好的方法是将整个补间移动到制作每个圆的循环内,因此每个圆只发生一次。

  2. The second issue with tweens is that you check if the circle is less than 300px, and tween it out (alpha) if it is. 补间的第二个问题是,您检查圆是否小于300px,如果补圆了,则将其补间(alpha)。 However since the circle is still moving while it fades, it means that each tick you are creating a NEW alpha tween for each circle. 但是,由于圆在淡入淡出时仍在移动,这意味着您为每个圆创建了一个新的alpha补间。 You should do this one time for each circle. 您应该为每个圈子执行一次 You can do this by setting a flag on the element that it is fading out, so it doesn't happen more than once. 您可以通过在要淡出的元素上设置一个标志来做到这一点,这样就不会发生多次。

  3. You are never removing circles from your circles array. 您绝不会从circles数组中删除圈子。 This means your array is growing by 10 circles per tick ~ so about 300 circles per second. 这意味着您的数组每刻增长了10个圆圈〜大约每秒300个圆圈。 After 10 seconds you have 3000 circles, etc. With shapes, you are going to hit a performance max pretty quickly, even after resolving the issues with the tweens that I outlined above. 10秒后,您将获得3000个圆等。使用形状,即使解决了我上面概述的补间问题,您也将很快达到最高性能。 When you remove from the stage, also remove from the array. 从舞台上移开时,也要从阵列移开。

  4. Graphics are slow. 图形很慢。 If you want something super performant, use images, or cached shapes. 如果您想获得超级高性能,请使用图像或缓存的形状。 Your demo has random colors for each sprite, but the Spire demo does not. 您的演示中每个精灵都有随机的颜色,但是Spire演示中没有。 If you want some variety you could pre-cache a bunch of colors, and draw from an object pool of images, ideally in a SpriteSheet. 如果您想要一些变化,则可以预先缓存一堆颜色,并从对象的图像库中进行绘制,最好是在SpriteSheet中。

Overall, the overhead of Tweens is the biggest issue. 总体而言,Tweens的开销是最大的问题。 You could probably refactor this to get better performance without using tweens, since the animations are pretty predictable. 您可以重构它以获得更好的性能,而无需使用补间,因为动画是可以预测的。

Cheers, 干杯,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM