使用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 相关文章推荐
使用新的消息弹出框blackbirdjs
Oct 16 Javascript
JavaScript中的this到底是什么(一)
Dec 09 Javascript
JavaScript如何实现跨域请求
Aug 05 Javascript
Ajax 加载数据 练习代码
Jan 05 Javascript
详解使用Vue.Js结合Jquery Ajax加载数据的两种方式
Jan 10 Javascript
原生js实现电商侧边导航效果
Jan 19 Javascript
js封装成插件的步骤方法
Sep 11 Javascript
利用Three.js如何实现阴影效果实例代码
Sep 26 Javascript
JS实现标签滚动切换效果
Dec 25 Javascript
vue 解决循环引用组件报错的问题
Sep 06 Javascript
JavaScript实现简单的图片切换功能(实例代码)
Apr 10 Javascript
keep-Alive搭配vue-router实现缓存页面效果的示例代码
Jun 24 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 长文章分页函数 带使用方法,不会分割段落,翻页在底部
2009/10/22 PHP
php实现12306余票查询、价格查询示例
2014/04/17 PHP
PHP Opcache安装和配置方法介绍
2015/05/28 PHP
PHP数组操作类实例
2015/07/11 PHP
PHP批量获取网页中所有固定种子链接的方法
2016/11/18 PHP
php判断电子邮件是否正确方法
2018/12/04 PHP
extjs form textfield的隐藏方法
2008/12/29 Javascript
JavaScript内核之基本概念
2011/10/21 Javascript
JS无法捕获滚动条上的mouse up事件的原因猜想
2012/03/21 Javascript
javascript父、子页面交互技巧总结
2014/08/08 Javascript
JS自定义对象实现Java中Map对象功能的方法
2015/01/20 Javascript
JavaScript模板引擎用法实例
2015/07/10 Javascript
AngularJS中监视Scope变量以及外部调用Scope方法
2016/01/23 Javascript
JS中Json数据的处理和解析JSON数据的方法详解
2016/06/29 Javascript
NodeJS实现图片上传代码(Express)
2017/06/30 NodeJs
JS实现上传图片的三种方法并实现预览图片功能
2017/07/14 Javascript
jquery实现左右轮播图效果
2017/09/28 jQuery
浅谈es6语法 (Proxy和Reflect的对比)
2017/10/24 Javascript
AngularJS实现的根据数量与单价计算总价功能示例
2017/12/26 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
2018/10/30 Javascript
vue组件内部引入外部js文件的方法
2020/01/18 Javascript
[05:15]DOTA2英雄梦之声_第16期_灰烬之灵
2014/06/21 DOTA
python 类对象和实例对象动态添加方法(分享)
2017/12/31 Python
django中的图片验证码功能
2019/09/18 Python
基于python3生成标签云代码解析
2020/02/18 Python
python实现拼图小游戏
2020/02/22 Python
python 引用传递和值传递详解(实参,形参)
2020/06/05 Python
解决PyCharm不在run输出运行结果而不是再Console里输出的问题
2020/09/21 Python
Charlotte Tilbury英国官网:英国彩妆品牌
2017/05/26 全球购物
商务英语大学生职业生涯规划书范文
2014/01/01 职场文书
交警个人先进事迹材料
2014/05/11 职场文书
初中同学会活动方案
2014/08/22 职场文书
卖房授权委托书样本
2014/10/05 职场文书
房屋所有权证明
2014/10/20 职场文书
2014年学校法制宣传日活动总结
2014/11/01 职场文书
工作简报范文
2015/07/21 职场文书