使用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 判断代码全收集
Apr 28 Javascript
js取消单选按钮选中并判断对象是否为空
Nov 14 Javascript
解决自定义$(id)的方法与jquery选择器$冲突的问题
Jun 14 Javascript
javascript正则表达式之search()用法实例
Jan 19 Javascript
jQuery实现分章节锚点“回到顶部”动画特效代码
Oct 23 Javascript
Angularjs 动态添加指令并绑定事件的方法
Apr 13 Javascript
vue 2.0路由之路由嵌套示例详解
May 08 Javascript
详解Vue.js使用Swiper.js在iOS
Sep 10 Javascript
基于vue和react的spa进行按需加载的实现方法
Sep 29 Javascript
autojs 蚂蚁森林能量自动拾取即给指定好友浇水的实现方法
May 03 Javascript
详解Vue中Axios封装API接口的思路及方法
Oct 10 Javascript
jQuery实现穿梭框效果
Jan 19 jQuery
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
将数字格式的计算结果转为汉字格式
2006/10/09 PHP
那些年一起学习的PHP(一)
2012/03/21 PHP
基于php设计模式中单例模式的应用分析
2013/05/15 PHP
php之CodeIgniter学习笔记
2013/06/17 PHP
PHP远程采集图片详细教程
2014/07/01 PHP
PHP日志LOG类定义与用法示例
2018/09/06 PHP
jquery调用asp.net 页面后台的实现代码
2011/04/27 Javascript
基于jquery的9行js轻松实现tab控件示例
2013/10/12 Javascript
JavaScript 32位整型无符号操作示例
2013/12/08 Javascript
浅析node.js中close事件
2014/11/26 Javascript
jQuery插件pagination实现分页特效
2015/04/12 Javascript
jQuery实现带延迟的二级tab切换下拉列表效果
2015/09/01 Javascript
微信小程序 下拉菜单的实现
2017/04/06 Javascript
JavaScript实现多重继承的方法分析
2018/01/09 Javascript
Vue项目分环境打包的实现步骤
2018/04/02 Javascript
angular的输入和输出的使用方法
2018/09/22 Javascript
jQuery实现的自定义轮播图功能详解
2018/12/28 jQuery
详解基于iview-ui的导航栏路径(面包屑)配置
2019/02/22 Javascript
转换layUI的数据表格中的日期格式方法
2019/09/19 Javascript
一篇超完整的Vue新手入门指导教程
2020/11/18 Vue.js
python使用urlparse分析网址中域名的方法
2015/04/15 Python
python如何实现代码检查
2019/06/28 Python
SELENIUM自动化模拟键盘快捷键操作实现解析
2019/10/28 Python
新秀丽拉杆箱美国官方网站:Samsonite美国
2016/07/25 全球购物
网站域名和主机:Domain.com
2019/04/01 全球购物
GafasWorld西班牙:购买太阳镜、眼镜和隐形眼镜
2019/09/08 全球购物
波兰最大的电商平台:Allegro.pl
2021/02/06 全球购物
写出一个方法实现冒泡排序
2016/07/08 面试题
怀念母亲教学反思
2014/04/28 职场文书
低碳环保标语
2014/06/12 职场文书
师范大学生求职信
2014/06/13 职场文书
迎国庆演讲稿
2014/09/15 职场文书
单位工作证明书格式
2014/10/04 职场文书
环境卫生工作汇报材料
2014/10/28 职场文书
交警正风肃纪剖析材料
2014/10/29 职场文书
2016年社区党支部公开承诺书
2016/03/25 职场文书