first commit
This commit is contained in:
103
src/utils/cropUtils.js
Normal file
103
src/utils/cropUtils.js
Normal 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;
|
||||
};
|
||||
Reference in New Issue
Block a user