繁体   English   中英

Javascript提高画布性能

[英]Javascript improve canvas performance

我创建了一个背景画布,可绘制约300个对象。现在,当我移动鼠标时,它会滞后很多时间。 可能不是因为画布无法绘制300个对象?

我已经进行了一些有关优化的研究,例如仅使用整数,因此抗混叠将更少。

<script>
  var stars = [];
  var starCount = 500;
  var starColors = ["#125A89", "#409897", "#042B44", "#125987"];

  //Setup canvas
  var canvas = document.getElementById("background");
  var ctx = canvas.getContext("2d");

  //Initialize all the measurements
  function initialize() {
    var backgroundWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    var backgroundHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

    document.getElementById("myCanvas").setAttribute('width', backgroundWidth);
    document.getElementById("myCanvas").setAttribute('height', backgroundHeight);

    //Start the background and draw it
    createStars(starCount);
    drawBackground();
  }

  //Create the star objects in a array
  function createStars(starCount) {
    stars = [];
    for (var i = 0; i < starCount; i ++) {
      var star = {
        size: getRandomInt(1, 3),
        Yspeed: getRandomInt(4, 10),
        Xpos: getRandomInt(0, canvas.width),
        Ypos: getRandomInt(0, canvas.height),
        color: starColors[getRandomInt(0, starColors.length)]
      }
      stars.push(star);
    }
  }

  //Generate random number
  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  function drawBackground() {
    //Clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    //Draw background
    ctx.rect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "#000000";
    ctx.fill();

    //Draw al the stars from the array
    for (var i = 0; i < stars.length; i ++) {
      var star = stars[i];

      ctx.beginPath();
      ctx.rect(star.Xpos, star.Ypos, star.size, star.size);

      if (ctx.fillStyle != star.color) ctx.fillStyle = star.color;
      ctx.fill();

      if (star.Ypos + star.size > canvas.height) star.Ypos = -star.size;
      else star.Ypos += star.Yspeed;
    }

    //Call the next draw cycle
    setTimeout(function() {
      window.requestAnimationFrame(drawBackground);
    }, 1000/60);
  }
</script>

初始化函数称为onresizeonload ,我可以做一些更改来优化代码吗? 还是我只是在推动极限。

这里对requestAnimationFrame的工作方式有些误解。

您无需尝试以每秒60次的速度强制对requestAnimationFrame的调用(re:1000/60)。 那是自动发生的。

window.requestAnimationFrame()方法告诉浏览器您希望执行动画,并请求浏览器在下一次重绘之前调用指定的函数来更新动画。 该方法将回调作为要在重绘之前调用的参数。

回调次数通常为每秒60次,但按照W3C的建议,通常将与大多数Web浏览器中的显示刷新率匹配。
-window.requestAnimationFrame() MDN

您在这里真正要做的是每1000/60调用一次超时,然后尝试调用drawBackground 由于超时不可靠,因此会产生斜坡效应,并导致您观察到滞后问题。

从您的代码中删除setTimeout,而只需使用

window.requestAnimationFrame(drawBackground);

JSFiddle演示


除了使用timeOut之外,在其运行requestAnimationFrame时多次调用drawBackground也不是一个好主意-尤其是考虑到它处理的数据不在函数范围内,这意味着无论如何更新它都使用stars数组。 使用一个标志来确保动画还没有开始,以防止多次调用它来初始化。

var animationRunning = false;
function initialize() {
    //... existing code
    if(!animationRunning){
        drawBackground();
        animationRunning = true;
    }
}

暂无
暂无

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

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