Przeglądaj źródła

图片可放大与拖拽

lanxin 2 tygodni temu
rodzic
commit
dffbad0420

Plik diff jest za duży
+ 1 - 1
public/myData/myData.js


+ 2 - 1
src/App.tsx

@@ -7,6 +7,7 @@ import SpinLoding from './components/SpinLoding'
 import store, { RootState } from './store'
 import { useDispatch, useSelector } from 'react-redux'
 import NotFound from '@/components/NotFound'
+import TouchContainer from './components/TouchContainer'
 import { envFlag } from './utils/http'
 import AsyncSpinLoding from './components/AsyncSpinLoding'
 import { Image } from 'antd'
@@ -1039,7 +1040,7 @@ export default function App() {
             closeIcon: <img src={require('@/assets/img/closeWithTxt.png')} draggable='false' alt='' />,
             imageRender: (originalNode) => (
               <div className='previewImage'>
-                <div className='Ori'>{originalNode}</div>
+                <TouchContainer className='Ori'>{originalNode}</TouchContainer>
                 <div className="ImgFromTxt">{lookBigImg.fromTxt}</div>
               </div>
             ),

BIN
src/assets/img/A7_diwen0.png


BIN
src/assets/img/A7_diwen1.png


BIN
src/assets/img/A7_diwen2.png


BIN
src/assets/img/A7_diwen3.png


+ 6 - 3
src/assets/styles/base.css

@@ -217,9 +217,6 @@ textarea {
   .ant-image-mask {
     background: rgba(0, 0, 0, 0.8) !important;
   }
-  .ant-image-preview-wrap {
-    transform: rotate(90deg) !important;
-  }
   .ant-image-preview-footer {
     display: none !important;
     transform: scale(0.7) rotate(90deg) translate(-178%, -50%);
@@ -229,6 +226,9 @@ textarea {
     transform: scale(0.7) rotate(90deg) translate(755px, -203%);
     transform-origin: left bottom;
   }
+  .previewImage {
+    transform: rotate(90deg);
+  }
   .previewImage .Ori {
     height: 40%;
   }
@@ -355,6 +355,9 @@ textarea {
   width: 100% !important;
   height: 100% !important;
 }
+.ant-image-preview-footer {
+  display: none !important;
+}
 #root .ant-tooltip .tooltip_MT {
   height: 100%;
   font-size: 16px;

+ 7 - 4
src/assets/styles/base.less

@@ -281,10 +281,6 @@ textarea {
     background: rgba(0, 0, 0, 0.8) !important;
   }
 
-  .ant-image-preview-wrap {
-    transform: rotate(90deg) !important;
-  }
-
   .ant-image-preview-footer {
     display: none !important;
     transform: scale(0.7) rotate(90deg) translate(-178%, -50%);
@@ -297,6 +293,7 @@ textarea {
   }
 
   .previewImage {
+    transform: rotate(90deg);
     .Ori {
       height: 40%;
     }
@@ -316,6 +313,8 @@ textarea {
 
   }
 
+
+
   #root .ant-tooltip .tooltip_MT {
 
     .top {
@@ -471,6 +470,10 @@ textarea {
   }
 }
 
+.ant-image-preview-footer {
+  display: none !important;
+}
+
 #root .ant-tooltip .tooltip_MT {
   height: 100%;
   font-size: 16px;

+ 8 - 0
src/components/TouchContainer/index.module.scss

@@ -0,0 +1,8 @@
+.TouchContainer {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  overflow: hidden;
+  touch-action: none;
+  user-select: none;
+}

+ 107 - 0
src/components/TouchContainer/index.tsx

@@ -0,0 +1,107 @@
+import React, { useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+
+type TCProps = { className?: string; children?: React.ReactNode }
+function TouchContainer(props: TCProps) {
+  // 缩放比例 和 偏移量
+  const [zoom, setZoom] = useState(1)
+  const [offsetX, setOffsetX] = useState(0)
+  const [offsetY, setOffsetY] = useState(0)
+  const touchDataRef = useRef({
+    startX: 0, // 触摸起始点 X 坐标
+    startY: 0, // 触摸起始点 Y 坐标
+    startOffsetX: 0, // 元素起始偏移 X
+    startOffsetY: 0, // 元素起始偏移 Y
+    initialDistance: 0, // 两指缩放的初始距离
+    initialZoom: 1, // 初始缩放比例
+    midX: 0, // 两指缩放的中点 X 坐标
+    midY: 0 // 两指缩放的中点 Y 坐标
+  })
+
+  // useEffect(() => {
+  //   const touchContainer = document.getElementById('touch-container')
+  //   if (!touchContainer) return
+
+  //   touchContainer.addEventListener('touchmove', handleTouchMove)
+  //   touchContainer.addEventListener('touchstart', handleTouchStart)
+  //   return () => {
+  //     touchContainer.removeEventListener('touchmove', handleTouchMove)
+  //     touchContainer.removeEventListener('touchstart', handleTouchStart)
+  //   }
+  // }, [offsetX, offsetY])
+
+  const handleTouchStart = (e: TouchEvent | React.TouchEvent) => {
+    const touch = e.touches[0]
+    console.log('touch start', touch.clientX, touch.clientY)
+    touchDataRef.current.startX = touch.clientX
+    touchDataRef.current.startY = touch.clientY
+    touchDataRef.current.startOffsetX = offsetX
+    touchDataRef.current.startOffsetY = 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)
+      touchDataRef.current.initialDistance = distance
+      touchDataRef.current.initialZoom = zoom
+      // 计算中点坐标
+      const midX = (t1.clientX + t2.clientX) / 2
+      const midY = (t1.clientY + t2.clientY) / 2
+      touchDataRef.current.midX = midX
+      touchDataRef.current.midY = midY
+    }
+  }
+
+  const handleTouchMove = (e: TouchEvent | React.TouchEvent) => {
+    console.log('touch move')
+    const touch = e.touches[0]
+    const dx = touch.clientY - touchDataRef.current.startY
+    const dy = -touch.clientX + touchDataRef.current.startX
+    if (e.touches.length === 1) {
+      setOffsetX(prev => {
+        const newX = touchDataRef.current.startOffsetX - dx * 0.5
+        return newX
+      })
+      setOffsetY(prev => {
+        const newY = touchDataRef.current.startOffsetY - dy * 0.5
+        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(3, distance / touchDataRef.current.initialDistance * touchDataRef.current.initialZoom))
+      setZoom(newZoom)
+      setOffsetX(prev => {
+        const deltaMidX = (touch2.clientX + touch.clientX) / 2 - touchDataRef.current.midX
+        const newX = touchDataRef.current.startOffsetX + deltaMidX - dx * 0.5
+        return newX
+      })
+      setOffsetY(prev => {
+        const deltaMidY = (touch2.clientY + touch.clientY) / 2 - touchDataRef.current.midY
+        const newY = touchDataRef.current.startOffsetY + deltaMidY - dy * 0.5
+        return newY
+      })
+    }
+  }
+
+  const contRef = useRef<HTMLDivElement>(null)
+  return (
+    <div
+      id='touch-container'
+      ref={contRef}
+      onTouchMove={handleTouchMove}
+      onTouchStart={handleTouchStart}
+      className={`${styles.TouchContainer} ${props.className}`}
+      style={{ transform: `translate(${-offsetX}px, ${-offsetY}px) scale(${zoom})` }}
+    >
+      {props.children}
+    </div>
+  )
+}
+
+const MemoTouchContainer = React.memo(TouchContainer)
+
+export default MemoTouchContainer

+ 14 - 4
src/pages/A5wenwu/index.tsx

@@ -3,7 +3,7 @@ import styles from './index.module.scss'
 import { callIframeFu } from '@/utils/history'
 import classNames from 'classnames'
 import { useSelector } from 'react-redux'
-import { RootState } from '@/store'
+import store, { RootState } from '@/store'
 import Zback from '@/components/Zback'
 import Zclose from '@/components/Zclose'
 
@@ -143,7 +143,12 @@ function A5wenwu() {
           }}
         />
 
-        <div className='TContainner'>
+        <div className='TContainner' onClick={() => {
+          store.dispatch({
+            type: 'layout/lookBigImg',
+            payload: { url: require('@/assets/sgImg/img_tapian.png'), show: true, fromTxt: '' }
+          })
+        }}>
           <img src={require('@/assets/sgImg/img_tapian.png')} alt='' />
         </div>
       </div>
@@ -160,11 +165,16 @@ function A5wenwu() {
           }}
         />
 
-        <div className='TContainner'>
+        <div className='TContainner' onClick={() => {
+          store.dispatch({
+            type: 'layout/lookBigImg',
+            payload: { url: require('@/assets/sgImg/img_xiantu.png'), show: true, fromTxt: '' }
+          })
+        }}>
           <img src={require('@/assets/sgImg/img_xiantu.png')} alt='' />
         </div>
       </div>
-    </div>
+    </div >
   )
 }
 

+ 1 - 0
src/pages/A6ybwx/A6_1_zxys/index.module.scss

@@ -11,6 +11,7 @@
   background-position: center center;
   background-size: 100% 100%;
   background-color: rgba(255, 233, 182, 1);
+  overflow: hidden;
 
   :global {
     .back {

+ 53 - 17
src/pages/A6ybwx/Genealogy/components/Graph/index.tsx

@@ -34,7 +34,11 @@ function Graph({ setCurrentNodeIndex }: { setCurrentNodeIndex: (index: number) =
     startX: 0,    // 触摸起始点 X 坐标
     startY: 0,    // 触摸起始点 Y 坐标
     startOffsetX: 0, // 元素起始偏移 X
-    startOffsetY: 0  // 元素起始偏移 Y
+    startOffsetY: 0,  // 元素起始偏移 Y
+    initialDistance: 0, // 两指缩放的初始距离
+    initialZoom: 1, // 初始缩放比例
+    midX: 0, // 两指缩放的中点 X 坐标
+    midY: 0 // 两指缩放的中点 Y 坐标
   });
 
   const graphRef = useRef<HTMLDivElement>(null);
@@ -196,22 +200,54 @@ function Graph({ setCurrentNodeIndex }: { setCurrentNodeIndex: (index: number) =
     startRef.current.startY = touch.clientY;
     startRef.current.startOffsetX = offsetX;
     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 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'
         }}
       >
-        {/* <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 />
       </div>
       <div className={styles.tip}>

+ 1 - 0
src/pages/A6ybwx/StatueArt/index.module.scss

@@ -11,6 +11,7 @@
   background-image: url('../../../assets/img/A6_ffhy_bg.jpg');
   background-color: rgba(255, 233, 182, 1);
   background-size: 100% 100%;
+  overflow: hidden;
 
   :global {
     .back {

+ 4 - 0
src/pages/A7wjwj/conponents/Discover/index.module.scss

@@ -34,6 +34,10 @@
           font-size: 9px;
           max-height: 71px;
           overflow: auto;
+          &::-webkit-scrollbar {
+            width: 0;
+            height: 0;
+          }
         }
 
         .btn {

+ 1 - 1
src/pages/A7wjwj/conponents/Shuxing/index.tsx

@@ -79,7 +79,7 @@ function Shuxing({ style }: Props, ref: any) {
               <img
                 className='diwen'
                 draggable={false}
-                src={require(`@/assets/img/A7_diwen${currentIndex % 2 === 0 ? '1' : '2'}.png`)}
+                src={require(`@/assets/img/A7_diwen${currentIndex}.png`)}
                 alt=''
               />
               <img src={myData.shuxing[currentIndex].img} alt='' />

+ 5 - 0
src/pages/A7wjwj/conponents/Weijie/index.module.scss

@@ -5,6 +5,11 @@
   overflow: auto;
   top: 20%;
 
+  &::-webkit-scrollbar {
+    width: 0;
+    height: 0;
+  }
+
   :global {
     p {
       font-size: 16px;