封装运动框架实战左右与上下滑动的焦点轮播图(实例)


Posted in Javascript onOctober 17, 2017

在这篇文章打造通用的匀速运动框架(实例讲解)中,封装了一个匀速运动框架,我们在这个框架的基础之上,加上缓冲运动效果,然后用运动框架来做幻灯片(上下,左右)。

封装运动框架实战左右与上下滑动的焦点轮播图(实例)

缓冲运动通常有两种常见的表现:比如让一个div从0运动到500,一种是事件触发的时候,速度很快, 一种是事件触发的时候慢,然后慢慢加快.我们来实现先块后慢的,常见的就是开车,比如刚从高速路上下来的车,就是120km/小时,然后进入匝道,变成40km/时. 或者40km/小时进入小区,最后停车,变成0km/小时. 从120km/小时->40km/小时, 或者40km->0km/小时,都是速度先块后慢,这种运动怎么用程序来表示呢?

封装运动框架实战左右与上下滑动的焦点轮播图(实例)

可以用目标距离( 500 ) - 当前距离( 200 ) / 一个系数( 比如12 ),就能达到速度由块而慢的变化,当前距离在起点,分子(500 - 0 )最大,所以速度最大,如果当前距离快要接近500,分子最小,除完之后的速度也是最小。

<style>
 div{
  width: 200px;
  height: 200px;
  background:red;
  position: absolute;
  left: 0px;
 }
 </style>
 <script>
 window.onload = function(){
  var oBtn = document.querySelector( "input" ),
  oBox = document.querySelector( '#box' ),
  speed = 0, timer = null;
  oBtn.onclick = function(){
  timer = setInterval( function(){
   speed = ( 500 - oBox.offsetLeft ) / 8;
   oBox.style.left = oBox.offsetLeft + speed + 'px';
  }, 30 );
  }
 }
 </script>
</head>
<body>
 <input type="button" value="动起来">
 <div id="box"></div>
</body>
但是,div并不会乖乖地停止在500px这个目标位置,最终却是停在497.375px,只要查看当前的速度,当前的值就知道原因了
封装运动框架实战左右与上下滑动的焦点轮播图(实例)
封装运动框架实战左右与上下滑动的焦点轮播图(实例)

你会发现,速度永远都在0.375这里停着,获取到的当前的距离停在497px? 这里有个问题,我们的div不是停在497.375px吗,怎么获取到的没有了后面的小数0.375呢?计算机在处理浮点数会有精度损失。我们可以单独做一个小测试:

<div id="box"></div>
 <script>
 var oBox = document.querySelector( '#box' );
 alert( oBox.offsetLeft );
 </script>

你会发现这段代码获取到左偏移是30px而不是行间样式中写的30.2px。因为在获取当前位置的时候,会舍去小数,所以速度永远停在0.375px, 位置也是永远停在497,所以,为了到达目标,我们就得把速度变成1,对速度向上取整( Math.ceil ),我们就能把速度变成1,div也能到达500

oBtn.onclick = function(){
 timer = setInterval( function(){
 speed = ( 500 - oBox.offsetLeft ) / 8;
 if( speed > 0 ) {
  speed = Math.ceil( speed );
 }
 console.log( speed, oBox.offsetLeft );
 oBox.style.left = oBox.offsetLeft + speed + 'px';
 }, 30 );
}

第二个问题,如果div的位置是在900,也就是说从900运动到500,有没有这样的需求呢? 肯定有啊,轮播图,从右到左就是这样的啊。

<style>
 #box{
  width: 200px;
  height: 200px;
  background:red;
  position: absolute;
  left: 900px;
 }
 </style>
 <script>// <![CDATA[
 window.onload = function(){
  var oBtn = document.querySelector( "input" ),
  oBox = document.querySelector( '#box' ),
  speed = 0, timer = null;
  oBtn.onclick = function(){
  timer = setInterval( function(){
   speed = ( 500 - oBox.offsetLeft ) / 8;
   if( speed > 0 ) {
   speed = Math.ceil( speed );
   }
   oBox.style.left = oBox.offsetLeft + speed + 'px';
  }, 30 );
  }
 }
 // ]]></script>
