JavaScript水波纹效果帧率减缓

3
我写了一个超级简单的JavaScript脚本,用于为网站创建水波纹效果,这个假象非常有效,但我遇到了一些问题,我的计时器在处理多个实例时会有延迟。最初,我尝试使用一些CSS3效果来实现,但是渲染元素的计算机会在一段时间后冻结屏幕,所以我重写了代码,重复改变单个PNG文件,这在很大程度上有所帮助,但仍然会卡顿。我不确定如何改善这个问题,是否使用预加载可能有所帮助(我怀疑不会),或者是否有其他优化方法可以修复这个非常有前途的开始。
以下是我的代码:
body{
    background-color:#444;
    position:absolute;
    overflow: hidden;
    z-index:0;}
.circle{
    position:absolute;
    background-image:url(circle5.png);
    background-size:cover;
    background-repeat:no-repeat;
    overflow:hidden;
    z-index:2;} 

以及JavaScript

var locX = '';
var checkX = '';
var locY = '';
var checkY = '';
var eventTimer = setInterval(function(){changeCs()}, 1);//'FRAMERATE' of state changes in milliseconds

//Listen for user mouse movement, fetch current location of cursor, initiate droplets
document.onmousemove = function(e){
    var event = e || window.event;
    locX = event.clientX;
    locY = event.clientY;
    createC();}

//We create divs with the circular image stretched to the otherwise blank div   
function createC(){
//Check to see if the X and Y are the same as in previous cycle, if so movement has stopped.
  if(parseInt(locX) != parseInt(checkX) && parseInt(locY) != parseInt(checkY)){
    var n_Circle = document.createElement('div');
    n_Circle.setAttribute('class','circle');
    n_Circle.setAttribute('style','width:10px;height:3px;opacity:.4;');
    document.body.appendChild(n_Circle);
//We obtain the coordinates of the cursor, and use the same X as the user.
//However with the Y we are shifting downward from the top to maintain illusion of water surface -*THINK EYE LEVEL*
    n_Circle.style.top = parseInt(.75 * window.innerHeight) + parseInt(locY * .4) + 'px';
    n_Circle.style.left = parseInt(locX) + 'px';
    window.setTimeout(function(){createC()},parseInt(Math.random() * 200 + 100));
  }else{return;}//EXIT Function loop
  //ASSIGN new check values before end ot the cycle
  checkX = locX;
  checkY = locY;

  }
//We manipulate the droplet images by this quantity every 'frame'
function changeCs(){
    var arrayCs = document.getElementsByClassName('circle');
    for(i=0; i < arrayCs.length; i++){
        arrayCs[i].style.width = parseInt(arrayCs[i].style.width) + 100 + 'px';
        arrayCs[i].style.left = parseInt(arrayCs[i].style.left) - 50 + 'px';
//The ratio of expansion does not match to the images aspect ratio.
//This helps to create the illusion of depth to the surface deformation
//by shearing a portion of the ellipse away, conveying a sense of depth and angularity
        arrayCs[i].style.height = parseInt(arrayCs[i].style.height) + 26 + 'px'; 
        arrayCs[i].style.top = parseInt(arrayCs[i].style.top) - 14 + 'px';
        arrayCs[i].style.opacity = arrayCs[i].style.opacity - .01;
        if(arrayCs[i].style.opacity <= .00){
            document.body.removeChild(arrayCs[i]);}}}

会尽快在JSFiddle上创建一个示例。非常欢迎任何想法。


http://jsfiddle.net/QNf4K/ 是一个效果的示例。 - Thomas Cheney
另外需要注意的是,我之前也尝试过使用CSS过渡效果,但这似乎几乎立即就会导致我的浏览器死机。看来任何过度使用CSS都会导致浏览器冻结。 - Thomas Cheney
1个回答

1

看看这是否有所改善,对我来说似乎更快了,但由于我不太清楚您的期望是什么,很难确定。Fiddler链接:http://jsfiddle.net/QNf4K/4/

与其每次创建div元素,我只创建了一次,然后进行克隆。并且我缓存了长度。

    var locX = '';
    var checkX = '';
    var locY = '';
    var checkY = '';
    var eventTimer = setInterval(function(){changeCs()}, 1);//'FRAMERATE' of state changes in milliseconds
    var ln_Circle = document.createElement('div');
        ln_Circle.setAttribute('class','circle');
        ln_Circle.setAttribute('style','width:10px;height:3px;opacity:.4;');

  //  then just cloned it here:
    var n_Circle = ln_Circle.cloneNode(true);

 //   I also cached the length here:


            var l = arrayCs.length, i = 0;
            for(; i < l; i++){

// 然后添加了一个测试,检查arrayCs[i]是否存在

          if( arrayCs[i]){
            arrayCs[i].style.width = parseInt(arrayCs[i].style.width) + 100 + 'px';

太棒了。在多个渲染中,似乎显著提高了帧率和流畅度。但我不确定对于数组Cs的测试是否理解正确。 - Thomas Cheney
“for(; i < l; i++){" 这是一个错别字还是正确的上下文使用?我以前没有在任何地方遇到过,但对JavaScript仍然很陌生。” - Thomas Cheney
1
嘿 - 很高兴它能帮到你(如果你喜欢的话,可以接受为答案:-),正在努力建立声誉).. “for”循环只是一种简写方式,并且是有效的。我加入了“if”语句,因为在我的控制台中,通过那段代码生成未定义的内容。也许这是个异常情况。我把它放在那里作为预防措施,也许你不需要它。再次感谢它能帮到您。 - james emanon
现在也在想,当缓存arrayCs.length时,这是否本质上创建了一个对象及其属性的字符串? - Thomas Cheney
1
嘿 - 每次循环迭代时,您都在集合上调用方法“.length”。这是您每次重复调用的调用。因此,由于集合大小不会改变,因此它是开销。这就是为什么我要缓存它,以便循环不必每次进行“长度”调用。我只缓存“它”的长度,没有更多。您正在使用“i”引用引用对象属性,即.. arrayCs [i]。 - james emanon
我现在明白了,我在检查.length的计数时创建了资源瓶颈,因此在多次迭代中,对数组长度的检查显着拖慢了性能,对吗?再次感谢您的反馈。 - Thomas Cheney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接