Javascript 如何优化大型画布动画

Javascript 如何优化大型画布动画,javascript,html,css,canvas,Javascript,Html,Css,Canvas,我有一个大画布动画,我从一个代码笔。问题是它有时运行得有点慢。这就是为什么我想知道如何优化这个动画,使其运行更平稳?我希望尽可能多的提示,我可以得到,如果你能改变代码中的任何东西来帮助我,我将不胜感激 $(window).on("load", function() { (function() { var requestAnimationFrame = window.requestAnimationFrame || window.mozReque

我有一个大画布动画,我从一个代码笔。问题是它有时运行得有点慢。这就是为什么我想知道如何优化这个动画,使其运行更平稳?我希望尽可能多的提示,我可以得到,如果你能改变代码中的任何东西来帮助我,我将不胜感激

$(window).on("load", function() {
    (function() {
      var requestAnimationFrame =
        window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback) {
          window.setTimeout(callback, 1000 / 60);
        };
      window.requestAnimationFrame = requestAnimationFrame;
    })();

    // Terrain stuff.
    var background = document.getElementById("bgCanvas"),
      bgCtx = background.getContext("2d"),
      width = 1920,
      height = 1080;

    if (height < 400) {
      height = 400;
    }

    background.width = width;
    background.height = height;

    function Terrain(options) {
      options = options || {};
      this.terrain = document.createElement("canvas");
      this.terCtx = this.terrain.getContext("2d");
      this.scrollDelay = options.scrollDelay || 90;
      this.lastScroll = new Date().getTime();

      this.terrain.width = width;
      this.terrain.height = height;
      this.fillStyle = options.fillStyle || "#191D4C";
      this.mHeight = options.mHeight || height;

      // generate
      this.points = [];

      var displacement = options.displacement || 140,
        power = Math.pow(2, Math.ceil(Math.log(width) / Math.log(2)));

      // set the start height and end height for the terrain
      this.points[0] = this.mHeight; //(this.mHeight - (Math.random() * this.mHeight / 2)) - displacement;
      this.points[power] = this.points[0];

      // create the rest of the points
      for (var i = 1; i < power; i *= 2) {
        for (var j = power / i / 2; j < power; j += power / i) {
          this.points[j] =
            (this.points[j - power / i / 2] + this.points[j + power / i / 2]) /
              2 +
            Math.floor(Math.random() * -displacement + displacement);
        }
        displacement *= 0.6;
      }

      document.body.appendChild(this.terrain);
    }

    Terrain.prototype.update = function() {
      // draw the terrain
      this.terCtx.clearRect(0, 0, width, height);
      this.terCtx.fillStyle = this.fillStyle;

      if (new Date().getTime() > this.lastScroll + this.scrollDelay) {
        this.lastScroll = new Date().getTime();
        this.points.push(this.points.shift());
      }

      this.terCtx.beginPath();
      for (var i = 0; i <= width; i++) {
        if (i === 0) {
          this.terCtx.moveTo(0, this.points[0]);
        } else if (this.points[i] !== undefined) {
          this.terCtx.lineTo(i, this.points[i]);
        }
      }

      this.terCtx.lineTo(width, this.terrain.height);
      this.terCtx.lineTo(0, this.terrain.height);
      this.terCtx.lineTo(0, this.points[0]);
      this.terCtx.fill();
    };

    // Second canvas used for the stars
    bgCtx.fillStyle = "#05004c";
    bgCtx.fillRect(0, 0, width, height);

    // stars
    function Star(options) {
      this.size = Math.random() * 2;
      this.speed = Math.random() * 0.05;
      this.x = options.x;
      this.y = options.y;
    }

    Star.prototype.reset = function() {
      this.size = Math.random() * 2;
      this.speed = Math.random() * 0.05;
      this.x = width;
      this.y = Math.random() * height;
    };

    Star.prototype.update = function() {
      this.x -= this.speed;
      if (this.x < 0) {
        this.reset();
      } else {
        bgCtx.fillRect(this.x, this.y, this.size, this.size);
      }
    };

    function ShootingStar() {
      this.reset();
    }

    ShootingStar.prototype.reset = function() {
      this.x = Math.random() * width;
      this.y = 0;
      this.len = Math.random() * 80 + 10;
      this.speed = Math.random() * 10 + 6;
      this.size = Math.random() * 1 + 0.1;
      // this is used so the shooting stars arent constant
      this.waitTime = new Date().getTime() + Math.random() * 3000 + 500;
      this.active = false;
    };

    ShootingStar.prototype.update = function() {
      if (this.active) {
        this.x -= this.speed;
        this.y += this.speed;
        if (this.x < 0 || this.y >= height) {
          this.reset();
        } else {
          bgCtx.lineWidth = this.size;
          bgCtx.beginPath();
          bgCtx.moveTo(this.x, this.y);
          bgCtx.lineTo(this.x + this.len, this.y - this.len);
          bgCtx.stroke();
        }
      } else {
        if (this.waitTime < new Date().getTime()) {
          this.active = true;
        }
      }
    };

    var entities = [];

    // init the stars
    for (var i = 0; i < height; i++) {
      entities.push(
        new Star({
          x: Math.random() * width,
          y: Math.random() * height
        })
      );
    }

    // Add 2 shooting stars that just cycle.
    entities.push(new ShootingStar());
    entities.push(new ShootingStar());
    entities.push(new Terrain({ mHeight: height / 2 - 120 }));
    entities.push(
      new Terrain({
        displacement: 120,
        scrollDelay: 50,
        fillStyle: "rgb(17,20,40)",
        mHeight: height / 2 - 60
      })
    );
    entities.push(
      new Terrain({
        displacement: 100,
        scrollDelay: 20,
        fillStyle: "rgb(10,10,5)",
        mHeight: height / 2
      })
    );

    //animate background
    function animate() {
      bgCtx.fillStyle = "#110E19";
      bgCtx.fillRect(0, 0, width, height);
      bgCtx.fillStyle = "#ffffff";
      bgCtx.strokeStyle = "#ffffff";

      var entLen = entities.length;

      while (entLen--) {
        entities[entLen].update();
      }
      requestAnimationFrame(animate);
    }
    animate();
  });
$(窗口).on(“加载”,函数(){
(功能(){
var请求动画帧=
window.requestAnimationFrame||
window.mozRequestAnimationFrame||
window.webkitRequestAnimationFrame||
window.msRequestAnimationFrame||
函数(回调){
设置超时(回调,1000/60);
};
window.requestAnimationFrame=requestAnimationFrame;
})();
//地形的东西。
var background=document.getElementById(“bgCanvas”),
bgCtx=background.getContext(“2d”),
宽度=1920,
高度=1080;
如果(高度<400){
高度=400;
}
背景宽度=宽度;
背景高度=高度;
功能地形(选项){
选项=选项| |{};
this.terrain=document.createElement(“画布”);
this.terCtx=this.terrain.getContext(“2d”);
this.scrollDelay=options.scrollDelay | | 90;
this.lastcoll=new Date().getTime();
this.terrain.width=宽度;
this.terrain.height=高度;
this.fillStyle=options.fillStyle | |“#191D4C”;
this.mHeight=options.mHeight | | height;
//产生
此参数为.points=[];
var位移=选项。位移| | 140,
power=Math.pow(2,Math.ceil(Math.log(width)/Math.log(2));
//设置地形的起始高度和结束高度
this.points[0]=this.mHeight;//(this.mHeight-(Math.random()*this.mHeight/2))-位移;
this.points[power]=this.points[0];
//创建其余的点
对于(var i=1;ithis.lastScroll+this.scrollDelay){
this.lastcoll=new Date().getTime();
this.points.push(this.points.shift());
}
this.terCtx.beginPath();
对于(变量i=0;i=高度){
这是reset();
}否则{
bgCtx.lineWidth=this.size;
bgCtx.beginPath();
bgCtx.moveTo(this.x,this.y);
bgCtx.lineTo(this.x+this.len,this.y-this.len);
bgCtx.stroke();
}
}否则{
if(this.waitTime

编辑:当我说慢的时候,我的意思是动画起伏不平,不平滑

我很确定这是你的
地形#更新
。特别是你的循环

    Terrain.prototype.update = function() {
      for (var i = 0; i <= width; i++) {
        if (i === 0) {
          this.terCtx.moveTo(0, this.points[0]);
        } else if (this.points[i] !== undefined) {
          this.terCtx.lineTo(i, this.points[i]);
        }
      }
编辑:
再看一眼,你似乎也在屏幕上画了1000个
Star
对象。你可能想考虑降低这个数字。你用这个会让每个人的电脑着火的

你说的慢是什么意思?您的FPS较差,或者您的代码需要花费时间来呈现内容。你能补充一些关于你想要达到的目标的信息吗?@karthick,我的意思是动画是起伏的,不平滑的。我增加了间隔,这对你很有帮助,谢谢。关于星星,我在想,是否有可能只把它们放在画布的上半部分,因为它的一半被地形遮住了。一个人怎么做呢?那样的话,事情看起来是一样的,但恒星数量明显减少。我通过简单地将Y轴上产生的恒星数量减半来修正这一点。谢谢你,先生!总是乐于助人。祝你的项目顺利完成
for (var i = 0; i <= width; i += 3) { // or maybe an even higher interval