Научил писать анимацию на js

внешний интерфейс JavaScript

Научу вас писать js анимацию

peek 2018-10-18 02-19

Я считаю, что все должны быть незнакомы с этим эффектом цифровой градиентной анимации. Далее разберем, как реализовать эту анимацию с помощью js.

Реализация цифровой градиентной анимации

Если подумать, разве это число не меняется от 0 до 5000 с течением времени? Подумайте иначе, это не процесс перехода от 0 к 1 (или от 0% к 100%). Анимация требует времени, за определенное время число изменяется от 0 до 1. Можно ли абстрагироваться от постепенного течения времени? Другими словами, не истекает ли время? Тогда процесс чисел от 0 до 1 не может быть преобразован в процесс времени от начала до конца. Следуя этой идее, анимацию можно абстрагировать от того, какой процент текущего времени прошел, а затем использовать этот процент для соответствующих преобразований. Затем реализуйте этот цифровой градиент.

<div class="box">0</div>
<script>
  const oBox = document.querySelector('.box')

  const startTime = + new Date
  let timer = null

  function step() {
    const percent = Math.min(1, (+new Date - startTime) / 5000)// 动画时间为 5s

    if (percent < 1) {
      oBox.innerHTML = ~~(5000 * percent)
      timer = requestAnimationFrame(step)
    } else {
      oBox.innerHTML = ~~(5000 * 1)
      cancelAnimationFrame(timer)
    }
  }

  timer = requestAnimationFrame(step)
</script>

Видно, что эффект анимации соответствует ожиданиям, что указывает на то, что идея создания анимации по количеству затраченного времени верна.

Реализовать класс Animator

Подводя итог вышеприведенной реализации цифровой анимации, мы можем реализовать такой класс анимации, который может задавать продолжительность анимации и активно вызывать во время процесса анимации.onUpdateфункция, которая вызывается после завершения анимацииonCompleteфункция.

class Animator {
  constructor() {
    this.durationTime = 0
    this.eventHandlers = new Map()
  }

  duration(time) {
    if (typeof time !== 'number') {
      throw new Error('Duration must be a number')
    }

    this.durationTime = time

    return this
  }

  on(type, handler) {
    if (typeof handler !== 'function') {
      throw new Error('Handler must be a function')
    }

    this.eventHandlers.set(type, handler)

    return this
  }

  animate() {
    const duration = this.durationTime
    const update = this.eventHandlers.get('update') || (t => t)
    const complete = this.eventHandlers.get('complete') || (() => {})

    let timer = null
    const startTime = +new Date()

    function step() {
      const percent = Math.min(1, (+new Date() - startTime) / duration)

      if (percent < 1) {
        update(percent)
        timer = requestAnimationFrame(step)
      } else {
        cancelAnimationFrame(timer)
        update(1)
        complete()
      }
    }

    timer = requestAnimationFrame(step)
  }
}

Приведенная выше цифровая градиентная анимация также может быть достигнута с использованием этого класса:

const oBox = document.querySelector('.box')

new Animator()
  .duration(3000)
  .on('update', t => (oBox.innerHTML = ~~(t * 5000)))
  .on('complete', () => alert('ok'))
  .animate()

Усовершенствованный класс Animator

Я считаю, что многие передовые студенты правыeasing,easing-in-outНе странно, то как добиться подобного эффекта с анимацией js это? Секрет заключается в ослаблении функции. Мы делаем процент анимации при прохождении времени в анимацию, прохождение времени является линейным, это мыслимая кривая из 0-1 раз одинакова, но мы можем использовать время, умноженное на процент функции, как Долгое, как функции могут гарантировать от 0-1, все еще составляет от 0-1, процентное изменение в середине, которые мы можем, независимо от того, что. Например: y = x * x, если 0 x * x, - это функция ослабления.

Улучшите класс Animator:

class Animator {
  constructor() {
    this.durationTime = 0
    this.easingFn = k => k
    this.eventHandlers = new Map()
  }

  easing(fn) {
    if (typeof fn !== 'function') {
      throw new Error('Easing must be a function, such as k => k')
    }

    this.easingFn = fn

    return this
  }

  duration(time) {
    if (typeof time !== 'number') {
      throw new Error('Duration must be a number')
    }

    this.durationTime = time

    return this
  }

  on(type, handler) {
    if (typeof handler !== 'function') {
      throw new Error('Handler must be a function')
    }

    this.eventHandlers.set(type, handler)

    return this
  }

  animate() {
    const duration = this.durationTime
    const easing = this.easingFn
    const update = this.eventHandlers.get('update') || (t => t)
    const complete = this.eventHandlers.get('complete') || (() => {})

    let timer = null
    const startTime = +new Date()

    function step() {
      const percent = Math.min(1, (+new Date() - startTime) / duration)

      if (percent < 1) {
        update(easing(percent))
        timer = requestAnimationFrame(step)
      } else {
        cancelAnimationFrame(timer)
        update(easing(1))
        complete()
      }
    }

    timer = requestAnimationFrame(step)
  }
}

использовать :

const oBox1 = document.querySelector('.box1')
const oBox2 = document.querySelector('.box2')
const oBox3 = document.querySelector('.box3')

new Animator()
  .duration(3000)
  .easing(x => k * k)
  .on('update', t => oBox1.style.left = t * 500 + 'px')
  .on('complete', () => alert('ok'))
  .animate()

new Animator()
  .duration(3000)
  .easing(k => (1 - --k * k * k * k))
  .on('update', t => oBox2.style.left = t * 500 + 'px')
  .on('complete', () => alert('ok'))
  .animate()

new Animator()
  .duration(3000)
  .easing(k => 1 - Math.sqrt(1 - k * k))
  .on('update', t => oBox3.style.left = t * 500 + 'px')
  .on('complete', () => alert('ok'))
  .animate()

peek 2018-10-18 02-01

Для более интересных функций смягчения рекомендуется посмотретьФункция смягчения для tween.js.