From 05f4e08ad1a924151bd76df8730c55218f4acf4b Mon Sep 17 00:00:00 2001 From: schmelczerandras Date: Sat, 31 Oct 2020 20:42:44 +0100 Subject: [PATCH] Add improvements --- package.json | 24 +++++++------ src/helper/extract-insights.ts | 2 ++ src/helper/handle-full-screen.ts | 48 ++++++++++++++++++++++++++ src/helper/handle-insights.ts | 12 ++++--- src/index.html | 41 ++++++++++++++++------ src/index.ts | 17 +++++++-- src/scenes/blob/blob-scene.ts | 3 +- src/scenes/blob/blob.ts | 2 -- src/scenes/metaball/metaball-scene.ts | 1 - src/scenes/rain/droplet.ts | 4 +-- src/scenes/rain/rain-scene.ts | 6 ++-- src/scenes/tunnel-scene.ts | 8 ++--- src/settings.ts | 2 +- src/styles/index.scss | 28 ++++++++++++--- static/maximize.svg | 7 ++++ static/minimize.svg | 7 ++++ static/{ => no-change}/og-image.png | Bin tsconfig.json | 6 ++-- webpack.config.js | 43 ++++++++--------------- 19 files changed, 185 insertions(+), 76 deletions(-) create mode 100644 src/helper/handle-full-screen.ts create mode 100644 static/maximize.svg create mode 100644 static/minimize.svg rename static/{ => no-change}/og-image.png (100%) diff --git a/package.json b/package.json index 36dbec5..d2276f0 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "webpack-dev-server --mode development", "lint": "npx eslint --fix \"src/**/*.ts\" && npx prettier --write \"src/**/*.ts\"", - "build": "rm -rf dist/* && webpack --mode production && find dist -type f -not -regex \"dist\\/.*\\.\\(html\\|png\\|ico\\|svg\\|jpg\\|txt\\)\" | xargs rm && sed -i 's/^\\/\\/#.*.map//' dist/index.html" + "build": "webpack --mode production" }, "keywords": [], "author": "András Schmelczer (https://schmelczer.dev/)", @@ -27,6 +27,7 @@ "@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", "eslint": "^7.9.0", "eslint-config-prettier": "^6.11.0", @@ -34,24 +35,25 @@ "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", + "html-webpack-inline-source-plugin": "^1.0.0-beta.2", + "html-webpack-inline-svg-plugin": "^2.3.0", + "html-webpack-plugin": "^4.5.0", "mini-css-extract-plugin": "^0.9.0", "optimize-css-assets-webpack-plugin": "^5.0.4", "postcss-loader": "^3.0.0", "prettier": "^2.1.2", "raw-loader": "^4.0.1", "resolve-url-loader": "^3.1.1", - "sass": "^1.26.3", - "sass-loader": "^9.0.3", - "sdf-2d": "^0.6.3", - "source-map-loader": "^1.1.0", + "sass": "^1.27.0", + "sass-loader": "^8.0.2", + "sdf-2d": "^0.7.0", + "source-map-loader": "^1.1.1", "svg-url-loader": "^6.0.0", - "terser-webpack-plugin": "^2.3.8", + "ts-config-webpack-plugin": "^2.0.0", "ts-loader": "^8.0.3", - "typescript": "^3.9.7", - "webpack": "^4.44.1", + "typescript": "^4.0.3", + "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "webpack-dev-server": "^3.10.3" + "webpack-dev-server": "^3.11.0" } } diff --git a/src/helper/extract-insights.ts b/src/helper/extract-insights.ts index fdd3075..f460c1b 100644 --- a/src/helper/extract-insights.ts +++ b/src/helper/extract-insights.ts @@ -8,10 +8,12 @@ export const extractInsights = ( fps?: number; renderScale?: number; lightScale?: number; + version?: string; } => ({ fps: insights?.fps, vendor: insights?.vendor, renderer: insights?.renderer, renderScale: insights?.renderPasses.distance.renderScale, lightScale: insights?.renderPasses.lights.renderScale, + version: insights?.sdf2dVersion, }); diff --git a/src/helper/handle-full-screen.ts b/src/helper/handle-full-screen.ts new file mode 100644 index 0000000..6428c48 --- /dev/null +++ b/src/helper/handle-full-screen.ts @@ -0,0 +1,48 @@ +export const handleFullScreen = ( + minimizeButton: HTMLElement, + maximizeButton: HTMLElement, + target: HTMLElement +) => { + if (!document.fullscreenEnabled) { + minimizeButton.style.visibility = 'hidden'; + maximizeButton.style.visibility = 'hidden'; + return; + } + + const isInFullScreen = (): boolean => document.fullscreenElement !== null; + + const showButtons = () => { + minimizeButton.style.visibility = isInFullScreen() ? 'visible' : 'hidden'; + maximizeButton.style.visibility = isInFullScreen() ? 'hidden' : 'visible'; + }; + + showButtons(); + + let currentWindowHeight = innerHeight; + + const followToggle = () => { + showButtons(); + currentWindowHeight = innerHeight; + }; + + const triggerToggle = async () => { + await (isInFullScreen() ? document.exitFullscreen() : target.requestFullscreen()); + followToggle(); + }; + + addEventListener('keydown', (e) => { + if (e.key === 'F11') { + triggerToggle(); + e.preventDefault(); + } + }); + + addEventListener('resize', () => { + if (isInFullScreen && currentWindowHeight > innerHeight) { + followToggle(); + } + }); + + maximizeButton.addEventListener('click', triggerToggle); + minimizeButton.addEventListener('click', triggerToggle); +}; diff --git a/src/helper/handle-insights.ts b/src/helper/handle-insights.ts index 7f54cf0..6dfe73a 100644 --- a/src/helper/handle-insights.ts +++ b/src/helper/handle-insights.ts @@ -2,8 +2,12 @@ const baseUri = 'https://insights.decla.red'; const type = 'sdf-2d-demo'; export const handleInsights = async (initialData: any): Promise<(data: any) => void> => { - const sessionId = await createSession(initialData); - return (data) => createFrame(sessionId, data); + try { + const sessionId = await createSession(initialData); + return (data) => createFrame(sessionId, data); + } catch { + return () => null; + } }; const createSession = async (data: any): Promise => { @@ -12,8 +16,8 @@ const createSession = async (data: any): Promise => { return sessionId; }; -const createFrame = async (sessionId: string, data: any): Promise => - await sendPostRequest(`${baseUri}/${type}/sessions/${sessionId}`, data); +const createFrame = (sessionId: string, data: any): Promise => + sendPostRequest(`${baseUri}/${type}/sessions/${sessionId}`, data).catch(); const sendPostRequest = async (uri: string, data: any): Promise => await fetch(uri, { diff --git a/src/index.html b/src/index.html index cbafc27..22120e8 100644 --- a/src/index.html +++ b/src/index.html @@ -33,20 +33,41 @@

