在这篇文章[js高手之路]打造通用的匀速运动框架中,封装了一个匀速运动框架,我们在这个框架的基础之上,加上缓冲运动效果,然后用运动框架来做幻灯片(上下,左右),效果如下:【选择器用的是html5的,你的浏览器需要支持html5新选择器,才能看见效果额】

  • 1
  • 2
  • 3
  • 4
  • 5

缓冲运动通常有两种常见的表现:比如让一个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" style="position:absolute;left:30.2px;width:200px;height:300px;background:red;"></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">
<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="" style="opacity:1;">
<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:;
padding:;
}
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:;
padding:;
}
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(); }

[js高手之路]封装运动框架实战左右与上下滑动的焦点轮播图的更多相关文章

  1. 原生js焦点轮播图

    原生js焦点轮播图主要注意这几点: 1.前后按钮实现切换,同时注意辅助图2.中间的button随着前后按钮对应切换,同时按button也能跳转到相应的index3.间隔调用与无限轮播.4.注意在动画时 ...

  2. js焦点轮播图

    汇集网上焦点轮播图的实现方式,自己试了下,不过鼠标悬浮停止动画和鼠标离开动画播放好像没生效,不太明白,最后两行代码中,为什么可以直接写stop和play.不用加括号调用函数么?求懂的大神指点! 所用知 ...

  3. 封装一个简单的原生js焦点轮播图插件

    轮播图实现的效果为,鼠标移入左右箭头会出现,可以点击切换图片,下面的小圆点会跟随,可以循环播放(为了方便理解,没有补2张图做无缝轮播).本篇文章的主要目的是分享封装插件的思路. 轮播图我一开始是写成非 ...

  4. Flask实战第54天:cms删除轮播图功能完成

    后台逻辑 编辑cms.views.py @bp.route('/dbanner/',methods=['POST']) @login_required def dbanner(): banner_id ...

  5. Flask实战第53天:cms编辑轮播图功能完成

    后端逻辑 表单验证, 这里编辑就是和添加的内容一样,所以可以直接继承添加轮播图的表单验证,然后多加一个轮播图的id即可 编辑cmd.forms.py class UpdateBannerForm(Ad ...

  6. Flask实战第52天:cms添加轮播图前端代码逻辑完成

    首页我们在模态框中的保存按钮加一个id,这样方便我们选取这个按钮 <button type="button" class="btn btn-primary" ...

  7. JS+css3焦点轮播图PC端

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 原生js焦点轮播图的实现

    继续学习打卡,武汉加油,逆战必胜!今日咱们主要探讨一下原生js写轮播图的问题, 简单解析一下思路: 1,首先写好css样式问题 2,考虑全局变量:自动播放的定时器,以及记录图片位置的角标Index 2 ...

  9. [js高手之路]匀速运动与实例实战(侧边栏,淡入淡出)

    javascript中,如何让一个元素(比如div)运动起来呢? 设置基本的样式,一定要让div有定位( 当然用margin的变化也可以让元素产生运动效果 ); <style> div { ...

随机推荐

  1. 如何解决xshell中无法输入中文的问题

    自从安上了xshell以后,用着那叫一个顺手,美中不足的就是一直无法输入中文.不过,既然学习IT,就要习惯英文嘛~直到--我遇到了脚本,写好一个脚本,必要的注释是少不了的,但是作为一个英文渣渣,我真的 ...

  2. 集美大学网络1413第九次作业成绩(团队五) -- 测试与发布(Alpha版本)

    NO.NE团队的项目链接有效,六个核桃和六指神功团队可以请教下他们,避免因IP地址无效或者因tomcat不打开就不能访问的情况,毕竟助教没办法知道此时此刻它是开着还是关闭啊啊啊... 题目 团队作业5 ...

  3. 201521123010 《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  4. 201521123023《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. (1)File可以表示一个特定文件的名称,也能表示一个目录下的一组文件的名称. (2)继承自InputStre ...

  5. Java课程设计—学生成绩管理系统(54号童欢)

    1. 团队课程设计博客链接 http://www.cnblogs.com/wufuckshuo/p/7063183.html 2.个人责模块或任务说明 负责模块/任务:主函数(调用其他的功能函数),添 ...

  6. 201521123109 《java程序设计》第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1. 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) ...

  7. 201521123089 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-21.1 截图你的提交结果(出现 ...

  8. 今天的第一个程序-南阳acm输入三个数排序

    #include<stdio.h>main(){    int a,b,c,t;    scanf("%d%d%d",&a,&b,&c);    ...

  9. 关于Java中数组的常用操作方法

    1. 声明一个数组 String[] arr1 = new String[5]; String[] arr2 = {"a","b","c", ...

  10. springmvc03-异常处理-静态文件

    1,一个简单的登录 login.jsp页面 <%@ page language="java" contentType="text/html; charset=UTF ...