假如说你需要写一个手风琴效果的菜单。
啥啥啥啥是手风琴效果?
- 每个菜单里有子菜单,子菜单默认是都是收起的。
- 某个菜单点击的时候展开子菜单,再次点击可收起。
- 展开菜单时候收起其他展开的菜单。(最多只能有一项展开)
这里面的功能,和动画有关的,就是展开、收起子菜单的交互。
- 收起的效果,是通过让子菜单的高度设置为0。
- 展开的效果,是通过让子菜单的高度从0,设置到目标高度。
但是收起和展开,不能是一瞬间完成,否则就会看起来很生硬,这就需要用到动画效果。
因此可以封装一个工具函数,让我们很方便的开发动画效果。
动画的本质,是让某个数据从初始值逐渐变化到目标值。
是让一个大变化拆分成很多个小步来执行,一次变化一点,从而形成连贯的感觉。
function animate(option) {
var from = option.from //初始值
var to = option.to //目标值
var totalDuration = option.totalDuration || 500 //动画总持续时间
var singleDuration = option.singleDuration || 10 //单步持续时间
var onAnimate = option.onAnimate //单步动作内容(要干的事情)
var onEnd = option.onEnd //动画结束回调
var currentValue = from //当前值
var totalSteps = Math.floor(totalDuration / singleDuration) //总需步数
var currentStep = 0 //当前步数
var distance = to - from //总变化值
var singleStepDistance = distance / totalSteps //单次变化值
var timerId = setInterval(() => {
currentStep++
if (currentStep < totalSteps) {
currentValue += singleStepDistance
} else {
currentValue = to
clearInterval(timerId)
onEnd()
}
onAnimate && onAnimate(currentValue)
}, singleDuration);
}
封装好了,可以这样使用:
function openMenu(submenu) {
animate({
from: 0,
to: submenu.children[0].clientHeight * submenu.children.length,
totalDuration: 200,
singleDuration: 10,
onAnimate: function (value) {
submenu.style.height = value + 'px'
},
onEnd: function () {
submenu.setAttribute('status', 'opened')
}
})
}