简体   繁体   English

如何使用 React 在客户端裁剪图像而不会丢失分辨率

[英]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 while cropping裁剪时的图像

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.

相关问题 我应该如何使用 jcrop 在客户端裁剪图像并上传它? - How should I crop the image at client side using jcrop and upload it? 如何使用php或任何其他语言减小图像文件大小而又不损失质量或分辨率? - How to reduce Image file size without losing quality or resolution using php or any other language? Reactjs:如何在客户端将图像最小化为特定的纵横比? - Reactjs: how to minimally crop an image to a certain aspect ratio in client side? 如何在不丢失 PostBack 功能的情况下将我自己的 JavaScript 链接到客户端 - How do I chain my own JavaScript into the client side without losing PostBack functionality 如何使用 HTML5 画布和 JavaScript 裁剪图像以便离线裁剪图像? - How can i crop image using the HTML5 canvas and JavaScript in order to crop an image offline? 在客户端裁剪和上传图像而不涉及服务器端代码 - Crop and upload image on client-side without server-side code involve 在没有服务器端代码的情况下,在客户端将画布 html5 裁剪为 base64 图像 - crop canvas html5 to image as base64 on client side without server-side code 上传前在JS客户端裁剪分辨率和修剪视频长度? - Crop resolution and trim video length in JS client side before uploading? 如何仅使用Javascript裁剪图像? - How can I crop an image using only Javascript? 如何使用 JavaScript 裁剪图像区域? - How can I crop an area of an image using JavaScript?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM