原生JS实现图片无缝滚动方法(附带封装的运动框架)


Posted in Javascript onOctober 01, 2017

话说轮播图效果是前端er学习JS的必经之路啊,很多同学写的第一个JS效果应该就是它了,在各大网站我们都会经常见到,但是无缝滚动运动效果的轮播图,对于小白们来说还是有一定难度的。

我们来看看思路吧~

首先我们要实现的效果有以下几点:

小圆点:点击小圆点显示与之对应的图片

向左和向右按钮:点击向左按钮图片向后运动,点击向右按钮图片向前运动

定时器:每隔 2s 自动播放

主要难点在于:

当图片运动到最后一张,点击向右的按钮时,应该显示第一张;

当前显示的是第一张,点击向左的按钮时,应该显示最后一张;

思路:

1、先将第一张图片复制 添加到 ul 最后面,将最后一张图片复制 添加到 ul 最前面(此时 ul 的第一张图片是pic3,最后一张图片是pic0);

2、当图片(ul)运动到pic3,继续向前运动,运动到最后一张pic0时,瞬间把 ul 拉回到第二张图片pic0的位置,然后在继续向前运动;

3、当图片(ul)向后运动到第一张图片pic3时,瞬间把 ul 拉回到倒数第二张图片pic3的位置。

4、还有非常关键的一点:定义iNow变量,用于对应当前显示的图片与ol中的小圆点,并且可以用来关联 ul 的位置。

html代码:

<div id="tab">
  <ul>
    <li><img src="image/pic0.jpg" alt="" /></li>
    <li><img src="image/pic1.jpg" alt="" /></li>
    <li><img src="image/pic2.jpg" alt="" /></li>
    <li><img src="image/pic3.jpg" alt="" /></li>
  </ul>
  <ol>
    <li class="on"></li>
    <li></li>
    <li></li>
    <li></li>
  </ol>
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" class="prev" id="prev"><</a>
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" class="next" id="next">></a>                 
</div>

css代码:

*{margin: 0; padding: 0;}
li{ list-style: none;}
#tab{
  width: 670px;
  height: 240px;
  border: 1px solid #ccc;
  margin: 50px auto;
  position: relative;
}
#tab ul{
  width: 2680px;
  height: 240px;
  position: absolute;
  left: 0;
  top: 0;
  overflow: hidden;
}
#tab ul li{
  float: left;
  width: 670px;
}
#tab ul li img{
  width: 670px;
}
#tab ol{
  width: 80px;
  position: absolute;
  bottom: 10px;
  left: 50%;
  margin-left: -40px;
  overflow: hidden;
}
#tab ol li{
  float: left;
  width: 10px;
  height: 10px;
  background: #ccc;
  border-radius: 50%;
  margin: 5px;
  cursor: pointer;
}
#tab ol .on{
  background: #f00;
}
#tab .prev,#tab .next{
  display: none;
  width: 40px;
  height: 60px;
  background: rgba(0,0,0,.3);
  filter:alpha(opacity:30);
  text-decoration: none;
  text-align: center;
  line-height: 60px;
  font-size: 30px;
  color: #fff;
  position: absolute;
  top: 50%;
  margin-top: -30px;
}
#tab .prev{
  left: 0;
}
#tab .next{
  right: 0;
}

js 代码:

其中animate()是封装好的运动框架,最后面附有说明

