• 阿成
    2019-04-20
    const tweenFns = {
      linear: (from, to, t, d) => from + (to - from) * (t / d)
    }

    /**
     * only support "linear" timing-function
     * duration unit is "ms"
     * @param {HTMLElement} el
     * @param {({prop: String, value: String, duration: Number})[]} list
     */
    function transitionTo(el, list) {
      let startTime
      let oldStyle = new Map()
      let newStyle = new Map()
      for (let prop of list) {
        oldStyle.set(prop.name, window.getComputedStyle(el)[prop.name])
      }
      for (let prop of list) {
        el.style[prop.name] = prop.value
      }
      for (let prop of list) {
        newStyle.set(prop.name, window.getComputedStyle(el)[prop.name])
      }
      for (let prop of list) {
        el.style[prop.name] = oldStyle.get(prop.name)
      }


      requestAnimationFrame(run)

      function run(time) {
        if (startTime == null) startTime = time
        let t = time - startTime
        let done = true
        for (let prop of list) {
          if (t >= prop.duration) {
            el.style[prop.name] = newStyle.get(prop.name)
            continue
          }
          done = false
          let oldPropValue = oldStyle.get(prop.name)
          let newPropValue = newStyle.get(prop.name)
          if (prop.name === 'transform') {
            if (oldPropValue === 'none') oldPropValue = 'matrix(1, 0, 0, 1, 0, 0)'
            if (newPropValue === 'none') newPropValue = 'matrix(1, 0, 0, 1, 0, 0)'
          }
          el.style[prop.name] = generateNewStyle(oldPropValue, newPropValue, t, prop.duration, tweenFns.linear)
        }
        if (!done) requestAnimationFrame(run)
      }
    }

    function generateNewStyle(from, to, t, duration, tweenFn) {
      let fromExp = /[\d.-]+/g
      let toExp = /[\d.-]+/g
      let fromMatch
      let toMatch
      let result = ''
      let lastIndex = 0
      while (fromMatch = fromExp.exec(from)) {
        result += from.slice(lastIndex, fromMatch.index)
        toMatch = toExp.exec(to)
        result += tweenFn(+fromMatch[0], +toMatch[0], t, duration)
        lastIndex = fromExp.lastIndex
      }
      result += from.slice(lastIndex)
      return result
    }
    展开
     1
     14
  • 阿成
    2019-04-20
    跟CSS的transition比,JS更加偏向指令式,而CSS更加偏向声明式,当然,这本身也是两门语言自身的特点,CSS用法简单直观,JS则在控制方面有更大的灵活性。

    上面我只实现了 linear timing function(其他的函数实现网上大把大把的...),具体用法如下:
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
      <style>
        #ball {
          width: 100px;
          height: 100px;
          background: blue;
        }
      </style>
    </head>
    <body>
      <div id="ball"></div>

      <script src="transition.js"></script>
      <script>
        transitionTo(document.getElementById('ball'), [
          {name: 'transform', duration: 1000, value: 'translate(400px, 200px) rotate(40deg)'},
          {name: 'backgroundColor', duration: 1000, value: 'red'},
          {name: 'width', duration: 1000, value: '200px'},
          {name: 'height', duration: 1000, value: '200px'}
        ])
      </script>
    </body>
    </html>
    展开
    
     11
  • 许童童
    2019-04-20
    这个课后练习有点难啊。希望老师可以带着大家过一遍。
    
     3
  • geekdocs.cn
    2019-09-27
    一脸懵逼状态看完的~
     1
     1
我们在线,来聊聊吧