/**
* Float a number of things up on a page (hearts, flowers, 👌 ...)
* <br>
* You give the options in an object.
*
* @module floating
* @param {string} [options.content='👌']
* the character or string to float
* @param {number} [options.number=1]
* the number of items
* @param {number} [options.duration=10]
* the amount of seconds it takes to float up
* @param {number|string} [options.repeat='infinite']
* the number of times you want the animation to repeat
* @param {string} [options.direction='normal']
* The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction">
* animation-direction</a> of the main animation
* @param {number|array} [options.sizes=2]
* The size (in em) of each element. Giving two values in an array will
* give a random size between those values.
*/
export default function floating(
{
content = '👌',
number = 1,
duration = 10,
repeat = 'infinite',
direction = 'normal',
size = 2,
} = {}
) {
const style = document.createElement('style');
style.id = 'floating-style';
if (!document.getElementById('floating-style')) {
document.head.appendChild(style);
}
const MAX = 200;
const styles = `
.float-container {
width: 100vw;
height: 100vh;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
.float-container div * {
width: 1em;
height: 1em
}
@keyframes float{
${Array(MAX)
.map((v, x) => ({
percent: x * 100 / MAX,
width: Math.sin(x / 10) * 10,
height: 110 + x * (-120 / MAX),
}))
.map(
({ percent, width, height }) =>
`${percent}% {
transform: translate(
${width}vw,
${height}vh
)
}`
)
.join('')}
}`;
document.getElementById('floating-style').innerHTML = styles;
const container = document.createElement('div');
container.className = 'float-container';
const _size = Array.isArray(size)
? Math.floor(Math.random() * (size[1] - size[0] + 1)) + size[0]
: size;
for (let i = 0; i < number; i++) {
const floater = document.createElement('div');
floater.innerHTML = content;
floater.style.cssText = `
position: absolute;
left: 0;
font-size: ${_size}em;
transform: translateY(110vh);
animation:
float
${duration}s
linear
${i * Math.random()}s
${repeat}
${direction};
margin-left: ${Math.random() * 100}vw;`;
floater.addEventListener('animationend', e => {
if (e.animationName === 'float') {
container.removeChild(floater);
}
});
container.appendChild(floater);
}
document.body.appendChild(container);
}