JS动画函数的封装(很实用)

2 阅读1分钟

假如说你需要写一个手风琴效果的菜单。

啥啥啥啥是手风琴效果?

  • 每个菜单里有子菜单,子菜单默认是都是收起的。
  • 某个菜单点击的时候展开子菜单,再次点击可收起。
  • 展开菜单时候收起其他展开的菜单。(最多只能有一项展开

这里面的功能,和动画有关的,就是展开、收起子菜单的交互。

  • 收起的效果,是通过让子菜单的高度设置为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')
  }
})
}