window.onload = function(){
  var oTab = document.getElementById('tab');
  var oUl = oTab.getElementsByTagName('ul')[0];
  var aLi1 = oUl.children;
  var oOl = oTab.getElementsByTagName('ol')[0];
  var aLi2 = oOl.children;
  var prev = document.getElementById('prev');
  var next = document.getElementById('next');
  //设置ul的初始位置
  var iNow = 1;  
  oUl.style.left=-aLi1[0].offsetWidth*iNow+'px';
  //定时器
  var timer = null;

  //克隆第一张图片 添加在ul的最后面
  var oLi1 = aLi1[0].cloneNode(true);
  //克隆最后一张图片 添加在ul的最前面
  var oLi2 = aLi1[aLi1.length-1].cloneNode(true);
  oUl.appendChild(oLi1);
  oUl.insertBefore(oLi2,aLi1[0]);
  oUl.style.width = aLi1[0].offsetWidth*aLi1.length+"px";
  //鼠标移入tab: 关闭定时器,左右按钮显示
  oTab.onmouseover = function(){
    clearInterval(timer);
    prev.style.display = 'block';
    next.style.display = 'block';
  }
  //鼠标移出tab: 开启定时器,左右按钮隐藏
  oTab.onmouseout = function(){
    timer = setInterval(function(){
      toNext();
    },2000);
    prev.style.display = 'none';
    next.style.display = 'none';
  }
  //点击小圆点
  for(var i=0;i<aLi2.length;i++){
    (function(index){
      aLi2[index].onclick = function(){
        iNow = index+1;
        for(var i=0;i<aLi2.length;i++){
          aLi2[i].className = '';
        }
        aLi2[index].className = 'on';
        animate(oUl,{left: -iNow*aLi1[0].offsetWidth});
      }
    })(i);
  }
  //上一个
  prev.onclick=function(){
    iNow--;
    animate(oUl,{left: -iNow*aLi1[0].offsetWidth},{complete:function(){
      if(iNow == 0){
        iNow = aLi1.length-2;
        oUl.style.left=-aLi1[0].offsetWidth*iNow+'px';
      }
      for(var i=0;i<aLi2.length;i++){
        aLi2[i].className = '';
      }
      aLi2[iNow-1].className = 'on';
    }});
  }
  //下一个
  next.onclick=function(){
    toNext();
  }
  function toNext(){
    iNow++;
    animate(oUl,{left: -iNow*aLi1[0].offsetWidth},{complete:function(){
      if(iNow == aLi1.length-1){
        iNow = 1;
        oUl.style.left=-aLi1[0].offsetWidth*iNow+'px';
      }
      for(var i=0;i<aLi2.length;i++){
        aLi2[i].className = '';
      }
      aLi2[iNow-1].className = 'on';
    }});
  }
  //设置定时器
  timer = setInterval(function(){
    toNext();
  },2000);
}

封装的animate()运动框架

/*
 * 参数说明:
 * obj: 运动对象
 * json(json形式): 需要修改的属性
 * options(json形式): 
 *       duration: 运动时间
 *       easing: 运动方式(匀速、加速、减速)
 *       complete: 运动完成后执行的函数
*/
function animate(obj,json,options){
  var options=options || {};        
  var duration=options.duration || 500;  //运动时间,默认值为500ms;
  var easing=options.easing || 'linear';  //运动方式,默认为linear匀速
  var start={};
  var dis={};

  for(var name in json){
    start[name]=parseFloat(getStyle(obj,name));  //起始位置
    dis[name]=json[name]-start[name];      //总距离
  }

  var count=Math.floor(duration/30);         //总次数
  var n=0;  //次数

  clearInterval(obj.timer);
  obj.timer=setInterval(function(){
     if(n>count){
      clearInterval(obj.timer);
      options.complete && options.complete();
    }else{
      for(var name in json){
        switch(easing){
          //匀速
          case 'linear':
            var a=n/count;
            var cur=start[name]+dis[name]*a;  //当前位置
            break;
          //加速
          case 'ease-in':
            var a=n/count;
            var cur=start[name]+dis[name]*a*a*a;
            break;
          //减速
          case 'ease-out':
            var a=1-n/count;
            var cur=start[name]+dis[name]*(1-a*a*a);
            break;
        }
         if(name=='opacity'){
          obj.style.opacity=cur;
          obj.style.filter = 'alpha(opacity='+cur*100+')';  //兼容IE8及以下
        }else{
          obj.style[name]=cur+'px';
        }
      }
    }
    n++;
  },30);
}
//获取非行间样式
function getStyle(obj,sName){
  return (obj.currentStyle || getComputedStyle(obj,false))[sName];
}

