From 62af83b74fc7b20048186b1ecedf9a55759f5789 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Fri, 21 Dec 2018 03:32:42 -0500 Subject: [PATCH] Adds snow --- src/ui/scss/main.scss | 23 +++++++++ src/ui/welcome/index.html | 14 ++++++ src/ui/welcome/index.ts | 2 + src/ui/welcome/snow.ts | 117 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+) create mode 100644 src/ui/welcome/snow.ts diff --git a/src/ui/scss/main.scss b/src/ui/scss/main.scss index 656202b..8a4a6f4 100644 --- a/src/ui/scss/main.scss +++ b/src/ui/scss/main.scss @@ -10,6 +10,29 @@ body { line-height: 1.4; } +canvas.snow { + max-width: calc(100% - 20px); + pointer-events: none; + position: fixed; + z-index: 2147483646; +} + +.snow__trigger { + cursor: pointer; + position: fixed; + right: 10px; + top: 5px; + transform: rotate(-20deg); + width: 22px; + z-index: 2147483647; + + & svg:hover { + & path:first-child { + fill: #f30000; + } + } +} + a { border: 0; color: var(--link-color); diff --git a/src/ui/welcome/index.html b/src/ui/welcome/index.html index 2b33a42..c15e35f 100644 --- a/src/ui/welcome/index.html +++ b/src/ui/welcome/index.html @@ -5,6 +5,20 @@ + +
+ + + + + +
diff --git a/src/ui/welcome/index.ts b/src/ui/welcome/index.ts index 4096bc0..975dcff 100644 --- a/src/ui/welcome/index.ts +++ b/src/ui/welcome/index.ts @@ -1,4 +1,6 @@ 'use strict'; import { WelcomeApp } from './app'; +import { Snow } from './snow'; new WelcomeApp(); +requestAnimationFrame(() => new Snow()); diff --git a/src/ui/welcome/snow.ts b/src/ui/welcome/snow.ts new file mode 100644 index 0000000..fc82e23 --- /dev/null +++ b/src/ui/welcome/snow.ts @@ -0,0 +1,117 @@ +'use strict'; + +function randomBetween(min: number, max: number) { + return min + Math.random() * (max - min); +} + +class Snowflake { + alpha = 0; + radius = 0; + x = 0; + y = 0; + + private _vx = 0; + private _vy = 0; + + constructor() { + this.reset(); + } + + reset() { + this.alpha = randomBetween(0.1, 0.9); + this.radius = randomBetween(1, 4); + this.x = randomBetween(0, window.innerWidth); + this.y = randomBetween(0, -window.innerHeight); + this._vx = randomBetween(-3, 3); + this._vy = randomBetween(2, 5); + } + + update() { + this.x += this._vx; + this.y += this._vy; + + if (this.y + this.radius > window.innerHeight) { + this.reset(); + } + } +} + +export class Snow { + snowing = false; + + private readonly _canvas: any; + private readonly _ctx: any; + private _height: number = 0; + private _width: number = 0; + private readonly _snowflakes: Snowflake[] = []; + + private readonly _clearBound: any; + private readonly _updateBound: any; + + constructor() { + this._clearBound = this.clear.bind(this); + this._updateBound = this.update.bind(this); + + this._canvas = document.querySelector('canvas.snow'); + this._ctx = this._canvas.getContext('2d'); + + const trigger = document.querySelector('.snow__trigger'); + if (trigger) { + trigger.addEventListener('click', () => this.onToggle()); + } + + window.addEventListener('resize', () => this.onResize()); + this.onResize(); + + this.onToggle(); + } + + onToggle() { + this.snowing = !this.snowing; + if (this.snowing) { + this.createSnowflakes(); + requestAnimationFrame(this._updateBound); + } + } + + onResize() { + this._height = window.innerHeight; + this._width = window.innerWidth; + this._canvas.width = this._width; + this._canvas.height = this._height; + } + + clear() { + this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + this._snowflakes.length = 0; + } + + createSnowflakes() { + const flakes = window.innerWidth / 4; + + for (let i = 0; i < flakes; i++) { + this._snowflakes.push(new Snowflake()); + } + } + + update() { + this._ctx.clearRect(0, 0, this._width, this._height); + + const color = document.body.classList.contains('vscode-light') ? '#424242' : '#fff'; + + for (const flake of this._snowflakes) { + flake.update(); + + this._ctx.save(); + this._ctx.fillStyle = color; + this._ctx.beginPath(); + this._ctx.arc(flake.x, flake.y, flake.radius, 0, Math.PI * 2); + this._ctx.closePath(); + this._ctx.globalAlpha = flake.alpha; + this._ctx.fill(); + this._ctx.restore(); + } + + requestAnimationFrame(this.snowing ? this._updateBound : this._clearBound); + } +}