需求: 图片需要能够自适应,并且满足不同屏幕的布局要求(我们分为pc大小屏幕,pad,mobile)。容器固定为16:9(期望用户上传图片的比例为16:9,但是你不能指望用户一定按照你的要求做);当图片尺寸不合适时(16:8或者16:10),自动对图片进行缩放处理,图片居中;
PC效果
Pad效果
Mobile效果
import { ReactComponent as FallbackIcon } from '@/images/fallback.svg';
import { useEffect, useState } from 'react';
import styles from './index.module.scss';
interface BackgroundImageProps {
src?: string;
className?: string;
}
export function BackgroundImage({ src }: BackgroundImageProps) {
const [hasError, setHasError] = useState(false);
useEffect(() => {
if (!src) {
setHasError(true);
return;
}
const img = new Image();
img.src = src;
img.onload = () => setHasError(false);
img.onerror = () => setHasError(true);
return () => {
img.onload = null;
img.onerror = null;
};
}, [src]);
return (
<div className={styles.imgWrapper}>
<div className={styles.imgInner}>
{hasError ? (
<FallbackIcon className={styles.imgLoadError} />
) : (
<img src={src} alt="背景图像" />
)}
</div>
</div>
);
}
.imgWrapper {
padding-left: 100%;
padding-top: calc(100% * 9 / 16);
position: relative;
}
.imgInner {
display: flex;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
overflow: hidden;
img {
display: block;
width: 100%;
height: 100%;
margin: auto;
object-fit: contain;
}
}
.imgLoadError {
margin: auto;
}
还可以对这个组件进行一些扩展,比如宽高比例接受传参、图片加载失败的兜底图接受传参、自元素接受传参(不一定是Img,可以是任意的ReactNode,scss根据具体需求自己做一些调整就好);感兴趣的同学可以自己动手丰富一下组件功能