Update carousels, card hover, and IranBay branding.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
export type Area = {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
|
||||
function loadImage(src: string): Promise<HTMLImageElement> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const image = new Image();
|
||||
image.addEventListener("load", () => resolve(image));
|
||||
image.addEventListener("error", (error) => reject(error));
|
||||
image.crossOrigin = "anonymous";
|
||||
image.src = src;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Crop that may extend outside the source image.
|
||||
* Outside pixels stay transparent (PNG) or fillColor (JPEG).
|
||||
*/
|
||||
export async function getCroppedImageFile(
|
||||
imageSrc: string,
|
||||
pixelCrop: Area,
|
||||
fileName: string,
|
||||
mimeType = "image/jpeg",
|
||||
quality = 0.92,
|
||||
fillColor = "#ffffff",
|
||||
): Promise<File> {
|
||||
const image = await loadImage(imageSrc);
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) throw new Error("Could not crop image.");
|
||||
|
||||
const outputWidth = Math.max(1, Math.round(pixelCrop.width));
|
||||
const outputHeight = Math.max(1, Math.round(pixelCrop.height));
|
||||
canvas.width = outputWidth;
|
||||
canvas.height = outputHeight;
|
||||
|
||||
if (mimeType !== "image/png") {
|
||||
ctx.fillStyle = fillColor;
|
||||
ctx.fillRect(0, 0, outputWidth, outputHeight);
|
||||
} else {
|
||||
ctx.clearRect(0, 0, outputWidth, outputHeight);
|
||||
}
|
||||
|
||||
const srcX = Math.max(0, pixelCrop.x);
|
||||
const srcY = Math.max(0, pixelCrop.y);
|
||||
const srcRight = Math.min(image.naturalWidth, pixelCrop.x + pixelCrop.width);
|
||||
const srcBottom = Math.min(
|
||||
image.naturalHeight,
|
||||
pixelCrop.y + pixelCrop.height,
|
||||
);
|
||||
const srcWidth = srcRight - srcX;
|
||||
const srcHeight = srcBottom - srcY;
|
||||
|
||||
if (srcWidth > 0 && srcHeight > 0) {
|
||||
const destX = Math.round(srcX - pixelCrop.x);
|
||||
const destY = Math.round(srcY - pixelCrop.y);
|
||||
ctx.drawImage(
|
||||
image,
|
||||
srcX,
|
||||
srcY,
|
||||
srcWidth,
|
||||
srcHeight,
|
||||
destX,
|
||||
destY,
|
||||
srcWidth,
|
||||
srcHeight,
|
||||
);
|
||||
}
|
||||
|
||||
const blob = await new Promise<Blob>((resolve, reject) => {
|
||||
canvas.toBlob(
|
||||
(result) => {
|
||||
if (result) resolve(result);
|
||||
else reject(new Error("Could not export cropped image."));
|
||||
},
|
||||
mimeType,
|
||||
quality,
|
||||
);
|
||||
});
|
||||
|
||||
const base = fileName.replace(/\.[^.]+$/, "") || "image";
|
||||
const extension = mimeType === "image/png" ? "png" : "jpg";
|
||||
return new File([blob], `${base}-cropped.${extension}`, { type: mimeType });
|
||||
}
|
||||
Reference in New Issue
Block a user