import { Image as AntdImage, ImageProps, ConfigProvider } from 'antd';
import React, {
createContext,
useCallback,
useContext,
useEffect,
useState,
} from 'react';
import './index.less';
import classNames from 'classnames';
import { Icon } from '../Icon';
import errorIcon from './icons/error.png';
import { Modal } from 'antd';
import { GroupConsumerProps } from 'rc-image/lib/PreviewGroup';
import { useRequest } from 'ahooks';
// 提供回调函数给image
export const ImageGroupContext = createContext({
beforeOpenPreview: (src: string) => {},
changeImages: (src: string, isDelete = false) => {},
});
interface ImageExtraProps {}
const Image = (props: ImageProps & ImageExtraProps) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('btri-image');
const { beforeOpenPreview, changeImages } = useContext(ImageGroupContext);
const { preview, src } = props;
useEffect(() => {
const resSrc = (typeof preview === 'object' && preview?.src) || src;
changeImages(resSrc);
return () => {
changeImages(resSrc, true);
};
}, []);
// 重新处理preview
const [_previewVisible, setPreviewVisible] = useState(false);
const getPreview = useCallback(() => {
const basePreview = {
visible: false,
onVisibleChange: (e: boolean, pre) => {
setPreviewVisible(e);
typeof preview !== 'boolean' && preview?.onVisibleChange?.(e, pre);
},
mask: (
{
beforeOpenPreview(props.src);
}}
>
预览
),
};
switch (preview) {
case false:
return false;
case true:
return basePreview;
default:
return { ...preview, ...basePreview };
}
}, [preview, props.src, beforeOpenPreview]);
// previewImage状态变量
const [_scale, setScale] = useState(1);
const [_degree, setDegree] = useState(0);
// 图片移动功能
const [position, setPosition] = useState([0, 0]);
const [margin, setMargin] = useState([0, 0]);
const [isMoving, setIsMoving] = useState(false);
const updatePosition = (pos: [number, number]) => {
setPosition(prePos => {
(prePos?.[0] || prePos?.[1]) &&
setMargin(preMargin => {
return [
preMargin[0] + pos[0] - prePos[0],
preMargin[1] + pos[1] - prePos[1],
];
});
return pos;
});
return new Promise(resolve => {
resolve();
});
};
const { run } = useRequest(updatePosition, {
throttleWait: 30,
});
useEffect(() => {
if (!_previewVisible) {
setMargin([0, 0]);
setScale(1);
setDegree(0);
}
}, [_previewVisible]);
return (
<>
}
{...props}
className={classNames(`${prefixCls}-box`, props.className)}
rootClassName={classNames(`${prefixCls}-root`, props.rootClassName)}
preview={getPreview()}
>
{
setPreviewVisible(false);
}}
style={{ background: 'transparent' }}
width="100%"
className={classNames(`${prefixCls}-preview`)}
closeIcon={
}
maskStyle={{
background: '#050505',
opacity: 0.6,
}}
centered
>
{
setIsMoving(true);
}}
onMouseUp={() => {
setIsMoving(false);
setPosition([0, 0]);
}}
onMouseMove={e => {
isMoving && run([e.clientX, e.clientY]);
}}
draggable={false}
>
{
setScale(pre => pre + 1);
}}
>
{
setScale(pre => pre - 1 || 1);
}}
>
{
setDegree(pre => pre - 90);
}}
>
{
setDegree(pre => pre + 90);
}}
>
>
);
};
const PreviewGroup: React.FC = props => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('btri-image-group');
const { preview } = props;
// previewImage状态变量
const [_scale, setScale] = useState(1);
const [_degree, setDegree] = useState(0);
// 收集图片
const [images, setImages] = useState([]);
// 展示序号
const [_previewIndex, setPreviewIndex] = useState(0);
// 重新处理preview
const [_previewVisible, setPreviewVisible] = useState(false);
const getPreview = useCallback(() => {
const basePreview = {
visible: false,
onVisibleChange: (e: boolean, pre) => {
setPreviewVisible(e);
typeof preview !== 'boolean' && preview?.onVisibleChange?.(e, pre);
},
mask: (
),
};
switch (preview) {
case false:
return false;
case true:
return basePreview;
default:
return { ...preview, ...basePreview };
}
}, [preview]);
const switchPicture = useCallback(
i => {
setPreviewIndex(pre => (pre + i + images.length) % images.length);
},
[images],
);
// 图片移动功能
const [position, setPosition] = useState([0, 0]);
const [margin, setMargin] = useState([0, 0]);
const [isMoving, setIsMoving] = useState(false);
const updatePosition = (pos: [number, number]) => {
setPosition(prePos => {
(prePos?.[0] || prePos?.[1]) &&
setMargin(preMargin => {
return [
preMargin[0] + pos[0] - prePos[0],
preMargin[1] + pos[1] - prePos[1],
];
});
return pos;
});
return new Promise(resolve => {
resolve();
});
};
const { run } = useRequest(updatePosition, {
throttleWait: 30,
});
useEffect(() => {
if (!_previewVisible) {
setMargin([0, 0]);
setScale(1);
setDegree(0);
}
}, [_previewVisible]);
return (
<>
{
const index = images.findIndex(item => item === src);
setPreviewIndex(index);
},
changeImages: (src, isDelete) => {
if (isDelete) {
setImages(pre => pre.filter(item => item === src));
} else {
setImages(pre => pre.concat(src));
}
},
}}
>
{props.children}
{
setPreviewVisible(false);
}}
style={{ background: 'transparent' }}
width="100%"
className={classNames(`${prefixCls}-preview`)}
closeIcon={
}
maskStyle={{
background: '#050505',
opacity: 0.6,
}}
centered
>
{
setIsMoving(true);
}}
onMouseUp={() => {
setIsMoving(false);
setPosition([0, 0]);
}}
onMouseMove={e => {
isMoving && run([e.clientX, e.clientY]);
}}
draggable={false}
>
{
setScale(pre => pre + 1);
}}
>
{
setScale(pre => pre - 1 || 1);
}}
>
{
setDegree(pre => pre - 90);
}}
>
{
setDegree(pre => pre + 90);
}}
>
{
setMargin([0, 0]);
setScale(1);
setDegree(0);
switchPicture(-1);
}}
>
{
setMargin([0, 0]);
setScale(1);
setDegree(0);
switchPicture(1);
}}
>
>
);
};
Image.PreviewGroup = PreviewGroup;
export { Image };