wangbinyq / personal-wiki

2 stars 0 forks source link

How to write an anime library #22

Open wangbinyq opened 6 years ago

wangbinyq commented 6 years ago

The engine

We need a mechanism to deal with layout thrashing. So we have an engine that group all animations into to a requestAnimationFrame callback.

const engine = (function () {
  let animations = {}
  let raf = 0

  function play () { raf = requestAnimationFrame(step) }
  function step () { animations.forEach((anim) => anim.step()); if (animations.length) play() }
  function add (anim) { animations.push(anim) }
  function remove (anim) { const index = animations.indexOf(index); animations.splice(index, 1) }

  return {
    play, step, add, remove, raf
  } 
})()

The tween and animation

A tween object repersent a property change. It is an object like this:

const defaultTweenSetting = {
  target: Element,
  property: string,
  duration: number,
  easing: Function,
  from: number,
  to: number,
  unit: string
}

This object can describe what to be change (target, property), how long it will last (duration), how does the chnage looks like (easing), and the start and end value (from, to and unit).

An animation object group list of tweens and play the real animation by add it self to the engine and step the tween.

class Animation {
  constructor (tweens) {
    this.tweens
  }

  step (now) {
    let elapsed = 0
    if (!this.startTime) {
       this.startTime = now
    }
    const elapsed = now - this.startTime
    finisheds = this.tweens.map((tween) => {
      const process = Math.min(1, elapsed / tween.duration)
      const eased = tween.easing(process)
      const value = tween.from + (tween.to - tween.from) * eased
      tween.target.style[tween.property] = value + tween.unit
      if (process >= 1) {
        return true
      }
    })
    if (finisheds.every((f) => f)) {
       this.pause()
    }
  }

  play () {
    engine.add(this)
  }
  pause () {
    engine.remove(this)
  }
  restart () {
    this.pause()
    this.startTime = 0
    this.play()
  }
}

The Libraries

Now we have engine, tween and Animtaion. Use those object or class you can build some style animatons you what to. But it's not enough, we need construct the tweens ourself and we only support css style property animation. There are some realy awesome animation libraries exist:

Others

Unit transfrom

  1. jquery.adjustCSS: calculate the scale between current unit and the excepted unit, then apply the new united value.
  2. velocityjs:
    if (fromUnit !== toUnit) {
    currentValue = `calc(${from * (1 - eased) + fromUnit} + ${to * eased + toUnit})`
    }