From fd4b01e8c73f5db47719516ccdc79a021317eac2 Mon Sep 17 00:00:00 2001
From: muerwre <gotham48@gmail.com>
Date: Thu, 4 Apr 2019 18:03:36 +0700
Subject: [PATCH] added god-rays for fun :-)

---
 src/components/main/GodRays/index.tsx | 139 ++++++++++++++++++++++++++
 src/containers/LoginLayout/index.tsx  |   2 +
 2 files changed, 141 insertions(+)
 create mode 100644 src/components/main/GodRays/index.tsx

diff --git a/src/components/main/GodRays/index.tsx b/src/components/main/GodRays/index.tsx
new file mode 100644
index 00000000..595ffc52
--- /dev/null
+++ b/src/components/main/GodRays/index.tsx
@@ -0,0 +1,139 @@
+import * as React from 'react';
+
+interface IGodRaysProps {
+  raised?: boolean,
+}
+
+export class GodRays extends React.Component<IGodRaysProps> {
+  state = {
+    width: 0,
+    height: 0,
+    rays: [...new Array(6)].map(() => ({
+      angle: Math.random() * 1.4 - 0.7,
+      iterator: Math.random() > 0.5 ? 1 : -1,
+      speed: Math.random() * 0.0005 + 0.0005,
+      weight: Math.random() * 300,
+      opacity: Math.random(),
+      pulsar: Math.random() > 0.5 ? 1 : -1,
+    })),
+    particles: [],
+  };
+
+  init = () => {
+    window.requestAnimationFrame(() => this.draw());
+
+    this.inc = 1;
+  };
+
+  draw = () => {
+    if ((this.props.raised) || !this.canvas) {
+      return setTimeout(() => window.requestAnimationFrame(this.draw), 1000);
+    }
+
+    const { width, height, rays, particles } = this.state;
+
+    const ctx = this.canvas.getContext('2d');
+
+    ctx.globalCompositeOperation = "luminosity";
+    ctx.clearRect(0, 0, width, height + 100); // clear canvas
+    ctx.save();
+
+    rays.map(({ angle, iterator, weight, speed, pulsar, opacity }, index) => {
+      const gradient = ctx.createLinearGradient(0, 0, 0, height * 1.3);
+      gradient.addColorStop(0.2, `rgba(255, 255, 255, ${opacity * 0.1})`);
+      gradient.addColorStop(1, `rgba(255, 255, 255, 0)`);
+
+      const gradient2 = ctx.createLinearGradient(0, 0, 0, height * 1.3);
+      gradient2.addColorStop(0.2, `rgba(255, 255, 255, ${opacity * 0.2})`);
+      gradient2.addColorStop(1, "rgba(255, 255, 255, 0)");
+
+      ctx.save();
+      ctx.translate(width / 2, -600);
+      ctx.rotate(angle);
+      ctx.translate(-width / 2, 600);
+
+      ctx.beginPath();
+      ctx.fillStyle = gradient;
+      ctx.moveTo(((width / 2) - (weight / 2)), -600);
+      ctx.lineTo(((width / 2) + (weight / 2)), -600);
+      ctx.lineTo(((width / 2) + (weight / 2 + 300)), height * 1.4);
+      ctx.lineTo(((width / 2) - (weight / 2 + 300)), height * 1.4);
+      ctx.fill();
+      ctx.closePath();
+
+      ctx.beginPath();
+      ctx.fillStyle = gradient2;
+      ctx.moveTo(((width / 2) - (weight / 6)), -600);
+      ctx.lineTo(((width / 2) + (weight / 6)), -600);
+      ctx.lineTo(((width / 2) + (weight / 6 + 50)), height * 1.4);
+      ctx.lineTo(((width / 2) - (weight / 6 + 250)), height * 1.4);
+      ctx.fill();
+      ctx.closePath();
+
+      rays[index].angle += iterator * speed;
+      rays[index].opacity += pulsar * 0.01;
+
+      if (rays[index].angle > 0.8) rays[index].iterator = -1;
+      if (rays[index].angle < -0.8) rays[index].iterator = 1;
+
+      if (rays[index].opacity >= 1) rays[index].pulsar = -1;
+      if (rays[index].opacity <= 0) rays[index].pulsar = 1;
+
+      ctx.restore();
+    });
+
+    setTimeout(() => window.requestAnimationFrame(this.draw), 1000 / 15);
+  };
+
+  generateParticles = ({ width, height }) => {
+    const particles = [...new Array(1)].map(() => ({
+      // left: Math.random() * width / 2 + width / 4,
+      left: Math.random() * width * 0.7 + 0.15,
+      top: Math.random() * (height + 400) - 400,
+      iterator: Math.random() * 10,
+      speed: Math.random() * 0.2 + 0.2,
+    }));
+
+    this.setState({ particles });
+  };
+
+  componentDidMount() {
+    const { innerWidth: width, innerHeight: height } = window;
+
+    this.setState({ width, height });
+    // this.generateParticles({ width, height });
+
+    this.init();
+  }
+
+  render(){
+    const { width, height } = this.state;
+
+    return (
+      <div style={{
+        position: 'fixed',
+        top: 0,
+        left: 0,
+        width: '100%',
+        height: '100%',
+        zIndex: -1,
+        opacity: 0.5,
+        pointerEvents: 'none',
+      }}>
+        <canvas
+          width={width}
+          height={height + 100}
+          style={{
+            filter: 'blur(20px)',
+            position: 'relative',
+            top: -100,
+          }}
+          ref={el => { this.canvas = el; }}
+        />
+      </div>
+    );
+  }
+
+  canvas: HTMLCanvasElement;
+  inc;
+};
diff --git a/src/containers/LoginLayout/index.tsx b/src/containers/LoginLayout/index.tsx
index b03ac67e..57bfd79e 100644
--- a/src/containers/LoginLayout/index.tsx
+++ b/src/containers/LoginLayout/index.tsx
@@ -1,11 +1,13 @@
 import * as React from 'react';
 import { LoginForm } from '$components/login/LoginForm';
 import { Header } from "$components/main/Header";
+import { GodRays } from "$components/main/GodRays";
 
 const style = require('./style.scss');
 
 export const LoginLayout: React.FunctionComponent<{}> = () => (
   <div className={style.wrapper}>
+    <GodRays />
     <div className={style.header}>
       <Header />
     </div>