巧用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. 仿造学步园效果