@erikwatson/snowfall 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,34 +15,75 @@ displayed over the top. [Check out this example](http://erikwatson.me/?snow).
15
15
  - Density of snowflakes looks correct even when the window is resized.
16
16
  - Small, with no dependencies.
17
17
 
18
- ## Instructions
18
+ ## Instructions - Package Manager
19
19
 
20
- First, install.
20
+ ### Install it
21
21
 
22
22
  ```sh
23
- # if you're using yarn
23
+ # if you're using yarn install with
24
24
  yarn add @erikwatson/snowfall
25
25
 
26
- # if you're using npm
26
+ # if you're using npm install with
27
27
  npm install @erikwatson/snowfall
28
28
  ```
29
29
 
30
- Then...
30
+ ### Use it
31
+
32
+ Add a div with an ID of `snow-container` to your page. You will need to set the
33
+ width and height of this yourself using CSS.
31
34
 
32
35
  ```html
33
- <!-- You are expected to size and position this yourself with CSS -->
34
36
  <div id="snow-container"></div>
37
+ ```
38
+
39
+ Then, at the bottom of your page body add the following.
40
+
41
+ ```html
42
+ <script
43
+ type="text/javascript"
44
+ src="./node_modules/@erikwatson/snowfall/dist/snowfall.min.js"
45
+ ></script>
46
+ <script>
47
+ // You can change the defaults by passing in a config object here
48
+ // Use the Visual Config Editor to create one
49
+ snowfall.start()
50
+ </script>
51
+ ```
52
+
53
+ **WARNING:** You should symlink to the .js file rather than have a publicly
54
+ accessible node_modules folder. It is this way here just to keep example simple.
55
+
56
+ ## Instructions - CDN
35
57
 
36
- <!-- Include the lib, wherever you've put it -->
37
- <script type="text/javascript" src="./path/to/snowfall.min.js"></script>
58
+ First, add a div with an ID of `snow-container` to your page. You will need to
59
+ set the width and height of this yourself using CSS.
60
+
61
+ ```html
62
+ <div id="snow-container"></div>
38
63
  ```
39
64
 
40
- ```js
41
- // You can change the defaults by passing in a config object here
42
- // Use the Visual Config Editor to create one
43
- snowfall.start()
65
+ Then, at the bottom of your page body add the following.
66
+
67
+ ```html
68
+ <script src="https://cdn.jsdelivr.net/npm/@erikwatson/snowfall/dist/snowfall.min.js"></script>
69
+ <script>
70
+ // You can change the defaults by passing in a config object here
71
+ // Use the Visual Config Editor to create one
72
+ snowfall.start()
73
+ </script>
44
74
  ```
45
75
 
46
- ## Authors
76
+ ### Specify Version
77
+
78
+ It is not recommended to always use the latest version, especially in
79
+ production. You can change the CDN url to specify control over the version using
80
+ the `@version` syntax like so.
81
+
82
+ - **latest release**: https://cdn.jsdelivr.net/npm/@erikwatson/snowfall/dist/snowfall.min.js
83
+ - **major release**: https://cdn.jsdelivr.net/npm/@erikwatson/snowfall@3/dist/snowfall.min.js
84
+ - **minor release**: https://cdn.jsdelivr.net/npm/@erikwatson/snowfall@3.1/dist/snowfall.min.js
85
+ - **patch release**: https://cdn.jsdelivr.net/npm/@erikwatson/snowfall@3.0.1/dist/snowfall.min.js
86
+
87
+ ## Author
47
88
 
48
89
  - [Erik Watson](http://erikwatson.me)
@@ -1 +1 @@
1
- window.snowfall=function(t){var e={};function n(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(i,r,function(e){return t[e]}.bind(null,r));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){const i=n(1),r=document.querySelector("#snow-container"),o=document.createElement("canvas"),a=o.getContext("2d");let d=i.create(0,.7),s=i.create(0,0),l=200,c=[],u="#0d0014",f="#8d90b7",h="#ffffff",y=1,g=.02;function p(t,e){(d=i.fromDegrees(t)).multiplyScalar(e)}function v(t,e){(s=i.fromDegrees(t)).multiplyScalar(e)}function m(){o.width=r.offsetWidth,o.height=r.offsetHeight,c=P(q())}function w(){c.forEach(t=>{b.x=s.x,b.y=s.y,b.multiplyScalar(t.size+t.random),t.pos.add(b),M.x=d.x,M.y=d.y,M.multiplyScalar(t.size+t.random),t.pos.add(M);const e=t.noise;S=i.create(y*Math.sin(g*x+e),0),t.pos.add(S),t.pos.x>o.width&&(t.pos.x=0),t.pos.x<0&&(t.pos.x=o.width),t.pos.y>o.height&&(t.pos.y=0,t.pos.x=Math.random()*o.width),t.pos.y<0&&(t.pos.y=o.height,t.pos.x=Math.random()*o.width)}),x+=1,function(){a.clearRect(0,0,o.width,o.height),u&&(a.fillStyle=u,a.fillRect(0,0,o.width,o.height));const t=c.filter(t=>t.size>=7),e=c.filter(t=>t.size<7);a.fillStyle=f,e.forEach(t=>{a.beginPath(),z(t.pos,t.size),a.fill()}),a.fillStyle=h,t.forEach(t=>{a.beginPath(),z(t.pos,t.size),a.fill()})}(),window.requestAnimationFrame(w)}let x=0;const b=i.create(0,0),M=i.create(0,0);let S=null;function P(t){let e=[];for(;t--;)e.push({pos:i.create(Math.random()*o.width,Math.random()*o.height),size:3+5*Math.random(),noise:10*Math.random(),amplitude:2*Math.random(),frequency:.01*Math.random(),random:Math.random()});return e}function q(){const t=o.width*o.height;return Math.round(l*(t/2073600))}function z(t,e){a.arc(t.x,t.y,e,0,2*Math.PI,!1)}t.exports={setAmplitude:function(t){y=t},setBackground:function(t){u=t},setDensity:function(t){l=t,c=P(q())},setFrequency:function(t){g=t},setGravity:p,setPrimary:function(t){f=t},setSecondary:function(t){h=t},setWind:v,start:function(t={}){void 0!==t.bg&&(u=t.bg),void 0!==t.primary&&(f=t.primary),void 0!==t.secondary&&(h=t.secondary),void 0!==t.density&&(l=t.density),void 0!==t.wave&&(void 0!==t.wave.amplitude&&(y=t.wave.amplitude),void 0!==t.wave.frequency&&(g=t.wave.frequency)),void 0!==t.gravity&&(void 0!==t.gravity.angle&&void 0!==t.gravity.strength&&p(t.gravity.angle,t.gravity.strength),void 0!==t.gravity.angle&&void 0===t.gravity.strength&&p(t.gravity.angle,.6),void 0===t.gravity.angle&&void 0!==t.gravity.strength&&p(90,t.gravity.strength)),void 0!==t.wind&&(void 0!==t.wind.angle&&void 0!==t.wind.strength&&v(t.wind.angle,t.wind.strength),void 0!==t.wind.angle&&void 0===t.wind.strength&&v(t.wind.angle,0),void 0===t.wind.angle&&void 0!==t.wind.strength&&v(0,t.wind.strength)),o.width=r.offsetWidth,o.height=r.offsetHeight,r.appendChild(o),c=P(q()),window.onresize=m,window.requestAnimationFrame(w)}}},function(t,e){function n(t,e){let r=t,o=e;const a=()=>Math.sqrt(r*r+o*o),d=t=>{r*=t,o*=t},s=()=>{let t=a();r/=t,o/=t};return{add:t=>{r+=t.x,o+=t.y},addScalar:t=>{r+=t,o+=t},clone:i,divide:t=>{r/=t.x,o/=t.y},divideScalar:t=>{r/=t,o/=t},dot:t=>r*t.x+o*t.y,getLength:a,getOpposite:t=>n(-t.x,-t.y),getPerp:()=>n(-o,r),isEqualTo:t=>r==t.x&&o==t.y,multiply:t=>{r*=t.x,o*=t.y},multiplyScalar:d,normalise:s,setLength:t=>{s(),d(t)},subtract:t=>{r-=t.x,o-=t.y},subtractScalar:t=>{r-=t,o-=t},set x(t){r=t},get x(){return r},set y(t){o=t},get y(){return o}}}const i=t=>n(t.x,t.y);t.exports={clone:i,create:n,fromDegrees:t=>{const e=t*(Math.PI/180);return n(Math.cos(e),Math.sin(e))}}}]);
1
+ window.snowfall=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){const i=n(1),{lerp:r}=n(2),o=document.querySelector("#snow-container"),a=document.createElement("canvas"),d=a.getContext("2d");let s=i.create(0,.7),l=i.create(0,0),c=200,u=[],f="#0d0014",g="#8d90b7",h="#ffffff",y=1,p=.02,v=!1,m=!1,w=!1;function x(e,t){(s=i.fromDegrees(e)).multiplyScalar(t)}function S(e,t){(l=i.fromDegrees(e)).multiplyScalar(t)}function b(){a.width=o.offsetWidth,a.height=o.offsetHeight,u=q(j())}function M(){w||(u.forEach(e=>{P.x=l.x,P.y=l.y,P.multiplyScalar(e.size+e.random),e.pos.add(P),O.x=s.x,O.y=s.y,O.multiplyScalar(e.size+e.random),e.pos.add(O);const t=e.noise;let n=i.create(y*Math.sin(p*z+t),0);e.pos.add(n),e.pos.x>a.width&&(e.pos.x=0),e.pos.x<0&&(e.pos.x=a.width),e.pos.y>a.height&&(e.pos.y=e.pos.y-a.height,e.pos.x=Math.random()*a.width),e.pos.y<0&&(e.pos.y=a.height-e.pos.y,e.pos.x=Math.random()*a.width),e.renderedSize<e.size&&(e.renderedSize=r(e.renderedSize,e.size,.025))}),previousPageYOffset=window.pageYOffset,z+=1,function(){d.clearRect(0,0,a.width,a.height),f&&(d.fillStyle=f,d.fillRect(0,0,a.width,a.height));const e=u.filter(e=>e.size>=7),t=u.filter(e=>e.size<7);d.fillStyle=g,t.forEach(e=>{d.beginPath(),_(e.pos,e.renderedSize),d.fill()}),d.fillStyle=h,e.forEach(e=>{d.beginPath(),_(e.pos,e.renderedSize),d.fill()})}()),window.requestAnimationFrame(M)}let z=0;const P=i.create(0,0),O=i.create(0,0);function q(e){let t=[];for(;e--;){const e=3+5*Math.random(),n=!0===v?0:e;t.push({pos:i.create(Math.random()*a.width,Math.random()*a.height),size:e,renderedSize:n,noise:10*Math.random(),amplitude:2*Math.random(),frequency:.01*Math.random(),random:Math.random()})}return t}function j(){const e=a.width*a.height;return Math.round(c*(e/2073600))}function _(e,t){d.arc(e.x,e.y,t,0,2*Math.PI,!1)}function E(){u=q(j())}e.exports={setAmplitude:function(e){y=e},setBackground:function(e){f=e},setDensity:function(e){c=e,E()},setFade:function(e){v=e,E()},setScroll:function(e){m=e},setFrequency:function(e){p=e},setGravity:x,setPrimary:function(e){g=e},setSecondary:function(e){h=e},setWind:S,setPaused:function(e){w=e},togglePaused:function(){w=!w},start:function(e={}){void 0!==e.bg&&(f=e.bg),void 0!==e.primary&&(g=e.primary),void 0!==e.secondary&&(h=e.secondary),void 0!==e.density&&(c=e.density),void 0!==e.fadeIn&&(v=e.fadeIn),void 0!==e.scroll&&(m=e.scroll),void 0!==e.wave&&(void 0!==e.wave.amplitude&&(y=e.wave.amplitude),void 0!==e.wave.frequency&&(p=e.wave.frequency)),void 0!==e.gravity&&(void 0!==e.gravity.angle&&void 0!==e.gravity.strength&&x(e.gravity.angle,e.gravity.strength),void 0!==e.gravity.angle&&void 0===e.gravity.strength&&x(e.gravity.angle,.7),void 0===e.gravity.angle&&void 0!==e.gravity.strength&&x(90,e.gravity.strength)),void 0!==e.wind&&(void 0!==e.wind.angle&&void 0!==e.wind.strength&&S(e.wind.angle,e.wind.strength),void 0!==e.wind.angle&&void 0===e.wind.strength&&S(e.wind.angle,0),void 0===e.wind.angle&&void 0!==e.wind.strength&&S(0,e.wind.strength)),a.width=o.offsetWidth,a.height=o.offsetHeight,o.appendChild(a),u=q(j()),window.onresize=b,window.requestAnimationFrame(M)}}},function(e,t){function n(e,t){let r=e,o=t;const a=()=>Math.sqrt(r*r+o*o),d=e=>{r*=e,o*=e},s=()=>{let e=a();r/=e,o/=e};return{add:e=>{r+=e.x,o+=e.y},addScalar:e=>{r+=e,o+=e},clone:i,divide:e=>{r/=e.x,o/=e.y},divideScalar:e=>{r/=e,o/=e},dot:e=>r*e.x+o*e.y,getLength:a,getOpposite:e=>n(-e.x,-e.y),getPerp:()=>n(-o,r),isEqualTo:e=>r==e.x&&o==e.y,multiply:e=>{r*=e.x,o*=e.y},multiplyScalar:d,normalise:s,setLength:e=>{s(),d(e)},subtract:e=>{r-=e.x,o-=e.y},subtractScalar:e=>{r-=e,o-=e},set x(e){r=e},get x(){return r},set y(e){o=e},get y(){return o}}}const i=e=>n(e.x,e.y);e.exports={clone:i,create:n,fromDegrees:e=>{const t=e*(Math.PI/180);return n(Math.cos(t),Math.sin(t))}}},function(e,t){e.exports={lerp:function(e,t,n){return e*(1-n)+t*n}}}]);
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@erikwatson/snowfall",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "Nice snow in a JS Canvas.",
5
- "main": "dist/snowfall.js",
5
+ "main": "dist/snowfall.min.js",
6
6
  "repository": "git@github.com:erikwatson/snowfall.js.git",
7
7
  "author": "Erik Watson <erik@erikwatson.me>",
8
8
  "license": "MIT",
@@ -16,6 +16,7 @@
16
16
  "build": "yarn webpack --config ./webpack.development.js",
17
17
  "build:production": "yarn webpack --config ./webpack.production.js",
18
18
  "build:all": "yarn build && yarn build:production",
19
+ "build:docs": "yarn jsdoc src/snowfall.js -d ./docs README.md",
19
20
  "watch": "yarn run build --watch",
20
21
  "pub": "yarn build:all && npm publish"
21
22
  },
package/dist/snowfall.js DELETED
@@ -1,586 +0,0 @@
1
- window["snowfall"] =
2
- /******/ (function(modules) { // webpackBootstrap
3
- /******/ // The module cache
4
- /******/ var installedModules = {};
5
- /******/
6
- /******/ // The require function
7
- /******/ function __webpack_require__(moduleId) {
8
- /******/
9
- /******/ // Check if module is in cache
10
- /******/ if(installedModules[moduleId]) {
11
- /******/ return installedModules[moduleId].exports;
12
- /******/ }
13
- /******/ // Create a new module (and put it into the cache)
14
- /******/ var module = installedModules[moduleId] = {
15
- /******/ i: moduleId,
16
- /******/ l: false,
17
- /******/ exports: {}
18
- /******/ };
19
- /******/
20
- /******/ // Execute the module function
21
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
22
- /******/
23
- /******/ // Flag the module as loaded
24
- /******/ module.l = true;
25
- /******/
26
- /******/ // Return the exports of the module
27
- /******/ return module.exports;
28
- /******/ }
29
- /******/
30
- /******/
31
- /******/ // expose the modules object (__webpack_modules__)
32
- /******/ __webpack_require__.m = modules;
33
- /******/
34
- /******/ // expose the module cache
35
- /******/ __webpack_require__.c = installedModules;
36
- /******/
37
- /******/ // define getter function for harmony exports
38
- /******/ __webpack_require__.d = function(exports, name, getter) {
39
- /******/ if(!__webpack_require__.o(exports, name)) {
40
- /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
41
- /******/ }
42
- /******/ };
43
- /******/
44
- /******/ // define __esModule on exports
45
- /******/ __webpack_require__.r = function(exports) {
46
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
47
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
48
- /******/ }
49
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
50
- /******/ };
51
- /******/
52
- /******/ // create a fake namespace object
53
- /******/ // mode & 1: value is a module id, require it
54
- /******/ // mode & 2: merge all properties of value into the ns
55
- /******/ // mode & 4: return value when already ns object
56
- /******/ // mode & 8|1: behave like require
57
- /******/ __webpack_require__.t = function(value, mode) {
58
- /******/ if(mode & 1) value = __webpack_require__(value);
59
- /******/ if(mode & 8) return value;
60
- /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
61
- /******/ var ns = Object.create(null);
62
- /******/ __webpack_require__.r(ns);
63
- /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
64
- /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
65
- /******/ return ns;
66
- /******/ };
67
- /******/
68
- /******/ // getDefaultExport function for compatibility with non-harmony modules
69
- /******/ __webpack_require__.n = function(module) {
70
- /******/ var getter = module && module.__esModule ?
71
- /******/ function getDefault() { return module['default']; } :
72
- /******/ function getModuleExports() { return module; };
73
- /******/ __webpack_require__.d(getter, 'a', getter);
74
- /******/ return getter;
75
- /******/ };
76
- /******/
77
- /******/ // Object.prototype.hasOwnProperty.call
78
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
79
- /******/
80
- /******/ // __webpack_public_path__
81
- /******/ __webpack_require__.p = "";
82
- /******/
83
- /******/
84
- /******/ // Load entry module and return exports
85
- /******/ return __webpack_require__(__webpack_require__.s = "./src/snowfall.js");
86
- /******/ })
87
- /************************************************************************/
88
- /******/ ({
89
-
90
- /***/ "./src/snowfall.js":
91
- /*!*************************!*\
92
- !*** ./src/snowfall.js ***!
93
- \*************************/
94
- /*! no static exports found */
95
- /***/ (function(module, exports, __webpack_require__) {
96
-
97
- /**
98
- * @module snowfall
99
- */
100
-
101
- const vec2 = __webpack_require__(/*! ./vec2 */ "./src/vec2.js")
102
-
103
- const appContainer = document.querySelector('#snow-container')
104
-
105
- const canvas = document.createElement('canvas')
106
- const ctx = canvas.getContext('2d')
107
-
108
- let gravity = vec2.create(0, 0.7)
109
- let wind = vec2.create(0, 0)
110
- let density = 200
111
-
112
- let snowflakes = []
113
-
114
- let bg = '#0d0014'
115
- let primary = '#8d90b7'
116
- let secondary = '#ffffff'
117
-
118
- let amplitude = 1.0
119
- let frequency = 0.02
120
-
121
- /**
122
- * @param {Object} config - A config, possibly from the Visual Config Editor.
123
- * @param {string} config.bg - A hex string representing the Background Colour
124
- * of the canvas.
125
- * @param {string} config.primary - A hex string representing the colour of the
126
- * snowflakes in the foreground.
127
- * @param {string} config.secondary - A hex string representing the colour of
128
- * the snowflakes in the background.
129
- * @param {number} config.density - A number representing the required density
130
- * of snowflakes on screen. Note, this is not the actual number of snowflakes.
131
- *
132
- * @param {Object} config.wave - Configure the wave motion of the snowflakes.
133
- * @param {number} config.wave.frequency - The frequency of the wave the
134
- * snowflakes follow.
135
- * @param {number} config.wave.amplitude - The amplitude of the wave the
136
- * snowflakes follow.
137
- *
138
- * @param {Object} config.gravity - Configure the gravity of the simulation.
139
- * @param {number} config.gravity.angle - The angle of gravity, in degrees.
140
- * @param {number} config.gravity.strength - The strength of gravity.
141
- *
142
- * @param {Object} config.wind - Configure the wind.
143
- * @param {number} config.wind.angle - The angle of the wind, in degrees.
144
- * @param {number} config.wind.strength - The strength of the wind.
145
- */
146
- function start(config = {}) {
147
- if (config.bg !== undefined) {
148
- bg = config.bg
149
- }
150
-
151
- if (config.primary !== undefined) {
152
- primary = config.primary
153
- }
154
-
155
- if (config.secondary !== undefined) {
156
- secondary = config.secondary
157
- }
158
-
159
- if (config.density !== undefined) {
160
- density = config.density
161
- }
162
-
163
- if (config.wave !== undefined) {
164
- if (config.wave.amplitude !== undefined) {
165
- amplitude = config.wave.amplitude
166
- }
167
-
168
- if (config.wave.frequency !== undefined) {
169
- frequency = config.wave.frequency
170
- }
171
- }
172
-
173
- if (config.gravity !== undefined) {
174
- if (
175
- config.gravity.angle !== undefined &&
176
- config.gravity.strength !== undefined
177
- ) {
178
- setGravity(config.gravity.angle, config.gravity.strength)
179
- }
180
-
181
- if (
182
- config.gravity.angle !== undefined &&
183
- config.gravity.strength === undefined
184
- ) {
185
- setGravity(config.gravity.angle, 0.6)
186
- }
187
-
188
- if (
189
- config.gravity.angle === undefined &&
190
- config.gravity.strength !== undefined
191
- ) {
192
- setGravity(90, config.gravity.strength)
193
- }
194
- }
195
-
196
- if (config.wind !== undefined) {
197
- if (config.wind.angle !== undefined && config.wind.strength !== undefined) {
198
- setWind(config.wind.angle, config.wind.strength)
199
- }
200
-
201
- if (config.wind.angle !== undefined && config.wind.strength === undefined) {
202
- setWind(config.wind.angle, 0.0)
203
- }
204
-
205
- if (config.wind.angle === undefined && config.wind.strength !== undefined) {
206
- setWind(0.0, config.wind.strength)
207
- }
208
- }
209
-
210
- canvas.width = appContainer.offsetWidth
211
- canvas.height = appContainer.offsetHeight
212
- appContainer.appendChild(canvas)
213
-
214
- snowflakes = makeSnowflakes(requiredSnowflakes())
215
-
216
- window.onresize = onResize
217
- window.requestAnimationFrame(onEnterFrame)
218
- }
219
-
220
- /**
221
- * Set the background colour
222
- *
223
- * @param {string} colour - The background colour of the Canvas
224
- */
225
- function setBackground(col) {
226
- bg = col
227
- }
228
-
229
- /**
230
- * Sets the colour of the Snowflakes in the foreground
231
- *
232
- * @param {string} colour - A Hex string representing the colour of the
233
- * foreground snow.
234
- */
235
- function setPrimary(col) {
236
- primary = col
237
- }
238
-
239
- /**
240
- * Sets the colour of the Snowflakes in the background
241
- *
242
- * @param {string} colour - A Hex string representing the colour of the
243
- * background snow.
244
- */
245
- function setSecondary(col) {
246
- secondary = col
247
- }
248
-
249
- /**
250
- * Set the density of the Snowflakes. This is the number of snowflakes on screen
251
- * at a resolution of 1280 x 1080, but this number is scaled up and down at
252
- * higher and lower resolutions respectively to give a consistent look when
253
- * resizing.
254
- *
255
- * @param {number} density - A number representing the density of snowflakes.
256
- */
257
- function setDensity(den) {
258
- density = den
259
- restart()
260
- }
261
-
262
- /**
263
- * Set the Amplitude of the Wave motion of the Snowflakes
264
- *
265
- * @param {number} amplitude - The Amplitude to set
266
- */
267
- function setAmplitude(num) {
268
- amplitude = num
269
- }
270
-
271
- /**
272
- * Set the Frequency of the Wave motion of the Snowflakes.
273
- *
274
- * @param {number} frequency - The frequency to set
275
- */
276
- function setFrequency(freq) {
277
- frequency = freq
278
- }
279
-
280
- /**
281
- * Set the angle and strength of gravity in the simulation.
282
- *
283
- * @param {number} angle - The angle of gravity, in degrees
284
- * @param {number} strength - The strength of the gravity
285
- */
286
- function setGravity(degrees, strength) {
287
- gravity = vec2.fromDegrees(degrees)
288
- gravity.multiplyScalar(strength)
289
- }
290
-
291
- /**
292
- * Set the angle and strength of the wind in the simulation.
293
- *
294
- * @param {number} angle - The angle of the wind, in degrees
295
- * @param {number} strength - The strength of the wind
296
- */
297
- function setWind(degrees, strength) {
298
- wind = vec2.fromDegrees(degrees)
299
- wind.multiplyScalar(strength)
300
- }
301
-
302
- function onResize() {
303
- canvas.width = appContainer.offsetWidth
304
- canvas.height = appContainer.offsetHeight
305
-
306
- snowflakes = makeSnowflakes(requiredSnowflakes())
307
- }
308
-
309
- function onEnterFrame() {
310
- update()
311
- render()
312
-
313
- window.requestAnimationFrame(onEnterFrame)
314
- }
315
-
316
- let t = 0
317
-
318
- const w = vec2.create(0, 0)
319
- const g = vec2.create(0, 0)
320
-
321
- let sine = null
322
-
323
- function update() {
324
- snowflakes.forEach(snowflake => {
325
- w.x = wind.x
326
- w.y = wind.y
327
-
328
- w.multiplyScalar(snowflake.size + snowflake.random)
329
-
330
- snowflake.pos.add(w)
331
-
332
- g.x = gravity.x
333
- g.y = gravity.y
334
-
335
- g.multiplyScalar(snowflake.size + snowflake.random)
336
-
337
- snowflake.pos.add(g)
338
-
339
- const phase = snowflake.noise
340
-
341
- sine = vec2.create(amplitude * Math.sin(frequency * t + phase), 0)
342
-
343
- snowflake.pos.add(sine)
344
-
345
- if (snowflake.pos.x > canvas.width) {
346
- snowflake.pos.x = 0
347
- }
348
-
349
- if (snowflake.pos.x < 0) {
350
- snowflake.pos.x = canvas.width
351
- }
352
-
353
- if (snowflake.pos.y > canvas.height) {
354
- snowflake.pos.y = 0
355
- snowflake.pos.x = Math.random() * canvas.width
356
- }
357
-
358
- if (snowflake.pos.y < 0) {
359
- snowflake.pos.y = canvas.height
360
- snowflake.pos.x = Math.random() * canvas.width
361
- }
362
- })
363
-
364
- t += 1
365
- }
366
-
367
- function render() {
368
- ctx.clearRect(0, 0, canvas.width, canvas.height)
369
-
370
- if (bg) {
371
- ctx.fillStyle = bg
372
- ctx.fillRect(0, 0, canvas.width, canvas.height)
373
- }
374
-
375
- const bgSize = 7
376
-
377
- const foreground = snowflakes.filter(x => x.size >= bgSize)
378
- const background = snowflakes.filter(x => x.size < bgSize)
379
-
380
- ctx.fillStyle = primary
381
- background.forEach(snowflake => {
382
- ctx.beginPath()
383
- drawCircle(snowflake.pos, snowflake.size)
384
- ctx.fill()
385
- })
386
-
387
- ctx.fillStyle = secondary
388
- foreground.forEach(snowflake => {
389
- ctx.beginPath()
390
- drawCircle(snowflake.pos, snowflake.size)
391
- ctx.fill()
392
- })
393
- }
394
-
395
- function makeSnowflakes(num) {
396
- let result = []
397
-
398
- while (num--) {
399
- result.push({
400
- pos: vec2.create(
401
- Math.random() * canvas.width,
402
- Math.random() * canvas.height
403
- ),
404
- size: 3 + Math.random() * 5,
405
- // Random value, just to add some uncertainty
406
- noise: Math.random() * 10,
407
- amplitude: Math.random() * 2,
408
- frequency: Math.random() * 0.01,
409
- random: Math.random()
410
- })
411
- }
412
-
413
- return result
414
- }
415
-
416
- // This function figures out how many snowflakes we should use for our given
417
- // canvas size.
418
- //
419
- // Just setting a fixed number of snowflakes would give an uneven distribution
420
- // of snowflakes across different screen sizes, for example.
421
- function requiredSnowflakes() {
422
- const tenEightyPee = 1920 * 1080
423
- const thisScreen = canvas.width * canvas.height
424
- const snowflakeCount = Math.round(density * (thisScreen / tenEightyPee))
425
-
426
- return snowflakeCount
427
- }
428
-
429
- function drawCircle(position, radius) {
430
- ctx.arc(position.x, position.y, radius, 0, 2 * Math.PI, false)
431
- }
432
-
433
- function restart() {
434
- snowflakes = makeSnowflakes(requiredSnowflakes())
435
- }
436
-
437
- module.exports = {
438
- setAmplitude,
439
- setBackground,
440
- setDensity,
441
- setFrequency,
442
- setGravity,
443
- setPrimary,
444
- setSecondary,
445
- setWind,
446
- start
447
- }
448
-
449
-
450
- /***/ }),
451
-
452
- /***/ "./src/vec2.js":
453
- /*!*********************!*\
454
- !*** ./src/vec2.js ***!
455
- \*********************/
456
- /*! no static exports found */
457
- /***/ (function(module, exports) {
458
-
459
- function create(_x, _y) {
460
- let x = _x
461
- let y = _y
462
-
463
- const add = v => {
464
- x += v.x
465
- y += v.y
466
- }
467
-
468
- const addScalar = s => {
469
- x += s
470
- y += s
471
- }
472
-
473
- const divide = v => {
474
- x /= v.x
475
- y /= v.y
476
- }
477
-
478
- const divideScalar = s => {
479
- x /= s
480
- y /= s
481
- }
482
-
483
- const dot = v => {
484
- return x * v.x + y * v.y
485
- }
486
-
487
- const getLength = () => {
488
- return Math.sqrt(x * x + y * y)
489
- }
490
-
491
- const getOpposite = v => {
492
- return create(-v.x, -v.y)
493
- }
494
-
495
- const getPerp = () => {
496
- return create(-y, x)
497
- }
498
-
499
- const isEqualTo = v => {
500
- return x == v.x && y == v.y
501
- }
502
-
503
- const multiply = v => {
504
- x *= v.x
505
- y *= v.y
506
- }
507
-
508
- const multiplyScalar = s => {
509
- x *= s
510
- y *= s
511
- }
512
-
513
- const normalise = () => {
514
- let l = getLength()
515
-
516
- x = x / l
517
- y = y / l
518
- }
519
-
520
- const setLength = l => {
521
- normalise()
522
- multiplyScalar(l)
523
- }
524
-
525
- const subtract = v => {
526
- x -= v.x
527
- y -= v.y
528
- }
529
-
530
- const subtractScalar = s => {
531
- x -= s
532
- y -= s
533
- }
534
-
535
- return {
536
- add,
537
- addScalar,
538
- clone,
539
- divide,
540
- divideScalar,
541
- dot,
542
- getLength,
543
- getOpposite,
544
- getPerp,
545
- isEqualTo,
546
- multiply,
547
- multiplyScalar,
548
- normalise,
549
- setLength,
550
- subtract,
551
- subtractScalar,
552
- set x(_x) {
553
- x = _x
554
- },
555
- get x() {
556
- return x
557
- },
558
- set y(_y) {
559
- y = _y
560
- },
561
- get y() {
562
- return y
563
- }
564
- }
565
- }
566
-
567
- const fromDegrees = degrees => {
568
- const rad = degrees * (Math.PI / 180)
569
- return create(Math.cos(rad), Math.sin(rad))
570
- }
571
-
572
- const clone = v => {
573
- return create(v.x, v.y)
574
- }
575
-
576
- module.exports = {
577
- clone,
578
- create,
579
- fromDegrees
580
- }
581
-
582
-
583
- /***/ })
584
-
585
- /******/ });
586
- //# sourceMappingURL=snowfall.js.map