无限单个 div 动画

Posted

技术标签:

【中文标题】无限单个 div 动画【英文标题】:Infinite individual div animation 【发布时间】:2020-10-07 01:07:47 【问题描述】:

我想为我的缩略图 div 的移动行为设置动画。我希望每个单独的 div 以不同的方式移动。网格本身也可以在两个方向上无限滚动。目前我有以下问题:

div 全部移到页面左侧 动画有时会停止 有时网格在第一次初始滚动时会闪烁

您可以在这支笔中看到结果: https://codepen.io/Dennisade/pen/OJymaKZ

这就是我设置 css 的方式:

CSS:

.grid-image 
  text-align: center;
  width: 50%;
  margin-bottom: 18%;
  pointer-events: none;
  will-change: transform;
  transition: 20s linear

JS

//MOVING ANIMATION

setInterval(function() 
    $('.grid-image').each(function(index)
        var yAxis= index * Math.floor(Math.random()-2);
        var xAxis= index * Math.floor(Math.random()-1);
        $('.grid-image').css('transform', 'matrix(1, 0, 0, 1, ' + yAxis + ',' + xAxis + ')');
    );
, 50);


//ENDLESS SCROLL

var origDocHeight = document.body.offsetHeight;

var clone = $(".wrapper").contents().clone();
clone.appendTo(".wrapper");
clone.prependTo(".wrapper");

$(document).scroll(function() 

    var scrollWindowPos = $(document).scrollTop(); 

    if(scrollWindowPos >= origDocHeight )  
        $(document).scrollTop(0); 
    
    if(scrollWindowPos <= 0 )  
         $(document).scrollTop(origDocHeight); 
             
);

【问题讨论】:

【参考方案1】:

这里似乎有两个独立的部分。首先,div 没有正确移动,然后它们完全停止移动。其次,滚动无法正常工作。

先看div的运动:

我不熟悉 jquery,但您的问题之一似乎是这一行

$('.grid-image').css('transform', 'matrix(1, 0, 0, 1, ' + yAxis + ',' + xAxis + ')');

不会更新当前元素的转换设置,但会更改 grid-image 类的所有元素的 CSS。为确保每个 div 获得其新矩阵,您可以将上面的行更改为

this.style.transform='matrix(1, 0, 0, 1, ' + yAxis + ',' + xAxis + ')';//incidentally did you want the x and y this way round?

另一个问题是除第一个 div 之外的所有 div 仍将在其变换矩阵中以相同的 xAxis 和 yAxis 结束。这是因为 Math.floor(Math.random()) 等价于 Math.floor(Math.random()*1) 给出一个从 0(包括)到 1(不包括)的随机整数,所以它总是 0。根据您希望这些值有多大,您可以使用更高的整数。例如,Math.floor(Math.random()*10) 给出一个从 0 到 9 的随机整数。

我不知道你是否有意这样做,但第一个 div 永远不会改变它的变换,因为它的索引是 0,所以这些行总是设置 xAxis 和 yAxis = 0

var yAxis= index * Math.floor(Math.random()-2);
var xAxis= index * Math.floor(Math.random()-1);

例如,将 1 添加到索引将确保第一个 div 获得新值。

现在更仔细地查看坐标轴的计算,CSS 变换矩阵将其最后两个参数解释为 translateX 和 translateY。这些是相对于元素的当前位置的。在原始值中,这些值始终为负数,因此所有元素逐渐向左移动并(随着增量较小而不太明显)向上移动。

使用您的 Codepen,我的笔记本电脑变得非常热,风扇变得疯狂 - 每秒 20 次对这么多元素进行矩阵变换需要进行大量计算。我试图通过注意到您没有缩放或倾斜元素来缓解这种情况,因此可以使用平移变换而不是矩阵变换。

如果我们将 setInterval 调用替换为

setInterval(function() 
    $('.grid-image').each(function(index)
        var yAxis= (index+1) * Math.floor(Math.random()*1000) * (Math.random() < 0.5 ? -1 : 1);
        var xAxis= (index+1) * Math.floor(Math.random()*1000) * (Math.random() < 0.5 ? -1 : 1);
        this.style.transform='translate('+xAxis+'px,'+yAxis+'px)';
    );
, 50);

