uo-tashtagol.kemobl.ru

Форк
0
324 строки · 13.3 Кб
1
(function () {
2
    let lastTime = 0;
3
    let vendors = ['webkit', 'moz'];
4
    for (let x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
5
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
6
        window.cancelAnimationFrame =
7
            window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
8
    }
9

10
    if (!window.requestAnimationFrame)
11
        window.requestAnimationFrame = function (callback, element) {
12
            let currTime = new Date().getTime();
13
            let timeToCall = Math.max(0, 16 - (currTime - lastTime));
14
            let id = window.setTimeout(function () { callback(currTime + timeToCall); },
15
                timeToCall);
16
            lastTime = currTime + timeToCall;
17
            return id;
18
        };
19

20
    if (!window.cancelAnimationFrame)
21
        window.cancelAnimationFrame = function (id) {
22
            clearTimeout(id);
23
        };
24
}());
25

26
(function () {
27
    let Snowfall = function (element, opts) {
28
        let defaults = {
29
            flakeCount: 35,
30
            flakeColor: '#ffffff',
31
            flakeIndex: 999999,
32
            minSize: 1,
33
            maxSize: 2,
34
            minSpeed: 1,
35
            maxSpeed: 5,
36
            round: false,
37
            shadow: false,
38
            collection: false,
39
            collectionHeight: 40,
40
            deviceorientation: false
41
        },
42
            options = { ...defaults, ...opts },
43
            random = function random(min, max) {
44
                return Math.round(min + Math.random() * (max - min));
45
            };
46

47
        if (!element.data) {
48
            element.data = {}
49
        }
50
        element.data.snowfall = this;
51
        let canvasCollection = []
52

53
        function Flake(_x, _y, _size, _speed, _id) {
54
            this.id = _id;
55
            this.x = _x;
56
            this.y = _y;
57
            this.size = _size;
58
            this.speed = _speed;
59
            this.step = 0;
60
            this.stepSize = random(1, 10) / 100;
61

62
            if (options.collection) {
63
                this.target = canvasCollection[random(0, canvasCollection.length - 1)];
64
            }
65

66
            let flakeMarkup = null;
67

68
            if (options.image) {
69
                flakeMarkup = document.createElement("img");
70
                flakeMarkup.src = options.image;
71
            } else {
72
                flakeMarkup = document.createElement("div");
73
                flakeMarkup.style.background = options.flakeColor;
74
            }
75
            let attrs = { 'class': 'snowfall-flakes', 'id': 'flake-' + this.id }
76
            let style = { 'width': `${this.size}px`, 'height': `${this.size}px`, 'position': 'absolute', 'top': this.y, 'left': this.x, 'fontSize': 0, 'zIndex': options.flakeIndex }
77
            for (const key in attrs) flakeMarkup.setAttribute(key, attrs[key]);
78
            for (const key in style) flakeMarkup.style[key] = style[key];
79

80
            if (element.tagName === document.tagName) element = document.body;
81
            element.append(flakeMarkup);
82

83
            this.element = document.getElementById('flake-' + this.id);
84

85
            // Update function, used to update the snow flakes, and checks current snowflake against bounds
86
            this.update = function () {
87
                this.y += this.speed;
88

89
                if (this.y > (elHeight) - (this.size + 6)) {
90
                    this.reset();
91
                }
92

93
                this.element.style.top = this.y + 'px';
94
                this.element.style.left = this.x + 'px';
95

96
                this.step += this.stepSize;
97

98
                if (doRatio === false) {
99
                    this.x += Math.cos(this.step);
100
                } else {
101
                    this.x += (doRatio + Math.cos(this.step));
102
                }
103

104
                // Pileup check
105
                if (options.collection) {
106
                    let canvas = this.target.element,
107
                        parentBounds = canvas.data.parent.getBoundingClientRect();
108
                    canvas.style.width = parentBounds.width + 'px';
109
                    canvas.style.left = parentBounds.left + 'px';
110
                    if (this.x > this.target.x && this.x < this.target.width + this.target.x && this.y > this.target.y && this.y < this.target.height + this.target.y) {
111
                        let ctx = canvas.getContext("2d"),
112
                            curX = this.x - this.target.x,
113
                            curY = this.y - this.target.y,
114
                            colData = this.target.colData;
115
                        if (colData[parseInt(curX)][parseInt(curY + this.speed + this.size)] !== undefined || curY + this.speed + this.size > this.target.height) {
116
                            if (curY + this.speed + this.size > this.target.height) {
117
                                while (curY + this.speed + this.size > this.target.height && this.speed > 0) {
118
                                    this.speed *= .5;
119
                                }
120

121
                                ctx.fillStyle = "#fff";
122

123
                                if (colData[parseInt(curX)][parseInt(curY + this.speed + this.size)] == undefined) {
124
                                    colData[parseInt(curX)][parseInt(curY + this.speed + this.size)] = 1;
125
                                    ctx.fillRect(curX, (curY) + this.speed + this.size, this.size, this.size);
126
                                } else {
127
                                    colData[parseInt(curX)][parseInt(curY + this.speed)] = 1;
128
                                    ctx.fillRect(curX, curY + this.speed, this.size, this.size);
129
                                }
130
                                this.reset();
131
                            } else {
132
                                // flow to the sides
133
                                this.speed = 1;
134
                                this.stepSize = 0;
135

136
                                if (parseInt(curX) + 1 < this.target.width && colData[parseInt(curX) + 1][parseInt(curY) + 1] == undefined) {
137
                                    // go left
138
                                    this.x++;
139
                                } else if (parseInt(curX) - 1 > 0 && colData[parseInt(curX) - 1][parseInt(curY) + 1] == undefined) {
140
                                    // go right
141
                                    this.x--;
142
                                } else {
143
                                    //stop
144
                                    ctx.fillRect(curX, curY, this.size, this.size);
145
                                    colData[parseInt(curX)][parseInt(curY)] = 1;
146
                                    this.reset();
147
                                }
148
                            }
149
                        }
150
                    }
151
                }
152

153
                if (this.x > (elWidth) - widthOffset || this.x < widthOffset) {
154
                    this.reset();
155
                }
156
            }
157

158
            // Resets the snowflake once it reaches one of the bounds set
159
            this.reset = function () {
160
                this.y = 0;
161
                this.x = random(widthOffset, elWidth - widthOffset);
162
                this.stepSize = random(1, 10) / 100;
163
                this.size = random((options.minSize * 100), (options.maxSize * 100)) / 100;
164
                this.speed = random(options.minSpeed, options.maxSpeed);
165
            }
166
        }
167

168
        // local vars
169
        let flakes = [],
170
            flakeId = 0,
171
            i = 0,
172
            elHeight = element.clientHeight,
173
            elWidth = element.clientWidth,
174
            widthOffset = 0,
175
            snowTimeout = 0;
176

177
        // Collection Piece ******************************
178
        if (options.collection !== false) {
179
            let testElem = document.createElement('canvas');
180
            if (!!(testElem.getContext && testElem.getContext('2d'))) {
181
                let elements = document.querySelectorAll(options.collection),
182
                    collectionHeight = options.collectionHeight;
183

184
                for (let i = 0; i < elements.length; i++) {
185
                    let bounds = elements[i].getBoundingClientRect(),
186
                        canvas = document.createElement('canvas'),
187
                        collisionData = [],
188
                        ctx = canvas.getContext('2d');
189
                    canvas.data = {}
190

191
                    if (bounds.top - collectionHeight > 0) {
192
                        document.body.appendChild(canvas);
193
                        canvas.style.position = 'absolute';
194
                        canvas.height = collectionHeight;
195
                        canvas.width = bounds.width;
196
                        canvas.style.left = bounds.left + 'px';
197
                        canvas.style.top = bounds.top - collectionHeight + 'px';
198
                        canvas.data.parent = elements[i];
199

200
                        for (let w = 0; w < bounds.width; w++) {
201
                            collisionData[w] = [];
202
                        }
203

204
                        if (options.image) {
205
                            const img = new Image();
206
                            img.src = options.image;
207
                            img.onload = function () {
208
                                const pattern = ctx.createPattern(img, 'repeat');
209
                                ctx.fillStyle = pattern;
210
                            }
211
                        } else {
212
                            ctx.fillStyle = "#fff";
213
                        }
214

215
                        canvasCollection.push({ element: canvas, x: bounds.left, y: bounds.top - collectionHeight, width: bounds.width, height: collectionHeight, colData: collisionData });
216
                    }
217
                }
218
            } else {
219
                // Canvas element isnt supported
220
                options.collection = false;
221
            }
222
        }
223
        // ************************************************
224

225
        // This will reduce the horizontal scroll bar from displaying, when the effect is applied to the whole page
226
        if (element.tagName === document.tagName) {
227
            widthOffset = 25;
228
        }
229

230
        // Bind the window resize event so we can get the innerHeight again
231
        window.addEventListener("resize", function () {
232
            elHeight = element.clientHeight;
233
            elWidth = element.offsetWidth;
234
            console.log(elHeight);
235
        });
236

237
        // initialize the flakes
238
        for (i = 0; i < options.flakeCount; i += 1) {
239
            flakeId = flakes.length;
240
            flakes.push(new Flake(random(widthOffset, elWidth - widthOffset), random(0, elHeight), random((options.minSize * 100), (options.maxSize * 100)) / 100, random(options.minSpeed, options.maxSpeed), flakeId));
241
        }
242

243
        // This adds the style to make the snowflakes round via border radius property 
244
        if (options.round) {
245
            let style = { '-moz-border-radius': options.maxSize, '-webkit-border-radius': options.maxSize, 'border-radius': options.maxSize }
246
            document.querySelectorAll('.snowfall-flakes').forEach(elem => {
247
                for (const key in style) {
248
                    elem.setAttribute(key, attributes[key]);
249
                }
250
            });
251
        }
252

253
        // This adds shadows just below the snowflake so they pop a bit on lighter colored web pages
254
        if (options.shadow) {
255
            let style = { '-moz-box-shadow': '1px 1px 1px #555', '-webkit-box-shadow': '1px 1px 1px #555', 'box-shadow': '1px 1px 1px #555' }
256
            document.querySelectorAll('.snowfall-flakes').forEach(elem => {
257
                for (const key in style) {
258
                    elem.setAttribute(key, attributes[key]);
259
                }
260
            });
261
        }
262

263
        // On newer Macbooks Snowflakes will fall based on deviceorientation
264
        let doRatio = false;
265
        if (options.deviceorientation) {
266
            window.addEventListener('deviceorientation', function (event) {
267
                doRatio = event.originalEvent.gamma * 0.1;
268
            });
269
        }
270

271
        // this controls flow of the updating snow
272
        function snow() {
273
            for (let i = 0; i < flakes.length; i += 1) {
274
                flakes[i].update();
275
            }
276

277
            snowTimeout = requestAnimationFrame(function () { snow() });
278
        }
279

280
        snow();
281

282
        // clears the snowflakes
283
        this.clear = function (element) {
284
            element.querySelectorAll('.snowfall-flakes').forEach(elem => elem.remove());
285
            flakes = [];
286
            cancelAnimationFrame(snowTimeout);
287
        }
288
    };
289

290
    // Initialize the options and the plugin
291
    // NodeList.prototype.snowfall = function (options) {
292
    //     for (let i = 0; i < this.length; i++) {
293
    //         const element = this[i];
294
    //         if (typeof options === "object" || options === undefined) {
295
    //             new Snowfall(element, options);
296
    //         } else if (typeof options === "string") {
297
    //             if (element.data.snowfall) {
298
    //                 element.data.snowfall.clear(element);
299
    //             }
300
    //         }
301
    //     }
302
    // }
303

304
    // Node.prototype.snowfall = function (options) {
305
    //     this.snowfall(options);
306
    //     return this;
307
    // }
308
    Node.prototype.snowfall = function (options) {
309
        options = options || {}
310

311
        if (typeof options === 'string' && this.data?.snowfall) {
312
            this.data.snowfall.clear(this);
313
            return this;
314
        }
315

316
        new Snowfall(this, options)
317

318
        return this;
319
    }
320

321
    NodeList.prototype.snowfall = function (options) {
322
        this.forEach(el => el.snowfall(options));
323
    }
324
})();

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.