以上这篇原生JS实现图片无缝滚动方法(附带封装的运动框架)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript自然分类法算法实现代码
Oct 11 Javascript
JS获取DropDownList的value值与text值的示例代码
Jan 07 Javascript
js中函数调用的两种常用方法使用介绍
Jul 17 Javascript
动态加载css方法实现和深入解析
Jan 18 Javascript
vue-router+vuex addRoutes实现路由动态加载及菜单动态加载
Sep 28 Javascript
JS Testing Properties 判断属性是否在对象里的方法
Oct 01 Javascript
jquery写出PC端轮播图实例
Jan 26 jQuery
在小程序中集成redux/immutable/thunk第三方库的方法
Aug 12 Javascript
详解js动态获取浏览器或页面等容器的宽高
Mar 13 Javascript
vue组件创建的三种方式小结
Feb 03 Javascript
Vue项目配置跨域访问和代理proxy设置方式
Sep 08 Javascript
36个正则表达式(开发效率提高80%)
Nov 17 Javascript
原生js封装运动框架的示例讲解
Oct 01 #Javascript
JS Testing Properties 判断属性是否在对象里的方法
Oct 01 #Javascript
基于原生js运动方式关键点的总结(推荐)
Oct 01 #Javascript
vuejs使用递归组件实现树形目录的方法
Sep 30 #Javascript
Easy UI动态树点击文字实现展开关闭功能
Sep 30 #Javascript
js实现轮播图的两种方式(构造函数、面向对象)
Sep 30 #Javascript
React实践之Tree组件的使用方法
Sep 30 #Javascript
You might like
PHP+Ajax实时自动检测是否联网的方法
2015/07/01 PHP
php使用ZipArchive函数实现文件的压缩与解压缩
2015/10/27 PHP
ecshop适应在PHP7的修改方法解决报错的实现
2016/11/01 PHP
Yii2单元测试用法示例
2016/11/12 PHP
PHP示例演示发送邮件给某个邮箱
2019/04/03 PHP
javascript:void(0)是什么意思示例介绍
2013/11/17 Javascript
Windows 系统下安装和部署Egret的开发环境
2014/07/31 Javascript
JQuery自动触发事件的方法
2015/06/13 Javascript
JS获取文件大小方法小结
2015/12/08 Javascript
js实现密码强度检测【附示例】
2016/03/30 Javascript
vuejs动态组件给子组件传递数据的方法详解
2016/09/09 Javascript
利用JS判断鼠标移入元素的方向
2016/12/11 Javascript
Radio 单选JS动态添加的选项onchange事件无效的解决方法
2016/12/12 Javascript
jquery实现折叠菜单效果【推荐】
2017/03/08 Javascript
JavaScript实现全选取消效果
2017/12/14 Javascript
简化vuex的状态管理方案的方法
2018/06/02 Javascript
微信小程序自定义音乐进度条的实例代码
2018/08/28 Javascript
node中的cookie的具体使用
2018/09/13 Javascript
iphone刘海屏页面适配方法
2019/05/07 Javascript
egg.js的基本使用和调用数据库的方法示例
2019/05/18 Javascript
JS 遍历 json 和 JQuery 遍历json操作完整示例
2019/11/11 jQuery
浅谈vue单页面中有多个echarts图表时的公用代码写法
2020/07/19 Javascript
解决Vue的文本编辑器 vue-quill-editor 小图标样式排布错乱问题
2020/08/03 Javascript
JavaScript代码简化技巧实例解析
2020/09/09 Javascript
[02:17]TI4西雅图DOTA2前线报道 啸天mik夫妻档解说
2014/07/08 DOTA
[01:19]DOTA2城市挑战赛报名开始 开启你的城市传奇
2018/03/23 DOTA
pyinstaller 3.6版本通过pip安装失败的解决办法(推荐)
2020/01/18 Python
Python的in,is和id函数代码实例
2020/04/18 Python
JACK & JONES荷兰官网:男士服装和鞋子
2021/03/07 全球购物
音乐专业应届生教师求职信
2013/11/04 职场文书
销售总监岗位职责
2014/01/04 职场文书
事业单位人员的自我评价范文
2014/09/21 职场文书
党的群众路线教育实践活动个人整改措施
2014/10/27 职场文书
小学生反邪教心得体会
2016/01/15 职场文书
Kubernetes中Deployment的升级与回滚
2022/04/01 Servers
Python用any()函数检查字符串中的字母以及如何使用all()函数
2022/04/14 Python