Javascript is required for this website.

+
+ + +
+
+

Encountered an error

+

+
+
+ + minimize + maximize +
+

SDF-2D

- logo +
- - - -
-
-

Encountered an error

-

-
-
diff --git a/src/index.ts b/src/index.ts index 5eb0136..95ad527 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,10 +6,12 @@ import '../static/favicons/favicon-32x32.png'; import '../static/favicons/favicon.ico'; import '../static/logo-white.svg'; import '../static/no-change/404.html'; +import '../static/no-change/og-image.png'; import '../static/no-change/robots.txt'; -import '../static/og-image.png'; import { extractInsights } from './helper/extract-insights'; +import { handleFullScreen } from './helper/handle-full-screen'; import { handleInsights } from './helper/handle-insights'; +import { Random } from './helper/random'; import { removeUnnecessaryOutlines } from './helper/remove-unnecessary-outlines'; import { BlobScene } from './scenes/blob/blob-scene'; import { MetaballScene } from './scenes/metaball/metaball-scene'; @@ -18,14 +20,18 @@ import { TunnelScene } from './scenes/tunnel-scene'; import './styles/index.scss'; const scenes = [TunnelScene, MetaballScene, RainScene, BlobScene]; +Random.seed = 2; glMatrix.setMatrixArrayType(Array); removeUnnecessaryOutlines(); const canvas = document.querySelector('canvas') as HTMLCanvasElement; +const canvasContainer = document.querySelector('#canvas-container') as HTMLCanvasElement; const errorText = document.querySelector('#error-text') as HTMLParamElement; const errorsContainer = document.querySelector('#errors-container') as HTMLDivElement; const toggleButton = document.querySelector('#toggle-text'); +const minimizeButton = document.querySelector('#minimize') as HTMLElement; +const maximizeButton = document.querySelector('#maximize') as HTMLElement; const overlay = document.querySelector('#overlay') as HTMLDivElement; let textVisible = true; @@ -43,18 +49,25 @@ toggleButton.addEventListener('click', handleTextToggle); handleTextToggle(); const startInsightsSession = async (): Promise<(data: any) => unknown> => { - const { vendor, renderer } = extractInsights((await compile(canvas, [])).insights); + const dummyRenderer = await compile(document.createElement('canvas'), []); + const { vendor, renderer, version } = extractInsights(dummyRenderer.insights); + dummyRenderer.destroy(); + return await handleInsights({ vendor, renderer, referrer: document.referrer, connection: (navigator as any)?.connection?.effectiveType, devicePixelRatio: devicePixelRatio, + height: innerHeight, + width: innerWidth, + version, }); }; const main = async () => { const sendFramePromise = startInsightsSession(); + handleFullScreen(minimizeButton, maximizeButton, canvasContainer); try { let i = 0; diff --git a/src/scenes/blob/blob-scene.ts b/src/scenes/blob/blob-scene.ts index 3848700..da4a3f8 100644 --- a/src/scenes/blob/blob-scene.ts +++ b/src/scenes/blob/blob-scene.ts @@ -32,7 +32,6 @@ export class BlobScene implements Scene { Blob.descriptor, ], this.drawNextFrame.bind(this), - {}, { ambientLight: rgb255(89, 25, 115), enableHighDpiRendering: true, @@ -65,6 +64,8 @@ export class BlobScene implements Scene { const q = (currentTime % 8000) / 4300; this.blob.animate(currentTime); + this.blob.position = [width / 2, -length / 4 + length / 2]; + [ new Circle([width / 2, -length / 4], length / 2), this.blob, diff --git a/src/scenes/blob/blob.ts b/src/scenes/blob/blob.ts index b5a56fc..e475703 100644 --- a/src/scenes/blob/blob.ts +++ b/src/scenes/blob/blob.ts @@ -120,8 +120,6 @@ export class Blob extends Drawable { Math.sin((q > 1 ? q - 1 : 0) * Math.PI) * 10 ) ); - - this.position = this.center; } public minDistance(target: vec2): number { diff --git a/src/scenes/metaball/metaball-scene.ts b/src/scenes/metaball/metaball-scene.ts index afddd39..8d17a87 100644 --- a/src/scenes/metaball/metaball-scene.ts +++ b/src/scenes/metaball/metaball-scene.ts @@ -43,7 +43,6 @@ export class MetaballScene implements Scene { }, ], this.drawNextFrame.bind(this), - {}, { ambientLight: rgb(0.1, 0.1, 0.3), enableHighDpiRendering: true, diff --git a/src/scenes/rain/droplet.ts b/src/scenes/rain/droplet.ts index 0bea6d8..2f1977e 100644 --- a/src/scenes/rain/droplet.ts +++ b/src/scenes/rain/droplet.ts @@ -1,8 +1,8 @@ import { ReadonlyVec2, vec2 } from 'gl-matrix'; -import { DropletFactory, rgb } from 'sdf-2d'; +import { DropletFactory, rgb255 } from 'sdf-2d'; import { Random } from '../../helper/random'; -export const Droplet = DropletFactory(rgb(0.3, 1, 1)); +export const Droplet = DropletFactory(rgb255(122, 122, 255)); export class DropletWrapper { public readonly drawable: InstanceType; diff --git a/src/scenes/rain/rain-scene.ts b/src/scenes/rain/rain-scene.ts index 7542cd7..72c8adc 100644 --- a/src/scenes/rain/rain-scene.ts +++ b/src/scenes/rain/rain-scene.ts @@ -7,8 +7,8 @@ import { Droplet, DropletWrapper } from './droplet'; export class RainScene implements Scene { private droplets: Array = []; - private light1: CircleLight = new CircleLight(vec2.create(), rgb255(184, 41, 255), 2); - private light2: CircleLight = new CircleLight(vec2.create(), rgb255(255, 31, 109), 2); + private light1: CircleLight = new CircleLight(vec2.create(), rgb255(184, 41, 255), 1.5); + private light2: CircleLight = new CircleLight(vec2.create(), rgb255(255, 31, 109), 1.5); private overlay: HTMLDivElement; public insights?: any; @@ -32,8 +32,8 @@ export class RainScene implements Scene { }, ], this.drawNextFrame.bind(this), - {}, { + backgroundColor: rgb(0.5, 0.5, 0.5), ambientLight: rgb(0.2, 0.2, 0.2), enableHighDpiRendering: true, } diff --git a/src/scenes/tunnel-scene.ts b/src/scenes/tunnel-scene.ts index a1f5f81..9f5a504 100644 --- a/src/scenes/tunnel-scene.ts +++ b/src/scenes/tunnel-scene.ts @@ -70,12 +70,12 @@ export class TunnelScene implements Scene { } public async run(canvas: HTMLCanvasElement, overlay: HTMLDivElement): Promise { - const noiseTexture = await renderNoise([1024, 1], 15, 1); + const noiseTexture = await renderNoise([1024, 1], 15, 0.5); this.canvas = canvas; this.overlay = overlay; - for (let i = 0; i < 200; i++) { + for (let i = 0; i < 30; i++) { this.generateTunnel(); } @@ -92,8 +92,8 @@ export class TunnelScene implements Scene { }, ], this.drawNextFrame.bind(this), - { lightPenetrationRatio: 0.5 }, { + lightPenetrationRatio: 0.5, isWorldInverted: true, enableHighDpiRendering: true, ambientLight: rgb(0.35, 0.1, 0.45), @@ -123,7 +123,7 @@ export class TunnelScene implements Scene { const height = renderer.canvasSize.y; this.deltaSinceStart += deltaTime; - const startX = this.deltaSinceStart / 3; + const startX = this.deltaSinceStart / 4; const endX = startX + width; renderer.setViewArea(vec2.fromValues(startX, height), vec2.fromValues(width, height)); diff --git a/src/settings.ts b/src/settings.ts index 3234bb3..6955a52 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,3 +1,3 @@ export const settings = { - sceneTimeInMilliseconds: 7000, + sceneTimeInMilliseconds: 8000, }; diff --git a/src/styles/index.scss b/src/styles/index.scss index 133c215..7dff410 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -11,8 +11,7 @@ $breakpoint: 800px; } html, -body, -canvas#main { +body { height: 100%; width: 100%; overflow: hidden; @@ -50,7 +49,7 @@ body { padding-top: 2px; } - img { + .logo { @include square(64px); padding-left: 8px; } @@ -58,12 +57,33 @@ body { @media (max-width: $breakpoint) { font-size: 2rem; - img { + .logo { @include square(40px); } } } + #canvas-container { + &, + canvas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + .full-screen-control { + position: absolute; + right: 0; + bottom: 0; + box-sizing: content-box; + @include square(40px); + padding: 16px; + cursor: pointer; + } + } + #overlay { right: 0; white-space: pre-wrap; diff --git a/static/maximize.svg b/static/maximize.svg new file mode 100644 index 0000000..7118488 --- /dev/null +++ b/static/maximize.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/static/minimize.svg b/static/minimize.svg new file mode 100644 index 0000000..93a212a --- /dev/null +++ b/static/minimize.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/static/og-image.png b/static/no-change/og-image.png similarity index 100% rename from static/og-image.png rename to static/no-change/og-image.png diff --git a/tsconfig.json b/tsconfig.json index ce9fe38..46145ba 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,8 @@ "experimentalDecorators": true, "moduleResolution": "Node", "module": "es6", - "lib": ["es2016", "dom"] - } + "lib": ["es2016", "dom"], + "skipLibCheck": true + }, + "exclude": ["node_modules"] } diff --git a/webpack.config.js b/webpack.config.js index 59b6e06..0ca16e9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,13 +1,15 @@ const path = require('path'); +const CleanWebpackPlugin = require('clean-webpack-plugin').CleanWebpackPlugin; const HtmlWebpackPlugin = require('html-webpack-plugin'); -const TerserJSPlugin = require('terser-webpack-plugin'); -const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); +const TsConfigWebpackPlugin = require('ts-config-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin'); +const HtmlWebpackInlineSVGPlugin = require('html-webpack-inline-svg-plugin'); const Sass = require('sass'); const PATHS = { entryPoint: path.resolve(__dirname, 'src/index.ts'), + entryHtml: path.resolve(__dirname, 'src/index.html'), bundles: path.resolve(__dirname, 'dist'), }; @@ -17,10 +19,9 @@ module.exports = { }, target: 'web', output: { - filename: '[name].[contenthash].js', path: PATHS.bundles, }, - devtool: 'source-map', + //devtool: 'source-map', watchOptions: { aggregateTimeout: 600, ignored: /node_modules/, @@ -29,21 +30,12 @@ module.exports = { host: '0.0.0.0', disableHostCheck: true, }, - optimization: { - minimize: true, - usedExports: true, - minimizer: [ - new TerserJSPlugin({ - sourceMap: true, - test: /\.js$/, - }), - new OptimizeCSSAssetsPlugin({}), - ], - }, plugins: [ + new CleanWebpackPlugin(), + new MiniCssExtractPlugin(), new HtmlWebpackPlugin({ xhtml: true, - template: './src/index.html', + template: PATHS.entryHtml, minify: { collapseWhitespace: true, removeComments: true, @@ -54,11 +46,11 @@ module.exports = { }, inlineSource: '.(js|css)$', }), - new HtmlWebpackInlineSourcePlugin(), - new MiniCssExtractPlugin({ - filename: '[name].[contenthash].css', - chunkFilename: '[id].[contenthash].css', + new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin), + new HtmlWebpackInlineSVGPlugin({ + inlineAll: true, }), + new TsConfigWebpackPlugin(), ], module: { rules: [ @@ -84,14 +76,7 @@ module.exports = { ], }, { - test: /\.ts$/, - use: { - loader: 'ts-loader', - }, - exclude: /node_modules/, - }, - { - test: /\.(ico|png|jpg)$/, + test: /\.(ico|png)$/, use: { loader: 'file-loader', query: { @@ -101,7 +86,7 @@ module.exports = { }, }, { - test: /no-change.*(html|txt)$/i, + test: /no-change.*$/i, use: { loader: 'file-loader', query: {