Chrome for android 在许多 setInterval 后滞后

Chrome for android lags down after many setInterval

我正在为我的一个应用程序尝试这个演示,但其中一个触摸屏电视正在使用 android 平板电脑 6.0.1,多次点击后它确实滞后。我怀疑是因为那里的 setinterval 脚本。

https://codepen.io/ShawnCG/pen/ZYVada

这是该演示的主要 javascript。

var d = document, $d = $(d),
    w = window, $w = $(w),
    wWidth = $w.width(), wHeight = $w.height(),
    credit = $('.credit > a'),
    particles = $('.particles'),
    particleCount = 0,
    sizes = [
      15, 20, 25, 35, 45
    ],
    colors = [
      '#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5',
      '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4CAF50',
      '#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800',
      '#FF5722', '#795548', '#9E9E9E', '#607D8B', '#777777'
    ],

    mouseX = $w.width() / 2, mouseY = $w.height() / 2;

function updateParticleCount () {
  $('.particle-count > .number').text(particleCount);
};

$w
.on( 'resize' , function () {
  wWidth = $w.width();
  wHeight = $w.height();
});

$d
.on( 'mousemove touchmove' , function ( event ) {
  event.preventDefault();
  event.stopPropagation();
  mouseX = event.clientX;
  mouseY = event.clientY;
  if( !!event.originalEvent.touches ) {
    mouseX = event.originalEvent.touches[0].clientX;
    mouseY = event.originalEvent.touches[0].clientY;
  }
})
.on( 'mousedown touchstart' , function( event ) {
  if( event.target === credit.get(0) ){
    return;
  }
  mouseX = event.clientX;
  mouseY = event.clientY;
  if( !!event.originalEvent.touches ) {
    mouseX = event.originalEvent.touches[0].clientX;
    mouseY = event.originalEvent.touches[0].clientY;
  }
  var timer = setInterval(function () {
    $d
    .one('mouseup mouseleave touchend touchcancel touchleave', function () {
      clearInterval( timer );
    })
    createParticle( event );
  }, 1000 / 60)

});


function createParticle ( event ) {
  var particle = $('<div class="particle"/>'),
      size = sizes[Math.floor(Math.random() * sizes.length)],
      color = colors[Math.floor(Math.random() * colors.length)],
      negative = size/2,
      speedHorz = Math.random() * 10,
      speedUp = Math.random() * 25,
      spinVal = 360 * Math.random(),
      spinSpeed = ((36 * Math.random())) * (Math.random() <=.5 ? -1 : 1),
      otime,
      time = otime = (1 + (.5 * Math.random())) * 1000,
      top = (mouseY - negative),
      left = (mouseX - negative),
      direction = Math.random() <=.5 ? -1 : 1 ,
      life = 10;

  particle
  .css({
    height: size + 'px',
    width: size + 'px',
    top: top + 'px',
    left: left + 'px',
    background: color,
    transform: 'rotate(' + spinVal + 'deg)',
    webkitTransform: 'rotate(' + spinVal + 'deg)'
  })
  .appendTo( particles );
  particleCount++;
  updateParticleCount();

  var particleTimer = setInterval(function () {
    time = time - life;
    left = left - (speedHorz * direction);
    top = top - speedUp;
    speedUp = Math.min(size, speedUp - 1);
    spinVal = spinVal + spinSpeed;


    particle
    .css({
      height: size + 'px',
      width: size + 'px',
      top: top + 'px',
      left: left + 'px',
      opacity: ((time / otime)/2) + .25,
        transform: 'rotate(' + spinVal + 'deg)',
        webkitTransform: 'rotate(' + spinVal + 'deg)'
    });

    if( time <= 0 || left <= -size || left >= wWidth + size || top >= wHeight + size ) {
      particle.remove();
        particleCount--;
      updateParticleCount();
      clearInterval(particleTimer);
    }
  }, 1000 / 60);  
}

我已将同一动画的 jquery 更改为 gsap。因此,我使用的不是 $(element).css(),而是 Tweenlite.set()

是否有硬件加速浏览器播放此类动画的方法?

如有任何帮助,我们将不胜感激。

最大的性能损失是因为您使用了 DOM 元素。如果您改为使用 <canvas> 作为粒子,它的性能会 好得多 (如果您愿意,您可以获得成百上千个粒子而不会带来太大的性能风险) .

但是,您可以使此 DOM 动画 比当前的 更高效。最大的改变是使用 transforms 而不是 topleft。在 GSAP 中,您可以通过影响 xy 属性来实现。您还应该使用变换的 scale 而不是影响 width/height。在 GSAP 中,您还应该设置 rotation 而不是实际的转换本身(它会为您生成 属性 transform)。我还建议使用 GSAP 的 .set() 方法而不是 jQuery 的 .css()。要获得更高的性能,请使用 GSAP 的 .quickSetter() 方法。

使用 GSAP 的 .delayedCall 而不是 setInterval 也会更可靠。更好的是,使用 gsap.ticker() 并从中调用所有更新函数!

一共得到this demo.

可以进行其他优化,例如重复使用相同的粒子而不是 creating/destroying 旧粒子,但就 DOM 动画而言,性能已接近极限。就像我一开始说的,这种东西非常适合<canvas>