profile-picture-generator
Version:
FridaysForFuture profile picture generator
74 lines (64 loc) • 2.06 kB
text/typescript
import { fileToDataURL } from "../../util";
import { AvatarOptions, squareImageAvatar } from "./avatar";
import { CanvasLayer, drawLayer } from "./Layers";
export type Ctx = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
export type TemplateRenderFunction = (options: AvatarOptions) => CanvasLayer[];
/**
* Generates a canvas that contains the generated image.
*/
async function generateCanvas(
layers: CanvasLayer[],
width: number,
height: number
) {
const canvas = window["OffscreenCanvas"]
? new OffscreenCanvas(width, height)
: document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx: Ctx = canvas.getContext("2d");
for (const layer of layers) {
await drawLayer(ctx, layer, width, height);
}
return canvas;
}
export async function clientBuildImageUrl(
file: File,
width: number,
height: number,
borderWidth: number,
zoomFactor: number,
templateUrl: string,
templateRenderFunction: TemplateRenderFunction = squareImageAvatar
) {
const uploadDataUrl = await fileToDataURL(file);
const layers: CanvasLayer[] = templateRenderFunction({
width,
height,
borderWidth,
template: templateUrl,
src: uploadDataUrl,
srcRotation: 1,
srcOffsetX: 0,
srcOffsetY: 0,
zoomFactor,
});
const canvas = await generateCanvas(layers, width, height);
let url = "";
if (canvas instanceof HTMLCanvasElement) {
if (canvas.toBlob) {
console.debug("Create Url via HTMLCanvasElement.toBlob");
const blob = await new Promise(resolve => canvas.toBlob(resolve, "image/png"));
url = URL.createObjectURL(blob);
} else {
// Fallback for Internet Explorer, might not work as the data url can become quite long
console.debug("Create Url via HTMLCanvasElement.toDataURL");
url = canvas.toDataURL("image/png");
}
} else {
console.debug("Create Url via OffscreenCanvas.convertToBlob");
const blob = await canvas.convertToBlob();
url = URL.createObjectURL(blob);
}
return url;
}