CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 27s
CI / Build server (push) Successful in 29s
CI / Build client (push) Successful in 43s
CI / Playwright E2E tests (push) Successful in 2m2s
CI / Build and push Docker image (push) Successful in 45s
CI / Notify (push) Successful in 2s
49 lines
2.0 KiB
TypeScript
49 lines
2.0 KiB
TypeScript
/** Obrázky stylu Hell Girl (plamen + symbol ohně) — server je cachuje, viz server/src/confetti.ts. */
|
|
const HELLGIRL_IMAGES_URL = '/api/confetti/hellgirl';
|
|
|
|
export type HellGirlImages = { flame: string, symbol: string };
|
|
|
|
let imagesPromise: Promise<HellGirlImages | undefined> | undefined;
|
|
|
|
/** Načte URL obrázků (jednou za běh aplikace). Při chybě vrátí undefined a příště to zkusí znovu. */
|
|
export const loadHellGirlImages = (): Promise<HellGirlImages | undefined> => {
|
|
imagesPromise ??= fetch(HELLGIRL_IMAGES_URL)
|
|
.then(r => r.ok ? r.json() : undefined)
|
|
.then(images => images?.flame && images?.symbol ? images as HellGirlImages : undefined)
|
|
.catch(() => undefined)
|
|
.then(images => {
|
|
if (!images) imagesPromise = undefined;
|
|
return images;
|
|
});
|
|
return imagesPromise;
|
|
};
|
|
|
|
/**
|
|
* Z obrázku symbolu (rudý tvar na bílém pozadí) udělá masku — průhlednost podle toho, jak
|
|
* moc pixel není bílý (zelený kanál). Barvu pak symbolu dodá CSS gradientem v paletě stylu.
|
|
*/
|
|
export const createSymbolMask = (src: string, size = 96): Promise<string | undefined> => new Promise(resolve => {
|
|
const img = new Image();
|
|
img.onload = () => {
|
|
try {
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = canvas.height = size;
|
|
const ctx = canvas.getContext('2d');
|
|
if (!ctx) return resolve(undefined);
|
|
ctx.drawImage(img, 0, 0, size, size);
|
|
const pixels = ctx.getImageData(0, 0, size, size);
|
|
const data = pixels.data;
|
|
for (let i = 0; i < data.length; i += 4) {
|
|
data[i + 3] = 255 - data[i + 1];
|
|
data[i] = data[i + 1] = data[i + 2] = 0;
|
|
}
|
|
ctx.putImageData(pixels, 0, 0);
|
|
resolve(canvas.toDataURL('image/png'));
|
|
} catch {
|
|
resolve(undefined);
|
|
}
|
|
};
|
|
img.onerror = () => resolve(undefined);
|
|
img.src = src;
|
|
});
|