使用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 相关文章推荐
kmock javascript 单元测试代码
Feb 06 Javascript
jQuery操作input type=radio的实现代码
Jun 14 Javascript
基于jquery的9行js轻松实现tab控件示例
Oct 12 Javascript
JQuery 图片滚动轮播示例代码
Mar 24 Javascript
js分页工具实例
Jan 28 Javascript
Bootstrap每天必学之警告框插件
Apr 26 Javascript
AngularJs解决跨域问题案例详解(简单方法)
May 19 Javascript
js操作DOM--添加、删除节点的简单实例
Jul 08 Javascript
js实现分页功能
May 24 Javascript
基于vue 开发中出现警告问题去除方法
Jan 25 Javascript
原生JS实现微信通讯录
Jun 18 Javascript
教你一步步实现一个简易promise
Nov 02 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扩展函数
2006/10/09 PHP
PHP脚本的10个技巧(1)
2006/10/09 PHP
javascript使用正则控制input输入框允许输入的值方法大全
2014/06/19 Javascript
推荐一个自己用的封装好的javascript插件
2015/01/29 Javascript
JS实现文字掉落效果的方法
2015/05/06 Javascript
avalon js实现仿google plus图片多张拖动排序附源码下载
2015/09/24 Javascript
基于JavaScript如何制作遮罩层对话框
2016/01/26 Javascript
Bootstrap3学习笔记(二)之排版
2016/05/20 Javascript
实例解析jQuery中proxy()函数的用法
2016/05/24 Javascript
Javascript 编码约定(编码规范)
2018/03/11 Javascript
vue 设置proxyTable参数进行代理跨域
2018/04/09 Javascript
微信小程序实现星级评价效果
2018/12/28 Javascript
Echarts动态加载多条折线图的实现代码
2019/05/24 Javascript
详解vue 2.6 中 slot 的新用法
2019/07/09 Javascript
JavaScript面向对象核心知识与概念归纳整理
2020/05/09 Javascript
python 查找文件夹下所有文件 实现代码
2009/07/01 Python
python处理中文编码和判断编码示例
2014/02/26 Python
Python中实现结构相似的函数调用方法
2015/03/10 Python
Python中pip更新和三方插件安装说明
2018/07/08 Python
Python3 Post登录并且保存cookie登录其他页面的方法
2018/12/28 Python
Scrapy框架爬取Boss直聘网Python职位信息的源码
2019/02/22 Python
python实现统计文本中单词出现的频率详解
2019/05/20 Python
numpy按列连接两个维数不同的数组方式
2019/12/06 Python
python用WxPython库实现无边框窗体和透明窗体实现方法详解
2020/02/21 Python
python 串行执行和并行执行实例
2020/04/30 Python
TripAdvisor德国:全球领先的旅游网站
2017/12/07 全球购物
德国运动营养和健身网上商店:Myprotein.de
2018/07/18 全球购物
TobyDeals美国:在电子产品上获得最好的优惠和折扣
2019/08/11 全球购物
TecoBuy澳大利亚:在线电子和小工具商店
2020/06/25 全球购物
专科毕业生求职简历的自我评价
2013/10/12 职场文书
个人简历自我评价
2014/01/06 职场文书
父亲生日宴会答谢词
2014/01/10 职场文书
整顿机关作风心得体会
2014/09/10 职场文书
煤矿安全保证书
2015/02/27 职场文书
2015纪念九一八事变84周年演讲稿
2015/03/19 职场文书
2015年圣诞节寄语
2015/08/17 职场文书