基于编写jQuery的无缝滚动插件


Posted in Javascript onAugust 02, 2014

首先来看下html骨架,如下:

<div class="box">
    <ul>
      <li>111</li>
      <li>222</li>
      <li>333</li>
    </ul>
</div>

结构简单明了,没什么说的。

讲下实现原理:

div box是最外层盒子,给它指定的宽高,记得给box添加一个 overflow:hidden (超出的内容隐藏)样式,因为滚动肯定是会超出box的。

我们通过js控制 ul 标签的margin 来实现滚动。横向滚动则是控制 margin-left ; 纵向滚动则是控制 margin-top;

初始状态时,我们还要进行条件判断,判断是否进行滚动。即: 当 ul 长度小于 外层 box 长度时不进行滚动,反之则进行滚动。

ul 的长度是通过计算得来的,即: ul 里面单个 li 的长度乘以 li 的个数。 ul_width = li_width * li_num;

之所以能实现无缝滚动,是因为每次滚动的长度刚好大于单个 li 的长度时,我们就将ul的第一个 li 移动到ul的最后,周而复始,无限循环(关于这

一点,你可以先不设置 overflow:hidden 来查看)。

讲个原理太TM考验我的表达能力了,希望我讲清楚了。

看插件的实现代码吧:

(function ($) {
  $.fn.Scroll = function (options) {
    //将当前上下文对象存入root
    var root = this;

    //默认配置
    var settings = {
      speed: 40,   //滚动速度,值越大速度越慢
      direction: "x" //滚动方向("x"或者"y" [x横向;y纵向])
    };

    //不为空,则合并参数
    if (options)
      $.extend(settings, options);


    var timer = [];   //计时器
    var marquee;    //滚动器(函数)
    var isRoll;     //判断是否滚动(函数)

    var _ul = $("> ul", root);     //ul标签
    var _li = $("> ul > li", root);   //li标签(集合)

    var li_num = _li.length;  //li标签个数
    var li_first = _li.first();  //获取单个li标签


    //判断为纵向还是横向,并进行相应操作
    if (settings.direction == "x") {


 



 var li_w = li_first.outerWidth(true); //单个li标签的宽度



 var ul_w = li_w * li_num; 


 //ul标签的宽度

      _ul.css({ width: ul_w }); //设置ul宽度

      marquee = function () {
        _ul.animate({ marginLeft: "-=1" }, 0, function () {
          var _mleft = Math.abs(parseInt($(this).css("margin-left")));
          if (_mleft > li_w) { //滚动长度一旦大于单个li的长度
            $("> li:first", $(this)).appendTo($(this)); //就把第一个li移到最后
            $(this).css("margin-left", 0); //滚动长度归0
          }
        });
      };
      //ul长度小于box长度时则不滚动,反之滚动
      isRoll = function (t) {
        if (ul_w <= root.width())
          clearInterval(t);
        else
          marquee();
      }
    }
    else {



 var li_h = li_first.outerHeight(true); //单个li标签的高度 



 var ul_h = li_h * li_num; //ul标签的高度

      _ul.css({ height: ul_h }); //设置ul高度

      marquee = function () {
        _ul.animate({ marginTop: "-=1" }, 0, function () {
          var _mtop = Math.abs(parseInt($(this).css("margin-top"))); //取绝对值
          if (_mtop > li_h) { 
            $("> li:first", $(this)).appendTo($(this));
            $(this).css("margin-top", 0);
          }
        });
      };
      //ul长度小于box长度时则不滚动,反之滚动
      isRoll = function (t) {
        if (ul_h <= root.height())
          clearInterval(t);
        else
          marquee();
      }
    }

    //遵循链式原则,并进行初始化
    return root.each(function (i) {
      //超出内容隐藏,防止用户没写overflow样式
      $(this).css({ overflow: "hidden" });

      timer[i] = setInterval(function () {
        isRoll(timer[i]);
      }, settings.speed);

      //鼠标进入停止滚动,离开继续滚动
      $(this).hover(function () {
        clearInterval(timer[i]);
      }, function () {
        timer[i] = setInterval(function () {
          isRoll(timer[i]);
        }, settings.speed);
      });

    });

  };
})(jQuery);

基本的代码说明注释写的很清楚了。下面对个别知识点作下讲解:

1.) var timer=[]; 之前timer并不是声明为数组类型的,是在我写demo的时候,由于页面同时存在两个无缝滚动的应用(为了演示横向和纵向), 出现了bug。

因为他们两个共用了一个timer计时器,当鼠标进入其中一个时,另一个的timer也被clear了。之后修改代码将其声明为数组对象,再通过root.each()就实
现了每个插件应用都有自己独立的timer计时器,互不干扰。也就是说此插件支持页面同时存在多个无缝滚动应用。

2.) outerWidth() /outerHeight()函数。 这个函数比较强大,它获取的不仅仅是元素的宽度/高度,

实际上 outerWidth()=width+borderLeft+borderRight+marginLeft+marinRight;
当它设置为true后,即:outerWidth(true),它也会将padding计算进来:
outerWidth()=width+borderLeft+borderRight+marginLeft+marinRight+paddingLeft+paddingRight;

怎么样,是不是很强大啊!

下面给出DEMO代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style type="text/css">
  *{ margin:0; padding:0;}
  ul,ul li{ list-style:none;}  
  .wrap{ width:1000px; margin:50px auto;}  
  .box1,.box2,.box3{ overflow:hidden; float:left;border:1px solid gray;}  
  .box1{ width:200px; height:450px;}
  .box1 ul li{ width:200px; height:100px;} 
  .box2,.box3{ width:450px;height:150px; margin:40px;}
  .box2 ul li,.box3 ul li{ width:100px; height:150px; float:left;}
  
