Skip to content

Instantly share code, notes, and snippets.

@vixalien
Created February 2, 2021 10:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vixalien/4a9fb790036d01399186e7c3050c2560 to your computer and use it in GitHub Desktop.
Save vixalien/4a9fb790036d01399186e7c3050c2560 to your computer and use it in GitHub Desktop.
Snowing using the Web Animations API and Promises
console.log('The weather today is predicted to be ❄snowy!')
svg_str = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 512 512"><path fill="currentColor" d="M440.5 345.8L408.1 327c11.8-12.3 26-18.2 26.2-18.3 7.5-3 11.4-11.4 8.9-19.1-1.9-5.9-7.4-9.8-13.5-9.8-1.9 0-3.7.4-5.5 1.1-1 .4-24.4 10-41.9 31.2l-96.3-56 96.3-56c17.5 21.2 40.8 30.8 41.9 31.2 1.8.7 3.6 1.1 5.5 1.1 6.1 0 11.6-4 13.5-9.8 2.5-7.7-1.4-16.1-8.9-19.1-.1-.1-14.3-6-26.2-18.3l32.4-18.8c7.2-4.2 9.6-13.4 5.5-20.6-2.7-4.7-7.7-7.6-13.1-7.6-2.6 0-5.3.7-7.6 2L393.1 159c-4.5-16.2-2.7-31.4-2.6-32 1.1-8.1-4.1-15.6-12-17.3-1-.2-2-.3-3-.3-7.1 0-13 5.2-14.1 12.4-.2 1.1-3.6 26 6.1 52.2l-96 56v-99.2c26.9-4.7 46.8-20.2 47.7-20.9 3.1-2.5 5.1-6 5.4-10 .3-4-.9-7.8-3.6-10.8-2.9-3.2-7-5.1-11.4-5.1-3.4 0-6.8 1.2-9.5 3.3-.1.1-12.2 9.4-28.6 13.6V63.1c0-8.2-7.1-15.1-15.5-15.1s-15.5 6.9-15.5 15.1v37.5c-16.3-4.2-28.4-13.5-28.6-13.6-2.7-2.1-6-3.3-9.5-3.3-4.4 0-8.5 1.9-11.4 5.1-2.7 3-4 7-3.6 10.9.3 3.9 2.3 7.4 5.4 9.9.9.7 20.8 16.2 47.7 20.9v99.2l-96-56c9.6-26 6.2-51.1 6-52.2-1-7.2-6.9-12.4-14-12.4-1 0-2 .1-3 .3-7.9 1.6-13.2 9.3-12 17.3 0 .2 2 15.5-2.6 31.9L86.6 140c-2.3-1.3-4.9-2-7.6-2-5.4 0-10.4 2.9-13.1 7.6-4.1 7.2-1.7 16.5 5.5 20.6l32.4 18.8c-11.7 12.1-25.7 18.1-26.2 18.3-7.5 3-11.4 11.4-8.9 19.1 1.9 5.9 7.4 9.8 13.5 9.8 1.9 0 3.7-.4 5.5-1.1 1-.4 24.4-10 41.9-31.2l96.3 56-96.3 56c-17.5-21.2-40.8-30.8-41.9-31.2-1.8-.7-3.6-1.1-5.5-1.1-6.1 0-11.6 4-13.5 9.8-2.5 7.7 1.4 16 8.9 19.1.5.2 14.5 6.2 26.2 18.3l-32.4 18.8c-7.2 4.2-9.6 13.4-5.5 20.6 2.7 4.7 7.7 7.6 13.1 7.6 2.6 0 5.3-.7 7.6-2l32.3-18.8c4.6 16.5 2.6 31.8 2.6 32-1.2 8 4.1 15.7 12 17.3 1 .2 2 .3 3 .3 7.1 0 13-5.2 14.1-12.4.2-1.1 3.6-26-6.1-52.2l96-56v99.2c-26.9 4.7-46.8 20.2-47.7 20.9-3.1 2.5-5.1 6-5.4 10-.3 4 .9 7.8 3.6 10.8 2.9 3.2 7 5.1 11.4 5.1 3.4 0 6.8-1.2 9.5-3.3.1-.1 12.3-9.4 28.6-13.6v37.5c0 8.2 7.1 15.1 15.5 15.1s15.5-6.9 15.5-15.1v-37.5c16.3 4.2 28.4 13.5 28.6 13.6 2.7 2.1 6.1 3.3 9.5 3.3 4.4 0 8.5-1.9 11.4-5.1 2.7-3 4-7 3.6-10.9-.3-3.9-2.3-7.4-5.4-9.9-.9-.7-20.8-16.2-47.7-20.9V282l96 56c-9.6 26-6.2 51.1-6 52.2 1 7.2 6.9 12.4 14 12.4 1 0 2-.1 3-.3 7.9-1.6 13.1-9.2 12-17.3-.1-.5-1.9-15.7 2.6-32l32.2 18.8c2.3 1.3 4.9 2 7.6 2 5.4 0 10.4-2.9 13.1-7.6 4.1-6.9 1.7-16.2-5.5-20.4z"/></svg>`
snow = new DOMParser().parseFromString(svg_str, 'text/xml').children[0]
// set the svg's position to fixed
snow.style.position = "fixed"
snow.style.top = '-24px'
// new snowflake
let newSnow = () => {
// create a new snow
let clonedSnow = snow.cloneNode(true);
// assign to it a random left
let left = Math.floor(document.body.offsetWidth * Math.random())
clonedSnow.style.left = left + 'px';
// add it to the dom
document.body.append(clonedSnow)
// assign to it a random speed
let time = Math.max(10 * Math.random(), 5) * 1000
let anim = clonedSnow.animate([ { top: (window.innerHeight + 24) + 'px' } ], { duration: time, fill: 'forwards' })
// garbage collection
anim.onfinish = el => el.target.effect.target.remove()
return snow
}
wait = time => new Promise(res => setTimeout(res, time))
let asyncIterate = async (start, iterations, fn) => {
let i = start;
let call = res => fn(res)
.then(async result => {
if (i >= iterations) return result;
i++
return await call(i)
});
return await call(i);
}
// also don't run it for people who do not
if(window.matchMedia && window.matchMedia('(prefers-reduced-motion: true)').matches) {
console.log('No snow for you because you (prefers-reduced-motion)')
} else {
asyncIterate(0, Infinity, async () => {
// wait 10 seconds if the user is not active
// if (navigator.userActivation && !navigator.userActivation.isActive) return await wait(10000);
if (document.visibilityState && document.visibilityState != 'visible') return await wait(10000).then(() => console.log('page was not visible'));
await wait(Math.max(3 * Math.random(), 1) * 300)
newSnow();
})
}
@vixalien
Copy link
Author

vixalien commented Feb 6, 2021

Read the relevant blog post here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment