要点:
1.原来想写animate()的多态形式的,写到一半想起来,js不需要在声明变量时就声明数据类型,无法完成多态的性质,可以通过曲线方法完成多态效果,以后再说。
2.getComputerStyle计算样式属性,可以将setoff系列没能获取到的样式属性获取出来,getComputerStyle能返回所调用对象的所有样式键值对,形成一个样式对象
3.这个例子中有原来可以改变一个参数,到后面通过对象改变多个参数,理解对象即为键值对的意义,同时理解var-in遍历对象的
4.通过这个案例,里面有改变一个属性的动画函数,里面改变元素的样式的left用的是 ["字符串" ]方式来获取属性,因为字符串可以是变量,而点语法获取属性要是固定属性,不能是变量。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
input{
margin-top: 20px;
}
div{
margin-top: 30px;
width: 225px;
height: 175px;
background-color: #6D1F9B;
position: absolute;
/*一定要是相对定位,不然写的移动的位置不能改变而显示出来*/
}
</style>
</head>
<body>
<input type="button" value="移动!" id="btn1">
<input type="button" value="变变变" id="btn2">
<div id="div"></div>
<script type="text/javascript">
function myGet(id){
return document.getElementById(id);
}
myGet("btn1").onclick = function(){
animate2(myGet("div"),"top",500);
}
myGet("btn2").onclick = function(){
animate(myGet("div"),{"top":200,"width":500,"height":500,"left":500,"opacity":0.3},function(){
animate(myGet("div"),{"top":100,"width":200,"height":200,"left":100,"opacity":0.9})});
}
function getStyle(element,attr){
return window.getComputedStyle ? window.getComputedStyle(element,null)[attr]
: element.currentStyle[attr];
// 将原来的if-else语句进行判断也兼容代码的方式,进行简化,写成三目运算符的方式
// 属性后面的[attr]是跟点语法的作用是一样的,但是这里不能使用点语法获取attr的对象属性,因为attr是变量只有用[]接收不同类型字符串
// 获取的计算后的样式都是带有单位的
}
function animate2(element,attr,target){
clearInterval(element.intervalName);
// 每次点击移动按钮的时候,清理定时器,将原来的定时器清理掉,不然会叠加多线程多个定时器,加快速度
element.intervalName = setInterval(function(){
var current = parseInt(getStyle(element,attr));
// 通过getStyle()获取的是带有单位的属性值,通过parseInt转换成值类型,不用number()是因为转换过后的可能是nun
var step = 80;
// 每次增加80像素
step = current<target?step:-step;
// 判断是在目标的左边还是右边,从而判断是前进还是后退
current += step;
if(Math.abs(target-current)>Math.abs(step)){
element.style[attr] = current + "px";
}else{
clearInterval(element.intervalName);
element.style[attr] = target + "px";
// 当执行到最后一步时,如果不满增加的长度,而再一次执行时,而又超过目标像素的距离,
// 所以设置直接一步到目标距离,而不会
}
},300)
}
function animate(element,json,fn){
clearInterval(element.intervalName);
// 清理定时器
element.intervalName = setInterval(function(){
var flag = true;
// 哈哈哈,又是这个,因为遍历for循环遍历有先后顺序,要都到达指定位置才能清理计时器
for(var attr in json){
if(attr == "zIndex"){
// css中的属性中间是连字符的属性,在js操作中,将下划线去掉同驼峰原则
// 层级的操作,直接赋值即可不需要其他的操作
element.style[attr] = json[attr];
}else if(attr == "opacity"){
var current = getStyle(element,attr)*100;
var target = json[attr]*100;
// 将attr对应的值获取到,直接通过对象的键值获取,这个参数没有单位直接获取值
var step = (target - current)/10;
step = step>0 ? Math.ceil(step) : Math.floor(step);
current += step;
element.style[attr] = current/100;
// 透明度不需要其他的参数,前面放大100倍,变回来
}else{
// 其他不同的属性
// 遍历json数组对象,每次将遍历的数组对象属性进行设置
var current = parseInt(getStyle(element,attr));
var target = json[attr];
// 将attr对应的值获取到,直接通过对象的键值获取
var step = (target - current)/10;
// 将从当前位置到目标距离走十分之一
step = step>0 ? Math.ceil(step) : Math.floor(step);
// Math.ceil()和Math.floor()分别是向上和向下取整
current += step;
element.style[attr] = current + "px";
}
if(current != target){
flag = false;
// 也是类似于多线程,只有每个都为true才能到达指定位置
}
}
if(flag){
clearInterval(intervalName);
// 所有的动画执行完成之后,可以再执行一个函数
if(fn){
fn();
}
// 这里调用的函数,也可以是本身这个函数,还可以 进行多次动画
}
},300)
}
</script>
</body>
</html>
效果: