magic-snowflakes
Version:
Falling snowflakes
2 lines • 12.7 kB
JavaScript
/*! Snowflakes | © 2026 Denis Seleznev | MIT License | https://github.com/hcodes/snowflakes/ */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Snowflakes=e()}(this,function(){"use strict";var t=function(){return t=Object.assign||function(t){for(var e,i=1,n=arguments.length;i<n;i++)for(var o in e=arguments[i])Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t},t.apply(this,arguments)};function e(){return{color:"#5ECDEF",container:document.body,count:50,speed:1,stop:!1,rotation:!0,minOpacity:.6,maxOpacity:1,minSize:10,maxSize:25,types:6,width:void 0,height:void 0,wind:!0,zIndex:9999,autoResize:!0}}function i(t,e){return"number"==typeof t&&isFinite(t)?t:e}function n(t,e){var n,o,a=t||{},s={container:void 0===a.container?e.container:a.container,color:void 0===a.color?e.color:a.color,stop:void 0===a.stop?e.stop:a.stop,rotation:void 0===a.rotation?e.rotation:a.rotation,wind:void 0===a.wind?e.wind:a.wind,autoResize:void 0===a.autoResize?e.autoResize:a.autoResize,count:e.count,types:e.types,speed:e.speed,minOpacity:e.minOpacity,maxOpacity:e.maxOpacity,minSize:e.minSize,maxSize:e.maxSize,zIndex:e.zIndex};s.count=Math.max(0,Math.floor(i(a.count,e.count))),s.types=Math.max(0,Math.floor(i(a.types,e.types))),s.speed=i(a.speed,e.speed),s.speed<=0&&(s.speed=e.speed),s.minOpacity=Math.max(0,Math.min(1,i(a.minOpacity,e.minOpacity))),s.maxOpacity=Math.max(0,Math.min(1,i(a.maxOpacity,e.maxOpacity))),s.minSize=Math.max(0,i(a.minSize,e.minSize)),s.maxSize=Math.max(0,i(a.maxSize,e.maxSize)),s.minOpacity>s.maxOpacity&&(n=[s.maxOpacity,s.minOpacity],s.minOpacity=n[0],s.maxOpacity=n[1]),s.minSize>s.maxSize&&(o=[s.maxSize,s.minSize],s.minSize=o[0],s.maxSize=o[1]);var r=i(a.width,e.width),h=i(a.height,e.height);s.width=void 0===r?void 0:Math.max(0,r),s.height=void 0===h?void 0:Math.max(0,h);var d=i(a.zIndex,e.zIndex);return s.zIndex=d<0?Math.ceil(d):Math.floor(d),s}function o(t,e){return t+Math.floor(Math.random()*(e-t))}function a(t,e,i,n,o){return e===i?n:n+(o-n)*(t-e)/(i-e)}"function"==typeof SuppressedError&&SuppressedError;function s(t,e,i){return Math.floor(a(t,0,20,e,i))}function r(t,e,i,n,o){return a(t,e,i,n,o)}function h(t,e){return t/50/e}function d(t,e,i,n,o){var s=h(n,o);return a(t,e,i,s,s/3)}function c(t,e,i){return t*h(e,i)}function p(t,e,i,n,o){for(var a=function(t,e,i){var n=Math.ceil(i*Math.sqrt(2));return{fromY:"0px",toY:t?"calc(100vh + ".concat(n,"px)"):"".concat(e+n,"px")}}(e,i,o),r=a.fromY,h=a.toY,d=["@keyframes snowflake_gid_".concat(t,"_y{from{transform:translateY(").concat(r,")}to{transform:translateY(").concat(h,")}}")],c=0;c<=20;c++){var p=s(c,n,o)+"px";d.push("@keyframes snowflake_gid_".concat(t,"_x_").concat(c,"{from{transform:translateX(0px)}to{transform:translateX(").concat(p,")}}"))}return d.join("\n")}function l(t,e){Object.keys(e).forEach(function(i){t.style[i]=e[i]})}function m(t){l(t,{display:"block"})}function f(t){l(t,{display:"none"})}function u(t,e){return e||(e=document.createElement("style"),document.head.appendChild(e)),e.textContent=t,e}function y(t){t&&t.parentNode&&t.parentNode.removeChild(t)}function w(t){return"string"==typeof t&&""!==t}function z(t){for(var e,i=[],n=1;n<arguments.length;n++)i[n-1]=arguments[n];var o=i.filter(w);o.length&&(e=t.classList).add.apply(e,o)}function g(t){for(var e,i=[],n=1;n<arguments.length;n++)i[n-1]=arguments[n];var o=i.filter(w);o.length&&(e=t.classList).remove.apply(e,o)}var k=function(){function t(e,i){this.destroyed=!1,t.owners||(t.mainStyleNode=u('.snowflake{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:none;will-change:transform;animation:snowflake_unknown 10s linear}.snowflake__inner,.snowflake__inner:before{position:absolute;top:0;right:0;bottom:0;left:0}.snowflake__inner:before{content:"";background-color:currentColor;-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.snowflake__inner_wind{animation:snowflake_unknown 2s ease-in-out infinite alternate}.snowflake__inner_rotation:before{animation:snowflake_rotation 10s linear infinite}.snowflake__inner_rotation_reverse:before{animation:snowflake_rotation_reverse 10s linear infinite}@keyframes snowflake_rotation{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes snowflake_rotation_reverse{0%{transform:rotate(0deg)}to{transform:rotate(-1turn)}}.snowflakes{pointer-events:none}.snowflakes_paused .snowflake,.snowflakes_paused .snowflake__inner,.snowflakes_paused .snowflake__inner:before{animation-play-state:paused}.snowflakes_hidden{visibility:hidden}.snowflakes_body{position:fixed;top:0;left:0;width:100%;height:1px}\n')),t.owners++;try{this.animationStyleNode=u(i)}catch(t){throw this.destroy(),t}}return t.prototype.updateAnimation=function(t){this.destroyed||(this.animationStyleNode=u(t,this.animationStyleNode))},t.prototype.destroy=function(){this.destroyed||(this.destroyed=!0,y(this.animationStyleNode),delete this.animationStyleNode,t.owners--,t.owners||(y(t.mainStyleNode),delete t.mainStyleNode))},t.owners=0,t}(),_=function(){function t(t){var e=this;this.size=0,this.sizeInner=0,this.typeClass="",this.delayRandom=Math.random(),this.handleAnimationEnd=function(t){var i,n=e.elem;n&&(t.target===n&&(l(n,{left:e.getLeft()}),f(i=n),i.offsetHeight,m(i)))};var i=this.elem=document.createElement("div"),n=this.elemInner=document.createElement("div");this.update(t),this.typeClass=t.types?"snowflake__inner_type_"+o(0,t.types):"",z(i,"snowflake"),z(n,"snowflake__inner",this.typeClass,t.wind?"snowflake__inner_wind":"",t.rotation?"snowflake__inner_rotation"+(Math.random()>.5?"":"_reverse"):""),i.appendChild(n),i.onanimationend=this.handleAnimationEnd}return t.prototype.getLeft=function(){return 99*Math.random()+"%"},t.prototype.update=function(t){if(this.elem&&this.elemInner){var e=t.minSize===t.maxSize;this.sizeInner=e?0:o(0,20),this.size=s(this.sizeInner,t.minSize,t.maxSize);var i=this.getAnimationProps(t),n={animationName:"snowflake_gid_".concat(t.gid,"_y"),animationDelay:i.animationDelay,animationDuration:i.animationDuration,left:this.getLeft(),top:-Math.sqrt(2)*this.size+"px",width:this.size+"px",height:this.size+"px"};n.opacity=String(r(this.size,t.minSize,t.maxSize,t.minOpacity,t.maxOpacity)),l(this.elem,n);var a="snowflake_gid_".concat(t.gid,"_x_").concat(this.sizeInner);l(this.elemInner,{animationName:a,animationDelay:4*Math.random()+"s"})}},t.prototype.setParams=function(t,e){this.elem&&this.elemInner&&(t.speed===e.speed&&t.containerHeight===e.containerHeight||(this.resize(t),l(this.elem,{animationDelay:c(this.delayRandom,t.containerHeight,t.speed)+"s"})),t.minOpacity===e.minOpacity&&t.maxOpacity===e.maxOpacity||l(this.elem,{opacity:String(r(this.size,t.minSize,t.maxSize,t.minOpacity,t.maxOpacity))}),t.wind!==e.wind&&this.elemInner.classList.toggle("snowflake__inner_wind",t.wind),t.rotation!==e.rotation&&(g(this.elemInner,"snowflake__inner_rotation","snowflake__inner_rotation_reverse"),t.rotation&&z(this.elemInner,"snowflake__inner_rotation"+(Math.random()>.5?"":"_reverse"))),t.types!==e.types&&(g(this.elemInner,this.typeClass),this.typeClass=t.types?"snowflake__inner_type_"+o(0,t.types):"",z(this.elemInner,this.typeClass)))},t.prototype.resize=function(t){this.elem&&l(this.elem,{animationDuration:d(this.size,t.minSize,t.maxSize,t.containerHeight,t.speed)+"s"})},t.prototype.appendTo=function(t,e){this.elem&&t.insertBefore(this.elem,(null==e?void 0:e.elem)||null)},t.prototype.destroy=function(){this.elem&&(this.elem.onanimationend=null,y(this.elem),delete this.elem,delete this.elemInner)},t.prototype.getAnimationProps=function(t){return{animationDelay:c(this.delayRandom,t.containerHeight,t.speed)+"s",animationDuration:d(this.size,t.minSize,t.maxSize,t.containerHeight,t.speed)+"s"}},t}();return function(){function a(t){var i=this;this.destroyed=!1,this.flakes=[],this.handleResize=function(){i.params.autoResize&&i.resize()},this.handleOrientationChange=function(){i.handleResize()},this.params=n(t,e()),a.gid++,this.gid=a.gid,this.container=this.appendContainer(),this.params.stop&&this.stop(),this.styles=new k(this.gid,this.getAnimationStyle()),a.instanceCounter++,this.appendFlakes(),this.containerSize={width:this.width(),height:this.height()},window.addEventListener("resize",this.handleResize,!1),screen.orientation&&screen.orientation.addEventListener&&screen.orientation.addEventListener("change",this.handleOrientationChange)}return a.hasSupport=function(){return Boolean("onanimationend"in document)},Object.defineProperty(a,"defaultParams",{get:function(){return e()},enumerable:!1,configurable:!0}),a.prototype.start=function(){g(this.container,"snowflakes_paused")},a.prototype.stop=function(){z(this.container,"snowflakes_paused")},a.prototype.show=function(){g(this.container,"snowflakes_hidden")},a.prototype.hide=function(){z(this.container,"snowflakes_hidden")},a.prototype.setParams=function(e){if(!this.destroyed){var o=this.params,a=function(e,o){for(var a=t({},e),s=0,r=[["minSize","maxSize"],["minOpacity","maxOpacity"]];s<r.length;s++){var h=r[s],d=h[0],c=h[1],p=i(e[d],void 0),l=i(e[c],void 0);void 0!==p&&void 0===l&&(a[d]=Math.min(p,o[c])),void 0!==l&&void 0===p&&(a[c]=Math.max(l,o[d]))}return n(a,o)}(e,o),s=this.getFlakeParams(this.containerSize.height),r=a.minSize!==o.minSize||a.maxSize!==o.maxSize;this.params=a,a.container!==o.container&&(a.container.appendChild(this.container),this.container.classList.toggle("snowflakes_body",this.isBody())),a.color!==o.color&&l(this.container,{color:a.color}),a.zIndex!==o.zIndex&&l(this.container,{zIndex:String(a.zIndex)}),void 0!==e.stop&&(a.stop?this.stop():this.start());var h=r||a.container!==o.container||a.height!==o.height,d=h?this.height():this.containerSize.height,c=this.getFlakeParams(d);h&&this.styles.updateAnimation(this.getAnimationStyle(d)),r?(this.flakes.forEach(function(t){return t.destroy()}),this.flakes=[]):(this.removeExcessFlakes(),this.flakes.forEach(function(t){return t.setParams(c,s)})),this.flakes.length<a.count&&this.appendFlakes(c),a.container===o.container&&a.width===o.width||(this.containerSize.width=this.width()),this.containerSize.height=d}},a.prototype.resize=function(){if(!this.destroyed){var t=this.width(),e=this.height();if(e!==this.containerSize.height){this.containerSize.width=t,this.containerSize.height=e;var i=this.getFlakeParams();this.flakes.forEach(function(t){return t.resize(i)}),this.isBody()||(f(this.container),this.styles.updateAnimation(this.getAnimationStyle()),m(this.container))}}},a.prototype.destroy=function(){this.destroyed||(this.destroyed=!0,a.instanceCounter&&a.instanceCounter--,this.styles.destroy(),y(this.container),this.flakes.forEach(function(t){return t.destroy()}),this.flakes=[],window.removeEventListener("resize",this.handleResize,!1),screen.orientation&&screen.orientation.removeEventListener&&screen.orientation.removeEventListener("change",this.handleOrientationChange,!1))},a.prototype.isBody=function(){return this.params.container===document.body},a.prototype.appendContainer=function(){var t=document.createElement("div");return z(t,"snowflakes","snowflakes_gid_".concat(this.gid),this.isBody()?"snowflakes_body":""),l(t,{zIndex:String(this.params.zIndex),color:this.params.color}),this.params.container.appendChild(t),t},a.prototype.getFlakeParams=function(t){void 0===t&&(t=this.height());var e=this.params;return{containerHeight:t,gid:this.gid,count:e.count,speed:e.speed,rotation:e.rotation,minOpacity:e.minOpacity,maxOpacity:e.maxOpacity,minSize:e.minSize,maxSize:e.maxSize,types:e.types,wind:e.wind}},a.prototype.removeExcessFlakes=function(){var t=this.flakes.length,e=t-this.params.count;e<=0||(this.flakes=this.flakes.filter(function(i,n){return!(o(0,t-n)<e)||(e--,i.destroy(),!1)}))},a.prototype.appendFlakes=function(t){void 0===t&&(t=this.getFlakeParams());for(var e=new Set,i=this.flakes.length;i<this.params.count;i++){var n=new _(t);e.add(n),this.flakes.push(n)}this.flakes.sort(function(t,e){return t.size-e.size});for(i=this.flakes.length-1;i>=0;i--){n=this.flakes[i];e.has(n)&&n.appendTo(this.container,this.flakes[i+1])}},a.prototype.getAnimationStyle=function(t){return void 0===t&&(t=this.height()),p(this.gid,this.isBody(),t,this.params.minSize,this.params.maxSize)},a.prototype.width=function(){return this.params.width||(this.isBody()?window.innerWidth:this.params.container.offsetWidth)},a.prototype.height=function(){return this.params.height||(this.isBody()?window.innerHeight:this.params.container.offsetHeight+this.params.maxSize)},a.gid=0,a.instanceCounter=0,a}()});