@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 +54 -13
- package/dist/snowfall.min.js +1 -1
- package/package.json +3 -2
- package/dist/snowfall.js +0 -586
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
snowfall.
|
|
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
|
-
|
|
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)
|
package/dist/snowfall.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
window.snowfall=function(
|
|
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
|
|
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
|