</head>
<body>
 <input type="button" value="动起来">
 <div id="box"></div>
</body>
最后目标停在503.5px,速度这个时候是负值,最后速度停在-0.5,对于反方向的速度,我们就要把它变成-1,才能到达目标,所以用向下取整(Math.floor)
封装运动框架实战左右与上下滑动的焦点轮播图(实例)
oBtn.onclick = function(){
 timer = setInterval( function(){
 speed = ( 500 - oBox.offsetLeft ) / 8;
 if( speed > 0 ) {
  speed = Math.ceil( speed );
 }else {
  speed = Math.floor( speed );
 }
 console.log( speed, oBox.offsetLeft );
 oBox.style.left = oBox.offsetLeft + speed + 'px';
 }, 30 );
}

然后我们把这个缓冲运动整合到匀速运动框架,就变成:

function css(obj, attr, value) {
 if (arguments.length == 3) {
 obj.style[attr] = value;
 } else {
 if (obj.currentStyle) {
  return obj.currentStyle[attr];
 } else {
  return getComputedStyle(obj, false)[attr];
 }
 }
}

function animate(obj, attr, fn) {
 clearInterval(obj.timer);
 var cur = 0;
 var target = 0;
 var speed = 0;
 obj.timer = setInterval(function () {
 var bFlag = true;
 for (var key in attr) {
  if (key == 'opacity ') {
  cur = css(obj, 'opacity') * 100;
  } else {
  cur = parseInt(css(obj, key));
  }
  target = attr[key];
  speed = ( target - cur ) / 8;
  speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
  if (cur != target) {
  bFlag = false;
  if (key == 'opacity') {
   obj.style.opacity = ( cur + speed ) / 100;
   obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")";
  } else {
   obj.style[key] = cur + speed + "px";
  }
  }
 }
 if (bFlag) {
  clearInterval(obj.timer);
  fn && fn.call(obj);
 }
 }, 30 );
}

有了这匀速运动框架,我们就来做幻灯片:

上下幻灯片的html样式文件:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>slide - by ghostwu</title>
 <link rel="stylesheet" href="css/slide3.css" rel="external nofollow" >
 <script src="js/animate.js"></script>
 <script src="js/slide.js"></script>
</head>
<body>
<div id="slide">
 <div id="slide-img">
 <div id="img-container">
  <img src="./img/1.jpg" alt="">
  <img src="./img/2.jpg" alt="">
  <img src="./img/3.jpg" alt="">
  <img src="./img/4.jpg" alt="">
  <img src="./img/5.jpg" alt="">
 </div>
 </div>
 <div id="slide-nums">
 <ul>
  <li class="active"></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
 </ul>
 </div>
</div>
</body>
</html>

slide3.css文件:

* {
 margin: 0;
 padding: 0;
}
li {
 list-style-type: none;
}
#slide {
 width: 800px;
 height: 450px;
 position: relative;
 margin:20px auto;
}
#slide-img {
 position: relative;
 width: 800px;
 height: 450px;
 overflow: hidden;
}
#img-container {
 position: absolute;
 left: 0px;
 top: 0px;
 height: 2250px;
 /*font-size:0px;*/
}
#img-container img {
 display: block;
 float: left;
}
#slide-nums {
 position: absolute;
 right:10px;
 bottom:10px;
}
#slide-nums li {
 float: left;
 margin:0px 10px;
 background: white;
 width: 20px;
 height: 20px;
 text-align: center;
 line-height: 20px;
 border-radius:10px;
 text-indent:-999px;
 opacity:0.6;
 filter:alpha(opacity:60);
 cursor:pointer;
}
#slide-nums li.active {
 background: red;
}

animate.js文件:

