在这篇文章中,封装了一个匀速运动框架,我们在这个框架的基础之上,加上缓冲运动效果,然后用运动框架来做幻灯片(上下,左右),效果如下:【选择器用的是html5的,你的浏览器需要支持html5新选择器,才能看见效果额】
- 1
- 2
- 3
- 4
- 5
缓冲运动通常有两种常见的表现:比如让一个div从0运动到500,一种是事件触发的时候,速度很快, 一种是事件触发的时候慢,然后慢慢加快.我们来实现先块后慢的,常见的就是开车,比如刚从高速路上下来的车,就是120km/小时,然后进入匝道,变成40km/时. 或者40km/小时进入小区,最后停车,变成0km/小时. 从120km/小时->40km/小时, 或者40km->0km/小时,都是速度先块后慢,这种运动怎么用程序来表示呢?
可以用目标距离( 500 ) - 当前距离( 200 ) / 一个系数( 比如12 ),就能达到速度由块而慢的变化,当前距离在起点,分子(500 - 0 )最大,所以速度最大,如果当前距离快要接近500,分子最小,除完之后的速度也是最小。
1 10 23 24 25 26 27
你会发现,速度永远都在0.375这里停着,获取到的当前的距离停在497px? 这里有个问题,我们的div不是停在497.375px吗,怎么获取到的没有了后面的小数0.375呢?计算机在处理浮点数会有精度损失。我们可以单独做一个小测试:
1 2
你会发现这段代码获取到左偏移是30px而不是行间样式中写的30.2px。因为在获取当前位置的时候,会舍去小数,所以速度永远停在0.375px, 位置也是永远停在497,所以,为了到达目标,我们就得把速度变成1,对速度向上取整( Math.ceil ),我们就能把速度变成1,div也能到达500
1 oBtn.onclick = function(){ 2 timer = setInterval( function(){ 3 speed = ( 500 - oBox.offsetLeft ) / 8; 4 if( speed > 0 ) { 5 speed = Math.ceil( speed ); 6 } 7 console.log( speed, oBox.offsetLeft ); 8 oBox.style.left = oBox.offsetLeft + speed + 'px'; 9 }, 30 );10 }
第二个问题,如果div的位置是在900,也就是说从900运动到500,有没有这样的需求呢? 肯定有啊,轮播图,从右到左就是这样的啊。
1 10 26 27 28 29 30
1 oBtn.onclick = function(){ 2 timer = setInterval( function(){ 3 speed = ( 500 - oBox.offsetLeft ) / 8; 4 if( speed > 0 ) { 5 speed = Math.ceil( speed ); 6 }else { 7 speed = Math.floor( speed ); 8 } 9 console.log( speed, oBox.offsetLeft );10 oBox.style.left = oBox.offsetLeft + speed + 'px';11 }, 30 );12 }
然后我们把这个缓冲运动整合到匀速运动框架,就变成:
1 function css(obj, attr, value) { 2 if (arguments.length == 3) { 3 obj.style[attr] = value; 4 } else { 5 if (obj.currentStyle) { 6 return obj.currentStyle[attr]; 7 } else { 8 return getComputedStyle(obj, false)[attr]; 9 }10 }11 }12 13 function animate(obj, attr, fn) {14 clearInterval(obj.timer);15 var cur = 0;16 var target = 0;17 var speed = 0;18 obj.timer = setInterval(function () {19 var bFlag = true;20 for (var key in attr) {21 if (key == 'opacity ') {22 cur = css(obj, 'opacity') * 100;23 } else {24 cur = parseInt(css(obj, key));25 }26 target = attr[key];27 speed = ( target - cur ) / 8;28 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);29 if (cur != target) {30 bFlag = false;31 if (key == 'opacity') {32 obj.style.opacity = ( cur + speed ) / 100;33 obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")";34 } else {35 obj.style[key] = cur + speed + "px";36 }37 }38 }39 if (bFlag) {40 clearInterval(obj.timer);41 fn && fn.call(obj);42 }43 }, 30 );44 }
有了这匀速运动框架,我们就来做幻灯片:
上下幻灯片的html样式文件:
1 2 3 4 5slide - by ghostwu 6 7 8 9 10 111231 32132114 15 16 17 18 1920223023 24 25 26 27 28
29
slide3.css文件:
1 * { 2 margin: 0; 3 padding: 0; 4 } 5 li { 6 list-style-type: none; 7 } 8 #slide { 9 width: 800px;10 height: 450px;11 position: relative;12 margin:20px auto;13 }14 #slide-img {15 position: relative;16 width: 800px;17 height: 450px;18 overflow: hidden;19 }20 #img-container {21 position: absolute;22 left: 0px;23 top: 0px;24 height: 2250px;25 /*font-size:0px;*/26 }27 #img-container img {28 display: block;29 float: left;30 }31 #slide-nums {32 position: absolute;33 right:10px;34 bottom:10px;35 }36 #slide-nums li {37 float: left;38 margin:0px 10px;39 background: white;40 width: 20px;41 height: 20px;42 text-align: center;43 line-height: 20px;44 border-radius:10px;45 text-indent:-999px;46 opacity:0.6;47 filter:alpha(opacity:60);48 cursor:pointer;49 }50 #slide-nums li.active {51 background: red;52 }
animate.js文件:
1 function css(obj, attr, value) { 2 if (arguments.length == 3) { 3 obj.style[attr] = value; 4 } else { 5 if (obj.currentStyle) { 6 return obj.currentStyle[attr]; 7 } else { 8 return getComputedStyle(obj, false)[attr]; 9 }10 }11 }12 13 function animate(obj, attr, fn) {14 clearInterval(obj.timer);15 var cur = 0;16 var target = 0;17 var speed = 0;18 obj.timer = setInterval(function () {19 var bFlag = true;20 for (var key in attr) {21 if (key == 'opacity ') {22 cur = css(obj, 'opacity') * 100;23 } else {24 cur = parseInt(css(obj, key));25 }26 target = attr[key];27 speed = ( target - cur ) / 8;28 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);29 if (cur != target) {30 bFlag = false;31 if (key == 'opacity') {32 obj.style.opacity = ( cur + speed ) / 100;33 obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")";34 } else {35 obj.style[key] = cur + speed + "px";36 }37 }38 }39 if (bFlag) {40 clearInterval(obj.timer);41 fn && fn.call(obj);42 }43 }, 30 );44 }
slide.js文件:
1 window.onload = function () { 2 function Slide() { 3 this.oImgContainer = document.getElementById("img-container"); 4 this.aLi = document.getElementsByTagName("li"); 5 this.index = 0; 6 } 7 8 Slide.prototype.bind = function () { 9 var that = this;10 for (var i = 0; i < this.aLi.length; i++) {11 this.aLi[i].index = i;12 this.aLi[i].onmouseover = function () {13 that.moveTop( this.index );14 }15 }16 }17 18 Slide.prototype.moveTop = function (i) {19 this.index = i;20 for( var j = 0; j < this.aLi.length; j++ ){21 this.aLi[j].className = '';22 }23 this.aLi[this.index].className = 'active';24 animate( this.oImgContainer, {25 "top" : -this.index * 450,26 "left" : 027 });28 }29 30 var oSlide = new Slide();31 oSlide.bind();32 33 }
1 * { 2 margin: 0; 3 padding: 0; 4 } 5 li { 6 list-style-type: none; 7 } 8 #slide { 9 width: 800px;10 height: 450px;11 position: relative;12 margin:20px auto;13 }14 #slide-img {15 position: relative;16 width: 800px;17 height: 450px;18 overflow: hidden;19 }20 #img-container {21 position: absolute;22 left: 0px;23 top: 0px;24 width: 4000px;25 }26 #img-container img {27 display: block;28 float: left;29 }30 #slide-nums {31 position: absolute;32 right:10px;33 bottom:10px;34 }35 #slide-nums li {36 float: left;37 margin:0px 10px;38 background: white;39 width: 20px;40 height: 20px;41 text-align: center;42 line-height: 20px;43 border-radius:10px;44 text-indent:-999px;45 opacity:0.6;46 filter:alpha(opacity:60);47 cursor:pointer;48 }49 #slide-nums li.active {50 background: red;51 }
js调用文件:
1 window.onload = function () { 2 function Slide() { 3 this.oImgContainer = document.getElementById("img-container"); 4 this.aLi = document.getElementsByTagName("li"); 5 this.index = 0; 6 } 7 8 Slide.prototype.bind = function () { 9 var that = this;10 for (var i = 0; i < this.aLi.length; i++) {11 this.aLi[i].index = i;12 this.aLi[i].onmouseover = function () {13 that.moveLeft( this.index );14 }15 }16 }17 18 Slide.prototype.moveLeft = function (i) {19 this.index = i;20 for( var j = 0; j < this.aLi.length; j++ ){21 this.aLi[j].className = '';22 }23 this.aLi[this.index].className = 'active';24 animate( this.oImgContainer, {25 "left" : -this.index * 80026 });27 }28 29 var oSlide = new Slide();30 oSlide.bind();31 32 }