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 而不是 top
和 left
。在 GSAP 中,您可以通过影响 x
和 y
属性来实现。您还应该使用变换的 scale
而不是影响 width
/height
。在 GSAP 中,您还应该设置 rotation
而不是实际的转换本身(它会为您生成 属性 transform
)。我还建议使用 GSAP 的 .set()
方法而不是 jQuery 的 .css()
。要获得更高的性能,请使用 GSAP 的 .quickSetter()
方法。
使用 GSAP 的 .delayedCall
而不是 setInterval
也会更可靠。更好的是,使用 gsap.ticker()
并从中调用所有更新函数!
一共得到this demo.
可以进行其他优化,例如重复使用相同的粒子而不是 creating/destroying 旧粒子,但就 DOM 动画而言,性能已接近极限。就像我一开始说的,这种东西非常适合<canvas>
。
我正在为我的一个应用程序尝试这个演示,但其中一个触摸屏电视正在使用 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 而不是 top
和 left
。在 GSAP 中,您可以通过影响 x
和 y
属性来实现。您还应该使用变换的 scale
而不是影响 width
/height
。在 GSAP 中,您还应该设置 rotation
而不是实际的转换本身(它会为您生成 属性 transform
)。我还建议使用 GSAP 的 .set()
方法而不是 jQuery 的 .css()
。要获得更高的性能,请使用 GSAP 的 .quickSetter()
方法。
使用 GSAP 的 .delayedCall
而不是 setInterval
也会更可靠。更好的是,使用 gsap.ticker()
并从中调用所有更新函数!
一共得到this demo.
可以进行其他优化,例如重复使用相同的粒子而不是 creating/destroying 旧粒子,但就 DOM 动画而言,性能已接近极限。就像我一开始说的,这种东西非常适合<canvas>
。