使用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 相关文章推荐
JS中剪贴板兼容性、判断复制成功或失败
Mar 09 Javascript
jquery.alert 弹出式复选框实现代码
Jun 15 Javascript
JS获取月的最后一天与JS得到一个月份最大天数的实例代码
Dec 16 Javascript
JS的参数传递示例介绍
Feb 08 Javascript
jQuery 和 CSS 的文本特效插件集锦
Dec 12 Javascript
js显示当前日期时间和星期几
Oct 22 Javascript
jQuery自动或手动图片切换效果
Oct 11 jQuery
Vue实现带进度条的文件拖动上传功能
Feb 23 Javascript
vue组件name的作用小结
May 23 Javascript
nuxt中使用路由守卫的方法步骤
Jan 27 Javascript
微信小程序五子棋游戏AI实现方法【附demo源码下载】
Feb 20 Javascript
vue 路由守卫(导航守卫)及其具体使用
Feb 25 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
特详细的PHPMYADMIN简明安装教程
2008/08/01 PHP
实战mysql导出中文乱码及phpmyadmin导入中文乱码的解决方法
2010/06/11 PHP
php二维数组转成字符串示例
2014/02/17 PHP
PHP实现图片压缩的两则实例
2014/07/19 PHP
PHP 5.6.11中CURL模块问题的解决方法
2016/08/08 PHP
Laravel用户授权系统的使用方法示例
2018/09/16 PHP
Alliance vs Liquid BO3 第三场2.13
2021/03/10 DOTA
jquery validator 插件增加日期比较方法
2010/02/21 Javascript
微信小程序 实战小程序实例
2016/10/08 Javascript
Bootstrap3 多选和单选框(checkbox)
2016/12/29 Javascript
nodejs模块学习之connect解析
2017/07/05 NodeJs
JavaScript实现修改伪类样式
2017/11/27 Javascript
详解Node 定时器
2018/02/26 Javascript
nodejs实现获取本地文件夹下图片信息功能示例
2019/06/22 NodeJs
vue图片加载失败时用默认图片替换的方法
2019/08/29 Javascript
JS扁平化输出数组的2种方法解析
2019/09/17 Javascript
React 父子组件通信的实现方法
2019/12/05 Javascript
element中table高度自适应的实现
2020/10/21 Javascript
[53:36]Liquid vs VP Supermajor决赛 BO 第三场 6.10
2018/07/05 DOTA
PHP魔术方法__ISSET、__UNSET使用实例
2014/11/25 Python
python通过线程实现定时器timer的方法
2015/03/16 Python
Python基础教程之利用期物处理并发
2018/03/29 Python
解决项目pycharm能运行,在终端却无法运行的问题
2019/01/19 Python
10 分钟快速入门 Python3的教程
2019/01/29 Python
Python实现简单查找最长子串功能示例
2019/02/26 Python
Flask框架钩子函数功能与用法分析
2019/08/02 Python
突袭HTML5之Javascript API扩展5—其他扩展(应用缓存/服务端消息/桌面通知)
2013/01/31 HTML / CSS
洛杉矶生活休闲而精致的基础品牌:Mika Jaymes
2018/01/07 全球购物
波兰灯具、照明和LED购物网站:Lampy.pl
2019/03/11 全球购物
匡威爱尔兰官网:Converse爱尔兰
2019/06/09 全球购物
护士实习自我鉴定
2013/10/22 职场文书
行政人员岗位职责
2013/12/08 职场文书
四年大学生活的自我评价范文
2014/02/07 职场文书
房产继承公证书
2014/04/09 职场文书
2015年党风廉政建设责任书
2015/01/29 职场文书
微软Win11有哪些隐藏功能? windows11多个功能汇总
2021/11/21 数码科技