diff --git a/src/shared/initial-app/Intro/blob-anim.ts b/src/shared/initial-app/Intro/blob-anim/index.ts similarity index 76% rename from src/shared/initial-app/Intro/blob-anim.ts rename to src/shared/initial-app/Intro/blob-anim/index.ts index 29fa3714..116eca79 100644 --- a/src/shared/initial-app/Intro/blob-anim.ts +++ b/src/shared/initial-app/Intro/blob-anim/index.ts @@ -1,9 +1,10 @@ -import * as style from './style.css'; +import * as style from '../style.css'; +import { startBlobs, blobColor } from './meta'; /** * Control point x,y - point x,y - control point x,y */ -type BlobPoint = [number, number, number, number, number, number]; +export type BlobPoint = [number, number, number, number, number, number]; const maxRandomDistance = 0.25; @@ -47,46 +48,6 @@ const sevenPointCircle: BlobPoint[] = [ [-0.972, -0.386, -0.782, -0.623, -0.592, -0.861], ]; -/** Start points, for the shape we use in prerender */ -const startPoints: BlobPoint[][] = [ - [ - [-0.232, -1.029, 0.073, -1.029, 0.377, -1.029], - [0.565, -1.098, 0.755, -0.86, 0.945, -0.622], - [0.917, -0.01, 0.849, 0.286, 0.782, 0.583], - [0.85, 0.687, 0.576, 0.819, 0.302, 0.951], - [-0.198, 1.009, -0.472, 0.877, -0.746, 0.745], - [-0.98, 0.513, -1.048, 0.216, -1.116, -0.08], - [-0.964, -0.395, -0.774, -0.633, -0.584, -0.871], - ], - [ - [-0.505, -1.109, -0.201, -1.109, 0.104, -1.109], - [0.641, -0.684, 0.831, -0.446, 1.02, -0.208], - [1.041, 0.034, 0.973, 0.331, 0.905, 0.628], - [0.734, 0.794, 0.46, 0.926, 0.186, 1.058], - [-0.135, 0.809, -0.409, 0.677, -0.684, 0.545], - [-0.935, 0.404, -1.002, 0.108, -1.07, -0.189], - [-0.883, -0.402, -0.693, -0.64, -0.503, -0.878], - ], - [ - [-0.376, -1.168, -0.071, -1.168, 0.233, -1.168], - [0.732, -0.956, 0.922, -0.718, 1.112, -0.48], - [1.173, 0.027, 1.105, 0.324, 1.038, 0.621], - [0.707, 0.81, 0.433, 0.943, 0.159, 1.075], - [-0.096, 1.135, -0.37, 1.003, -0.644, 0.871], - [-0.86, 0.457, -0.927, 0.161, -0.995, -0.136], - [-0.87, -0.516, -0.68, -0.754, -0.49, -0.992], - ], - [ - [-0.309, -0.998, -0.004, -0.998, 0.3, -0.998], - [0.535, -0.852, 0.725, -0.614, 0.915, -0.376], - [1.05, -0.09, 0.982, 0.207, 0.915, 0.504], - [0.659, 0.807, 0.385, 0.939, 0.111, 1.071], - [-0.178, 1.048, -0.452, 0.916, -0.727, 0.784], - [-0.942, 0.582, -1.009, 0.285, -1.077, -0.011], - [-1.141, -0.335, -0.951, -0.573, -0.761, -0.811], - ], -]; - /* // Should it be needed, here's how the above was created: function createBezierCirclePoints(points: number): BlobPoint[] { @@ -154,9 +115,27 @@ class CentralBlobs { private rotatePos: number = 0; private blobs = Array.from( { length: 4 }, - (_, i) => new CircleBlob(sevenPointCircle, startPoints[i]), + (_, i) => new CircleBlob(sevenPointCircle, startBlobs[i]), ); + constructor() { + console.log( + `WARNING: There's a debug key listener here that must be removed before going live`, + ); + addEventListener('keyup', (event) => { + if (event.key !== 'b') return; + console.log( + JSON.stringify( + this.blobs.map((blob) => + blob + .frame(0) + .map((points) => points.map((point) => Number(point.toFixed(3)))), + ), + ), + ); + }); + } + draw( ctx: CanvasRenderingContext2D, timeDelta: number, @@ -235,7 +214,6 @@ export function startBlobAnim(canvas: HTMLCanvasElement) { deltaMultiplier = Math.max(0, deltaMultiplier - deltaMultiplierStep); if (deltaMultiplier === 0) { animating = false; - console.log(centralBlobs); return; } } else if (deltaMultiplier !== 1) { @@ -250,7 +228,7 @@ export function startBlobAnim(canvas: HTMLCanvasElement) { canvas.height = canvasBounds.height * devicePixelRatio; const loadImgBounds = loadImgEl.getBoundingClientRect(); - ctx.fillStyle = 'rgba(255, 0, 102, 0.3)'; + ctx.fillStyle = blobColor; ctx.scale(devicePixelRatio, devicePixelRatio); centralBlobs.draw( @@ -258,7 +236,7 @@ export function startBlobAnim(canvas: HTMLCanvasElement) { delta, loadImgBounds.left - canvasBounds.left + loadImgBounds.width / 2, loadImgBounds.top - canvasBounds.top + loadImgBounds.height / 2, - (loadImgBounds.width / 2) * (1 - maxRandomDistance), + loadImgBounds.height / 2 / (1 + maxRandomDistance), ); requestAnimationFrame(frame); diff --git a/src/shared/initial-app/Intro/blob-anim/meta.ts b/src/shared/initial-app/Intro/blob-anim/meta.ts new file mode 100644 index 00000000..3622a689 --- /dev/null +++ b/src/shared/initial-app/Intro/blob-anim/meta.ts @@ -0,0 +1,43 @@ +import type { BlobPoint } from '.'; + +/** Start points, for the shape we use in prerender */ +export const startBlobs: BlobPoint[][] = [ + [ + [-0.232, -1.029, 0.073, -1.029, 0.377, -1.029], + [0.565, -1.098, 0.755, -0.86, 0.945, -0.622], + [0.917, -0.01, 0.849, 0.286, 0.782, 0.583], + [0.85, 0.687, 0.576, 0.819, 0.302, 0.951], + [-0.198, 1.009, -0.472, 0.877, -0.746, 0.745], + [-0.98, 0.513, -1.048, 0.216, -1.116, -0.08], + [-0.964, -0.395, -0.774, -0.633, -0.584, -0.871], + ], + [ + [-0.505, -1.109, -0.201, -1.109, 0.104, -1.109], + [0.641, -0.684, 0.831, -0.446, 1.02, -0.208], + [1.041, 0.034, 0.973, 0.331, 0.905, 0.628], + [0.734, 0.794, 0.46, 0.926, 0.186, 1.058], + [-0.135, 0.809, -0.409, 0.677, -0.684, 0.545], + [-0.935, 0.404, -1.002, 0.108, -1.07, -0.189], + [-0.883, -0.402, -0.693, -0.64, -0.503, -0.878], + ], + [ + [-0.376, -1.168, -0.071, -1.168, 0.233, -1.168], + [0.732, -0.956, 0.922, -0.718, 1.112, -0.48], + [1.173, 0.027, 1.105, 0.324, 1.038, 0.621], + [0.707, 0.81, 0.433, 0.943, 0.159, 1.075], + [-0.096, 1.135, -0.37, 1.003, -0.644, 0.871], + [-0.86, 0.457, -0.927, 0.161, -0.995, -0.136], + [-0.87, -0.516, -0.68, -0.754, -0.49, -0.992], + ], + [ + [-0.309, -0.998, -0.004, -0.998, 0.3, -0.998], + [0.535, -0.852, 0.725, -0.614, 0.915, -0.376], + [1.05, -0.09, 0.982, 0.207, 0.915, 0.504], + [0.659, 0.807, 0.385, 0.939, 0.111, 1.071], + [-0.178, 1.048, -0.452, 0.916, -0.727, 0.784], + [-0.942, 0.582, -1.009, 0.285, -1.077, -0.011], + [-1.141, -0.335, -0.951, -0.573, -0.761, -0.811], + ], +]; + +export const blobColor = 'rgba(255, 0, 102, 0.3)'; diff --git a/src/shared/initial-app/Intro/index.tsx b/src/shared/initial-app/Intro/index.tsx index 8eef2357..803bb5c9 100644 --- a/src/shared/initial-app/Intro/index.tsx +++ b/src/shared/initial-app/Intro/index.tsx @@ -14,6 +14,7 @@ import logoWithText from 'url:./imgs/logo-with-text.svg'; import * as style from './style.css'; import type SnackBarElement from 'shared/initial-app/custom-els/snack-bar'; import 'shared/initial-app/custom-els/snack-bar'; +import { blobColor, startBlobs } from './blob-anim/meta'; const demos = [ { @@ -42,7 +43,10 @@ const demos = [ }, ]; -const blobAnimImport = import('./blob-anim'); +const blobAnimImport = + !__PRERENDER__ && matchMedia('(prefers-reduced-motion: reduce)').matches + ? undefined + : import('./blob-anim'); const installButtonSource = 'introInstallButton-Purple'; const supportsClipboardAPI = !__PRERENDER__ && navigator.clipboard && navigator.clipboard.read; @@ -63,10 +67,13 @@ interface Props { interface State { fetchingDemoIndex?: number; beforeInstallEvent?: BeforeInstallPromptEvent; + showBlobSVG: boolean; } export default class Intro extends Component { - state: State = {}; + state: State = { + showBlobSVG: true, + }; private fileInput?: HTMLInputElement; private blobCanvas?: HTMLCanvasElement; private installingViaButton = false; @@ -81,7 +88,16 @@ export default class Intro extends Component { // Listen for the appinstalled event, indicating Squoosh has been installed. window.addEventListener('appinstalled', this.onAppInstalled); - blobAnimImport.then((module) => module.startBlobAnim(this.blobCanvas!)); + if (blobAnimImport) { + blobAnimImport.then((module) => { + this.setState( + { + showBlobSVG: false, + }, + () => module.startBlobAnim(this.blobCanvas!), + ); + }); + } } componentWillUnmount() { @@ -198,7 +214,10 @@ export default class Intro extends Component { this.props.onFile!(new File([blob], 'image.unknown')); }; - render({}: Props, { fetchingDemoIndex, beforeInstallEvent }: State) { + render( + {}: Props, + { fetchingDemoIndex, beforeInstallEvent, showBlobSVG }: State, + ) { return (
{ />
+ {showBlobSVG && ( + + {startBlobs.map((points) => ( + { + const nextI = i === points.length - 1 ? 0 : i + 1; + let d = ''; + if (i === 0) { + d += `M${point[2]} ${point[3]}`; + } + return ( + d + + `C${point[4]} ${point[5]} ${points[nextI][0]} ${points[nextI][1]} ${points[nextI][2]} ${points[nextI][3]}` + ); + }) + .join('')} + /> + ))} + + )}