</style>
</head>

<body>
<div class="wrap">

  <div class="box1">
    <ul>
      <li>111纵向</li>
      <li>222纵向</li>
      <li>333纵向</li>
      <li>444纵向</li>
      <li>555纵向</li>
      <li>666纵向</li>
    </ul>
  </div>

  <div class="box2">
    <ul>
      <li>111横向</li>
      <li>222横向</li>
      <li>333横向</li>
      <li>444横向</li>
      <li>555横向</li>
      <li>666横向</li>
    </ul>
  </div> 
  
  <div class="box3">  
    <ul>
      <li>ul长度小于box长度,不滚动</li>
      <li>222横向</li>
      <li>333横向</li>      
    </ul>
  </div>  
</div>

<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.similar.scroll.js"></script>
<script type="text/javascript">
  $(function () {
    //奇数背景设置为灰色
    $('.box1 li:even,.box2 li:even,.box3 li:even').css({ backgroundColor: "gray" });

    $(".box1").Scroll({ direction: "y" }); //设置为纵向滚动
    $(".box2").Scroll(); //默认横向滚动
    $(".box3").Scroll();
  });
</script>
</body>
</html>

效果图片:

基于编写jQuery的无缝滚动插件

演示因为样式问题,大家可以自行美化。

Javascript 相关文章推荐
如何确保JavaScript的执行顺序 之jQuery.html并非万能钥匙
Mar 03 Javascript
Extjs 继承Ext.data.Store不起作用原因分析及解决
Apr 15 Javascript
js confirm()方法的使用方法实例
Jul 13 Javascript
JS可以控制样式的名称写法一览
Jan 16 Javascript
jquery实现在网页指定区域显示自定义右键菜单效果
Aug 25 Javascript
JS中动态创建元素的三种方法总结(推荐)
Oct 20 Javascript
详解JS构造函数中this和return
Sep 16 Javascript
jQuery实现IE输入框完成placeholder标签功能的方法
Sep 20 jQuery
vue项目中使用Hbuilder打包app 设置沉浸式状态栏的方法
Oct 22 Javascript
微信小程序制作表格的方法
Feb 14 Javascript
Vue.js路由实现选项卡简单实例
Jul 24 Javascript
js通过canvas生成图片缩略图
Oct 02 Javascript
js使用removeChild方法动态删除div元素
Aug 01 #Javascript
js使用html()或text()方法获取设置p标签的显示的值
Aug 01 #Javascript
js中的getAttribute方法使用示例
Aug 01 #Javascript
jquery append()方法与html()方法的区别及使用介绍
Aug 01 #Javascript
JS中产生20位随机数以0-9为例也可以是a-z A-Z
Aug 01 #Javascript
js控制再次点击按钮之间的间隔时间可防止重复提交
Aug 01 #Javascript
批量修改标签css样式以input标签为例
Jul 31 #Javascript
You might like
15个小时----从修改程序到自己些程序
2006/10/09 PHP
PHP包含文件函数include、include_once、require、require_once区别总结
2014/04/05 PHP
php使用imagick模块实现图片缩放、裁剪、压缩示例
2014/04/17 PHP
PHP捕获Fatal error错误的方法
2014/06/11 PHP
php实现随机显示图片方法汇总
2015/05/21 PHP
php中二维数组排序问题方法详解
2015/08/28 PHP
实例介绍PHP删除数组中的重复元素
2019/03/03 PHP
Laravel (Lumen) 解决JWT-Auth刷新token的问题
2019/10/24 PHP
js iframe跨域访问(同主域/非同主域)分别深入介绍
2013/01/24 Javascript
jQuery ui插件的使用方法代码实例
2013/05/08 Javascript
js实现图片旋转的三种方法
2014/04/10 Javascript
javascript中错误使用var造成undefined
2016/03/31 Javascript
jqGrid 学习笔记整理——进阶篇(一 )
2016/04/17 Javascript
使用React实现轮播效果组件示例代码
2016/09/05 Javascript
教你一步步用jQyery实现轮播器
2016/12/18 Javascript
微信小程序 如何获取网络状态
2019/07/26 Javascript
Layui实现带查询条件的分页
2019/07/27 Javascript
jquery.pager.js实现分页效果
2019/07/29 jQuery
JavaScript对象原型链原理解析
2020/01/22 Javascript
解决antd datepicker 获取时间默认少8个小时的问题
2020/10/29 Javascript
[39:02]DOTA2亚洲邀请赛 3.31 小组赛 B组 Mineski vs VGJ.T
2018/04/01 DOTA
pygame学习笔记(2):画点的三种方法和动画实例
2015/04/15 Python
windows 10下安装搭建django1.10.3和Apache2.4的方法
2017/04/05 Python
Python实现查看系统启动项功能示例
2018/05/10 Python
django admin后台添加导出excel功能示例代码
2019/05/15 Python
django admin 自定义替换change页面模板的方法
2019/08/23 Python
scrapy头部修改的方法详解
2020/12/06 Python
Lululemon英国官网:加拿大瑜伽服装品牌
2019/01/14 全球购物
阿里巴巴英国:Alibaba英国
2019/12/11 全球购物
介绍一下XMLHttpRequest对象
2012/02/12 面试题
在浏览器端如何得到服务器端响应的XML数据
2012/11/24 面试题
委托协议书范本
2014/04/22 职场文书
2014迎国庆标语大全
2014/09/19 职场文书
企业党支部工作总结2015
2015/05/21 职场文书
2015年关爱留守儿童工作总结
2015/05/22 职场文书
观看安全警示教育片心得体会
2016/01/15 职场文书