|
@@ -34,7 +34,11 @@ function Graph({ setCurrentNodeIndex }: { setCurrentNodeIndex: (index: number) =
|
|
|
startX: 0, // 触摸起始点 X 坐标
|
|
startX: 0, // 触摸起始点 X 坐标
|
|
|
startY: 0, // 触摸起始点 Y 坐标
|
|
startY: 0, // 触摸起始点 Y 坐标
|
|
|
startOffsetX: 0, // 元素起始偏移 X
|
|
startOffsetX: 0, // 元素起始偏移 X
|
|
|
- startOffsetY: 0 // 元素起始偏移 Y
|
|
|
|
|
|
|
+ startOffsetY: 0, // 元素起始偏移 Y
|
|
|
|
|
+ initialDistance: 0, // 两指缩放的初始距离
|
|
|
|
|
+ initialZoom: 1, // 初始缩放比例
|
|
|
|
|
+ midX: 0, // 两指缩放的中点 X 坐标
|
|
|
|
|
+ midY: 0 // 两指缩放的中点 Y 坐标
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const graphRef = useRef<HTMLDivElement>(null);
|
|
const graphRef = useRef<HTMLDivElement>(null);
|
|
@@ -196,22 +200,54 @@ function Graph({ setCurrentNodeIndex }: { setCurrentNodeIndex: (index: number) =
|
|
|
startRef.current.startY = touch.clientY;
|
|
startRef.current.startY = touch.clientY;
|
|
|
startRef.current.startOffsetX = offsetX;
|
|
startRef.current.startOffsetX = offsetX;
|
|
|
startRef.current.startOffsetY = offsetY;
|
|
startRef.current.startOffsetY = offsetY;
|
|
|
- }, [offsetX, offsetY])
|
|
|
|
|
|
|
+ if (e.touches.length === 2) {
|
|
|
|
|
+ const t1 = e.touches[0]
|
|
|
|
|
+ const t2 = e.touches[1]
|
|
|
|
|
+ // 记录两指缩放的初始数据:距离,当前缩放比例,中点坐标
|
|
|
|
|
+ const distance = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)
|
|
|
|
|
+ startRef.current.initialDistance = distance
|
|
|
|
|
+ startRef.current.initialZoom = zoom
|
|
|
|
|
+ // 计算中点坐标
|
|
|
|
|
+ const midX = (t1.clientX + t2.clientX) / 2
|
|
|
|
|
+ const midY = (t1.clientY + t2.clientY) / 2
|
|
|
|
|
+ startRef.current.midX = midX
|
|
|
|
|
+ startRef.current.midY = midY
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [offsetX, offsetY, zoom])
|
|
|
const handleTouchMove = useCallback((e: React.TouchEvent) => {
|
|
const handleTouchMove = useCallback((e: React.TouchEvent) => {
|
|
|
- const touch = e.touches[0];
|
|
|
|
|
- if (!touch) return;
|
|
|
|
|
- const dx = touch.clientY - startRef.current.startY;
|
|
|
|
|
- const dy = -touch.clientX + startRef.current.startX;
|
|
|
|
|
- setOffsetX(prev => {
|
|
|
|
|
- const newX = startRef.current.startOffsetX + dx;
|
|
|
|
|
- return Math.min(0, Math.max(-1640, newX));
|
|
|
|
|
- // return newX
|
|
|
|
|
- });
|
|
|
|
|
- setOffsetY(prev => {
|
|
|
|
|
- const newY = startRef.current.startOffsetY + dy;
|
|
|
|
|
- return Math.min(0, Math.max(-350, newY));
|
|
|
|
|
- // return newY
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ const touch = e.touches[0]
|
|
|
|
|
+ const dx = touch.clientY - startRef.current.startY
|
|
|
|
|
+ const dy = -touch.clientX + startRef.current.startX
|
|
|
|
|
+ if (e.touches.length === 1) {
|
|
|
|
|
+ setOffsetX(prev => {
|
|
|
|
|
+ const newX = startRef.current.startOffsetX + dx;
|
|
|
|
|
+ return Math.min(0, Math.max(-1640, newX));
|
|
|
|
|
+ // return newX
|
|
|
|
|
+ });
|
|
|
|
|
+ setOffsetY(prev => {
|
|
|
|
|
+ const newY = startRef.current.startOffsetY + dy;
|
|
|
|
|
+ return Math.min(0, Math.max(-350, newY));
|
|
|
|
|
+ // return newY
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ if (e.touches.length === 2) {
|
|
|
|
|
+ const touch2 = e.touches[1]
|
|
|
|
|
+ // 计算当前两指之间的距离
|
|
|
|
|
+ const distance = Math.hypot(touch2.clientX - touch.clientX, touch2.clientY - touch.clientY)
|
|
|
|
|
+ // 根据距离调整缩放比例
|
|
|
|
|
+ const newZoom = Math.max(0.8, Math.min(2, distance / startRef.current.initialDistance * startRef.current.initialZoom))
|
|
|
|
|
+ setZoom(newZoom)
|
|
|
|
|
+ setOffsetX(prev => {
|
|
|
|
|
+ const deltaMidX = (touch2.clientX + touch.clientX) / 2 - startRef.current.midX
|
|
|
|
|
+ const newX = startRef.current.startOffsetX - deltaMidX + dx * 0.5
|
|
|
|
|
+ return Math.min(0, Math.max(-1640, newX));
|
|
|
|
|
+ })
|
|
|
|
|
+ setOffsetY(prev => {
|
|
|
|
|
+ const deltaMidY = (touch2.clientY + touch.clientY) / 2 - startRef.current.midY
|
|
|
|
|
+ const newY = startRef.current.startOffsetY - deltaMidY + dy * 0.5
|
|
|
|
|
+ return Math.min(0, Math.max(-350, newY));
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
}, [])
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
|
|
@@ -299,7 +335,7 @@ function Graph({ setCurrentNodeIndex }: { setCurrentNodeIndex: (index: number) =
|
|
|
userSelect: 'none'
|
|
userSelect: 'none'
|
|
|
}}
|
|
}}
|
|
|
>
|
|
>
|
|
|
- {/* <div className="fixed" style={{ width: '5px', height: '5px', backgroundColor: '#000', borderRadius: '50%', position: 'absolute', top: '0', left: '0', transform: `translate(${zoomOrigin.x}px,${zoomOrigin.y}px)` }}></div> */}
|
|
|
|
|
|
|
+ <div className="fixed" style={{ width: '5px', height: '5px', backgroundColor: '#000', borderRadius: '50%', position: 'absolute', top: '0', left: '0', transform: `translate(${-offsetX}px,${-offsetY}px)` }}></div>
|
|
|
<NodeClickData />
|
|
<NodeClickData />
|
|
|
</div>
|
|
</div>
|
|
|
<div className={styles.tip}>
|
|
<div className={styles.tip}>
|