使用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 相关文章推荐
jQuery live( type, fn ) 委派事件实现
Oct 11 Javascript
DWZ table的原生分页浅谈
Mar 01 Javascript
jquery用data方法获取某个元素上的事件
Jun 23 Javascript
JavaScript检测字符串中是否含有html标签实现方法
Jul 01 Javascript
[原创]jQuery常用的4种加载方式分析
Jul 25 Javascript
JavaScript基础之流程控制语句的用法
Aug 31 Javascript
JS基于for语句编写的九九乘法表示例
Jan 04 Javascript
脚手架vue-cli工程webpack的基本用法详解
Sep 29 Javascript
详解Angular Karma测试的持续集成实践
Nov 15 Javascript
基于vue.js实现购物车
Jan 15 Javascript
Vue中el-form标签中的自定义el-select下拉框标签功能
Apr 20 Javascript
js实现扫雷源代码
Nov 27 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
sqlyog 中文乱码问题的设置方法
2008/10/19 PHP
PHP资源管理框架Assetic简介
2014/06/12 PHP
php可扩展的验证类实例(可对邮件、手机号、URL等验证)
2015/07/09 PHP
thinkPHP框架中layer.js的封装与使用方法示例
2019/01/18 PHP
Jquery 的outerHeight方法使用介绍
2013/09/11 Javascript
js单词形式的运算符
2014/05/06 Javascript
js创建对象的区别示例介绍
2014/07/24 Javascript
c#程序员对TypeScript的认识过程
2015/06/19 Javascript
IE和Firefox之间在JavaScript语法上的差异
2016/04/22 Javascript
详解Angular之constructor和ngOnInit差异及适用场景
2017/06/22 Javascript
JS实现多张图片预览同步上传功能
2017/06/23 Javascript
JavaScript定义函数的三种实现方法
2017/09/23 Javascript
vue项目中使用axios上传图片等文件操作
2017/11/02 Javascript
详解如何构建一个Angular6的第三方npm包
2018/09/07 Javascript
小程序实现左右来回滚动字幕效果
2018/12/28 Javascript
谈谈node.js中的模块系统
2020/09/01 Javascript
微信小程序实现倒计时功能
2020/11/19 Javascript
vue 实现基础组件的自动化全局注册
2020/12/25 Vue.js
[03:49]DOTA2 2015国际邀请赛中国区预选赛第二日现场百态
2015/05/27 DOTA
[01:16]DOTA2小知识课堂 Ep.03 芒果树无伤肉山
2019/12/05 DOTA
Python实现大文件排序的方法
2015/07/10 Python
详谈在flask中使用jsonify和json.dumps的区别
2018/03/26 Python
Python实现批量修改图片格式和大小的方法【opencv库与PIL库】
2018/12/03 Python
Python基础教程之if判断,while循环,循环嵌套
2019/04/25 Python
python 实现识别图片上的数字
2019/07/30 Python
新手入门学习python Numpy基础操作
2020/03/02 Python
Pycharm IDE的安装和使用教程详解
2020/04/30 Python
企业安全生产承诺书
2014/05/22 职场文书
本科毕业生应聘求职信
2014/07/06 职场文书
授权委托书样本及填写说明
2014/09/19 职场文书
一年级数学上册复习计划
2015/01/17 职场文书
2015年党建工作总结
2015/03/30 职场文书
关于调整工作时间的通知
2015/04/24 职场文书
幼儿教师继续教育培训心得体会
2016/01/19 职场文书
PyTorch 如何自动计算梯度
2021/05/23 Python
详解JVM系列之内存模型
2021/06/10 Javascript