我们得到所有 div 的随机运动。当然,运动量取决于时间间隔和 x 和 y 增量的计算,我这里有 *1000 以获得一些容易看到的运动。如果您希望元素在屏幕上移动更多,它需要更多。我在计算中保留了索引,但我不确定这是否是您想要的 - 向下移动的元素比顶部的移动更多,然后当您滚动时,您会再次发现较慢的元素(所以整体效果是一种模式的暗示,而不是完全的随机性)。 使用此代码我还没有看到动画停止 - 并且已经运行了很多分钟。笔记本电脑变热了,但不是那么热。我想可能存在一个问题,即功能较弱的处理器是否可以在时间间隔内完成所有矩阵变换。如果这被证明是一个问题,那么迁移到 setTimeout 会有所帮助,任何鼓励使用 GPU 的 CSS 更改也会有所帮助。

希望这对您的前两点有所帮助。

现在来看看滚动。这段代码

var clone = $(".wrapper").contents().clone();
clone.appendTo(".wrapper");
clone.prependTo(".wrapper");

仅将内容 div 的一份副本放入 .wrapper div。我认为这是因为它被附加,然后被附加,这意味着它不再被附加,即它不能同时出现在两个地方。用此代码替换它会提供 3 个内容 div 副本,我猜您知道这足以满足您的代码将用于显示的大小

var clone = $(".wrapper").contents().clone();
var clone2 = $(".wrapper").contents().clone();
clone.appendTo(".wrapper");
clone2.prependTo(".wrapper");

现在可以向后滚动,但向前滚动有问题。在这段代码中

$(document).scroll(function() 

    var scrollWindowPos = $(document).scrollTop(); 

    if(scrollWindowPos >= origDocHeight )  
        $(document).scrollTop(0); 
    
    if(scrollWindowPos <= 0 )  
         $(document).scrollTop(origDocHeight); 
             
);

其中 scrollWindowPos >= origDocHeight 它滚动到 0,这意味着下次 scrollWindowPos

$(document).scroll(function()

var scrollWindowPos = $(document).scrollTop(); 

if(scrollWindowPos >= origDocHeight )  
    $(document).scrollTop(1); /* used to be 0 - using 1 is a bit hacky but it does the job */

else if(scrollWindowPos <= 0 )  
     $(document).scrollTop(origDocHeight); 
         

);

它并不完美。通过抓住滚动条并将其向下移动来滚动会产生“闪烁”,但通过选择滚动条的向下箭头进行滚动可以平滑滚动,不会出现闪烁(Windows 10、Edge 和 Chrome)。目前我想不出如何进一步调查。

为了获得滚动条,我不得不在 Codepen 的 CSS 中删除 body 上的 display:none,所以我可能误解了你想要滚动的内容。

这是完整的 JS 代码,其中包含上述所有更改

//MOVING ANIMATION

    setInterval(function() 
        $('.grid-image').each(function(index)
            var yAxis= (index+1) * Math.floor(Math.random()*1000) * (Math.random() < 0.5 ? -1 : 1);
            var xAxis= (index+1) * Math.floor(Math.random()*1000) * (Math.random() < 0.5 ? -1 : 1);
            this.style.transform='translate('+xAxis+'px,'+yAxis+'px)';
        );
    , 50);

//ENDLESS SCROLL

var origDocHeight = document.body.offsetHeight;
var clone1 = $(".wrapper").contents().clone();
var clone = $(".wrapper").contents().clone();
clone.appendTo(".wrapper");
clone1.prependTo(".wrapper");

$(document).scroll(function() 

    var scrollWindowPos = $(document).scrollTop(); 

    if(scrollWindowPos >= origDocHeight )  
        $(document).scrollTop(1); 
    
    else if(scrollWindowPos <=0 )  
              $(document).scrollTop(origDocHeight); 
             
);

【讨论】:

以上是关于无限单个 div 动画的主要内容,如果未能解决你的问题,请参考以下文章

如何无限向前运行CSS动画

如何循环 jQuery div 动画?

在无限滑块轨道动画上使用 Element.prepend 的意外 DOM 排序行为

div盒子的缓动函数封装

动画设计属性

css动画(animation)