我如何从文件读取器返回调整大小的图像

问题描述 投票:0回答:2

我创建了一个负责调整图像大小的函数,现在我想从该函数返回调整大小后的图像。

我正在使用react,并且知道我可以通过使用state来解决问题,但我不喜欢此解决方案。

试图返回每个不同的范围,但我仍然收到undefined响应。同样,当我返回reader本身时,也会得到旧数据。

接口

   interface IHTMLInputEvent extends Event {
        target: HTMLInputElement & EventTarget;
    }

调整大小功能

function resizeImage(file: IHTMLInputEvent, width: number) {

        const fileName = file.target.files[0].name;
        const reader = new FileReader();

        reader.readAsDataURL(file.target.files[0]);

        reader.onload = (event) => {
            const img = new Image();
            img.src = event.target.result.toString();

            img.onload = () => {
                const elem = document.createElement('canvas');
                const scaleFactor = width / img.width;
                elem.width = width;
                elem.height = img.height * scaleFactor;

                const ctx = elem.getContext('2d');
                ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);

                ctx.canvas.toBlob((blob) => {
                    return new File([blob], fileName, { type: 'image/jpeg', lastModified: Date.now() });
                }, 'image/jpeg', 1);
            };
        };
    }

用于处理上传(到目前为止)的功能

function handleUpload(e: IHTMLInputEvent) {
        const resizedImage = resizeImage(e, 600);
    }

输入字段

 <input 
   className={classes.inputForUpload} 
   accept='image/*' 
   type='file' 
   ref={uploadImage} 
   onChange={(e: IHTMLInputEvent) => handleUpload(e)} 
  />

我想返回新创建的图像。

javascript reactjs typescript canvas filereader
2个回答
1
投票

您可以使用Promise解决此问题,

function resizeImage(file: IHTMLInputEvent, width: number) {

  return new Promise((resolve, reject) => {

    const fileName = file.target.files[0].name;
    const reader = new FileReader();

    reader.readAsDataURL(file.target.files[0]);

    reader.onload = (event) => {
      const img = new Image();
      img.src = event.target.result.toString();

      img.onload = () => {
        const elem = document.createElement('canvas');
        const scaleFactor = width / img.width;
        elem.width = width;
        elem.height = img.height * scaleFactor;

        const ctx = elem.getContext('2d');
        ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);

        ctx.canvas.toBlob((blob) => {
          resolve(new File([blob], fileName, {
            type: 'image/jpeg',
            lastModified: Date.now()
          }));
        }, 'image/jpeg', 1);
      };
    };
  });
}

使用asyncawait

async function handleUpload(e: IHTMLInputEvent) {
  const resizedImage = await resizeImage(e, 600);

  // do you suff here
}

JSX,

<input 
   className={classes.inputForUpload} 
   accept='image/*' 
   type='file' 
   ref={uploadImage} 
   onChange={async (e: IHTMLInputEvent) => await handleUpload(e)} 
/>

0
投票

请问您为什么不喜欢使用状态的解决方案?这似乎是一个非常标准的用例。

您的状态可能看起来像这样:

state = {
  imageDescription: '',
  imageUrl: null
};

您的操作处理程序将在成功时简单地设置状态,如下所示:

img.onload = () => {
  ...

  this.setState({ imageDescription: fileName, imageSrc: img.src })
};

最后,您的渲染函数将如下所示:

render() {
  const { imageDescription, imageUrl } = this.state;

  return (
    <Fragment>
       <input 
         className={classes.inputForUpload} 
         accept='image/*' 
         type='file' 
         ref={uploadImage} 
         onChange={(e: IHTMLInputEvent) => handleUpload(e)} 
       />
       <img src={imageUrl} alt={imageDescription} />
    </Fragment>
  )
}

P.S。您可以删除handleUpload并直接调用resizeImage。

© www.soinside.com 2019 - 2024. All rights reserved.