马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
import { Image } from ‘antd’;
import { useEffect, useRef, useState } from ‘react’;
import styles from ‘./index.module.less’;
interface PreviewHtmlWithImagesProps {
htmlContent: string;
}
const PreviewHtmlWithImages: React.FC = ({ htmlContent }) => {
const containerRef = useRef(null);
const [imageSrc, setImageSrc] = useState(’’);
const [visible, setVisible] = useState(false);
const [isZoomed, setIsZoomed] = useState(false);
const actionsRef = useRef(null);
// 新增:用于跟踪拖动状态
const isDraggingRef = useRef(false);
const startPosRef = useRef({ x: 0, y: 0 });
const processedHtml = htmlContent.replace(
/<img([^>]*)src="’"’>/gi,
(match, beforeSrc, src, afterSrc) => {
if (/data-src=/i.test(match)) return match;
return <img${beforeSrc}src="${src}" data-src="${src}" class="preview-image"${afterSrc}>;
},
);
useEffect(() => {
const images: any = containerRef.current?.querySelectorAll(’.preview-image’);
images?.forEach((img: HTMLImageElement) => {
const clickHandler = () => {
const src = img.getAttribute(‘data-src’);
setImageSrc(src || ‘’);
setVisible(true);
setIsZoomed(false);
};- img.style.cursor = 'zoom-in';
- img.addEventListener('click', clickHandler);
- return () => {
- img.removeEventListener('click', clickHandler);
- img.style.cursor = '';
- };
- });
复制代码 }, [processedHtml]);
useEffect(() => {
if (!visible) {
setIsZoomed(false);
return;
}- const previewContent: HTMLImageElement | null = document.querySelector(
- '.ant-image-preview-content',
- );
- const previewImg: HTMLImageElement | null = document.querySelector(
- '.ant-image-preview-img',
- ) as HTMLImageElement | null;
- const imgWrapper: HTMLImageElement | null = document.querySelector(
- '.ant-image-preview-img-wrapper',
- );
- if (!previewContent || !previewImg || !imgWrapper) return;
- // 阻止滚轮事件
- const handleWheel = (e: WheelEvent) => {
- e.preventDefault();
- e.stopPropagation();
- };
- // 鼠标按下事件
- const handleMouseDown = (e: MouseEvent) => {
- isDraggingRef.current = false;
- startPosRef.current = { x: e.clientX, y: e.clientY };
- };
- // 鼠标移动事件
- const handleMouseMove = (e: MouseEvent) => {
- // 移动超过5px才认为是拖动
- if (
- Math.abs(e.clientX - startPosRef.current.x) > 5 ||
- Math.abs(e.clientY - startPosRef.current.y) > 5
- ) {
- isDraggingRef.current = true;
- }
- };
- // 鼠标松开事件
- const handleMouseUp = () => {
- // 如果是拖动操作,则设置一个短暂的时间窗口忽略点击
- if (isDraggingRef.current) {
- setTimeout(() => {
- isDraggingRef.current = false;
- }, 100);
- }
- };
- // 点击事件处理
- const handleClick = (e: MouseEvent) => {
- // 如果是拖动后的点击,则忽略
- if (isDraggingRef.current) {
- e.preventDefault();
- e.stopPropagation();
- return;
- }
- if (!actionsRef.current) return;
- setIsZoomed((prev) => {
- const newState = !prev;
- previewImg.style.cursor = newState ? 'grab' : 'zoom-in';
- if (newState) {
- actionsRef.current.onZoomIn();
- } else {
- actionsRef.current.onZoomOut();
- }
- return newState;
- });
- };
- previewImg.style.cursor = isZoomed ? 'grab' : 'zoom-in';
- previewContent.addEventListener('wheel', handleWheel, { passive: false });
- imgWrapper.addEventListener('mousedown', handleMouseDown);
- imgWrapper.addEventListener('mousemove', handleMouseMove);
- imgWrapper.addEventListener('mouseup', handleMouseUp);
- previewImg.addEventListener('click', handleClick);
- return () => {
- previewContent.removeEventListener('wheel', handleWheel);
- imgWrapper.removeEventListener('mousedown', handleMouseDown);
- imgWrapper.removeEventListener('mousemove', handleMouseMove);
- imgWrapper.removeEventListener('mouseup', handleMouseUp);
- previewImg.removeEventListener('click', handleClick);
- previewImg.style.cursor = '';
- };
复制代码 }, [visible, isZoomed]);
return (
<>
<div className={styles.documentation} dangerouslySetInnerHTML={{ __html: processedHtml }} />
<Image
src={imageSrc}
rootClassName=“preview-images”
preview={{
visible,
src: imageSrc,
movable: isZoomed,
onVisibleChange: (vis) => setVisible(vis),
toolbarRender: (_: any, { actions }: any) => {
actionsRef.current = actions;
return null;
},
scaleStep: 0.5,
maxScale: 5,
}}
/>
</>
);
};
export default PreviewHtmlWithImages;
|