先上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
width: 100px;
height: 100px;
background-color: red;
margin-bottom: 50px;
opacity: 0.2;
}
</style>
</head>
<body>
<header>
<div></div>
<div></div>
<div></div>
<div></div>
</header>
<script>
// 获取header元素
header = document.querySelector('header')
// 设置鼠标移入时的事件
header.onmouseover = function (e) {
if (e.target.tagName == 'DIV'){
startMove(e.target,{
height: 500,
width: 500,
// 这里要注意将透明度乘以100
opacity: 100
})
}
}
// 设置鼠标移出时的事件
header.onmouseout = function (e) {
if (e.target.tagName == 'DIV'){
startMove(e.target,{
height: 100,
width: 100,
opacity: 20
})
}
}
function startMove(dom, attrObj){
// 将速度设置在定时器外部,因为达到缓冲效果,需要速度不停变化
var speed = null
// 为了不同dom之间的定时器互不干扰,给dom添加定时器属性
// 某个定时器只属于某个dom
clearInterval(dom.timer)
dom.timer = setInterval(function(){
// 设置定时器的锁,用于判断是否清除定时器
var bStop = true
// 遍历attrObj 将对象中的每一个属性进行运动
for (var attr in attrObj) {
//判断属性是否是透明度 分开获取样式属性
if (attr == 'opacity'){
// 使透明度变化更明显,不然下面取整时一下就到1,没有缓冲的效果
var iCur = parseFloat(window.getComputedStyle(dom).opacity) * 100
}else{
// 获取当前最终样式的属性
var iCur = parseFloat(window.getComputedStyle(dom)[attr])
}
// 求出速度 变化步长
// 此速度随着目标属性值与当前属性值的接近速度会越来越小,
// 达到缓冲的效果,不是7也可以,随便除以一个数字即可
speed = (attrObj[attr] - iCur) / 7
// 向远离0的方向取整,因为随目标属性值与当前属性值接近
// speed趋近于零点几,此时如果向靠近0的方向取整,
// 虽然看似效果达到了但会引发一个问题。
// 比如说speed = 0.1时,同时当前属性值与目标属性值还不相等时,
// Math.floor(speed) = 0,dom.style[attr] = iCur + 0 + 'px',
// 当前属性值与目标属性值永远不会相等
// 也就是说下面的锁会不关,导致dom中的定时器一直运行,占用内存。
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed)
// 分别对透明度和其他样式进行改变
if (attr == 'opacity'){
// 改变透明度时要除以100使其重新变成小数
dom.style.opacity = (iCur + speed) / 100
}
else{
// 其他属性不要忘记加px拼接字符串
dom.style[attr] = iCur + speed + 'px'
}
// 当前属性值不等于目标属性值时,关锁,使定时器继续工作
if (iCur != attrObj[attr]) {
bStop = false
// console.log(1)
}
}
// 一旦当前属性值等于目标属性值,bStop为true,锁开着,才能清除定时器
if (bStop) {
clearInterval(dom.timer)
}
},30)
}
</script>
</body>
</html>
设置4个div盒子,设置宽高,颜色及透明度,利用javascript使其宽高及透明度属性缓冲变化。实现过程注释里写的很清楚,这里只说一点:如果设置了锁,开锁和关锁的条件需仔细斟酌,要不然可能会出现该开的时候不开,该关的时候关不上的情况。此例需要注意的地方就是缓冲速度speed的取整问题,向远离0的方向取整才能恰当地关锁,清除定时器。