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 };