magic-snowflakes
Version:
Falling snowflakes
2 lines • 8.41 kB
JavaScript
/*! Snowflakes | © 2024 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={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 e(t,e){Object.keys(e).forEach((function(n){t.style[n]=e[n]}))}function n(t){e(t,{display:"block"})}function i(t){e(t,{display:"none"})}function o(t){t&&t.parentNode&&t.parentNode.removeChild(t)}function a(t){return"string"==typeof t&&""!==t}function s(t){for(var e,n=[],i=1;i<arguments.length;i++)n[i-1]=arguments[i];var o=n.filter(a);o.length&&(e=t.classList).add.apply(e,o)}function r(t){for(var e,n=[],i=1;i<arguments.length;i++)n[i-1]=arguments[i];var o=n.filter(a);o.length&&(e=t.classList).remove.apply(e,o)}function h(t,e){return t+Math.floor(Math.random()*(e-t))}function d(t,e,n,i,o){return i+(o-i)*(t-e)/(n-e)}function l(t,e,n){return Math.floor(d(t,0,20,e,n))}var c=function(){function t(t){var o=this;this.size=0,this.sizeInner=0,this.handleAnimationEnd=function(t){var a,s=o.elem;s&&(t.target===s&&(e(s,{left:o.getLeft()}),i(a=s),a.offsetHeight,n(a)))};var a=this.elem=document.createElement("div"),r=this.elemInner=document.createElement("div");this.update(t),s(a,"snowflake"),s(r,"snowflake__inner",t.types?"snowflake__inner_type_"+h(0,t.types):"",t.wind?"snowflake__inner_wind":"",t.rotation?"snowflake__inner_rotation"+(Math.random()>.5?"":"_reverse"):""),a.appendChild(r),a.onanimationend=this.handleAnimationEnd}return t.prototype.getLeft=function(){return 99*Math.random()+"%"},t.prototype.update=function(t){if(this.elem&&this.elemInner){var n=t.minSize===t.maxSize;this.sizeInner=n?0:h(0,20),this.size=l(this.sizeInner,t.minSize,t.maxSize);var i=this.getAnimationProps(t),o={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||(o.opacity=String(d(this.size,t.minSize,t.maxSize,t.minOpacity,t.maxOpacity))),e(this.elem,o);var a="snowflake_gid_".concat(t.gid,"_x_").concat(this.sizeInner);e(this.elemInner,{animationName:a,animationDelay:4*Math.random()+"s"})}},t.prototype.resize=function(t){if(this.elem){var n=this.getAnimationProps(t);e(this.elem,{animationDuration:n.animationDuration})}},t.prototype.appendTo=function(t){this.elem&&t.appendChild(this.elem)},t.prototype.destroy=function(){this.elem&&(this.elem.onanimationend=null,delete this.elem,delete this.elemInner)},t.prototype.getAnimationProps=function(t){var e=t.containerHeight/50/t.speed,n=e/3;return{animationDelay:Math.random()*e+"s",animationDuration:String(d(this.size,t.minSize,t.maxSize,e,n)+"s")}},t}();return function(){function a(t){var e=this;this.destroyed=!1,this.flakes=[],this.handleResize=function(){e.params.autoResize&&e.resize()},this.handleOrientationChange=function(){e.resize()},this.params=this.setParams(t),a.gid++,this.gid=a.gid,this.container=this.appendContainer(),this.params.stop&&this.stop(),this.appendStyles(),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)},a.prototype.start=function(){r(this.container,"snowflakes_paused")},a.prototype.stop=function(){s(this.container,"snowflakes_paused")},a.prototype.show=function(){r(this.container,"snowflakes_hidden")},a.prototype.hide=function(){s(this.container,"snowflakes_hidden")},a.prototype.resize=function(){var t=this.width(),e=this.height();if(e!==this.containerSize.height){this.containerSize.width=t,this.containerSize.height=e;var o=this.getFlakeParams();this.flakes.forEach((function(t){return t.resize(o)})),this.isBody()||(i(this.container),this.updateAnimationStyle(),n(this.container))}},a.prototype.destroy=function(){this.destroyed||(this.destroyed=!0,a.instanceCounter&&a.instanceCounter--,this.removeStyles(),o(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 s(t,"snowflakes","snowflakes_gid_".concat(this.gid),this.isBody()?"snowflakes_body":""),e(t,{zIndex:String(this.params.zIndex)}),this.params.container.appendChild(t),t},a.prototype.appendStyles=function(){a.instanceCounter||(this.mainStyleNode=this.injectStyle('.snowflake{animation:snowflake_unknown 10s linear;pointer-events:none;position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;will-change:transform}.snowflake__inner,.snowflake__inner:before{bottom:0;left:0;position:absolute;right:0;top:0}.snowflake__inner:before{background-size:100% 100%;content:""}.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{height:1px;left:0;position:fixed;top:0;width:100%}')),a.instanceCounter++,this.imagesStyleNode=this.injectStyle("".replace(/:color:/g,encodeURIComponent(this.params.color))),this.animationStyleNode=this.injectStyle(this.getAnimationStyle())},a.prototype.injectStyle=function(t,e){return function(t,e){return e||(e=document.createElement("style"),document.head.appendChild(e)),e.textContent=t,e}(t.replace(/_gid_value/g,"_gid_".concat(this.gid)),e)},a.prototype.getFlakeParams=function(){var t=this.height(),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.appendFlakes=function(){var t=this,e=this.getFlakeParams();this.flakes=[];for(var n=0;n<this.params.count;n++)this.flakes.push(new c(e));this.flakes.sort((function(t,e){return t.size-e.size})).forEach((function(e){e.appendTo(t.container)}))},a.prototype.setParams=function(e){var n=e||{},i={};return Object.keys(t).forEach((function(e){i[e]=void 0===n[e]?t[e]:n[e]})),i},a.prototype.getAnimationStyle=function(){for(var t=Math.ceil(this.params.maxSize*Math.sqrt(2)),e=this.isBody()?"calc(100vh + ".concat(t,"px)"):"".concat(this.height()+t,"px"),n=this.gid,i=["@keyframes snowflake_gid_".concat(n,"_y{from{transform:translateY(").concat("0px",")}to{transform:translateY(").concat(e,")}}")],o=0;o<=20;o++){var a=l(o,this.params.minSize,this.params.maxSize)+"px";i.push("@keyframes snowflake_gid_".concat(n,"_x_").concat(o,"{from{transform:translateX(0px)}to{transform:translateX(").concat(a,")}}"))}return i.join("\n")},a.prototype.updateAnimationStyle=function(){this.injectStyle(this.getAnimationStyle(),this.animationStyleNode)},a.prototype.removeStyles=function(){a.instanceCounter||(o(this.mainStyleNode),delete this.mainStyleNode),o(this.imagesStyleNode),delete this.imagesStyleNode,o(this.animationStyleNode),delete this.animationStyleNode},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.defaultParams=t,a}()}));