Use shaped.js
This commit is contained in:
parent
7b9ead0f63
commit
82447b6a92
5 changed files with 120 additions and 134 deletions
|
@ -1,126 +0,0 @@
|
|||
/* eslint-disable no-extra-parens */
|
||||
const PROBABILITY = 1 / 50000;
|
||||
const HEIGHT = 2;
|
||||
const MIN_LINE_LENGTH = 20;
|
||||
const MAX_LINE_LENGTH = 300;
|
||||
const SPEED = 0.4;
|
||||
const APPEAR_PROBABILITY = 1;
|
||||
|
||||
const COLORS = [
|
||||
"#000000",
|
||||
"#00ff64",
|
||||
"rgba(0,255,100,0.2)",
|
||||
"#0064ff"
|
||||
];
|
||||
|
||||
function randomBetween (min, max) {
|
||||
return (Math.random() * (max - min)) + min;
|
||||
}
|
||||
|
||||
export class BackgroundCanvas {
|
||||
constructor (element) {
|
||||
this._element = element;
|
||||
this._ctx = element.getContext("2d");
|
||||
this._destroyed = false;
|
||||
this._animationFrameRequestID = null;
|
||||
this._lines = null;
|
||||
this.width = null;
|
||||
this.height = null;
|
||||
|
||||
this._windowListeners = {
|
||||
touchstart: () => {
|
||||
this._isTouch = true;
|
||||
},
|
||||
resize: () => {
|
||||
this._points = [];
|
||||
this._init();
|
||||
}
|
||||
};
|
||||
|
||||
Object.entries(this._windowListeners)
|
||||
.forEach(([event, listener]) => window.addEventListener(event, listener, { passive: true }));
|
||||
|
||||
this._init();
|
||||
this._loop();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this._destroyed) {
|
||||
throw new Error("Instance is already destroyed.");
|
||||
}
|
||||
|
||||
this._destroyed = true;
|
||||
this._element = null;
|
||||
this._ctx = null;
|
||||
|
||||
Object.entries(this._windowListeners)
|
||||
.forEach(([event, listener]) => window.removeEventListener(event, listener));
|
||||
|
||||
if (this._animationFrameRequestID !== null) {
|
||||
cancelAnimationFrame(this._animationFrameRequestID);
|
||||
}
|
||||
}
|
||||
|
||||
get destroyed() {
|
||||
return this._destroyed;
|
||||
}
|
||||
|
||||
_init() {
|
||||
this._element.width = window.innerWidth;
|
||||
this._element.height = window.innerHeight;
|
||||
|
||||
this.width = this._element.clientWidth;
|
||||
this.height = this._element.clientHeight;
|
||||
|
||||
while (this._lines === null || this._lines.length < 8) {
|
||||
this._lines = [];
|
||||
|
||||
for (let x = 0; x < this.width; x += 1) {
|
||||
for (let y = 0; y < this.height; y += 1) {
|
||||
if (Math.random() < PROBABILITY) {
|
||||
const color = Math.round(Math.random() * (COLORS.length - 1));
|
||||
const length = 0;
|
||||
|
||||
this._lines.push({ x, y, color, length });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_loop() {
|
||||
this._animationFrameRequestID = null;
|
||||
|
||||
this._draw();
|
||||
|
||||
if (!this._destroyed) {
|
||||
requestAnimationFrame(() => this._loop());
|
||||
}
|
||||
}
|
||||
|
||||
_draw() {
|
||||
// eslint-disable-next-line unicorn/prevent-abbreviations
|
||||
const ctx = this._ctx;
|
||||
|
||||
if (ctx === null) return;
|
||||
|
||||
ctx.clearRect(0, 0, this.width, this.height);
|
||||
|
||||
for (const line of this._lines) {
|
||||
if (line.length === 0) {
|
||||
if (Math.random() < APPEAR_PROBABILITY) {
|
||||
line.length = randomBetween(MIN_LINE_LENGTH, MAX_LINE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.fillStyle = COLORS[line.color];
|
||||
ctx.fillRect(line.x, line.y, line.length, HEIGHT);
|
||||
|
||||
line.x += SPEED;
|
||||
|
||||
if (line.x >= this.width) {
|
||||
line.x = -line.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@nuxtjs/pwa": "^3.0.0-beta.19",
|
||||
"kiste": "^1.2.6",
|
||||
"kiste": "^1.2.7",
|
||||
"nuxt": "^2.11.0",
|
||||
"vue": "^2.6.11",
|
||||
"vue-ripple-directive": "^2.0.1"
|
||||
|
@ -28,6 +28,7 @@
|
|||
"sass": "^1.24.4",
|
||||
"sass-loader": "^8.0.1",
|
||||
"serve": "^11.3.0",
|
||||
"shaped.js": "^1.0.2",
|
||||
"svg-to-vue-component": "^0.3.8"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,19 +110,102 @@
|
|||
<script>
|
||||
import KNavigationBar from "kiste/components/KNavigationBar.vue";
|
||||
import KFooter from "kiste/components/KFooter.vue";
|
||||
import { Canvas } from "shaped.js";
|
||||
import AnimatedLogo from "@/components/AnimatedLogo.vue";
|
||||
import GitHubIcon from "@/assets/icons/github.svg";
|
||||
import TwitterIcon from "@/assets/icons/twitter.svg";
|
||||
import InstagramIcon from "@/assets/icons/instagram.svg";
|
||||
import EmailIcon from "@/assets/icons/email.svg";
|
||||
import { BackgroundCanvas } from "@/assets/js/background-canvas";
|
||||
|
||||
const COLORS = [
|
||||
"rgba(0, 0, 0, 0.8)",
|
||||
"rgba(0, 255, 150, 0.8)",
|
||||
"rgba(0, 255, 150, 0.2)",
|
||||
"rgba(0, 150, 255, 0.8)",
|
||||
"rgba(0, 150, 255, 0.2)"
|
||||
];
|
||||
|
||||
const LINES = [
|
||||
{
|
||||
minCount: 8,
|
||||
probability: 1 / 10000,
|
||||
height: 2,
|
||||
length: 100,
|
||||
speed: [-0.2, 0.2],
|
||||
colors: COLORS
|
||||
},
|
||||
{
|
||||
minCount: 8,
|
||||
probability: 1 / 50000,
|
||||
height: 5,
|
||||
length: [20, 200],
|
||||
speed: [0.2, 0.3],
|
||||
colors: COLORS,
|
||||
randomizeYAfterLeave: true
|
||||
},
|
||||
{
|
||||
probability: 1 / 50000,
|
||||
height: 50,
|
||||
length: 50,
|
||||
speed: [0.2, 0.5],
|
||||
colors: COLORS
|
||||
},
|
||||
{
|
||||
probability: 1 / 5000,
|
||||
height: 3,
|
||||
length: 3,
|
||||
speed: [-1, 1],
|
||||
colors: COLORS
|
||||
},
|
||||
{
|
||||
minCount: 8,
|
||||
probability: 1 / 50000,
|
||||
height: [20, 200],
|
||||
length: [20, 200],
|
||||
speed: [0.2, 0.3],
|
||||
colors: COLORS,
|
||||
randomizeYAfterLeave: true
|
||||
},
|
||||
{
|
||||
probability: 1 / 5000,
|
||||
height: [20, 200],
|
||||
length: 2,
|
||||
speed: [-0.2, 0.2],
|
||||
colors: COLORS
|
||||
}
|
||||
];
|
||||
|
||||
export default {
|
||||
name: "IndexPage",
|
||||
layout: "none",
|
||||
components: { AnimatedLogo, GitHubIcon, TwitterIcon, InstagramIcon, EmailIcon, KNavigationBar, KFooter },
|
||||
mounted () {
|
||||
const backgroundCanvas = new BackgroundCanvas(this.$refs.canvas);
|
||||
let nextConfig = 0;
|
||||
|
||||
if (localStorage !== undefined) {
|
||||
const rawValue = localStorage.getItem("nextBackground");
|
||||
|
||||
if (rawValue) {
|
||||
try {
|
||||
nextConfig = JSON.parse(rawValue);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
if (nextConfig > LINES.length - 1) {
|
||||
nextConfig = 0;
|
||||
}
|
||||
|
||||
if (localStorage !== undefined) {
|
||||
localStorage.setItem("nextBackground", nextConfig + 1);
|
||||
}
|
||||
|
||||
const config = LINES[nextConfig];
|
||||
const backgroundCanvas = new Canvas(this.$refs.canvas, {
|
||||
lines: config,
|
||||
fillWindowSize: true
|
||||
});
|
||||
|
||||
this.$once("hook:beforeDestroy", () => {
|
||||
backgroundCanvas.destroy();
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
<template>
|
||||
<div class="projects-page">
|
||||
<KNavigationBar title="Projects"/>
|
||||
<KNavigationBar title="Projects" background-after-scroll/>
|
||||
<div class="content">
|
||||
<h1 class="heading--1">
|
||||
Projects
|
||||
</h1>
|
||||
<GProject
|
||||
type="JavaScript library"
|
||||
title="shaped.js"
|
||||
github="moritzruth/shaped.js"
|
||||
npm="shaped.js"
|
||||
>
|
||||
Generate beautiful moving shapes using a canvas element which can for example be used for backgrounds.
|
||||
See it in action <nuxt-link class="link" to="/">on the home page</nuxt-link>.
|
||||
Every time you reload the page, it shows another variation.
|
||||
</GProject>
|
||||
<GProject
|
||||
type="App (english)"
|
||||
title="RelaxYourEyes"
|
||||
|
|
26
yarn.lock
26
yarn.lock
|
@ -5025,10 +5025,10 @@ kind-of@^6.0.0, kind-of@^6.0.2:
|
|||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
|
||||
integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
|
||||
|
||||
kiste@^1.2.6:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/kiste/-/kiste-1.2.6.tgz#4810d0aabb3fbe1a317079a71c854941cb504add"
|
||||
integrity sha512-v8K2LGhUnMT4PRMTVLM2kTKxNm7ypU9aw/3fcrnU69JVtHwpLtRPRVdoFbG6D3kaJv1H51XFQ5uUg+rA9drXmg==
|
||||
kiste@^1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/kiste/-/kiste-1.2.7.tgz#f861f4a50ee324fc96345eccfddfd20f62118a57"
|
||||
integrity sha512-VJFQqNVmufyjXZt+rrjjfymYFkNzBOUrREibioIDjZHFN1Hy5Mb3AywzjpGW3FLpjPAHQNb7uxj8rY45ndI1uQ==
|
||||
dependencies:
|
||||
chroma-js "^2.1.0"
|
||||
lodash.defaultsdeep "^4.6.1"
|
||||
|
@ -5219,6 +5219,11 @@ lodash.templatesettings@^4.0.0:
|
|||
dependencies:
|
||||
lodash._reinterpolate "^3.0.0"
|
||||
|
||||
lodash.throttle@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||
|
||||
lodash.topairs@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.topairs/-/lodash.topairs-4.3.0.tgz#3b6deaa37d60fb116713c46c5f17ea190ec48d64"
|
||||
|
@ -7150,6 +7155,11 @@ querystring@0.2.0, querystring@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
|
||||
|
||||
random-item@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/random-item/-/random-item-3.0.0.tgz#a94edca6845de662072e325c29eca8e85ef88ced"
|
||||
integrity sha512-IpO3Jk9/Dt79R7iS/Fn2d2asGXahMNnXLNRsgSmjTTtiS0tZ972BWEEm9uUgm3YAon5YFUt8126FA9wJAjmeZw==
|
||||
|
||||
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||
|
@ -7751,6 +7761,14 @@ shallow-clone@^3.0.0:
|
|||
dependencies:
|
||||
kind-of "^6.0.2"
|
||||
|
||||
shaped.js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/shaped.js/-/shaped.js-1.0.2.tgz#bb53612cd2def9e5e05f99ff2b74c2a6f576031f"
|
||||
integrity sha512-kSUdVpXNR1KDF5iknA6dwrkJ0rxgWOGmjmgCefoWTWPN2kon6QW972+K0L0rAEaxJYeWSgKcrKPEEuT3JGcccA==
|
||||
dependencies:
|
||||
lodash.throttle "^4.1.1"
|
||||
random-item "^3.0.0"
|
||||
|
||||
shebang-command@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue