使用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中的undefined,null,&quot;&quot;,0和false
Mar 08 Javascript
javascript动态加载实现方法一
Aug 22 Javascript
JS检测图片大小的实例
Aug 21 Javascript
使用JQuery快速实现Tab的AJAX动态载入(实例讲解)
Dec 11 Javascript
微信开发 消息推送实现代码
Oct 21 Javascript
jQuery基于Ajax方式提交表单功能示例
Feb 10 Javascript
JS简单实现点击按钮或文字显示遮罩层的方法
Apr 27 Javascript
Vue表单及表单绑定方法
Sep 04 Javascript
Node.js Buffer模块功能及常用方法实例分析
Jan 05 Javascript
使用原生js编写一个简单的框选功能方法
May 13 Javascript
bootstrap table实现iview固定列的效果实例代码详解
Sep 30 Javascript
vue离开当前页面触发的函数代码
Sep 01 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
基于qmail的完整WEBMAIL解决方案安装详解
2006/10/09 PHP
可定制的PHP缩略图生成程式(需要GD库支持)
2007/03/06 PHP
PHP有序表查找之插值查找算法示例
2018/02/10 PHP
Windows平台PHP+IECapt实现网页批量截图并创建缩略图功能详解
2019/08/02 PHP
判断JavaScript对象是否可用的最正确方法分析
2008/10/03 Javascript
利用javascript/jquery对上传文件格式过滤的方法
2009/07/25 Javascript
JQuery在光标位置插入内容的实现代码
2010/06/18 Javascript
jQuery实现简单滚动动画效果
2016/04/07 Javascript
javascript实现下雪效果【实例代码】
2016/05/03 Javascript
通过Ajax使用FormData对象无刷新上传文件方法
2016/12/08 Javascript
JavaScript变量作用域_动力节点Java学院整理
2017/06/27 Javascript
基于Vue2.X的路由和钩子函数详解
2018/02/09 Javascript
webpack打包node.js后端项目的方法
2018/03/10 Javascript
jquery实现搜索框功能实例详解
2018/07/23 jQuery
JavaScript实用代码小技巧
2018/08/23 Javascript
ES6 Promise对象的含义和基本用法分析
2019/06/14 Javascript
Vue 解决路由过渡动画抖动问题(实例详解)
2020/01/05 Javascript
Python Web开发模板引擎优缺点总结
2014/05/06 Python
python集合用法实例分析
2015/05/30 Python
Python实现提取谷歌音乐搜索结果的方法
2015/07/10 Python
Python json 错误xx is not JSON serializable解决办法
2017/03/15 Python
Python中%r和%s的详解及区别
2017/03/16 Python
python线程池threadpool实现篇
2018/04/27 Python
python实现手机销售管理系统
2019/03/19 Python
Django中如何使用sass的方法步骤
2019/07/09 Python
关于Keras Dense层整理
2020/05/21 Python
HomeAway的巴西品牌:Alugue Temporada
2018/04/10 全球购物
生产内勤岗位职责
2013/12/07 职场文书
工作自荐信
2013/12/11 职场文书
证券期货行业个人的自我评价
2013/12/26 职场文书
劳资专员岗位职责
2013/12/27 职场文书
先进党支部事迹材料
2014/01/13 职场文书
技术股东合作协议书
2014/12/02 职场文书
幼师小班个人总结
2015/02/12 职场文书
有关信念的名言语录集锦
2019/12/06 职场文书
MySQL中distinct和count(*)的使用方法比较
2021/05/26 MySQL