编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

「JavaScript从入门到精通」JS运动中级

wxchong 2024-08-16 06:06:39 开源技术 16 ℃ 0 评论

前面我们已经掌握了很多运动相关的知识,也构造出了自己的运动框架,当然,它离真正的完成版运动框架还有很远的距离。

链式运动框架

在我们讲解链式运动框架时,我们需要讲解一下什么是回调函数。在我们之前的一个运动函数startMove中,如果我们再添加一个参数,而且该参数是一个函数,我们希望在运动结束后调用这个函数——这就是所谓的回调函数。

function startMove(obj, attr, iTarget, fnEnd){
 clearInterval(obj.timer);
 obj.timer=setInterval(function (){
 var cur=0;
 if(attr=='opacity')
 {
 cur=Math.round(parseFloat(getStyle(obj, attr))*100);
 }
 else
 {
 cur=parseInt(getStyle(obj, attr));
 }
 var speed=(iTarget-cur)/6;
 speed=speed>0?Math.ceil(speed):Math.floor(speed);
 if(cur==iTarget)
 {
 clearInterval(obj.timer);
 if(fnEnd)fnEnd();
 }
 else
 {
 if(attr=='opacity')
 {
 obj.style.filter='alpha(opacity:'+(cur+speed)+')';
 obj.style.opacity=(cur+speed)/100;
 }
 else
 {
 obj.style[attr]=cur+speed+'px';
 }
 }
 }, 30);};

在clearInterval之后,我们调用这个函数(当然这里需要判断一下函数是否被传入)。

<!DOCTYPE HTML><html>
 <head>
 <meta charset="utf-8">
 <title>无标题文档</title>
 <style>
 #div1 {width:100px; height:100px; background:red; filter:alpha(opacity:30); opacity:0.3;}
 </style>
 <script src="move.js"></script>
 <script>
 window.onload=function ()
 {
 var oDiv=document.getElementById('div1');
 oDiv.onmouseover=function ()
 {
 startMove(oDiv, 'width', 300, function (){
 startMove(oDiv, 'height', 300, function (){
 startMove(oDiv, 'opacity', 100);
 });
 });
 };
 oDiv.onmouseout=function ()
 {
 startMove(oDiv, 'opacity', 30, function (){
 startMove(oDiv, 'height', 100, function (){
 startMove(oDiv, 'width', 100);
 });
 });
 };
 };
 </script>
 </head>
 <body>
 <div id="div1"></div>
 </body></html>

效果如下:

可以看到,我们通过回调函数的嵌套实现了一个比较炫酷的伸缩展开效果——这就是一个简单的链式运动框架。

完美运动框架

到目前为止,我们学习的运动框架依然是有问题存在的:

<html>
 <head>
 <meta charset="utf-8">
 <title>无标题文档</title>
 <style>
 #div1 {width:100px; height:100px; background:red;}
 </style>
 <script src="move.js"></script>
 <script>
 window.onload=function ()
 {
 var oBtn=document.getElementById('btn1');
 var oDiv=document.getElementById('div1');
 oBtn.onclick=function ()
 {
 startMove(oDiv, 'width', 300);
 startMove(oDiv, 'height', 300);
 };
 };
 </script>
 </head>
 <body>
 <input id="btn1" type="button" value="运动" />
 <div id="div1"></div>
 </body></html>

效果如下:

可以看到,我们试图让div的宽和高同时变化,但结果而言只有高度发生了变化,原因在于两次调用函数的定时器产生了干扰,因此只有后一个startmove函数生效了。那么,我们现在的运动框架无法使好几个属性同时发生变化,应该怎么解决它呢?答案是通过json,json有一个重要用法是循环——使用for in方法进行。我们之前传入属性和属性值是通过两个参数进行的,现在我们直接传入一个json,将属性和属性值分别作为键名和键值传入,这样我们就可以同时传入好几组值了。

function startMove(obj, json, fnEnd){
 clearInterval(obj.timer);
 obj.timer=setInterval(function (){
 var bStop=true; //假设:所有值都已经到了
 for(var attr in json)
 {
 var cur=0;
 if(attr=='opacity')
 {
 cur=Math.round(parseFloat(getStyle(obj, attr))*100);
 }
 else
 {
 cur=parseInt(getStyle(obj, attr));
 }
 var speed=(json[attr]-cur)/6;
 speed=speed>0?Math.ceil(speed):Math.floor(speed);
 if(cur!=json[attr])
 bStop=false;
 if(attr=='opacity')
 {
 obj.style.filter='alpha(opacity:'+(cur+speed)+')';
 obj.style.opacity=(cur+speed)/100;
 }
 else
 {
 obj.style[attr]=cur+speed+'px';
 }
 }
 if(bStop)
 {
 clearInterval(obj.timer);
 if(fnEnd)fnEnd();
 }
 }, 30);}

通过json键值对和for in循环,我们就可以同时改变一个元素的好几个属性了。这里注意一点,原本的运动框架当属性值等于目标值时,运动就会停下来,但同时运动的时候几个运动结束的时间并不是一样的——我们应该等所有运动都结束之后再关闭定时器,因此我们建立了一个bStop变量来判断是否所有运动都到达了终点。

<html>
 <head>
 <meta charset="utf-8">
 <title>无标题文档</title>
 <style>
 #div1 {width:100px; height:100px; background:red; filter:alpha(opacity:30); opacity:0.3;}
 </style>
 <script src="move2.js"></script>
 <script>
 window.onload=function ()
 {
 var oBtn=document.getElementById('btn1');
 var oDiv=document.getElementById('div1');
 oBtn.onclick=function ()
 {
 startMove(oDiv, {width:101, height: 300, opacity: 100}, function (){
 alert('a');
 });
 };
 };
 </script>
 </head>
 <body>
 <input id="btn1" type="button" value="运动" />
 <div id="div1"></div>
 </body></html>

效果如下:

这样,这个框架既可以同时改变元素的不同属性值(通过json实现),也可以分阶段进行属性值改变(通过回调函数实现),就形成了一个比较完美的运动框架,在css2范围内,这个运动框架已经足够使用了。

到这里我们的运动框架基本就已经讲解结束了,这里为大家总结一下我们编写过的运动框架:

  • startMove(iTarget) 运动框架

  • startMove(obj, iTarget) 多物体

  • startMove(obj, attr, iTarget) 任意值

  • startMove(obj, attr, iTarget, fn) 链式运动

  • startMove(obj, json) 多值运动

  • startMove(obj, json, fn) 完美运动框架

我是石川(Blue),如果你觉得我的文章还不错,请多帮我推荐给你的朋友,多谢了。

作者简介:前阿里巴巴高级技术经理,现开课吧技术学院院长。精通C/C++、Java、Python、前端开发等多种开发技术,曾参与淘宝网的早期建设和优化,拥有丰富的企业级系统开发经验,对HTML5移动端互联网技术及生态体系有深厚的造诣。

了解更多前端知识,可以关注文章的评论。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表