使用JavaScript 实现对象 匀速/变速运动的方法


Posted in Javascript onMay 08, 2013

实例1——控制一个对象的匀速移动和停止

HTML:

<input id="btn" type="button" value=" Move It ! "/>
    <div id="d1">
        <img id="i1" src="1.jpg" alt/>
    </div>

JS:实现向右运动
var timer=null;
    window.onload=function(){
        var odiv=document.getElementById('d1');
        var obtn=document.getElementById('btn');
        clearInterval(timer); //作用见要点①
        obtn.onclick=function(){
            timer=setInterval(function(){
                var speed=10;
                if(odiv.offsetLeft>=300){ //判断对象边距 到达指定位移则关闭定时器
                    clearInterval(timer);
                }else{
                    odiv.style.left=odiv.offsetLeft+speed+'px';
                }
            },30);
        }
    }

要点:
①if语句的条件不能用“==”运算符,如上述代码,当speed的值为基数如7时,不断增加的左边距不会出现300px值,而是到达294后直接跳到301,导致条件失效,无法停止。
②使用else语句是防止停止移动后,每点击一次按钮,div任会移动一个speed。
③在定时器之前,先关闭一下定时器,防止连续点击按钮时,同时打开多个定时器,使移动速度叠加后更快。

封装:

//object:要移动的对象id   itarget:水平位移位置
   var timer=null;
    function moveto(object,itarget){
        var obj=document.getElementById(object);
            clearInterval(timer);
            timer=setInterval(function(){
                var speed=0;
                if(obj.offsetLeft<itarget){  //通过对象距离父级的边距和水平位移量 判断左右位移方向
                    speed=10;
                }else{
                    speed=-10;
                }
                if(obj.offsetLeft==itarget){
                    clearInterval(timer);
                }else{
                    obj.style.left=obj.offsetLeft+speed+'px';
                };
            },30);
    }

实例2——修改上述封装的函数moveto(),使该对象变速停止

 JS:

var timer=null;
    function moveto(object,itarget){
        var obj=document.getElementById(object);
            clearInterval(timer);
            timer=setInterval(function(){
                var speed=0;
                if(obj.offsetLeft<itarget){//通过位移量除以10,使speed递减,实现减速停止。   乘以10则为加速。通过乘除的数字,控制快慢
                    speed=(itarget-obj.offsetLeft)/10; 
                }else{
                    speed=-(obj.offsetLeft-itarget)/10;
                }
                speed=speed>0?Math.ceil(speed):Math.floor(speed);//取整,解决最后不足1px的位移量被忽略的问题
                if(obj.offsetLeft==itarget){
                    clearInterval(timer);
                }else{
                    obj.style.left=obj.offsetLeft+speed+'px';
                };
                document.title=obj.offsetLeft;
            },30);
    }

要点:
①通过递减speed值,实现变速。
②移动到最后,当像素小于1px时,小于1px的几个值不会被添加(或减去)到对象left中,而是被忽略,所以最终位移量比设定的水平位移位置itarget要少几个像素。解决的办法是进行取整:正数向上取整ceil(),负数向下取整floor()。

 

 扩展:垂直位移的原理和水平位移的相同。

 补充1:
解决speed与itarget不能整除,导致对象不能精确到达itarget位置,而是在其左右抖动问题:

var timer=null;
    function moveto(object,itarget){
        var obj=document.getElementById(object);
            clearInterval(timer);
            timer=setInterval(function(){
                var speed=0;
                if(obj.offsetLeft<=itarget){
                    speed=7;
                }else{
                    speed=-7;
                }
//设置对象在离目标位置itarget的距离小于speed时,停止运动,同时设置对象的left直接移动到itarget的位置。
                if(Math.abs(itarget-obj.offsetLeft<=speed)){
                    clearInterval(timer);
                    obj.style.left=itarget+'px';
                }else{
                    obj.style.left=obj.offsetLeft+speed+'px';
                };
                document.title=obj.offsetLeft;
            },30);
    }

补充2:

offset的Bug:例如offsetWidth,它包含的不只是width,还包含padding和border。当给对象设置了填充或边框时,再将offsetWidth赋值给对象时,就会运动就会有差异。
解决:不用offset,而是通过创建一个兼容IE和FF的函数,获取元素的width属性值,来代替offsetWidth。该函数如下:getAttr()

