Dockerize
This commit is contained in:
parent
0048aa191e
commit
d9623a3274
10 changed files with 243 additions and 137 deletions
5
.dockerignore
Normal file
5
.dockerignore
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Dockerfile
|
||||
node_modules
|
||||
dist
|
||||
package-lock.json
|
||||
.*
|
||||
28
Dockerfile
Normal file
28
Dockerfile
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
FROM schmelczera/error-pages as build-error-pages
|
||||
RUN python build.py 403 404 50x
|
||||
|
||||
|
||||
FROM node:latest as build-webpage
|
||||
WORKDIR /home/node
|
||||
|
||||
COPY src src
|
||||
COPY static static
|
||||
COPY package.json custom.d.ts tsconfig.json webpack.config.js ./
|
||||
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
HEALTHCHECK --interval=1m --timeout=10s CMD curl --fail http://localhost/ || exit 1
|
||||
|
||||
WORKDIR /usr/share/nginx/html
|
||||
|
||||
RUN rm -rf *
|
||||
COPY --from=build-webpage /home/node/dist .
|
||||
COPY --from=build-error-pages /home/python/built errors
|
||||
RUN find . -type f | xargs gzip -k9 &&\
|
||||
chmod -R 555 .
|
||||
|
||||
COPY nginx-config /etc/nginx/
|
||||
53
nginx-config/nginx.conf
Normal file
53
nginx-config/nginx.conf
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
server_tokens off;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
access_log off;
|
||||
|
||||
sendfile on;
|
||||
sendfile_max_chunk 1m;
|
||||
tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
gzip on;
|
||||
gzip_static on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 10240;
|
||||
gzip_proxied any;
|
||||
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location ~* \.(jpg|jpeg|png|ico)$ {
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
error_page 403 /403.html;
|
||||
error_page 404 /404.html;
|
||||
error_page 500 501 502 503 504 /50x.html;
|
||||
|
||||
location ~ ^/(403|404|50x).html$ {
|
||||
root /usr/share/nginx/html/errors;
|
||||
internal;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
package.json
18
package.json
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"name": "sdf-2d-demo",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"description": "Some simple demos to showcase the possibilities of this library.",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "webpack-dev-server --mode development",
|
||||
"lint": "npx eslint --fix \"src/**/*.ts\" && npx prettier --write \"src/**/*.ts\"",
|
||||
"build": "webpack --mode production && find dist -type f -not -name '*.html' | xargs rm && sed -i 's/^\\/\\/#.*.map//' dist/index.html"
|
||||
"build": "webpack --mode production && find dist -type f -not -regex \"dist\\/.*\\.\\(html\\|png\\|ico\\|svg\\|jpg\\)\" | xargs rm && sed -i 's/^\\/\\/#.*.map//' dist/index.html"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "András Schmelczer <andras@schmelczer.dev> (https://schmelczer.dev/)",
|
||||
|
|
@ -21,25 +21,25 @@
|
|||
"defaults"
|
||||
],
|
||||
"sideEffects": [
|
||||
"*.scss"
|
||||
"*.scss",
|
||||
"*.png",
|
||||
"*.jpg",
|
||||
"*.ico",
|
||||
"*.svg"
|
||||
],
|
||||
"optimization": {
|
||||
"usedExports": true
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/gl-matrix": "^2.4.5",
|
||||
"@typescript-eslint/eslint-plugin": "^3.10.1",
|
||||
"@typescript-eslint/parser": "^3.10.1",
|
||||
"autoprefixer": "^9.8.6",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"css-loader": "^3.5.2",
|
||||
"cssnano": "^4.1.10",
|
||||
"eslint": "^7.9.0",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"eslint-plugin-unused-imports": "^0.1.3",
|
||||
"gl-matrix": "^3.3.0",
|
||||
"html-webpack-inline-source-plugin": "0.0.10",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
|
|
@ -48,12 +48,10 @@
|
|||
"prettier": "^2.1.2",
|
||||
"raw-loader": "^4.0.1",
|
||||
"resolve-url-loader": "^3.1.1",
|
||||
"responsive-loader": "^1.2.0",
|
||||
"sass": "^1.26.3",
|
||||
"sass-loader": "^9.0.3",
|
||||
"sdf-2d": "^0.0.0",
|
||||
"sdf-2d": "^0.1.0-alpha",
|
||||
"source-map-loader": "^1.1.0",
|
||||
"style-loader": "^1.1.4",
|
||||
"svg-url-loader": "^6.0.0",
|
||||
"terser-webpack-plugin": "^2.3.8",
|
||||
"ts-loader": "^8.0.3",
|
||||
|
|
|
|||
4
src/helper/remove-unnecessary-outlines.ts
Normal file
4
src/helper/remove-unnecessary-outlines.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export const removeUnnecessaryOutlines = () =>
|
||||
(document.onclick = (e) => {
|
||||
(e.target as HTMLElement)?.blur();
|
||||
});
|
||||
|
|
@ -2,31 +2,53 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<title>SDF-2D demo</title>
|
||||
|
||||
<meta property="og:image:width" content="1500" />
|
||||
<meta property="og:image:height" content="785" />
|
||||
<meta property="og:url" content="https://sdf2d.schmelczer.dev" />
|
||||
<meta property="og:image" content="https://sdf2d.schmelczer.dev/og-image.jpg" />
|
||||
|
||||
<meta name="theme-color" content="#103783" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Some simple demos to showcase the possibilities of this library."
|
||||
content="Some simple demos to showcase the possibilities of the sdf-2d library library. Click on the title to find out more."
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="static/favicons/apple-touch-icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="static/favicons/favicon-32x32.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href="static/favicons/favicon-16x16.png"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>Javascript is required for this website.</noscript>
|
||||
|
||||
<button id="info">
|
||||
<a href="https://github.com/schmelczerandras/sdf-2d" target="_BLANK">
|
||||
SDF-2D<img src="static/logo-white.svg" alt="logo" />
|
||||
<a id="info" href="https://github.com/schmelczerandras/sdf-2d" target="_BLANK">
|
||||
SDF-2D
|
||||
<img src="static/logo-white.svg" alt="logo" />
|
||||
</a>
|
||||
</button>
|
||||
|
||||
<button id="remove-clutter">Hide text</button>
|
||||
|
||||
<div id="overlay"></div>
|
||||
<code id="overlay"></code>
|
||||
<button id="toggle-text"></button>
|
||||
|
||||
<canvas id="main"></canvas>
|
||||
|
||||
<div id="errors-container">
|
||||
<div id="errors">
|
||||
<h1>Error</h1>
|
||||
<h1>Encountered an error</h1>
|
||||
<p id="error-text"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
103
src/index.scss
103
src/index.scss
|
|
@ -1,103 +0,0 @@
|
|||
$bg: linear-gradient(90deg, #103783, #9bafd9);
|
||||
|
||||
html,
|
||||
body,
|
||||
canvas#main {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
html {
|
||||
@media (max-width: 800px) {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
background: $bg;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: Helvetica, Tahoma, sans-serif;
|
||||
color: white;
|
||||
}
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
border: 2px solid white;
|
||||
border-radius: 6px;
|
||||
padding: 0.2em 0.5rem;
|
||||
background: none;
|
||||
}
|
||||
|
||||
#info,
|
||||
#overlay,
|
||||
#remove-clutter {
|
||||
margin: 1rem 1.25rem;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#info {
|
||||
left: 0;
|
||||
font-size: 2.5rem;
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
$size: 80px;
|
||||
width: $size;
|
||||
height: $size;
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#overlay {
|
||||
font-size: 0.75rem;
|
||||
right: 0;
|
||||
white-space: pre;
|
||||
font-family: 'Lucida Console', Monaco, monospace;
|
||||
}
|
||||
|
||||
#remove-clutter {
|
||||
bottom: 0;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
#errors-container {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
#errors {
|
||||
width: min(500px, 90vw);
|
||||
height: min(500px, 90vw);
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: left;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/index.ts
35
src/index.ts
|
|
@ -1,26 +1,40 @@
|
|||
import { glMatrix } from 'gl-matrix';
|
||||
import '../static/favicons/apple-touch-icon.png';
|
||||
import '../static/favicons/favicon-16x16.png';
|
||||
import '../static/favicons/favicon-32x32.png';
|
||||
import '../static/favicons/favicon.ico';
|
||||
//import '../static/og-image.jpg';
|
||||
import { DeltaTimeCalculator } from './helper/delta-time-calculator';
|
||||
import './index.scss';
|
||||
import { RainScene } from './scenes/rain/rain-scene';
|
||||
import { removeUnnecessaryOutlines } from './helper/remove-unnecessary-outlines';
|
||||
import { BlobScene } from './scenes/blob-scene';
|
||||
import { Scene } from './scenes/scene';
|
||||
import { TunnelScene } from './scenes/tunnel-scene';
|
||||
import './styles/index.scss';
|
||||
|
||||
const scenes = [TunnelScene, RainScene];
|
||||
const sceneIntervalInSeconds = 8;
|
||||
const scenes = [/*TunnelScene, RainScene*/ BlobScene];
|
||||
const sceneIntervalInSeconds = 80000;
|
||||
|
||||
glMatrix.setMatrixArrayType(Array);
|
||||
removeUnnecessaryOutlines();
|
||||
|
||||
const deltaTimeCalculator = new DeltaTimeCalculator();
|
||||
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
|
||||
const info = document.querySelector('#info');
|
||||
const info = document.querySelector('#info') as HTMLDivElement;
|
||||
const errorText = document.querySelector('#error-text') as HTMLParamElement;
|
||||
const errors = document.querySelector('#errors') as HTMLDivElement;
|
||||
const errorsContainer = document.querySelector('#errors-container') as HTMLDivElement;
|
||||
const button = document.querySelector('#remove-clutter');
|
||||
const toggleButton = document.querySelector('#toggle-text');
|
||||
const overlay = document.querySelector('#overlay') as HTMLDivElement;
|
||||
|
||||
button.addEventListener('click', () =>
|
||||
[info, button, overlay].forEach((e) => e.remove())
|
||||
let textVisible = false;
|
||||
const handleTextToggle = () => {
|
||||
[info, overlay, errors].forEach(
|
||||
(e) => (e.style.visibility = textVisible ? 'hidden' : 'inherit')
|
||||
);
|
||||
textVisible = !textVisible;
|
||||
toggleButton.innerHTML = textVisible ? 'Hide text' : 'Show text';
|
||||
};
|
||||
toggleButton.addEventListener('click', handleTextToggle);
|
||||
handleTextToggle();
|
||||
|
||||
const handleScene = async (SceneConstructor: new () => Scene) => {
|
||||
const scene = new SceneConstructor();
|
||||
|
|
@ -44,7 +58,6 @@ const handleScene = async (SceneConstructor: new () => Scene) => {
|
|||
|
||||
requestAnimationFrame(handleFrame);
|
||||
await isOver;
|
||||
|
||||
scene.destroy();
|
||||
};
|
||||
|
||||
|
|
@ -57,7 +70,7 @@ const main = async () => {
|
|||
} catch (e) {
|
||||
console.error(e);
|
||||
errorText.innerText = e;
|
||||
errorsContainer.style.display = 'flex';
|
||||
errorsContainer.style.visibility = 'visible';
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
76
src/scenes/blob-scene.ts
Normal file
76
src/scenes/blob-scene.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import { vec3 } from 'gl-matrix';
|
||||
import { Circle, CircleLight, compile, InvertedTunnel, Renderer } from 'sdf-2d';
|
||||
import { Scene } from './scene';
|
||||
|
||||
export class BlobScene implements Scene {
|
||||
private renderer: Renderer;
|
||||
private canvas: HTMLCanvasElement;
|
||||
private overlay: HTMLDivElement;
|
||||
|
||||
private tunnels: Array<InvertedTunnel> = [];
|
||||
private lights: Array<CircleLight> = [];
|
||||
|
||||
public async initialize(
|
||||
canvas: HTMLCanvasElement,
|
||||
overlay: HTMLDivElement
|
||||
): Promise<void> {
|
||||
this.canvas = canvas;
|
||||
this.overlay = overlay;
|
||||
this.renderer = await compile(
|
||||
canvas,
|
||||
[
|
||||
{
|
||||
...InvertedTunnel.descriptor,
|
||||
shaderCombinationSteps: [0, 1, 2, 4, 8, 12],
|
||||
},
|
||||
Circle.descriptor,
|
||||
{
|
||||
...CircleLight.descriptor,
|
||||
shaderCombinationSteps: [1, 2, 3, 4, 5, 6, 7],
|
||||
},
|
||||
],
|
||||
[vec3.fromValues(0.4, 1, 0.6), vec3.fromValues(1, 1, 0), vec3.fromValues(0.3, 1, 1)]
|
||||
);
|
||||
|
||||
this.renderer.setRuntimeSettings({
|
||||
ambientLight: vec3.fromValues(0.35, 0.1, 0.45),
|
||||
shadowLength: 550,
|
||||
});
|
||||
}
|
||||
|
||||
private deltaSinceStart = 0;
|
||||
public drawNextFrame(
|
||||
currentTime: DOMHighResTimeStamp,
|
||||
deltaTime: DOMHighResTimeStamp
|
||||
): void {
|
||||
const { width, height } = this.canvas.getBoundingClientRect();
|
||||
this.deltaSinceStart += deltaTime;
|
||||
this.renderer.setViewArea([0, height], [width, height]);
|
||||
|
||||
this.renderer.autoscaleQuality(deltaTime);
|
||||
this.overlay.innerText = JSON.stringify(
|
||||
this.renderer.insights,
|
||||
(_, v) => (v.toFixed ? Number(v.toFixed(2)) : v),
|
||||
' '
|
||||
);
|
||||
|
||||
const q = (this.deltaSinceStart % 5000) / 2500;
|
||||
console.log(q);
|
||||
|
||||
[
|
||||
new Circle([width / 2, -width / 4], width / 2),
|
||||
new CircleLight([q * width, Math.sin(q * Math.PI) * height], [1, 0.8, 0], 1),
|
||||
new CircleLight(
|
||||
[(q - 1) * width, Math.sin((q - 1) * Math.PI) * height],
|
||||
[0, 0.8, 1],
|
||||
1
|
||||
),
|
||||
].forEach((d) => this.renderer.addDrawable(d));
|
||||
|
||||
this.renderer.renderDrawables();
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this.renderer.destroy();
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ module.exports = {
|
|||
filename: '[name].[contenthash].js',
|
||||
path: PATHS.bundles,
|
||||
},
|
||||
devtool: isDevelopment ? 'source-map' : '',
|
||||
devtool: isDevelopment ? 'source-map' : 'null',
|
||||
watchOptions: {
|
||||
aggregateTimeout: 600,
|
||||
ignored: /node_modules/,
|
||||
|
|
@ -100,6 +100,16 @@ module.exports = {
|
|||
noquotes: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(ico|png|jpg)$/i,
|
||||
use: {
|
||||
loader: 'file-loader',
|
||||
query: {
|
||||
outputPath: '/',
|
||||
name: '[name].[ext]',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
enforce: 'pre',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue