一. 效果图
二. Html骨架结构
<div class="box"> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> </div>
三. 原理讲解
1. div.box是最外层盒子, 给它固定的宽高,记得给div.box添加一个 overflow:hidden 样式(超出的内容隐藏) ,因为滚动肯定会超出box的。
2. 我们通过js控制 ul 标签的 margin 来实现滚动。横向滚动控制 margin-left, 纵向则控制 margin-top。
3. 初始时,我们要进行条件判断,判断其是否应该滚动。即: 当 ul 宽度[横向](或高度[纵向])小于外层 div.box 时不进行滚动,反之则进行滚动。
4. ul 的长度是通过计算得来的,即:ul里面单个 li 的长度乘以 li 的个数。ul_width = li_width * li_num。
5. 之所以能实现无缝滚动,是因为每次滚动的长度刚好大于单个 li 的长度时,我们就将 ul 的第一个 li 移动到 ul 的最后,周而复始, 无限循环(关于这一点,你可以先不设置 overflow:hidden 来查看)。
四. 插件实现代码
(function ($) { $.fn.scroll = function (options) { var root = this, //将当前上下文对象存入root timer = [], //计时器 ulTag = $("> ul", root), //ul标签 liTag = $("> li", ulTag), //li标签(集合) liNum = liTag.length, //li标签个数 liOne = liTag.first(), //获取单个li标签 marquee, //滚动器(函数) liUnit, //单个li的宽或者高(横向时为宽,纵向时为高) ulUnit, //ul的宽或者高(横向时为宽,纵向时为高) limit, //root的宽或者高(横向时为宽,纵向时为高) cssName, //样式名称(横向时为margin-left,纵向时为margin-top) effect; //动画效果(横向时为marginLeft,纵向时为marginTop) //默认配置 var settings = { speed: 40, //滚动速度,值越大速度越慢 direction: "x" //滚动方向("x"或者"y" [x横向;y纵向]) }; //不为空,则合并参数 if (options){ $.extend(settings, options); } //横向 if(settings.direction === "x"){ limit = root.width(); cssName = "margin-left"; liUnit = liOne.outerWidth(true); ulUnit = liUnit * liNum; //单个li的宽 * li的个数 = ul的宽度 effect = { marginLeft : "-=1" }; ulTag.css({ ulUnit }); //设置ul的宽 } //纵向 if(settings.direction === "y"){ limit = root.height(); cssName = "margin-top"; liUnit = liOne.outerHeight(true); ulUnit = liUnit * liNum; //单个li的高 * li的个数 = ul的高度 effect = { marginTop : "-=1" }; ulTag.css({ height: ulUnit }); //设置ul的高 } marquee = function(){ ulTag.animate(effect, 0, function(){ //ul滚动的距离,取绝对值 var distance = Math.abs(parseInt($(this).css(cssName),10)); //如果滚动的距离一旦大于单个li的长度 if(distance > liUnit){ $("> li:first", $(this)).appendTo($(this)); //就把第一个li移到最后 $(this).css(cssName, 0); //滚动长度归0 } }); } //遵循链式原则,并进行初始化 return root.each(function (i) { //只有当ul的长度大于root长度时才进行滚动 if(ulUnit > limit){ timer[i] = setInterval(marquee,settings.speed); //鼠标进入停止滚动,离开继续滚动 $(this).hover(function () { clearInterval(timer[i]); }, function () { timer[i] = setInterval(marquee,settings.speed); }); } }); }; })(jQuery);
五. 关于代码的讲解
基本的说明注释写的很清楚了,下面针对个别知识点作下讲解
1. var timer=[] 之前 timer 并不是声明的数组类型,是在我写 demo 的时候,由于页面同时存在两个无缝滚动的应用(为了演示横向和纵向),出现了bug。因为它们两个共用了一个 timer 计时器,当鼠标进入其中一个时,另一个的 timer 也被 clear 了。之后修改代码将其声明为数组对象,再通过 root.each() 就实现了每个插件应用都有自己独立的 timer 计时器,互不干扰。也就是说此插件支持页面中同时存在多个无缝滚动的应用。
2. outerWidth() / outerHeight() 函数。 这个函数比较强大,它获取的不仅仅是元素的宽度 / 高度,
实际上 outerWidth() = width + borderLeft + borderRight + marginLeft + marginRight; 当它设置为 true 后,即:outerWidth(true),它也会将 padding 计算进来。
outerWidth(true) = width + borderLeft + borderRight + marginLeft + marginRight + paddingLeft + paddingRight;
六. 一个完整的示例,效果和上面的效果图一模一样
1. Html
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>jQuery无限滚动插件</title> <link rel="stylesheet" type="text/css" href="css/style.css" /> <!-- 此处引用的为下面的 Css 代码 --> </head> <body> <h3 class="title">jQuery无限滚动插件</h3> <div class="xbox"> <ul> <li><a href="#">x</a></li> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> </ul> </div> <div class="ybox"> <ul> <li><a href="#">y</a></li> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> </ul> </div> <script type="text/javascript" src="script/jquery.min.js"></script> <script type="text/javascript" src="script/jquery.similar.scroll.js"></script> <!-- 此处引用的为上面的插件实现代码 --> <script type="text/javascript"> $(function () { $(".xbox").scroll(); //默认横向滚动 $(".ybox").scroll({ direction: "y" }); //设置为纵向滚动 }); </script> </body> </html>
2. Css
body{ font-family: Arial; } body,ul,li{ margin:0; padding:0; } ul,li,img{ list-style: none; } .title{ width: 100%; text-align: center; } .xbox,.ybox{ overflow: hidden; margin: 20px auto; padding: 5px; border: 2px solid #DDD; } .xbox{ width: 500px; height: 50px; } .xbox ul li{ float: left; margin-right: 5px; } .xbox ul li a, .ybox ul li a{ display: block; width:100px; height: 50px; box-shadow: 0 0 40px rgba(0,0,0,0.2) inset; text-decoration: none; color: gray; font-size: 20px; text-align: center; line-height: 50px; } .ybox{ width: 100px; height: 250px; } .ybox ul li{ margin-bottom: 5px; }