原生JS实现元素的多值运动
原生JS实现元素的多值运动。
在介绍JS运动内容时,我们陆续介绍了简单的运动,图片透明度运动,摩擦运动和缓冲运动。这些运动基本上都是一个元素的单一运动。如果在一个元素身上同时发生两种运动形式呢?应该比如当鼠标点击元素时,元素的宽和高同时发生改变,或者先改变元素的宽,再改变元素的高,发生在一个元素上的这种运动形式就叫多值运动,应该如何操作?
1、当改变的宽高距离一样
在同一时间内,元素的宽高改变是一样值的时候,这个时候可以一起运动。但是同时改变宽和高,按理来说我们要用到数组,但数组不好调用。如果将两个宽高运动拆开来运动,下面的定时器会清除掉上面的定时器。我们考虑用JSON来操作。直接调用函数的形式来操作。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>无标题文档</title>
<style>
#div1 {width:100px; height: 100px; background: red; position: absolute; left: 0px; top: 30px; left: 400px;}
</style>
<script>
window.onload = function() {
var oDiv1 = document.getElementById('div1');
//用JSON方式调用函数
oDiv1.onclick = function() {
startMove(this, {
width : 200,
height: 200
}, 10);
}
function startMove(obj, json, iSpeed) {
clearInterval(obj.iTimer);//开始清除定时器
var iCur = 0;
obj.iTimer = setInterval(function() {
for ( var attr in json ) {
var iTarget = json[attr];
if (attr == 'opacity') {
iCur = Math.round(css( obj, 'opacity' ) * 100);
} else {
iCur = parseInt(css(obj, attr));
}
if (iCur == iTarget) {
clearInterval(obj.iTimer);
} else {
if (attr == 'opacity') {
obj.style.opacity = (iCur + iSpeed) / 100;
obj.style.filter = 'alpha(opacity='+ (iCur + iSpeed) +')';
} else {
obj.style[attr] = iCur + iSpeed + 'px';
}
}
}
}, 30);
}
function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
如果改变的宽高是不一样的值会发生什么呢?在同一时间内,如果宽高改变的值不一样,那么改变的最长的那边将不会达到目标,运动就会停止。
2、当改变的宽高不一致时
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>无标题文档</title>
<style>
#div1 {width:100px; height: 100px; background: red; position: absolute; left: 0px; top: 30px; left: 400px;}
</style>
<script>
window.onload = function() {
var oDiv1 = document.getElementById('div1');
oDiv1.onclick = function() {
startMove(this, {
width : 200,
height: 300
}, 10);
}
function startMove(obj, json, iSpeed) {
clearInterval(obj.iTimer);
var iCur = 0;
obj.iTimer = setInterval(function() {
var iBtn = true;
for ( var attr in json ) {
//什么时候停止定时器?所有属性都运动到了目标点的时候
var iTarget = json[attr];
if (attr == 'opacity') {
iCur = Math.round(css( obj, 'opacity' ) * 100);
} else {
iCur = parseInt(css(obj, attr));
}
if (iCur != iTarget) {
iBtn = false;
if (attr == 'opacity') {
obj.style.opacity = (iCur + iSpeed) / 100;
obj.style.filter = 'alpha(opacity='+ (iCur + iSpeed) +')';
} else {
obj.style[attr] = iCur + iSpeed + 'px';
}
}
}
//在这里来看下,所有属性是不是都到了目标点
if (iBtn) {
clearInterval(obj.iTimer);
}
}, 30);
}
function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
上面两个例子都是宽高一起运动,如果宽高改变值不一致的情况下,先一起运动,高再继续运动。如果我们想要先改变宽度,当宽度到达目标点后,再改变高度值,如何操作呢?
3、先改变宽度值,再改变高度值
那我们需要调用两次函数,先改变宽度值,然后再改变高度值。其余的原理,运动过程都差不多,只是在最后停止定时器的时候,为了兼容性问题,要用到IE下的call()属性
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>无标题文档</title>
<style>
#div1 {width:100px; height: 100px; background: red; position: absolute; left: 0px; top: 30px; left: 400px;}
</style>
<script>
window.onload = function() {
var oDiv1 = document.getElementById('div1');
oDiv1.onclick = function() {
startMove(this, {
width : 200
}, 10, function() {
startMove(this, {
height : 200
}, 10);
});
}
function startMove(obj, json, iSpeed, fn) {
clearInterval(obj.iTimer);
var iCur = 0;
obj.iTimer = setInterval(function() {
var iBtn = true;
for ( var attr in json ) {
var iTarget = json[attr];
if (attr == 'opacity') {
iCur = Math.round(css( obj, 'opacity' ) * 100);
} else {
iCur = parseInt(css(obj, attr));
}
if (iCur != iTarget) {
iBtn = false;
if (attr == 'opacity') {
obj.style.opacity = (iCur + iSpeed) / 100;
obj.style.filter = 'alpha(opacity='+ (iCur + iSpeed) +')';
} else {
obj.style[attr] = iCur + iSpeed + 'px';
}
}
}
if (iBtn) {
clearInterval(obj.iTimer);
fn && fn.call(obj);
}
}, 30);
}
function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>