基于编写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:history.go()和History.back()的区别及应用
Nov 25 Javascript
关闭页面时window.location事件未执行的原因分析及解决方案
Sep 01 Javascript
简介JavaScript中的setTime()方法的使用
Jun 11 Javascript
EasyUI加载完Html内容样式渲染完成后显示
Jul 25 Javascript
Angular 页面跳转时传参问题
Aug 01 Javascript
Javascript发送AJAX请求实例代码
Aug 21 Javascript
解决ajax不能访问本地文件问题(利用js跨域原理)
Jan 24 Javascript
浅谈Vue数据绑定的原理
Jan 08 Javascript
在Angular中使用JWT认证方法示例
Sep 10 Javascript
webpack+vue-cli项目中引入外部非模块格式js的方法
Sep 28 Javascript
Vue 实现html中根据类型显示内容
Oct 28 Javascript
JavaScript实现左右滚动电影画布
Feb 06 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
php+ajax实现图片文件上传功能实例
2014/06/17 PHP
PHP进阶学习之垃圾回收机制详解
2019/06/18 PHP
JavaScript获取页面上某个元素的代码
2011/03/13 Javascript
JQuery将文本转化成JSON对象需要注意的问题
2011/05/09 Javascript
通过location.replace禁止浏览器后退防止重复提交
2014/09/04 Javascript
JS用斜率判断鼠标进入DIV四个方向的方法
2016/11/07 Javascript
JavaScript实现邮箱地址自动匹配功能代码
2016/11/28 Javascript
常用的javascript设计模式
2017/01/11 Javascript
使用Bootstrap + Vue.js实现添加删除数据示例
2017/02/27 Javascript
基于滚动条位置判断的简单实例
2017/12/14 Javascript
微信小程序 扭蛋抽奖机css3动画实现详解
2019/07/19 Javascript
[01:46]新英雄登场
2019/09/10 DOTA
Pandas中DataFrame的分组/分割/合并的实现
2019/07/16 Python
Python Django 封装分页成通用的模块详解
2019/08/21 Python
python SocketServer源码深入解读
2019/09/17 Python
python脚本实现音频m4a格式转成MP3格式的实例代码
2019/10/09 Python
python 比较2张图片的相似度的方法示例
2019/12/18 Python
对Pytorch 中的contiguous理解说明
2021/03/03 Python
Carter’s官方旗舰店:美国受欢迎的婴童服装品牌
2018/01/21 全球购物
Diptyque英国官方网站:源自法国的知名香氛品牌
2019/08/28 全球购物
Napapijri西班牙在线商店:夹克、外套、运动衫等
2020/11/05 全球购物
广州某公司软件工程师面试题
2014/12/22 面试题
医学专业个人求职自荐信格式
2013/09/23 职场文书
房产继承公证书
2014/04/09 职场文书
《永远的白衣战士》教学反思
2014/04/25 职场文书
组工干部对照检查材料
2014/08/25 职场文书
2014客服代表实习自我鉴定
2014/09/18 职场文书
建设办主任四风问题整改思路和措施
2014/09/20 职场文书
学院党的群众路线教育实践活动第一阶段情况汇报
2014/10/25 职场文书
党支部半年考察意见
2015/06/01 职场文书
上甘岭观后感
2015/06/10 职场文书
离婚协议书范本(2016最新版)
2016/03/18 职场文书
自考生自我评价
2019/06/21 职场文书
立秋之描写立秋的作文(五年级)
2019/08/08 职场文书
小型企业的绩效考核制度模板
2019/11/21 职场文书
CSS控制继承中的height能变为可继承吗
2022/06/10 HTML / CSS