function getAttr(obj,attrName){
        var obj=document.getElementById(obj);
        if(obj.currentStyle){
            return obj.currentStyle[attrName]; //兼容IE
        }else{
            return getComputedStyle(obj,false)[attrName]; //兼容FF
        }
    }
Javascript 相关文章推荐
fix-ie5.js扩展在IE5下不能使用的几个方法
Aug 20 Javascript
javascript 获取页面的高度及滚动条的位置的代码
May 06 Javascript
JS动态改变表格边框宽度的方法
Mar 31 Javascript
js实现从右向左缓缓浮出网页浮动层广告的方法
May 09 Javascript
详细解读JavaScript的跨浏览器事件处理
Aug 12 Javascript
利用JS提交表单的几种方法和验证(必看篇)
Sep 17 Javascript
AngularJS中的JSONP实例解析
Dec 01 Javascript
Bootstrap modal使用及点击外部不消失的解决方法
Dec 13 Javascript
浅谈jQuery操作类数组的工具方法
Dec 23 Javascript
原生js实现日期计算器功能
Feb 17 Javascript
微信小程序实现打开内置地图功能【附源码下载】
Dec 07 Javascript
vue项目中axios请求网络接口封装的示例代码
Dec 18 Javascript
JavaScript 创建运动框架的实现代码
May 08 #Javascript
jQuery输入城市查看地图使用介绍
May 08 #Javascript
深入Javascript函数、递归与闭包(执行环境、变量对象与作用域链)使用详解
May 08 #Javascript
基于jquery实现拆分姓名的方法(纯JS版)
May 08 #Javascript
jQuery cdn使用介绍
May 08 #Javascript
不用锚点也可以平滑滚动到页面的指定位置实现代码
May 08 #Javascript
jquery实现图片左右间隔滚动特效(可自动播放)
May 08 #Javascript
You might like
PHP正则获取页面所有图片地址
2016/03/23 PHP
基于PHP实现通过照片获取ip地址
2016/04/26 PHP
PHP curl 或 file_get_contents 获取需要授权页面的方法
2017/05/05 PHP
PHP中使用CURL发送get/post请求上传图片批处理功能
2018/10/15 PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
2019/09/30 PHP
ThinkPHP5&amp;5.1实现验证码的生成、使用及点击刷新功能示例
2020/02/07 PHP
一个可以显示阴历的JS代码
2007/03/05 Javascript
JavaScript加强之自定义event事件
2013/09/21 Javascript
js日期对象兼容性的处理方法
2014/01/28 Javascript
js+div实现图片滚动效果代码
2014/02/10 Javascript
详解JavaScript的while循环的使用
2015/06/03 Javascript
JavaScript:Array类型全面解析
2016/05/19 Javascript
JS计算距当前时间的时间差实例
2017/12/29 Javascript
详解TypeScript+Vue 插件 vue-class-component的使用总结
2019/02/18 Javascript
JQuery Ajax跨域调用和非跨域调用问题实例分析
2019/04/16 jQuery
一波神奇的Python语句、函数与方法的使用技巧总结
2015/12/08 Python
asyncio 的 coroutine对象 与 Future对象使用指南
2016/09/11 Python
Python分析学校四六级过关情况
2017/11/22 Python
人生苦短我用python python如何快速入门?
2018/03/12 Python
Pandas标记删除重复记录的方法
2018/04/08 Python
python实现验证码识别功能
2018/06/07 Python
ubuntu17.4下为python和python3装上pip的方法
2018/06/12 Python
Python小白必备的8个最常用的内置函数(推荐)
2019/04/03 Python
如何基于Python制作有道翻译小工具
2019/12/16 Python
用python进行视频剪辑
2020/11/02 Python
jupyter notebook快速入门及使用详解
2020/11/13 Python
解决pytorch下出现multi-target not supported at的一种可能原因
2021/02/06 Python
意大利自行车商店:Cingolani Bike Shop
2019/09/03 全球购物
意向书范文
2014/03/31 职场文书
中华魂演讲稿
2014/05/13 职场文书
货物运输服务质量承诺书
2014/05/29 职场文书
2015年法务工作总结范文
2015/05/23 职场文书
师范生教育见习总结
2015/06/23 职场文书
月考总结与反思
2015/10/22 职场文书
安全生产协议书
2016/03/22 职场文书
MySQL数据库之内置函数和自定义函数 function
2022/06/16 MySQL