第十节 JS运动中级

时间:2024-06-10 19:04:20

链式运动框架、

  回调函数

    运动停止时,执行函数

    运动停止时,开始下一次运动

<!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);
}

32.js

    例子:土豆天气预报弹窗(已下架)    由于图片没有调好就没有写,有兴趣可根据上述代码自行写出

完美运动框架

  多个值同时变化(首先是出错情况)

<!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, {width: 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, {width: 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

  说“33.js”是一个完美运动框架,那是因为在一般应用情况下,该运动框架是不会出现什么错误,但是若我们把“startMove(oDiv, {width: 300, height: 300, opacity: 100});”改为“startMove(oDiv, {width: 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, {width: 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);
}

33-1.js

  检测运动停止(标志变量)    例子:伸缩同时淡入淡出的菜单,如上

运动框架总结:

  运动框架的演变过程:

    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>