页面结构
<div id="box">
<ul>
<li><img src="./images/1.jpg" alt=""></li>
<li><img src="./images/2.jpg" alt=""></li>
<li><img src="./images/3.jpg" alt=""></li>
<li><img src="./images/4.jpg" alt=""></li>
<li><img src="./images/5.jpg" alt=""></li>
</ul>
</div>
<script src="./animation.js"></script>
css
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
width: 2400px;
}
#box {
width: 1200px;
height: 400px;
border: 2px solid red;
margin: 100px auto;
overflow: hidden;
}
#box li {
width: 240px;
height: 400px;
float: left;
}
</style>
js
<script>
var box = document.querySelector('#box');//父盒子
var li = document.querySelectorAll('#box li');//图片
console.log(li);
// 鼠标移入事件
for (var i = 0; i < li.length; i++) {
// 给每一个li注册事件
li[i].onmouseover = function () {
for( var j=0;j<li.length;j++){
if(li[j]==this){
animationslow(li[j],{width:800})
}else{
animationslow(li[j],{width:100})
}
}
}
}
// 鼠标移出
box.onmouseout=function(){
for( var i=0;i<li.length;i++){
animationslow(li[i],{width:240})
}
}
</script>
js 缓动动画封装
function animationslow(ele, attrs, fn) {
// 1 清除上一次定时器
clearInterval(ele.timeID);
ele.timeID = setInterval(function () {
// 提出假设
var isOK = true;
for (var key in attrs) {
// 这边只需要把对象的属性名 和属性值 赋值给attr 和target 就不需要在去修改了
var attr = key; //把对象的属性名赋值给attr
var target = attrs[key];//把对象属性值赋值给target
//从这里开始需要做一个判断 判断这一次的属性是否为透明度 如果是透明度直接赋值 ,不走加px的环节
if (attr == 'opacity') {
//但是这边不是给直接量 需要动画来过渡赋值
// ele.style[attr] = 0.5;
//因为透明度通常是小数 如果用取整的话 不会改变 所以 我们需要去小数
var current = parseFloat(getComputedStyle(ele)[attr]);
// 这边因为编程语言的通病 小数点精度丢失 所以需要放大100倍
current *= 100;
target *= 100;
// 3计算每一次移动距离
var step = (target - current) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
//开始移动
current += step;
//这里需要注意 不能忘了除以100 将小数点恢复原状
ele.style[attr] = current / 100;
} else if (attr == 'zIndex') {
// 层级直接赋值
ele.style[attr] = target;
} else {
// 2 获取元素属性 此时属性值就不能写死 因为是用户传递过来的数据 获取的元素是字符串 需要转换数字类型
var current = parseInt(getComputedStyle(ele)[attr]);
// 3计算每一次移动距离
var step = (target - current) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
// 4开始移动
current += step;
// 这边需要修改修改的属性也是用户传递过来的
ele.style[attr] = current + 'px';
// 5终点检测 这边的检测就不写死 需要检测所有的属性值
if (current != target) {
isOK = false;
}
}
}
//这边需要写在外面 因为当所有的属性值判断完成才能停止定时器
if (isOK) {
clearInterval(ele.timeID);
// 需要在动画执行完毕之后执行 所以需要写在动画执行完毕之后的代码里面
// fn();但是我们还需要做一个判断 ,判断用户是否输入了动画完毕之后,要执行的代码
if (typeof fn == 'function') {//需要判断用户输入的是否需要执行的一段代码体
fn();
};
}
}, 30)
}