使用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 相关文章推荐
javascript各种复制代码收集
Sep 20 Javascript
编写可维护面向对象的JavaScript代码[翻译]
Feb 12 Javascript
容易被忽略的JS脚本特性
Sep 13 Javascript
jQuery validate插件submitHandler提交导致死循环解决方法
Jan 21 Javascript
JS转换HTML转义符的方法
Aug 24 Javascript
深入理解Vue-cli搭建项目后的目录结构探秘
Jul 13 Javascript
推荐一个基于Node.js的表单验证库
Feb 15 Javascript
JS数组splice操作实例分析
Oct 12 Javascript
JS自定义对象创建与简单使用方法示例
Jan 15 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
Feb 26 Javascript
vue+koa2搭建mock数据环境的详细教程
May 18 Javascript
Javascript新手入门之字符串拼接与变量的应用
Dec 03 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文件中是否含有bom的函数
2012/05/31 PHP
使用PHP备份MYSQL数据的多种方法
2014/01/15 PHP
PHP实现的操作数组类库定义与用法示例
2019/05/24 PHP
JavaScript 获取用户客户端操作系统版本
2009/08/25 Javascript
file控件选择上传文件确定后触发的js事件是哪个
2014/03/17 Javascript
JS实现在线统计一个页面内鼠标点击次数的方法
2015/02/28 Javascript
JavaScript中停止执行setInterval和setTimeout事件的方法
2015/05/14 Javascript
使用AngularJS创建单页应用的编程指引
2015/06/19 Javascript
jQuery-1.9.1源码分析系列(十一)DOM操作续之克隆节点
2015/12/01 Javascript
Kotlin学习第一步 kotlin语法特性
2017/05/25 Javascript
详解jquery选择器的原理
2017/08/01 jQuery
从对象列表中获取一个对象的方法,依据关键字和值
2017/09/20 Javascript
bootstrap响应式导航条模板使用详解(含下拉菜单,弹出框)
2017/11/17 Javascript
微信小程使用swiper组件实现图片轮播切换显示功能【附源码下载】
2017/12/12 Javascript
axios的拦截请求与响应方法
2018/08/11 Javascript
解决vue2.0路由跳转未匹配相应用路由避免出现空白页面的问题
2018/08/24 Javascript
详解VS Code使用之Vue工程配置format代码格式化
2019/03/20 Javascript
通过seajs实现JavaScript的模块开发及按模块加载
2019/06/06 Javascript
TypeScript类型声明书写详解
2019/08/28 Javascript
vue-i18n实现中英文切换的方法
2020/07/06 Javascript
javascript canvas实现简易时钟例子
2020/09/05 Javascript
解决ant Design中this.props.form.validateFields未执行的问题
2020/10/27 Javascript
JavaScript中条件语句的优化技巧总结
2020/12/04 Javascript
[57:59]EG vs Secret 2018国际邀请赛淘汰赛BO3 第一场 8.22
2018/08/23 DOTA
[01:00:13]完美世界DOTA2联赛 LBZS vs Forest 第一场 11.07
2020/11/09 DOTA
Python推导式简单示例【列表推导式、字典推导式与集合推导式】
2018/12/04 Python
python for 循环获取index索引的方法
2019/02/01 Python
pyqt5 使用label控件实时显示时间的实例
2019/06/14 Python
HTML5 video视频字幕的使用和制作方法
2018/05/03 HTML / CSS
HTML5的结构和语义(2):结构
2008/10/17 HTML / CSS
Yankee Candle官网:美国最畅销蜡烛品牌之一
2020/01/05 全球购物
培训讲师岗位职责
2014/04/13 职场文书
安全月活动总结
2014/05/05 职场文书
交通安全标语
2014/06/06 职场文书
离婚协议书范文2014(夫妻感情破裂)
2014/12/14 职场文书
python opencv旋转图片的使用方法
2021/06/04 Python