59 lines
1.6 KiB
JavaScript
59 lines
1.6 KiB
JavaScript
// Lightweight polyfill for web animations API element.animate()
|
|
// This is good enough for my use case, although not a full polyfill
|
|
// of the entire API
|
|
|
|
// via https://stackoverflow.com/a/15710692
|
|
function hashCode (s) {
|
|
return s.split('')
|
|
.reduce((a, b) => {
|
|
a = ((a << 5) - a) + b.charCodeAt(0)
|
|
return a & a
|
|
}, 0)
|
|
}
|
|
|
|
function generateCss (id, animations) {
|
|
let keyframes = animations.map(({ properties }, i) => (
|
|
`@keyframes keyframe-${id}-${i} {
|
|
${properties.map((obj, i) => (`${Math.round(100 * i / (properties.length - 1))}% {
|
|
${Object.keys(obj).map(key => `${key}: ${obj[key]};`).join('')}
|
|
}`
|
|
)).join('')}
|
|
}`
|
|
))
|
|
|
|
let animationCss = `.${id} {
|
|
animation: ${animations.map(({ options }, i) => {
|
|
return `keyframe-${id}-${i} ${options.duration}ms ${options.easing}`
|
|
}).join(',')};
|
|
}`
|
|
|
|
return keyframes + animationCss
|
|
}
|
|
|
|
export function animate (el, animations) {
|
|
if (typeof el.animate === 'function') {
|
|
return animations
|
|
.map(({ properties, options }) => el.animate(properties, options))
|
|
.map(anim => anim.play())
|
|
}
|
|
|
|
let hash = hashCode(JSON.stringify(animations))
|
|
let id = `anim-${hash}`
|
|
|
|
if (!document.getElementById(id)) {
|
|
let style = document.createElement('style')
|
|
style.id = id
|
|
style.textContent = generateCss(id, animations)
|
|
document.head.appendChild(style)
|
|
}
|
|
|
|
requestAnimationFrame(() => {
|
|
el.classList.add(id)
|
|
let wait = Math.max.apply(Math, animations.map(({ options }) => options.duration))
|
|
setTimeout(() => {
|
|
requestAnimationFrame(() => {
|
|
el.classList.remove(id)
|
|
})
|
|
}, wait)
|
|
})
|
|
}
|