上传多张图片后,缩略图由后端创建任务去生成。遇到问题就是,任务排队需要时间去等待,页面展示图片的缩略图怎么显示好呢?
目前我设置的是利用延时去加载一个loading的图片,先加载loading图片,3s后再去加载缩略图,缩略图加载失败则加载失败的图。
这样处理的问题就是,3s后任务还没有结束缩略图还未生成的话,就会显示加载失败的图片,用户会误以为缩略图生成失败。怎么解决这种问题呢?
interface IProps {
onClick: () => void;
src: any;
source?: any; // 原图
preThumb?: any;
waitThumb?: boolean; // 是否等待加载缩略图
}
const ImageWithLoading = (props: IProps) => {
const { onClick, source, waitThumb = false, preThumb } = props;
const [imgSrc, setImgSrc] = useState<any>(loadingImg);
const time: any = useRef();
useEffect(() => {
// 如果暂时没有图片显示,则延时去加载预上传的图片
if (!props.src && waitThumb && preThumb) {
time.current = setTimeout(() => {
onPreLoad(preThumb, false);
}, 3000);
}
return () => {
clearTimeout(time.current);
};
}, [props.src]);
const onPreLoad = (src: string, sourceSrc?: boolean) => {
const img = new Image();
img.onload = () => {
setImgSrc(preThumb);
};
// 若图片加载失败则加载原图, 若加载原图都失败则显示错误图片
img.onerror = () => {
if (sourceSrc) {
setImgSrc(errorImg);
} else {
onPreLoad(source, true);
}
};
img.src = src;
};
const onLoad = () => {
if (props.src) {
const img = new Image();
img.onload = () => {
setImgSrc(props.src);
};
img.onerror = () => {
setImgSrc(errorImg);
};
img.src = props.src;
}
};
return (
<>
<img
src={imgSrc}
onLoad={onLoad}
onClick={onClick}
width="100%"
style={{ maxHeight: '100%', objectFit: 'contain' }}
/>
</>
);
};
传图和页面展示是分开的两个页面,文件上传到minio上后返回的地址传到后端去生成的缩略图。
页面展示那里如果去读取图片的原图用FileRender生成缩略图的话,加载也比较慢。浏览器网速不行的话还是有限制的。
现在缩略图的功能,不需要后端,纯前端就可以完成。
js中有一个FileReader的方法,可以读取通过input[type=file]文件上传控件上传的文件,不用等待后端接口的数据就能展示缩略图。
参考链接:html5实现图片预览和查看原图;