feat:黄炎培对话对接中
This commit is contained in:
1 parent
3611a0857a
commit
6ab184b328
125 files changed
+6617
-2391
No files matched your search
@@ -26,15 +26,10 @@ export interface ExhibitOverlayProps {
|
||||
description?: string;
|
||||
/** 是否自动播放描述语音,默认 false */
|
||||
autoPlayDescription?: boolean;
|
||||
/** 自定义点击区域配置 */
|
||||
clickableAreas?: Array<{
|
||||
/** 区域名称 */
|
||||
name: string;
|
||||
/** 相对于图片的位置和大小(百分比) */
|
||||
position: { left: number; top: number; width: number; height: number };
|
||||
/** 点击回调 */
|
||||
onClick: () => void;
|
||||
}>;
|
||||
/** 点击展示 */
|
||||
onClick?: () => void;
|
||||
/** 是否禁用拖拽,默认 false。当为 true 时,禁用拖拽和缩放功能,确保 onClick 事件能正常触发 */
|
||||
disableDrag?: boolean;
|
||||
}
|
||||
|
||||
type Point = { x: number; y: number };
|
||||
@@ -54,7 +49,8 @@ const ExhibitOverlay = ({
|
||||
className,
|
||||
description,
|
||||
autoPlayDescription = false,
|
||||
clickableAreas,
|
||||
onClick,
|
||||
disableDrag = false,
|
||||
}: ExhibitOverlayProps) => {
|
||||
const maskSrc = getStaticImage("components/蒙版遮罩");
|
||||
const backSrc = getStaticImage("components/关闭");
|
||||
@@ -62,6 +58,7 @@ const ExhibitOverlay = ({
|
||||
// 获取缩放参数,用于视觉对齐
|
||||
const { scale, offsetX, offsetY, DESIGN_WIDTH, DESIGN_HEIGHT } = useScale();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
|
||||
// SSR 兼容:只在客户端挂载
|
||||
useEffect(() => {
|
||||
@@ -128,6 +125,7 @@ const ExhibitOverlay = ({
|
||||
pointers.current.clear();
|
||||
lastDistance.current = null;
|
||||
dragStartRef.current = null;
|
||||
setIsDragging(false);
|
||||
// 释放所有指针捕获
|
||||
if (containerRef.current) {
|
||||
pointers.current.forEach((_, pointerId) => {
|
||||
@@ -244,6 +242,9 @@ const ExhibitOverlay = ({
|
||||
// 指针按下:记录初始状态
|
||||
const handlePointerDown = useCallback(
|
||||
(e: React.PointerEvent<HTMLDivElement>) => {
|
||||
// 如果禁用了拖拽,直接返回,不处理拖拽事件
|
||||
if (disableDrag) return;
|
||||
|
||||
if (!containerRef.current || !viewElRef.current) return;
|
||||
try {
|
||||
containerRef.current.setPointerCapture(e.pointerId);
|
||||
@@ -266,6 +267,7 @@ const ExhibitOverlay = ({
|
||||
startY: e.clientY,
|
||||
startTransform: { ...transformRef.current },
|
||||
};
|
||||
setIsDragging(true);
|
||||
} else if (pointers.current.size === 2) {
|
||||
// 双指缩放:记录初始距离
|
||||
const values = Array.from(pointers.current.values());
|
||||
@@ -278,7 +280,7 @@ const ExhibitOverlay = ({
|
||||
}
|
||||
}
|
||||
},
|
||||
[getDistance]
|
||||
[getDistance, disableDrag]
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -397,6 +399,8 @@ const ExhibitOverlay = ({
|
||||
} else {
|
||||
dragStartRef.current = null;
|
||||
}
|
||||
|
||||
setIsDragging(pointers.current.size > 0);
|
||||
},
|
||||
[]
|
||||
);
|
||||
@@ -492,7 +496,7 @@ const ExhibitOverlay = ({
|
||||
|
||||
{/* 展品内容 - 在剩余空间中居中 */}
|
||||
<div
|
||||
className="absolute top-1/2 -translate-y-1/2"
|
||||
className="absolute top-1/2 -translate-y-1/2 pointer-events-none"
|
||||
style={{
|
||||
// 有描述时:从描述右侧30px开始,到右边界,在这个区域内居中
|
||||
left: description ? "520px" : "0", // 30 + 450 + 30
|
||||
@@ -510,17 +514,22 @@ const ExhibitOverlay = ({
|
||||
maxHeight: containerSize,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
cursor: disableDrag
|
||||
? "default"
|
||||
: isDragging
|
||||
? "grabbing"
|
||||
: "grab",
|
||||
}}
|
||||
onPointerDown={handlePointerDown}
|
||||
onPointerMove={handlePointerMove}
|
||||
onPointerUp={handlePointerUp}
|
||||
onPointerCancel={handlePointerUp}
|
||||
onWheel={handleWheel}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
onPointerDown={disableDrag ? undefined : handlePointerDown}
|
||||
onPointerMove={disableDrag ? undefined : handlePointerMove}
|
||||
onPointerUp={disableDrag ? undefined : handlePointerUp}
|
||||
onPointerCancel={disableDrag ? undefined : handlePointerUp}
|
||||
onWheel={disableDrag ? undefined : handleWheel}
|
||||
onDoubleClick={disableDrag ? undefined : handleDoubleClick}
|
||||
>
|
||||
<div
|
||||
ref={viewElRef}
|
||||
className="max-w-full max-h-full select-none relative"
|
||||
className="max-w-full max-h-full select-none relative pointer-events-auto"
|
||||
style={{
|
||||
transform: "translate3d(0px, 0px, 0) scale(1)",
|
||||
transformOrigin: "0 0",
|
||||
@@ -533,34 +542,13 @@ const ExhibitOverlay = ({
|
||||
WebkitPerspective: "1000",
|
||||
perspective: "1000",
|
||||
}}
|
||||
onClick={onClick}
|
||||
>
|
||||
<Image
|
||||
src={exhibitSrc}
|
||||
alt="展品"
|
||||
className="max-w-full max-h-full object-contain drop-shadow-2xl"
|
||||
/>
|
||||
{/* 可点击区域 */}
|
||||
{clickableAreas &&
|
||||
clickableAreas.map((area, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="absolute cursor-pointer transition-all duration-200 hover:bg-white/10"
|
||||
style={{
|
||||
left: `${area.position.left}%`,
|
||||
top: `${area.position.top}%`,
|
||||
width: `${area.position.width}%`,
|
||||
height: `${area.position.height}%`,
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
area.onClick();
|
||||
}}
|
||||
onPointerDown={(e) => {
|
||||
// 阻止拖拽事件
|
||||
e.stopPropagation();
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user