forked from external-repos/squoosh
Initial blob shape
This commit is contained in:
@@ -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);
|
||||
43
src/shared/initial-app/Intro/blob-anim/meta.ts
Normal file
43
src/shared/initial-app/Intro/blob-anim/meta.ts
Normal file
@@ -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)';
|
||||
@@ -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<Props, State> {
|
||||
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<Props, State> {
|
||||
// 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<Props, State> {
|
||||
this.props.onFile!(new File([blob], 'image.unknown'));
|
||||
};
|
||||
|
||||
render({}: Props, { fetchingDemoIndex, beforeInstallEvent }: State) {
|
||||
render(
|
||||
{}: Props,
|
||||
{ fetchingDemoIndex, beforeInstallEvent, showBlobSVG }: State,
|
||||
) {
|
||||
return (
|
||||
<div class={style.intro}>
|
||||
<input
|
||||
@@ -227,6 +246,31 @@ export default class Intro extends Component<Props, State> {
|
||||
/>
|
||||
</h1>
|
||||
<div class={style.loadImg}>
|
||||
{showBlobSVG && (
|
||||
<svg
|
||||
class={style.blobSvg}
|
||||
style={{ fill: blobColor }}
|
||||
viewBox="-1.25 -1.25 2.5 2.5"
|
||||
>
|
||||
{startBlobs.map((points) => (
|
||||
<path
|
||||
d={points
|
||||
.map((point, i) => {
|
||||
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('')}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
)}
|
||||
<div
|
||||
class={style.loadImgContent}
|
||||
style={{ visibility: __PRERENDER__ ? 'hidden' : '' }}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
margin: 8rem 0 -1.2rem;
|
||||
margin: 8rem 0 1rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
@@ -40,7 +40,14 @@
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.blob-svg {
|
||||
composes: abs-fill from '../util.css';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.load-img-content {
|
||||
position: relative;
|
||||
--size: 36rem;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
|
||||
Reference in New Issue
Block a user