[英]How can I crop an image on the client side without losing resolution using React
I'm trying to crop an image in a react application.我正在尝试在反应应用程序中裁剪图像。 I'm currently using a library called react-image-crop but it seems the cropped image is exactly the same size of crop area on the browser, means if I resize my browser window, the same area of the image comes to be different size.我目前正在使用一个名为 react-image-crop 的库,但裁剪后的图像似乎与浏览器上的裁剪区域大小完全相同,这意味着如果我调整浏览器 window 的大小,图像的相同区域大小会不同. is there any way to retain the resolution of the original image and be still able to crop on the client side?有什么方法可以保留原始图像的分辨率并且仍然能够在客户端进行裁剪? the picture below is the result of cropping of the same area of the picture in different browser sizes.下图是在不同浏览器尺寸下对图片同一区域进行裁剪的结果。
i'm pretty much using react-image-crop out of the box with following crop parameters我几乎使用开箱即用的 react-image-crop 和以下裁剪参数
const [crop, setCrop] = useState({unit: '%', width: 100, aspect: 16 / 9 });
Actually i have the same problem, i also use react-image-crop.实际上我有同样的问题,我也使用 react-image-crop。 My current solution is i create a modal with static size in px as a crop windows.我目前的解决方案是我创建一个以像素为单位的 static 大小的模态作为作物 windows。 so if the window size is smaller, the modal overflow will be activated.因此,如果 window 尺寸较小,将激活模态溢出。
more or less like this:或多或少像这样:
so scroller will dynamically change based on window size and it doesn't affect the image size.因此滚动条将根据 window 大小动态变化,并且不会影响图像大小。
If there is a real and better solution maybe i'd also like to hear about it:)如果有一个真正更好的解决方案,也许我也想听听它:)
in the hook version of the demo, replacing the getResizedCanvas (and moving it inside the react module) fixes the problem在演示的钩子版本中,替换 getResizedCanvas (并将其移动到反应模块中)修复了问题
const getResizedCanvas = () => {
const scaleX = imgRef.current.naturalWidth / imgRef.current.width;
const scaleY = imgRef.current.naturalHeight / imgRef.current.height;
const tmpCanvas = document.createElement("canvas");
tmpCanvas.width = Math.ceil(crop.width*scaleX);
tmpCanvas.height = Math.ceil(crop.height*scaleY);
const ctx = tmpCanvas.getContext("2d");
const image = imgRef.current;
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width*scaleX,
crop.height*scaleY,
);
return tmpCanvas;
}
I had the same issue with the cropper.我对割草机也有同样的问题。 But then adding scaled height and width to canvas and drawImage method worked for me.但是随后将缩放的高度和宽度添加到 canvas 和 drawImage 方法对我有用。
check below screenshots.检查下面的屏幕截图。
Image resolution after crop裁剪后的图像分辨率
const createCropPreview = async (image, crop, fileName) => {
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
const canvas = document.createElement("canvas");
canvas.width = Math.ceil(crop.width * scaleX);
canvas.height = Math.ceil(crop.height * scaleY);
const ctx = canvas.getContext("2d");
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width * scaleX,
crop.height * scaleY
);
return new Promise((resolve, reject) => {
canvas.toBlob((blob) => {
if (blob) {
blob.name = fileName;
window.URL.revokeObjectURL(previewUrl);
const obj = window.URL.createObjectURL(blob);
setPreviewUrl(obj);
props.setImg(obj, blob);
}
}, "image/jpeg");
});
};
For me, this was what actually fixed (using hook).对我来说,这实际上是固定的(使用钩子)。 Basically i'm calculating canvas size taking into account the window resolution in physical pixels to the resolution in CSS pixels for the current display device.基本上,我正在计算 canvas 大小,同时考虑到当前显示设备的物理像素中的 window 分辨率到 CSS 像素中的分辨率。
const canvas = document.createElement('canvas')
const crop = completedCrop
const scaleX = image.naturalWidth / image.width
const scaleY = image.naturalHeight / image.height
const ctx = canvas.getContext('2d')
const pixelRatio = window.devicePixelRatio
canvas.width = scaleX * crop.width * pixelRatio
canvas.height = scaleY * crop.height * pixelRatio
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0)
ctx.imageSmoothingQuality = 'high'
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width * scaleX,
crop.height * scaleY
)
You can also export the canvas blob as png (lossless) rather than jpeg, which will provide you a better image.您还可以将 canvas blob 导出为 png(无损)而不是 jpeg,这将为您提供更好的图像。
canvas.toBlob(
blob => {
const img = URL.createObjectURL(blob)
// do whatever you want...
},
'image/png',
1
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.