Skip to content

Instantly share code, notes, and snippets.

@rhythnic
Created September 6, 2018 19:02
Show Gist options
  • Save rhythnic/8c657486957f2e6f3ff7ce5db694a319 to your computer and use it in GitHub Desktop.
Save rhythnic/8c657486957f2e6f3ff7ce5db694a319 to your computer and use it in GitHub Desktop.
Factory for creating custom elements for text-animation.
// ***************************************
// AnimatedTextFactory
// Factory gives you a custom element that accepts a text property.
// Each character of the text is wrapped in an element and appended as a child.
// You can achieve cool effects by combining css animation with props
// set on the child nodes.
//
// Usage
// <template>
// <text-stagger-animation-delay text="The ants go marching one by one.">
// </text-stagger-animation-delay>
// </template>
//
// <script>
// window.customElements.define(
// 'text-stagger-animation-delay',
// AnimatedTextFactory({
// setCharProps: xs =>
// xs.forEach((x, i) => x.style.animationDelay = `${i/10}s`)
// })
// )
// </script>
//
// <style>
// text-stagger-animation-delay:hover > * {
// animation: fadeIn 2s infinite;
// }
// </style>
function AnimatedTextFactory (opts = {}) {
if (!opts.charTagName)
opts.charTagName = 'span'
if (!opts.setCharProps)
opts.setCharProps = () => {}
return class extends HTMLElement {
static get observedAttributes() {
return ['text'];
}
attributeChangedCallback(name, old, val) {
switch (name) {
case 'text':
return this.insertCharsIntoDom(val)
}
}
insertCharsIntoDom (text) {
Array.prototype.forEach.call(
this.querySelectorAll(opts.charTagName),
this.removeChild.bind(this)
)
if (!text) return
const chars = text
.split('')
.map(x => {
const el = document.createElement(opts.charTagName)
el.appendChild(document.createTextNode(x))
el.style.display = 'inline-block'
return el
})
chars.forEach(this.appendChild.bind(this))
opts.setCharProps(chars)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment