使用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 相关文章推荐
Jquery下判断Id是否存在的代码
Jan 06 Javascript
js获取事件源及触发该事件的对象
Oct 24 Javascript
基于jQuery的JavaScript模版引擎JsRender使用指南
Dec 29 Javascript
简介AngularJS的HTML DOM支持情况
Jun 17 Javascript
jQuery插件实现表格隔行变色及鼠标滑过高亮显示效果代码
Feb 25 Javascript
ionic js 模型 $ionicModal 可以遮住用户主界面的内容框
Jun 06 Javascript
jQuery的Each比JS原生for循环性能慢很多的原因
Jul 05 Javascript
详解Angular中$cacheFactory缓存的使用
Aug 19 Javascript
vue axios 给生产环境和发布环境配置不同的接口地址(推荐)
May 08 Javascript
监控微信小程序中的慢HTTP请求过程详解
Jul 05 Javascript
简单了解vue中父子组件如何相互传递值(基础向)
Jul 12 Javascript
2分钟实现一个Vue实时直播系统的示例代码
Jun 05 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下使用以下代码连接并测试
2008/04/09 PHP
一周让你学会PHP 不错的学习资料
2009/02/06 PHP
PHP COOKIE设置为浏览器进程
2009/06/21 PHP
PHP实现随机数字、字母的验证码功能
2018/08/01 PHP
实例化php类时传参的方法分析
2020/06/05 PHP
PHP8.0新功能之Match表达式的使用
2020/07/19 PHP
懒就要懒到底——鼠标自动点击(含时间判断)
2007/02/20 Javascript
asp.net+jquery滚动滚动条加载数据的下拉控件
2010/06/25 Javascript
基于jQuery的Spin Button自定义文本框数值自增或自减
2010/07/17 Javascript
Javascript之旅 对象的原型链之由来
2010/08/25 Javascript
JS自定义功能函数实现动态添加网址参数修改网址参数值
2013/08/02 Javascript
利用js(jquery)操作Cookie的方法说明
2013/12/19 Javascript
window.location.href中url中数据量太大时的解决方法
2013/12/23 Javascript
jquery中map函数遍历数组用法实例
2015/05/18 Javascript
IE8利用自带的setCapture和releaseCapture解决iframe的拖拽事件方法
2016/10/25 Javascript
js异步编程小技巧详解
2017/08/14 Javascript
Mint UI 基于 Vue.js 移动端组件库
2017/11/07 Javascript
node.js自动上传ftp的脚本分享
2018/06/16 Javascript
webpack自动打包和热更新的实现方法
2019/06/24 Javascript
在Express中提供静态文件的实现方法
2019/10/17 Javascript
基于 Vue 的 Electron 项目搭建过程图文详解
2020/07/22 Javascript
JS pushlet XMLAdapter适配器用法案例解析
2020/10/16 Javascript
[00:02]DOTA2新版本使用PA至宝后暴击展示
2014/11/19 DOTA
Python的网络编程库Gevent的安装及使用技巧
2016/06/24 Python
elasticsearch python 查询的两种方法
2019/08/04 Python
几款主流好用的富文本编辑器(所见即所得常用编辑器)介绍
2021/03/17 Javascript
html Table 表头固定的实现
2019/01/22 HTML / CSS
HTML5教程之html 5 本地数据库(Web Sql Database)
2014/04/03 HTML / CSS
canvas拼图功能实现代码示例
2018/11/21 HTML / CSS
马来西亚演唱会订票网站:StubHub马来西亚
2018/10/18 全球购物
绢花、人造花和人造花卉:BLOOM
2019/08/07 全球购物
Java基础类库面试题
2013/09/04 面试题
高中军训感想800字
2014/02/23 职场文书
项目经理任命书
2014/06/04 职场文书
导游词之开封禹王台风景区
2019/12/02 职场文书
你真的会用Mysql的explain吗
2022/03/31 MySQL