首先是对只改变单个运动框架进行封装
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
<style>
*{
margin: 0;
padding: 0;
}
#box{
width: 200px;
height: 200px;
background-color: #020202;
/*transition: 2s;*/
}
/*#box:hover {
width: 400px;
}*/
</style>
</head>
<body>
<div id="box"></div>
<script>
/*
让box的宽度从200px变到400px 所用时间为2s
*/
var oBox = document.getElementById('box');
// console.log(oBox);
//功能是让dom的attr属性从初始位置运动到target位置所用时间为time
function animation(dom,attr,target,time) {
//计算速度 (终点位置-起点位置)/ 时间 距离/时间 = 速度
/*
var speed = (target - getStyle(dom.width))/2 不能直接计算速度,getstyle函数获取到的数据是字符串,animation函数传入的值为数字,相减得到NaN,需要对getstyle获取到的数据进行处理,将字符串转化为数字
对获取到的字符串进行数据类型转化,将其变为数字,同时宽度可能出现小数点,因此采用parsefloat方法
*/
//存放初始属性值
var start = parseFloat(getStyle(dom,attr));
var speed = (target - start)/(time*1000); //time单位为m,为了与下面时间戳相减得到的时间进行单位统一,将s*1000得到ms
/*如何利用js改变元素的宽度?利用定时器每隔一段时间改变元素的宽度即可
需要的得到元素运动到任意时刻的位置
start + speed*(movedTime-startTime)
开始的位置+速度*已经运动的时间-起始运动的时间
*/
var startTime = new Date(); //利用时间戳获取dom运动的初始时间
// 回调函数的作用是让dom元素运动
var timer = setInterval (function () {
var movedTime = new Date();//每隔100ms获取一次元素已经开始运动的最新时间
var _t = movedTime - startTime; // 利用变量存储时间差值 时间戳相减单位是ms
//使用行内样式表设置dom的属性
dom.style[attr] = start + speed * _t + 'px';
// 方法一 对变化位置进行判断,当变化的距离大于传入的target时,清除定时器
// if(parseFloat(getStyle(dom,attr))>=target)
// {
// clearInterval(timer);
// dom.style[attr] = target + 'px'; //强制让元素等于终点值
// }
// },5)
// 方法二 对变化时间进行判断,变化时间差值大于传入的time时,清除定时器
if(_t/1000>=time)
{
clearInterval(timer);
dom.style[attr] = target + 'px'; //强制让元素等于终点值
}
},5)
//获取元素的初始值
function getStyle(dom,attr) {
// 做兼容
if (dom.currentStyle) { //如果是IE8以下
return dom.currentStyle[attr]
}else{ //IE8以上
return window.getComputedStyle(dom,null)[attr]
}
}
//console.log(getStyle(oBox,'width'));
}
animation(oBox,'width',400,2);
//如果想要改变多个属性,需要写多行代码进行改变
//animation(oBox,'height',400,2);
</script>
</body>
</html>
对多个属性同时进行改变
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
<style>
*{
margin: 0;
padding: 0;
}
#box{
width: 100px;
height: 100px;
background-color: #020202;
/*transition: 2s;*/
opacity: 0.5;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
/*
让box的多个css属性从初始值变化到终点值 所用的时间为2s
*/
var oBox = document.getElementById('box');
//获取元素的数值
function getStyle(dom,attr) {
if(dom.currentStyle){ //如果IE8以下
return dom.currentStyle[attr]
}else { //IE8以上
return window.getComputedStyle(dom,null)[attr];
}
}
function animation(dom,target,time,callBack) {
//遍历对象,attr是对象的属性名
var start = {}; //创建空对象存放dom样式的初始值
var speed = {}; //存放dom元素的速度
for(var attr in target){
start[attr] = parseFloat(getStyle(dom,attr)); //遍历对象将初始值存入新对象中,获取到的数据为字符串,用parseFloat将其转化为数字
speed[attr] = (target[attr] - start[attr]) /(time*1000); //变化距离-原始距离 / 时间 target[attr]为传入参数中的值
}
//console.log(start)
var startTime = new Date(); //获取dom运动的初始时间
var timer = setInterval( function () {
var movedTime = new Date();//每隔100ms获取一次元素已经开始运动的最新时间
var _t = movedTime - startTime; // 利用变量存储时间差值 时间戳相减单位是ms
for(var attr in target) {
if (attr==='opacity') {
dom.style[attr] = start[attr] + speed[attr]*_t;
}else{
dom.style[attr] = start[attr] + speed[attr]*_t+'px';
}
}
// 方法一 对变化位置进行判断,当变化的距离大于传入的target时,清除定时器
// if(parseFloat(getStyle(dom,attr))>=target)
// {
// clearInterval(timer);
// dom.style[attr] = target + 'px'; //强制让元素等于终点值
// }
// },5)
// 方法二 对变化时间进行判断,变化时间差值大于传入的time时,清除定时器
if(_t/1000>=time)
{
clearInterval(timer);
for(var attr in target){
if (attr==='opacity') {
dom.style[attr] = target[attr];
}else{
dom.style[attr] = target[attr]+'px';
}
//强制让元素等于终点值
}
//当运动到终点值的时候执行回调函数
callBack&&callBack.call(dom,start,time); //&&找假,写回调函数就会执行后面的,不写就会走前面的
}
},time)
}
animation(oBox,{
width:250,
height:250,
opacity:1
},1,function (start,time) {
// 这个回调函数的功能是回到初始位置
// animation(dom,start,time)
animation(this,start,time,function(){//当回到初始位置之后执行回调函数 让dom的颜色变红
this.style.backgroundColor = 'red';
});
});
</script>
</body>
</html>