巧用JS数组的slice方法进行循环排序,仿学步园文章推荐滚动效果

1. 仿站效果

今天看到学步园网站右边有个文章推荐的滚动栏目,觉得挺有意思,效果如下:

2. 原理猜想

如此小动画的效果,首先想到的可能是一个长数据列表,不断变化列表的长度,利用外部边框的遮罩裁剪效果,从而做出就像是文章标题在滚动的效果。

原理如下:

 

图中,黑色边框代表显示区域,灰色边框代表 ul>li 列表项目 ,Time1~Time3 分别代表不同时刻的列表项运行高度。

 双倍内容的列表项目整体上移动,利用显示区域的遮罩效果,达到一种标题在轮番切换的错觉。

至于为什么要双倍内容?是因为在运动到底部内容的时候,不会因为内容都在上方,而出现空白。

查看源代码发现,基本和上面的猜想一致。

 1 <div id="scat">
 2                 <ul>
 3             <li><a href="https://www.xuebuyuan.com/2201282.html" rel="bookmark" title="详细阅读作业的提交和监控(二)">作业的提交和监控(二)</a></li>
 4         </ul>
 5                 <ul>
 6             <li><a href="https://www.xuebuyuan.com/2201280.html" rel="bookmark" title="详细阅读作业的提交和监控(一)">作业的提交和监控(一)</a></li>
 7         </ul>
 8                 <ul>
 9             <li><a href="https://www.xuebuyuan.com/2198273.html" rel="bookmark" title="详细阅读Boost – Function 分析">Boost – Function 分析</a></li>
10         </ul>
11                 <ul>
12             <li><a href="https://www.xuebuyuan.com/2198272.html" rel="bookmark" title="详细阅读奇技淫巧 – C/C++ 宏自身迭代">奇技淫巧 – C/C++ 宏自身</a></li>
13         </ul>
14                 <ul>
15             <li><a href="https://www.xuebuyuan.com/2198221.html" rel="bookmark" title="详细阅读模板的 SFINAE 原则">模板的 SFINAE 原则</a></li>
16         </ul>
17                 <ul>
18             <li><a href="https://www.xuebuyuan.com/2198220.html" rel="bookmark" title="详细阅读Octopress 和 Git 的结合">Octopress 和 Git 的结合</a></li>
19         </ul>
20                 <ul>
21             <li><a href="https://www.xuebuyuan.com/2198208.html" rel="bookmark" title="详细阅读Electric-fence 介绍">Electric-fence 介绍</a></li>
22         </ul>
23                 <ul>
24             <li><a href="https://www.xuebuyuan.com/2198206.html" rel="bookmark" title="详细阅读原子操作浅谈">原子操作浅谈</a></li>
25         </ul>
26             
27                 <ul>
28             <li><a href="https://www.xuebuyuan.com/2201282.html" rel="bookmark" title="详细阅读作业的提交和监控(二)">作业的提交和监控(二)</a></li>
29         </ul>
30                 <ul>
31             <li><a href="https://www.xuebuyuan.com/2201280.html" rel="bookmark" title="详细阅读作业的提交和监控(一)">作业的提交和监控(一)</a></li>
32         </ul>
33                 <ul>
34             <li><a href="https://www.xuebuyuan.com/2198273.html" rel="bookmark" title="详细阅读Boost – Function 分析">Boost – Function 分析</a></li>
35         </ul>
36                 <ul>
37             <li><a href="https://www.xuebuyuan.com/2198272.html" rel="bookmark" title="详细阅读奇技淫巧 – C/C++ 宏自身迭代">奇技淫巧 – C/C++ 宏自身</a></li>
38         </ul>
39                 <ul>
40             <li><a href="https://www.xuebuyuan.com/2198221.html" rel="bookmark" title="详细阅读模板的 SFINAE 原则">模板的 SFINAE 原则</a></li>
41         </ul>
42                 <ul>
43             <li><a href="https://www.xuebuyuan.com/2198220.html" rel="bookmark" title="详细阅读Octopress 和 Git 的结合">Octopress 和 Git 的结合</a></li>
44         </ul>
45                 <ul>
46             <li><a href="https://www.xuebuyuan.com/2198208.html" rel="bookmark" title="详细阅读Electric-fence 介绍">Electric-fence 介绍</a></li>
47         </ul>
48                 <ul>
49             <li><a href="https://www.xuebuyuan.com/2198206.html" rel="bookmark" title="详细阅读原子操作浅谈">原子操作浅谈</a></li>
50         </ul>
51             </div>
学步园代码

3. 实现优化

但是,列表项目多写一倍,难免有些累赘,代码也不干净。

有没有其他的实现方式呢?

既然是动画,我们都知道,动画都是借助人眼的视觉暂留效果来实现的,如果只是人为的改变title的标题排序,是不是同样实现同样的效果呢(类比小人书的,每张图都是有一点点差异,在翻阅的速度变快的时候,好像小人书里的人物真的在跑起来。)

因此,在设计列表的时候,只是写一倍的列表项,然后通过编程实现列表的排序算法。

说到这个算法,也很简单,借助于数组存放 li 列表中的内容,然后定时改变数组的值,然后渲染列表就实现了列表项的排序。

举例:

对于数组  a = [1,2,3,4,5,6] ; 我们希望数组运动起来,依次就要实现:

a = [1,2,3,4,5,6]; // time1

a = [2,3,4,5,6,1]; // time2

a = [3,4,5,6,1,2]; // time3

a = [4,5,6,1,2,3]; // time4

a = [5,6,1,2,3,4]; // time5

a = [6,1,2,3,4,5]; // time6

a = [1,2,3,4,5,6]; // time7 (循环)

如此改变值,数组就好像动起来了。

但是,人工实现的话是很容易,但是如何封装成函数,让它自动适应数组条数。

考虑数组Array有slice方法,用于数组的切割。原型如下:

// slice 原型
arr.slice([begin[, end]])

// slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。
// 原始数组不会被改变。

因此,如下函数可以实现数组的动态变化:

/**
 * 数组循环
 * param:arr Array 待变化数组
 * return:变化后的数组
 */
function change(arr)
{
  return a.slice(1).concat(a.slice(0,1));
}

于是,仿写功能代码(引入jQuery):

 1     <ul>
 2             <li><a href="https://www.xuebuyuan.com/2201282.html" rel="bookmark" title="详细阅读作业的提交和监控(二)">1 作业的提交和监控(二)</a></li>
 3             <li><a href="https://www.xuebuyuan.com/2201280.html" rel="bookmark" title="详细阅读作业的提交和监控(一)">2 作业的提交和监控(一)</a></li>
 4             <li><a href="https://www.xuebuyuan.com/2198273.html" rel="bookmark" title="详细阅读Boost – Function 分析">3 Boost – Function 分析</a></li>
 5             <li><a href="https://www.xuebuyuan.com/2198272.html" rel="bookmark" title="详细阅读奇技淫巧 – C/C++ 宏自身迭代">4 奇技淫巧 – C/C++ 宏自身</a></li>
 6             <li><a href="https://www.xuebuyuan.com/2198221.html" rel="bookmark" title="详细阅读模板的 SFINAE 原则">5 模板的 SFINAE 原则</a></li>
 7             <li><a href="https://www.xuebuyuan.com/2198220.html" rel="bookmark" title="详细阅读Octopress 和 Git 的结合">6 Octopress 和 Git 的结合</a></li>
 8             <li><a href="https://www.xuebuyuan.com/2198208.html" rel="bookmark" title="详细阅读Electric-fence 介绍">7 Electric-fence 介绍</a></li>
 9             <li><a href="https://www.xuebuyuan.com/2198206.html" rel="bookmark" title="详细阅读原子操作浅谈">8 原子操作浅谈</a></li>
10 </ul>
 1 $(function(){
 2     
 3   var arr = [];
 4   
 5   $('a').each(function(){
 6     arr.push($(this).text())
 7     
 8   });
 9   
10   //console.log(arr);
11   
12   
13   var t = setTimeout(function(){
14     
15     rr();
16     
    // 延时处理函数(递归) 17 function rr() 18 { 19 arr = cc(arr); 20 $.each(arr,function(index,element){ 21 $('a').eq(index).html(arr[index]) 22 }); 23 t = setTimeout(function(){ 24 rr(); 25 },1000) 26 // clearTimeout(t); 27 } 28 },1000) 29 30 31 function cc(a) 32 { 33 return a.slice(1).concat(a.slice(0,1)); 34 } 35 36 37 38 });

效果如下:

4. 总结

1. 动画的实现原理是利用视觉暂留效应,与实现方式无关。

2. 数组的浅拷贝方法 Slice(start,[end])  ,所谓浅拷贝,也是不改变数组原值。 

参考文献

1. 仿造学步园效果

2. Array.prototype.slice() - JavaScript | MDN

posted @ 2019-10-28 19:36  缘起花渊  阅读(661)  评论(0编辑  收藏  举报