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


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 相关文章推荐
Ext JS Grid在IE6 下宽度的问题解决方法
Feb 15 Javascript
javascript实现des解密加密全过程
Apr 03 Javascript
jquery实现树形菜单完整代码
Dec 29 Javascript
一篇文章掌握RequireJS常用知识
Jan 26 Javascript
Javascript typeof与instanceof的区别
Oct 18 Javascript
微信小程序 swiper组件轮播图详解及实例
Nov 16 Javascript
微信小程序 首页制作简单实例
Apr 07 Javascript
基于原生js运动方式关键点的总结(推荐)
Oct 01 Javascript
Angular5中调用第三方库及jQuery的添加的方法
Jun 07 jQuery
vue组件横向树实现代码
Aug 02 Javascript
CryptoJS中AES实现前后端通用加解密技术
Dec 18 Javascript
原生JavaScript实现购物车
Jan 10 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 radio 单选框获取与保持值的实现代码
2010/05/15 PHP
PHP文章采集URL补全函数(FormatUrl)
2012/08/02 PHP
使用Discuz关键词服务器实现PHP中文分词
2014/03/11 PHP
PHP数组与对象之间使用递归实现转换的方法
2015/06/24 PHP
PHP MVC框架路由学习笔记
2016/03/02 PHP
asp 的 分词实现代码
2007/05/24 Javascript
兼容IE/Firefox/Opera/Safari的检测页面装载完毕的脚本Ext.onReady的实现
2009/07/14 Javascript
jquery 按键盘上的enter事件
2014/05/11 Javascript
JavaScript实现简单图片翻转的方法
2015/04/17 Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
2015/12/25 Javascript
JavaScript的Backbone.js框架环境搭建及Hellow world示例
2016/05/07 Javascript
JavaScript编码风格指南(中文版)
2016/08/26 Javascript
JS数组排序方法实例分析
2016/12/16 Javascript
详解js中常规日期格式处理、月历渲染和倒计时函数
2016/12/28 Javascript
JavaScript原生编写《飞机大战坦克》游戏完整实例
2017/01/04 Javascript
JS实现本地存储信息的方法(基于localStorage与userData)
2017/02/18 Javascript
利用require.js与angular搭建spa应用的方法实例
2017/07/19 Javascript
mock.js模拟前后台交互
2019/07/25 Javascript
vue中通过使用$attrs实现组件之间的数据传递功能
2019/09/01 Javascript
原生js实现滑块区间组件
2021/01/20 Javascript
Python图像的增强处理操作示例【基于ImageEnhance类】
2019/01/03 Python
利用Python+阿里云实现DDNS动态域名解析的方法
2019/04/01 Python
Python csv文件的读写操作实例详解
2019/11/19 Python
nginx搭建基于python的web环境的实现步骤
2020/01/03 Python
python文件及目录操作代码汇总
2020/07/08 Python
HTML5的表单(绝对特别强大的功能)使用示例
2013/06/20 HTML / CSS
用canvas画心电图的示例代码
2018/09/10 HTML / CSS
一些.net面试题
2014/10/06 面试题
物业管理求职自荐信
2013/09/25 职场文书
八一演出活动方案
2014/02/03 职场文书
财务科科长岗位职责
2014/03/10 职场文书
陈胜吴广起义口号
2014/06/20 职场文书
2014年环卫工作总结
2014/11/22 职场文书
金融专业银行实习证明模板
2014/11/28 职场文书
学校教学管理制度
2015/08/06 职场文书
Python中三种花式打印的示例详解
2022/03/19 Python