链式运动框架、
回调函数
运动停止时,执行函数
运动停止时,开始下一次运动
<!DOCTYPE html> <html lang="en"> <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="32.js"></script> <script> window.onload = function(){ var oDiv = document.getElementById('div1'); //链式运动——收缩展开运动 oDiv.onmouseover = function(){ startMove(oDiv, 'width', 300, function(){ // alert('宽度已变大!'); startMove(oDiv, 'height', 300, function () { startMove(oDiv, 'opacity', 100); }); }); }; oDiv.onmouseout = function(){ startMove(oDiv, 'opacity', 30, function(){ // alert('宽度已变大!'); startMove(oDiv, 'height', 100, function () { startMove(oDiv, 'width', 100); }); }); }; }; </script> </head> <body> <div id="div1"></div> </body> </html>
function getStyle(obj, name) {
if (obj.currentStyle) {
return obj.currentStyle[name];
} else {
return getComputedStyle(obj, false)[name];
}
}
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); //乘以100符合咱们平时对opacity的设置
} 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)+')'; //IE透明度
obj.style.opacity = (cur+speed)/100;
var oTxt = document.getElementById('txt1');
oTxt.value = obj.style.opacity;
} else {
obj.style[attr] = cur+speed+'px';
}
}
}, 30);
}
例子:土豆天气预报弹窗(已下架) 由于图片没有调好就没有写,有兴趣可根据上述代码自行写出
完美运动框架
多个值同时变化(首先是出错情况)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>运动框架小问题</title> <style> #div1{width: 100px; height: 100px; background: red; } </style> <script src="32.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); }; //问题来了,如果不加此句“startMove(oDiv, 'height', 300);” 则div变宽,好像没什么问题; //但是如果加上此句“startMove(oDiv, 'height', 300);” div只变长了,而未变宽,所以也就是说, //不能让多个值同时变化,否则会出错,解决办法是:用json循环来修改运动框架 }; </script> </head> <body> <input id="btn1" type="button" value="运动"/> <div id="div1"></div> </body> </html>
setStyle同时设置多个属性
参数传递:JSon的使用,for in遍历属性
var json = {a:12, b:5};
for (var i in json){ //json循环
alert(i+'='+json[i]);
}
运用到运动框架
<!DOCTYPE html> <html lang="en"> <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="33.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); startMove(oDiv, { 300, height: 300, opacity: 100}); //此时长和宽是同时运动的 }; //问题来了,如果不加此句“startMove(oDiv, 'height', 300);” 则div变宽,好像没什么问题; //但是如果加上此句“startMove(oDiv, 'height', 300);” div只变长了,而未变宽,所以也就是说, //不能让多个值同时变化,否则会出错,解决办法是:用json循环来修改运动框架,解决如上 }; </script> </head> <body> <input id="btn1" type="button" value="运动"/> <div id="div1"></div> </body> </html>
function getStyle(obj, name) { if (obj.currentStyle) { return obj.currentStyle[name]; } else { return getComputedStyle(obj, false)[name]; } } //32.js的改进版,json循环的使用 //startMove(oDiv, { 400, height: 400}) function startMove(obj, json, fnEnd) { clearInterval(obj.timer); obj.timer = setInterval(function () { for (var attr in json) { var cur = 0; if (attr == 'opacity') { cur = Math.round(parseFloat(getStyle(obj, attr))*100); //乘以100符合咱们平时对opacity的设置 } 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]) { clearInterval(obj.timer); if (fnEnd) fnEnd();//当参数传进来且运动结束后被调用 } else { if (attr == 'opacity') { obj.style.filter = 'alpha(opacity:'+(cur+speed)+')'; //IE透明度 obj.style.opacity = (cur+speed)/100; var oTxt = document.getElementById('txt1'); oTxt.value = obj.style.opacity; } else { obj.style[attr] = cur+speed+'px'; } } } }, 30); }
说“33.js”是一个完美运动框架,那是因为在一般应用情况下,该运动框架是不会出现什么错误,但是若我们把“startMove(oDiv, { 300, height: 300, opacity: 100});”改为“startMove(oDiv, { 101, height: 300, opacity: 100});”也就是说,宽度只增加一个像素,高度仍然增加200像素,此时运行时,高度的增加会出现一些小错误,即不会增加到300px,原因是,系统不会自己搜索每个状态是不是已经达到目标值,而是只要有一个达到目标值,系统就把定时器关掉了,所以才会出现错误,改进方法如下:(其中改进版的“33-1.js”,才是真正意义上的完美运动框架)
<!DOCTYPE html> <html lang="en"> <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="33-1.js"></script> <script> window.onload = function(){ var oBtn = document.getElementById('btn1'); var oDiv = document.getElementById('div1'); oBtn.onclick = function () { startMove(oDiv, { 101, height: 300, opacity: 100}, function () { //此时长、宽和透明度同时运动 alert("定时器已全部关闭!"); //该函数是检验程序是否运行完成的。 }); }; }; </script> </head> <body> <input id="btn1" type="button" value="运动"/> <div id="div1"></div> </body> </html>
function getStyle(obj, name) { if (obj.currentStyle) { return obj.currentStyle[name]; } else { return getComputedStyle(obj, false)[name]; } } 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); //乘以100符合咱们平时对opacity的设置 } 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 (cur==json[attr]) { // clearInterval(obj.timer); // // if (fnEnd) fnEnd();//当参数传进来且运动结束后被调用 // } else { // 改进提前关定时器的代码如下,先把之前关定时器的代码注释掉 if (attr == 'opacity') { obj.style.filter = 'alpha(opacity:'+(cur+speed)+')'; //IE透明度 obj.style.opacity = (cur+speed)/100; } else { obj.style[attr] = cur+speed+'px'; } obj.style[attr] = cur+speed+'px'; // } } if (bStop) { //如果bStop还是保持为true的话 clearInterval(obj.timer); if (fnEnd) fnEnd(); } }, 30); }
检测运动停止(标志变量) 例子:伸缩同时淡入淡出的菜单,如上
运动框架总结:
运动框架的演变过程:
startMove(iTarget) 运动框架 //学习入门
startMove(obj, iTarget) 多物体 //多出的参数“obj”可以任意指定让那个物体动起来
startMove(obj, attr, iTarget) 任意值 //可以任意指定一个物体动起来
startMove(obj, attr, iTarget, fn) 链式运动 //参数“fn”为当 前一次 运动结束之后,我们可以用“fn”再做一次运动
startMove(obj, json) 多值运动 //可以把多个值同时运动
startMove(obj, json, fn) 完美运动框架 //可以多值、多物体同时运动了
运动框架应用:
例:幻灯片
思想是:overflow=hidden,当显示 第0张图片时,top=0;当显示第1张图片时,第0张的top=-150;……当显示第n张图片时,第0张的top=-150*n;
链式运动:新浪微博
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>li淡出淡入</title> <style> *{margin: 0; padding: 0;} #ul1{ width: 400px; height: 400px; border: 1px solid black; margin: 10px auto; overflow: hidden; } #ul1 li{ border-bottom: 1px #999 dashed; padding: 4px; list-style: none; overflow: hidden; filter: alpha(opacity:0); opacity: 0; } </style> <script src="33-1.js"></script> <script> window.onload = function () { var oBtn = document.getElementById('btn1'); var oUl = document.getElementById('ul1'); var oTxt = document.getElementById('txt1'); oBtn.onclick = function () { var oLi = document.createElement('li'); oLi.innerHTML = oTxt.value; oTxt.value = ''; if (oUl.children.length>0){ oUl.insertBefore(oLi, oUl.children[0]); } else { oUl.appendChild(oLi); } //运动 var iHeight = oLi.offsetHeight; //先让高度展开 oLi.style.height = '0'; //链式运动的应用 startMove(oLi, {height: iHeight}, function () { //先是高度展开,然后淡出 startMove(oLi, {opacity: 100}); }); }; }; </script> </head> <body> <textarea id="txt1" rows="4" cols="40"></textarea> <button id="btn1">发布</button> <ul id="ul1"> <li>asldfjkba</li> </ul> </body> </html>