Научу вас писать js анимацию
Я считаю, что все должны быть незнакомы с этим эффектом цифровой градиентной анимации. Далее разберем, как реализовать эту анимацию с помощью 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()
Для более интересных функций смягчения рекомендуется посмотретьФункция смягчения для tween.js.