Merge branch 'main' of https://github.com/faisolavolut/julong-lib
This commit is contained in:
commit
ef8855b33c
|
|
@ -57,6 +57,7 @@
|
||||||
"next": "15.0.3",
|
"next": "15.0.3",
|
||||||
"react-chartjs-2": "^5.3.0",
|
"react-chartjs-2": "^5.3.0",
|
||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
|
"react-easy-crop": "^5.2.0",
|
||||||
"react-icons": "^5.3.0",
|
"react-icons": "^5.3.0",
|
||||||
"react-resizable": "^3.0.5",
|
"react-resizable": "^3.0.5",
|
||||||
"react-resizable-panels": "^2.1.7",
|
"react-resizable-panels": "^2.1.7",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
export const createImage = (url: string): Promise<HTMLImageElement> =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const image = new Image();
|
||||||
|
image.addEventListener("load", () => resolve(image));
|
||||||
|
image.addEventListener("error", (error) => reject(error));
|
||||||
|
image.setAttribute("crossOrigin", "anonymous"); // needed to avoid cross-origin issues
|
||||||
|
image.src = url;
|
||||||
|
});
|
||||||
|
|
||||||
|
export function getRadianAngle(degreeValue: number): number {
|
||||||
|
return (degreeValue * Math.PI) / 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the new bounding area of a rotated rectangle.
|
||||||
|
*/
|
||||||
|
export function rotateSize(
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
rotation: number
|
||||||
|
): { width: number; height: number } {
|
||||||
|
const rotRad = getRadianAngle(rotation);
|
||||||
|
|
||||||
|
return {
|
||||||
|
width:
|
||||||
|
Math.abs(Math.cos(rotRad) * width) + Math.abs(Math.sin(rotRad) * height),
|
||||||
|
height:
|
||||||
|
Math.abs(Math.sin(rotRad) * width) + Math.abs(Math.cos(rotRad) * height),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crops and rotates an image
|
||||||
|
*/
|
||||||
|
export default async function getCroppedImg(
|
||||||
|
imageSrc: string,
|
||||||
|
pixelCrop: { x: number; y: number; width: number; height: number },
|
||||||
|
rotation: number = 0,
|
||||||
|
flip: { horizontal: boolean; vertical: boolean } = {
|
||||||
|
horizontal: false,
|
||||||
|
vertical: false,
|
||||||
|
}
|
||||||
|
): Promise<string | null> {
|
||||||
|
const image = await createImage(imageSrc);
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rotRad = getRadianAngle(rotation);
|
||||||
|
|
||||||
|
// Calculate bounding box of the rotated image
|
||||||
|
const { width: bBoxWidth, height: bBoxHeight } = rotateSize(
|
||||||
|
image.width,
|
||||||
|
image.height,
|
||||||
|
rotation
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set canvas size to match the bounding box
|
||||||
|
canvas.width = bBoxWidth;
|
||||||
|
canvas.height = bBoxHeight;
|
||||||
|
|
||||||
|
// Translate canvas context to a central location to allow rotating and flipping around the center
|
||||||
|
ctx.translate(bBoxWidth / 2, bBoxHeight / 2);
|
||||||
|
ctx.rotate(rotRad);
|
||||||
|
ctx.scale(flip.horizontal ? -1 : 1, flip.vertical ? -1 : 1);
|
||||||
|
ctx.translate(-image.width / 2, -image.height / 2);
|
||||||
|
|
||||||
|
// Draw rotated image
|
||||||
|
ctx.drawImage(image, 0, 0);
|
||||||
|
|
||||||
|
const croppedCanvas = document.createElement("canvas");
|
||||||
|
const croppedCtx = croppedCanvas.getContext("2d");
|
||||||
|
|
||||||
|
if (!croppedCtx) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the size of the cropped canvas
|
||||||
|
croppedCanvas.width = pixelCrop.width;
|
||||||
|
croppedCanvas.height = pixelCrop.height;
|
||||||
|
|
||||||
|
// Draw the cropped image onto the new canvas
|
||||||
|
croppedCtx.drawImage(
|
||||||
|
canvas,
|
||||||
|
pixelCrop.x,
|
||||||
|
pixelCrop.y,
|
||||||
|
pixelCrop.width,
|
||||||
|
pixelCrop.height,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
pixelCrop.width,
|
||||||
|
pixelCrop.height
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise<string | null>((resolve) => {
|
||||||
|
croppedCanvas.toBlob((file) => {
|
||||||
|
if (file) {
|
||||||
|
resolve(URL.createObjectURL(file));
|
||||||
|
} else {
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
}, "image/jpeg");
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue