lanxin 1 mese fa
parent
commit
bbfb3e2793

+ 49 - 8
src/pages/A6ybwx/Genealogy/components/GraphSVG/index.module.scss

@@ -1,9 +1,50 @@
-.graphSvg {
-  width: 2500px;
-  height: 800px;
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  background: #ccc;
+.SVGContainner {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  :global {
+    .graphSvg {
+      width: 100%;
+      height: 100%;
+      position: absolute;
+      top: 0;
+      left: 0;
+      background: #ccc;
+    }
+  }
+}
+
+.miniMap {
+  position: fixed;
+  left: 20px;
+  bottom: 20px;
+  width: 300px;
+  height: 80px;
+  background: rgba(0, 0, 0, 0.5);
+  border: 1px solid rgba(255, 233, 182, 0.5);
+  overflow: hidden;
+
+  .viewport {
+    position: absolute;
+    border: 1px solid #ffe9b6;
+    cursor: move;
+    background: rgba(255, 233, 182, 0.1);
+  }
+
+  .miniContent {
+    transform-origin: 0 0;
+    pointer-events: none;
+    width: 3000px;
+    height: 800px;
+    position: relative;
+    touch-action: none;
+    :global {
+      .nodeActiveG {
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+      }
+    }
+  }
 }

+ 98 - 9
src/pages/A6ybwx/Genealogy/components/GraphSVG/index.tsx

@@ -1,15 +1,104 @@
-import React from "react";
-import styles from "./index.module.scss";
-// import { ReactComponent as GraphSvg } from '@/assets/img/Graph.svg'
-function GraphSvg() {
+import React, { useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { ReactComponent as GraphSvg } from '@/assets/img/Graph.svg'
+import svgPanZoom from 'svg-pan-zoom'
+import { useDrag } from '@use-gesture/react'
+
+const MAIN_CONTENT_WIDTH = 1920
+const MAIN_CONTENT_HEIGHT = 945
+const MINIMAP_SCALE = 0.045
+function SvgGraph() {
+  const [startX, setStartX] = useState(0)
+  const [startY, setStartY] = useState(0)
+  const [offsetX, setOffsetX] = useState(0)
+  const [offsetY, setOffsetY] = useState(0)
+  const svgRef = useRef<any>(null)
+  const panZoomInstance = useRef<ReturnType<typeof svgPanZoom> | null>(null)
+
+  // 小地图相关逻辑
+
+  const miniMapScale = 0.1
+
+  // 小地图拖拽绑定
+  const bind = useDrag(({ offset: [x, y] }) => {
+    if (!panZoomInstance.current) return;
+    console.log(123123, offsetX, offsetY)
+    // 计算视口位置
+    const viewportX = x / miniMapScale;  // 减去初始 X 偏移
+    const viewportY = y / miniMapScale;
+
+
+    // 更新主视图位置
+    panZoomInstance.current.pan({  // 使用正确的实例方法
+      x: -viewportX,
+      y: -viewportY
+    });
+
+
+  });
+
+
+  // 设置拖拽
+  useEffect(() => {
+    if (svgRef.current) {
+      // 初始化 svg-pan-zoom
+      svgRef.current.setAttribute('viewBox', '0 0 3000 800')
+      panZoomInstance.current = svgPanZoom(svgRef.current, {
+        zoomEnabled: false,
+        dblClickZoomEnabled: false,
+        panEnabled: true,
+        controlIconsEnabled: false,
+        fit: false,
+        contain: false,
+        center: false,
+        beforePan: (newPos) => {
+          console.log(456, newPos.x, newPos.y)
+          setOffsetX(newPos.x);
+          setOffsetY(newPos.y);
+        },
+      })
+      panZoomInstance.current.pan({ x: 300, y: 100 })
+      panZoomInstance.current.zoom(2.85)
+      // setOffsetX(0)
+      // setOffsetY(-200)
+    }
+
+    return () => {
+      // 组件卸载时销毁实例
+      if (panZoomInstance.current) {
+        panZoomInstance.current.destroy()
+      }
+    }
+  }, [])
 
   return (
-    <div className={styles.graphSvg}>
-      {/* <GraphSvg className={styles.graphSvg} /> */}
-    </div>
+    <>
+      <div className={styles.SVGContainner}>
+        <GraphSvg ref={svgRef} className='graphSvg' />
+      </div>
+      <div className={styles.miniMap}>
+        <div
+          className={styles.viewport}
+          {...bind({ offsetX, offsetY })}
+          style={{
+            transform: `translate(${-offsetX * miniMapScale}px, ${-offsetY * miniMapScale}px)`,
+            width: `${MAIN_CONTENT_WIDTH * MINIMAP_SCALE}px`,
+            height: `${MAIN_CONTENT_HEIGHT * MINIMAP_SCALE}px`
+          }}
+        />
+        <div
+          className={styles.miniContent}
+          style={{
+            transform: `scale(${miniMapScale})`,
+          }}
+        >
+          <GraphSvg className='graphSvg' />
+        </div>
+      </div>
+    </>
   )
 }
 
-const MemoGraphSvg = React.memo(GraphSvg);
+const MemoSvgGraph = React.memo(SvgGraph)
 
-export default MemoGraphSvg;
+export default MemoSvgGraph

+ 3 - 2
src/pages/A6ybwx/Genealogy/index.tsx

@@ -2,7 +2,7 @@ import React, { useState } from 'react'
 import styles from './index.module.scss'
 import Graph from './components/Graph'
 import MemuSider from '@/components/MenuSider'
-
+import SvgGraph from './components/GraphSVG'
 function Genealogy({ setGotoTab }: { setGotoTab: (tab: number) => void }) {
   const [isShowIntro, setIsShowIntro] = useState(true)
   const [currentNodeIndex, setCurrentNodeIndex] = useState(-1)
@@ -17,7 +17,8 @@ function Genealogy({ setGotoTab }: { setGotoTab: (tab: number) => void }) {
       </div>
       <MemuSider activeTab={1} />
 
-      <Graph setCurrentNodeIndex={setCurrentNodeIndex} />
+      {/* <Graph setCurrentNodeIndex={setCurrentNodeIndex} /> */}
+      <SvgGraph />
 
       {isShowGesture && <div className={styles.gesture} onClick={() => setIsShowGesture(false)}>
         <img src={require('@/assets/img/A6_gen_gesture.png')} draggable='false' alt='' />