function css(obj, attr, value) {
 if (arguments.length == 3) {
 obj.style[attr] = value;
 } else {
 if (obj.currentStyle) {
  return obj.currentStyle[attr];
 } else {
  return getComputedStyle(obj, false)[attr];
 }
 }
}

function animate(obj, attr, fn) {
 clearInterval(obj.timer);
 var cur = 0;
 var target = 0;
 var speed = 0;
 obj.timer = setInterval(function () {
 var bFlag = true;
 for (var key in attr) {
  if (key == 'opacity ') {
  cur = css(obj, 'opacity') * 100;
  } else {
  cur = parseInt(css(obj, key));
  }
  target = attr[key];
  speed = ( target - cur ) / 8;
  speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
  if (cur != target) {
  bFlag = false;
  if (key == 'opacity') {
   obj.style.opacity = ( cur + speed ) / 100;
   obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")";
  } else {
   obj.style[key] = cur + speed + "px";
  }
  }
 }
 if (bFlag) {
  clearInterval(obj.timer);
  fn && fn.call(obj);
 }
 }, 30 );
}

slide.js文件:

window.onload = function () {
 function Slide() {
 this.oImgContainer = document.getElementById("img-container");
 this.aLi = document.getElementsByTagName("li");
 this.index = 0;
 }

 Slide.prototype.bind = function () {
 var that = this;
 for (var i = 0; i < this.aLi.length; i++) {
  this.aLi[i].index = i;
  this.aLi[i].onmouseover = function () {
  that.moveTop( this.index );
  }
 }
 }

 Slide.prototype.moveTop = function (i) {
 this.index = i;
 for( var j = 0; j < this.aLi.length; j++ ){
  this.aLi[j].className = '';
 }
 this.aLi[this.index].className = 'active';
 animate( this.oImgContainer, {
  "top" : -this.index * 450,
  "left" : 0
 });
 }
 
 var oSlide = new Slide();
 oSlide.bind();

}

左右幻灯片只需要改下样式即可

样式文件:

* {
 margin: 0;
 padding: 0;
}
li {
 list-style-type: none;
}
#slide {
 width: 800px;
 height: 450px;
 position: relative;
 margin:20px auto;
}
#slide-img {
 position: relative;
 width: 800px;
 height: 450px;
 overflow: hidden;
}
#img-container {
 position: absolute;
 left: 0px;
 top: 0px;
 width: 4000px;
}
#img-container img {
 display: block;
 float: left;
}
#slide-nums {
 position: absolute;
 right:10px;
 bottom:10px;
}
#slide-nums li {
 float: left;
 margin:0px 10px;
 background: white;
 width: 20px;
 height: 20px;
 text-align: center;
 line-height: 20px;
 border-radius:10px;
 text-indent:-999px;
 opacity:0.6;
 filter:alpha(opacity:60);
 cursor:pointer;
}
#slide-nums li.active {
 background: red;
}

js调用文件:

window.onload = function () {
 function Slide() {
 this.oImgContainer = document.getElementById("img-container");
 this.aLi = document.getElementsByTagName("li");
 this.index = 0;
 }

 Slide.prototype.bind = function () {
 var that = this;
 for (var i = 0; i < this.aLi.length; i++) {
  this.aLi[i].index = i;
  this.aLi[i].onmouseover = function () {
  that.moveLeft( this.index );
  }
 }
 }

 Slide.prototype.moveLeft = function (i) {
 this.index = i;
 for( var j = 0; j < this.aLi.length; j++ ){
  this.aLi[j].className = '';
 }
 this.aLi[this.index].className = 'active';
 animate( this.oImgContainer, {
  "left" : -this.index * 800
 });
 }
 
 var oSlide = new Slide();
 oSlide.bind();

}

