JavaScript —— 实现 对象 匀速/变速运动
实例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 } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库