first commit

This commit is contained in:
2025-11-10 23:35:59 +03:00
commit 68165014ad
33 changed files with 2084 additions and 0 deletions

103
src/utils/cropUtils.js Normal file
View File

@@ -0,0 +1,103 @@
const loadImage = (file) =>
new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
URL.revokeObjectURL(image.src);
resolve(image);
};
image.onerror = (error) => {
URL.revokeObjectURL(image.src);
reject(error);
};
image.src = URL.createObjectURL(file);
});
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
const normalizeCropConfig = (config) => {
if (!config?.imageWidth || !config?.imageHeight) {
throw new Error('Geçerli bir crop referansı bulunamadı.');
}
const safeWidth = Math.max(
1,
config.width - (config.left ?? 0) - (config.right ?? 0),
);
const safeHeight = Math.max(
1,
config.height - (config.top ?? 0) - (config.bottom ?? 0),
);
const xStart = Math.max(0, config.cropAreaX + (config.left ?? 0));
const yStart = Math.max(0, config.cropAreaY + (config.top ?? 0));
return {
xRatio: xStart / config.imageWidth,
yRatio: yStart / config.imageHeight,
widthRatio: safeWidth / config.imageWidth,
heightRatio: safeHeight / config.imageHeight,
};
};
const cropImage = async (file, normalizedConfig) => {
const image = await loadImage(file);
const { width: imgWidth, height: imgHeight } = image;
const cropWidth = clamp(
Math.round(normalizedConfig.widthRatio * imgWidth),
1,
imgWidth,
);
const cropHeight = clamp(
Math.round(normalizedConfig.heightRatio * imgHeight),
1,
imgHeight,
);
const startX = clamp(
Math.round(normalizedConfig.xRatio * imgWidth),
0,
imgWidth - cropWidth,
);
const startY = clamp(
Math.round(normalizedConfig.yRatio * imgHeight),
0,
imgHeight - cropHeight,
);
const canvas = document.createElement('canvas');
canvas.width = cropWidth;
canvas.height = cropHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(image, startX, startY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);
const blob = await new Promise((resolve, reject) => {
canvas.toBlob((result) => {
if (result) {
resolve(result);
} else {
reject(new Error('Canvas blob oluşturulamadı.'));
}
}, 'image/png');
});
const url = URL.createObjectURL(blob);
return { blob, url };
};
export const applyCropToImages = async (images, config) => {
if (!images?.length) {
throw new Error('Önce görsel yüklemelisin.');
}
if (!config || !config.imageWidth) {
throw new Error('Crop ayarı bulunamadı.');
}
const normalized = normalizeCropConfig(config);
const results = [];
for (const image of images) {
const { blob, url } = await cropImage(image.file, normalized);
results.push({
id: image.id,
filename: image.file.name,
blob,
url,
order: image.order,
});
}
return results;
};