Как я могу вернуть измененное изображение из программы чтения файлов - PullRequest
0 голосов
/ 25 сентября 2019

Я создал функцию, которая заботится об изменении размера изображения, теперь я хочу вернуть измененное изображение из функции.

Я работаю с 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)} 
  />

Я хотел бывернуть новое созданное изображение.

Ответы [ 2 ]

1 голос
/ 25 сентября 2019

Вы можете решить эту проблему, используя 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);
      };
    };
  });
}

С async, await,

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 голосов
/ 25 сентября 2019

Могу я спросить, почему вам не нравится решение использования состояния?Это похоже на довольно стандартный вариант использования.

Ваше состояние может выглядеть примерно так:

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

Ваш обработчик действий просто установитState в случае успеха следующим образом:

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>
  )
}

PS вы можете удалить handleUpload и напрямую вызвать resizeImage.

...