从文件输入设置背景图像后移动性能不佳

Poor mobile performance after setting background image from file input

我目前正在使用 react(gatsby) 开发一个 web 应用程序,用户可以在其中发帖。帖子包含图像和多个文本字段。我通过使用文件类型输入从用户那里获取图像。我正在使用 FileReader 读取图像并将其传递给状态。因为我想向作者显示预览,所以我将 div 的背景图像设置为状态保存的图像。如果我这样做,应用程序会变得非常慢。在其中一个文本输入中键入时,会有非常明显的滞后。有谁知道为什么会这样?我知道根据大小,文件 reader 可能需要几秒钟才能加载图像,但为什么加载后的性能会受到如此大的影响?

这是我的文件输入:

<input type="file" accept="image/*" capture="camera" ref={cameraInputRef} 
    onChange = {e => {
      e.persist();
      readFile(e.target.files[0])
     }}
> 
</input>

这是我的文件阅读器:

 function readFile(file){
    // let fileReader = new FileReader();
    fileReader.addEventListener('load', () => {
      // puts image in state 
      setDishImage(fileReader.result);
    })
    fileReader.readAsDataURL(file)
  }

这是 div 上的 css:

 background-image: url(props.dishImage});
 background-position-y: center;
 background-size: cover;
 height:100vw;
 width:100%;

任何帮助或将不胜感激。

您当前的实施对于 select 大图像的用户来说并不理想(当 select 从相机胶卷中获取图像时,情况通常如此)。您可以通过在 canvas 中调整图像大小并生成 blob URL 来解决这个问题,例如:

function handleFileChange(event) {
  if (event.target.files.length === 0) {
    return;
  }
  const file = event.target.files[0];
  const fileReader = new FileReader();
  fileReader.onload = () => {
    const src = URL.createObjectURL(new Blob([fileReader.result], { type: file.type }));
    const img = new Image();
    img.onload = () => createPreview(img, file.type).then((preview) => {
      console.log(preview);
      previewImage.src = preview;
      previewImage.style.display = "block";

      // Remove in-memory blob URLs
      URL.revokeObjectURL(src);

      // Clean up the preview blob URL when you are done with the preview
      // URL.revokeObjectURL(preview);
  });
    img.src = src;
  };
  fileReader.readAsArrayBuffer(file);
}

function createPreview(img, type, constraints = { width: 640, height: 480 }) {
  return new Promise((resolve) => {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");

    canvas.width = constraints.width;
    canvas.height = constraints.height;

    const ratioH = canvas.width / img.width;
    const ratioV = canvas.height / img.height;
    const ratio = Math.min(ratioH, ratioV);

    ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, img.width * ratio, img.height * ratio);
    canvas.toBlob((blob) => resolve(URL.createObjectURL(blob)), type);
  });
}

const filePicker = document.querySelector("#filePicker");
const previewImage = document.querySelector("#previewImage");

filePicker.onchange = handleFileChange;
<input type="file" max="1" accept="image/*" id="filePicker"/>
<img src="" alt="Image Preivew" id="previewImage" style="display: none;" />

您可以使用新的 OffscreenCanvas API(如果用户的设备支持)进一步改进。