从文件输入设置背景图像后移动性能不佳
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(如果用户的设备支持)进一步改进。
我目前正在使用 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(如果用户的设备支持)进一步改进。