css 根据图片大小绘制坐标轴
背景:客户要求在展示的图片上绘制网格坐标轴, 并且图片尺寸不固定,根据图片尺寸计算出每个格子的尺寸。
如图
首先要注意的点
- 图片的宽高不固定
- 图片随着屏幕自适应
- 网格固定分成10块
- 实时获取当前图片尺寸
代码实现:
// js
const [offsetHeight, setoffsetHeight] = useState();
const [offsetWidth, setoffsetWidth] = useState();
// 图片上传/ 回显部分
<Form
form={form}
name="images_form"
autoComplete="off"
>
<Item noStyle dependencies={['background']}>
{({ getFieldValue }) => {
const background = getFieldValue('background') as UploadFile[];
const { status } = background?.[0] || {};
if (background?.length > 0) {
// 如果是新上传的图片
if (background?.[0].originFileObj) {
const fr = new FileReader();
fr.readAsDataURL(background?.[0].originFileObj);
fr.onload = (e) => {
const img = new window.Image();
img.src = (e.target?.result || '') as string;
document.body.appendChild(img);
img.onload = () => {
setoffsetHeight(img.offsetHeight);
setoffsetWidth(img.offsetWidth);
document.body.removeChild(img);
};
};
} else {
// 只有图片url时
const img = new window.Image();
img.src = background[0].url || '';
document.body.appendChild(img);
img.onload = () => {
setoffsetHeight(img.offsetHeight);
setoffsetWidth(img.offsetWidth);
document.body.removeChild(img);
};
}
}
return (
<Item
name="background"
rules={[{ required: true, message: '请上传背景图' }]}
valuePropName="fileList"
style={{ marginBottom: 0 }}
>
<UploadImg id="images_form_background" maxCount={1}>
{uploadButton(status === 'uploading')}
</UploadImg>
</Item>
);
}}
</Item>
</Form>
// 网格尺寸计算
const generateMultiples = (n: number, is: number) => {
// 创建一个空数组用于存储结果
const multiplesArray = [];
// 使用循环来计算倍数
for (let i = is; i <= 10; i++) {
multiplesArray.push(parseInt(n * i, 10));
}
return multiplesArray;
};
// 图片展示部分
<Flex className="preview-image" align="center" justify="center">
<div className={posterCode ? 'grids' : 'nonegrids'}>
{
offsetHeight && offsetWidth && posterCode ? (
<div>
<div
className="preview-image-grid"
style={{
backgroundSize: '10% 10%',
}}
/>
<div className="preview-image-top">
{
generateMultiples(offsetWidth / 10, 1).map(
(item) => <div><span>{item}</span></div>,
)
}
</div>
<div
className="preview-image-left"
>
{
generateMultiples(offsetHeight / 10, 0).map((item) => <span style={{ display: 'inline-flex' }}>{item}</span>)
}
</div>
</div>
) : null
}
<Image
height="100%"
id="images"
src={'/XXX/XXXX/imgsrc'}
fallback={emptyImg}
/>
</div>
</Flex>
css
.preview-image {
flex: 1 1 auto;
height: calc(100% - 72px);
position: relative;
.ant-image-img {
width: 100%;
object-fit: contain;
}
.nonegrids {
width: 100%;
height: 100%;
}
.grids {
width: 100%;
height: 100%;
.preview-image-grid {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
// /*90度直线,100灰度,0.1透明度,5%宽度,0透明度背景*/
background: linear-gradient(90deg, rgba(0, 0, 0, 0.3) 1%, transparent 1px),
/*0度直线,100灰度,0.1透明度,5%宽度,0透明度背景*/
linear-gradient(rgba(0, 0, 0, 0.3) 1%, transparent 1px);
// /*横纵向宽距*/
background-size: 10px 10px;
font-size: 0;
text-align: center;
z-index: 1000 !important;
border: 0.5 solid #646a73;
}
.preview-image-top {
width: 100%;
position: absolute;
top: -15px;
left: 0;
font-size: 10px;
z-index: 1000 !important;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
div {
width: 100%;
text-align: right;
}
}
.preview-image-left {
position: absolute;
top: 0;
left: -17px;
width: 10px;
height: 100%;
font-size: 10px;
z-index: 1000 !important;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-content: space-between;
}
}
}