以上这篇封装运动框架实战左右与上下滑动的焦点轮播图(实例)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript与asp.net(c#)互相调用方法
Dec 13 Javascript
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(上:事件篇)
Mar 24 Javascript
使用Node.js实现一个简单的FastCGI服务器实例
Jun 09 Javascript
AngularJs 动态加载模块和依赖
Sep 15 Javascript
Javascript使用function创建类的两种方法(推荐)
Nov 19 Javascript
jQuery实现广告条滚动效果
Aug 22 jQuery
jquery实现用户登陆界面(示例讲解)
Sep 06 jQuery
Angular2管道Pipe及自定义管道格式数据用法实例分析
Nov 29 Javascript
详解vue.js移动端配置flexible.js及注意事项
Apr 10 Javascript
微信小程序-form表单提交代码实例
Apr 29 Javascript
layui 弹出删除确认界面的实例
Sep 06 Javascript
Vue常用的全选/反选的示例代码
Feb 19 Javascript
Vue中封装input组件的实例详解
Oct 17 #Javascript
js获取文件里面的所有文件名(实例)
Oct 17 #Javascript
Vue中之nextTick函数源码分析详解
Oct 17 #Javascript
vue mint-ui 实现省市区街道4级联动示例(仿淘宝京东收货地址4级联动)
Oct 16 #Javascript
jquery一键控制checkbox全选、反选或全不选
Oct 16 #jQuery
Vue2.0父子组件传递函数的教程详解
Oct 16 #Javascript
使用clipboard.js实现复制功能的示例代码
Oct 16 #Javascript
You might like
PHP下MAIL的另一解决方案
2006/10/09 PHP
PHP迭代与递归实现无限级分类
2017/08/28 PHP
关于Curl在Swoole协程中的解决方案详析
2019/09/12 PHP
Laravel 登录后清空COOKIE的操作方法
2019/10/14 PHP
Js之软键盘实现(js源码)
2007/01/30 Javascript
JavaScript 模仿vbs中的 DateAdd() 函数的代码
2007/08/13 Javascript
function foo的原型与prototype属性解惑
2010/11/19 Javascript
js判断字符是否是汉字的两种方法小结
2014/01/03 Javascript
基于JQuery实现滚动到页面底端时自动加载更多信息
2014/01/31 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
2014/06/23 Javascript
jquery实现滑动特效代码
2015/08/10 Javascript
基于jquery实现表格无刷新分页
2016/01/07 Javascript
JavaScript 中 avalon绑定属性总结
2016/10/19 Javascript
关于webpack2和模块打包的新手指南(小结)
2017/08/07 Javascript
解决vue-cli webpack打包后加载资源的路径问题
2018/09/25 Javascript
JS散列表碰撞处理、开链法、HashTable散列示例
2019/02/08 Javascript
用 js 写一个 js 解释器过程详解
2019/08/02 Javascript
JS实现灯泡开关特效
2020/03/30 Javascript
vue-cli3 取消eslint校验代码的解决办法
2020/01/16 Javascript
Python中splitlines()方法的使用简介
2015/05/20 Python
tensorflow输出权重值和偏差的方法
2018/02/10 Python
python通过opencv实现图片裁剪原理解析
2020/01/19 Python
Python 序列化和反序列化库 MarshMallow 的用法实例代码
2020/02/25 Python
PyCharm GUI界面开发和exe文件生成的实现
2020/03/04 Python
pycharm实现猜数游戏
2020/12/07 Python
HTML5 Canvas如何实现纹理填充与描边(Fill And Stroke)
2013/07/15 HTML / CSS
Staples加拿大官方网站:办公用品一站式采购
2016/09/25 全球购物
Nasty Gal英国:美国女性服饰销售网站
2021/03/02 全球购物
阿联酋最好的手机、电子产品和家用电器网上商店:Eros Digital Home
2020/08/09 全球购物
写给老婆的检讨书
2014/02/21 职场文书
基层党支部公开承诺书
2014/05/29 职场文书
工作散漫检讨书
2014/09/16 职场文书
检讨书范文大全
2015/05/07 职场文书
创业计划书之面包店
2019/09/12 职场文书
python爬取企查查企业信息之selenium自动模拟登录企查查
2021/04/08 Python
方法汇总:Python 安装第三方库常用
2022/04/26 Python