Created
November 12, 2019 18:27
-
-
Save benrobygreene/26df915a93ef9274ceb3f42a14b79bde to your computer and use it in GitHub Desktop.
Marquee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { debounce } from 'common/Helpers'; | |
const dom = { | |
marquee: 'data-marquee-wrapper', | |
marqueeText: 'data-marquee-text', | |
}; | |
/** | |
* Build an animation for a marquee wrapper | |
* | |
* @param {String} text: the text to display in the marquee | |
* @param {Node} marqueeWrapper: the node to append the marquee text element to | |
* @param {int} index: the current marquee being built | |
*/ | |
const addMarqueeStyles = (itemWidth, marqueeWrapper, index) => { | |
const styleElement = document.createElement('style'); | |
styleElement.innerHTML = `@keyframes marquee-${index} { | |
0% { margin-left: 0px; } | |
100% { margin-left: -${itemWidth}px; } | |
}`; | |
marqueeWrapper.appendChild(styleElement); | |
marqueeWrapper.style.animation = `marquee-${index} 5s linear infinite`; | |
}; | |
/** | |
* Build a marquee text element to add to the marquee wrapper | |
* | |
* @param {String} text: the text to display in the marquee | |
* @param {Node} marqueeWrapper: the node to append the marquee text element to | |
* | |
* @return {Node}: the new node to add to the marquee wrapper | |
*/ | |
const buildMarqueeItem = (text, marqueeWrapper) => { | |
const newElement = document.createElement('span'); | |
newElement.classList.add('marquee-item'); | |
newElement.innerHTML = `${text} `; | |
marqueeWrapper.appendChild(newElement); | |
return newElement; | |
}; | |
/** | |
* Add the marquee items to the wrapper | |
* | |
* @param {Node} marqueeWrapper: the node to append the marquee text element to | |
* @param {int} index: the current marquee being built | |
*/ | |
const addMarqueeItems = (marqueeWrapper, index) => { | |
const text = marqueeWrapper.getAttribute(dom.marquee); | |
// Get a test element to check and see how many text elements to add to the marquee wrapper | |
const newMarqueeText = buildMarqueeItem(text, marqueeWrapper); | |
const itemWidth = newMarqueeText.getBoundingClientRect().width; | |
// Need to +1 to ensure that the marquee doesn't ever have blank space at the far end of the wrapper | |
// (would occur at the end of the animation) | |
const numToBuild = Math.floor(window.innerWidth / itemWidth + 1); | |
for (let i = 0; i < numToBuild; i++) { | |
buildMarqueeItem(text, marqueeWrapper); | |
} | |
// need to add the animation styles for the marquee now | |
addMarqueeStyles(itemWidth, marqueeWrapper, index); | |
}; | |
/** | |
* Loops through and sets up the individual marquee wrappers | |
*/ | |
const setupMarquees = () => { | |
const marqueeWrappers = document.querySelectorAll(`[${dom.marquee}]`); | |
marqueeWrappers.forEach((marqueeWrapper, index) => { | |
marqueeWrapper.innerHTML = ''; | |
addMarqueeItems(marqueeWrapper, index); | |
}); | |
}; | |
/** | |
* Reset all marquee wrappers to contain enough elements for new window size. | |
*/ | |
const resetMarquee = debounce(() => { | |
setupMarquees(); | |
}, 500); | |
/** | |
* Setup all marquee elements & debouncer for resetting on window resize. | |
*/ | |
const setup = () => { | |
setupMarquees(); | |
window.addEventListener('resize', resetMarquee); | |
}; | |
export default { | |
setup, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment