shaogen1995 1 year ago
parent
commit
ae9e8fcba3

BIN
pc/public/staticData/map/0.jpg


BIN
pc/public/staticData/map/1.jpg


BIN
pc/public/staticData/map/icon/3.jpg


BIN
pc/public/staticData/map/map1.png


BIN
pc/public/staticData/map/xianL.png


BIN
pc/public/staticData/map/xianR.png


BIN
pc/public/staticData/swData/2/1.png


BIN
pc/public/staticData/swData/2/2.png


BIN
pc/public/staticData/swData/2/3.png


BIN
pc/public/staticData/swData/3/4.png


+ 0 - 11
pc/src/assets/styles/base.css

@@ -113,14 +113,3 @@ textarea {
     bottom: 100px;
     bottom: 100px;
   }
   }
 }
 }
-.yunSon2 {
-  animation: moveyun 8s linear infinite alternate;
-}
-@keyframes moveyun {
-  0% {
-    transform: translate(0);
-  }
-  100% {
-    transform: translate(-1600px);
-  }
-}

+ 12 - 12
pc/src/assets/styles/base.less

@@ -146,18 +146,18 @@ textarea {
 
 
 
 
 
 
-.yunSon2 {
-  animation: moveyun 8s linear infinite alternate;
-}
+// .yunBox {
+//   animation: moveyun 1s linear infinite alternate;
+// }
 
 
-// 动画帧
-@keyframes moveyun {
-  0% {
-    transform: translate(0);
-  }
+// // 动画帧
+// @keyframes moveyun {
+//   0% {
+//     transform: translate(0);
+//   }
 
 
-  100% {
-    transform: translate(-1600px);
-  }
+//   100% {
+//     transform: translate(-1600px);
+//   }
 
 
-}
+// }

+ 69 - 0
pc/src/pages/A0Map/MapSon/index.module.scss

@@ -0,0 +1,69 @@
+.MapSon {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 2;
+  transform-style: preserve-3d;
+  perspective: 1000px;
+
+  :global {
+    .mapSonImg {
+      transition: all .3s linear;
+      position: absolute;
+      top: -3%;
+      left: -3%;
+      width: 106%;
+      height: 106%;
+      z-index: 1;
+
+      img {
+        width: 100%;
+        height: 100%;
+      }
+
+      .tagBox {
+        position: absolute;
+        z-index: 10;
+        cursor: pointer;
+        transition: all .2s;
+
+        &>img {
+          width: 20px;
+          height: 122px;
+          position: relative;
+          left: 50%;
+          transform: translateX(-50%);
+
+        }
+
+
+
+        .tagName {
+          min-width: 120px;
+          text-align: center;
+          padding: 0px 18px;
+          height: 40px;
+          line-height: 40px;
+          border-radius: 20px;
+          background-color: rgba(200, 185, 146, 0.3);
+          backdrop-filter: blur(4px);
+          color: var(--themeColor);
+          font-size: 18px;
+          transition: all .2s;
+
+        }
+
+        &:hover {
+          transform: scale(1.1);
+
+          .tagName {
+            color: #47392C;
+          }
+        }
+      }
+    }
+
+  }
+}

+ 86 - 0
pc/src/pages/A0Map/MapSon/index.tsx

@@ -0,0 +1,86 @@
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import styles from "./index.module.scss";
+import { envUrl } from "@/utils/env";
+import { TabType, imgLodingFu, mapData1 } from "../data";
+
+type Props = {
+  sId: number;
+};
+
+function MapSon({ sId }: Props) {
+  const [tag, setTag] = useState([] as TabType[]);
+
+  useEffect(() => {
+    setTag(mapData1.find((v) => v.id === sId)!.son);
+  }, [sId]);
+
+  const mapBac1 = useRef<HTMLDivElement>(null);
+
+  const mouseMoveFu = useCallback((e: MouseEvent) => {
+    let x = (e.clientX / window.innerWidth) * 2 - 1;
+    let y = -(e.clientY / window.innerHeight) * 2 + 1;
+
+    // x = x > 1 ? 1 : x < -1 ? -1 : x;
+    // y = y > 1 ? 1 : y < -1 ? -1 : y;
+
+    // const moveParam = `rotateX(${y * 2.5}deg) rotateY(${x}deg) translate3d(${
+    //   -x * 10
+    // }px,${y * 10}px,10px)`;
+
+    const moveParam = `translate(${-x * 10}px,${y * 10}px)`;
+
+    if (mapBac1.current) mapBac1.current.style.transform = moveParam;
+  }, []);
+
+  useEffect(() => {
+    if (mapBac1.current) {
+      const dom1 = mapBac1.current;
+      dom1.addEventListener("mousemove", mouseMoveFu);
+      return () => {
+        dom1.removeEventListener("mousemove", mouseMoveFu);
+      };
+    }
+  }, [mouseMoveFu]);
+
+  return (
+    <div className={styles.MapSon}>
+      {/* 大图片加载 */}
+      <div className="mapSonImg" ref={mapBac1}>
+        <img
+          src={`${envUrl}/map/${sId}.jpg`}
+          alt=""
+          onLoad={() => imgLodingFu(sId)}
+        />
+
+        {/* 标签 */}
+        {tag.map((v) => (
+          <div
+            onClick={() => window.open(v.link)}
+            className="tagBox"
+            key={v.id}
+            style={{ left: v.x, top: v.y, bottom: v.b, right: v.r }}
+          >
+            {v.type === "底部" ? (
+              <>
+                <img src={`${envUrl}/map/xianL.png`} alt="" />
+                <div className="tagName">{v.name}</div>
+              </>
+            ) : (
+              <>
+                <div className="tagName">{v.name}</div>
+                <img src={`${envUrl}/map/xianR.png`} alt="" />
+              </>
+            )}
+
+            {/* <img src="" alt="" /> */}
+            {/* {v.type==='b'?<img/>} */}
+          </div>
+        ))}
+      </div>
+    </div>
+  );
+}
+
+const MemoMapSon = React.memo(MapSon);
+
+export default MemoMapSon;

+ 94 - 5
pc/src/pages/A0Map/data.ts

@@ -1,19 +1,97 @@
-export const mapData1 = [
+import store from "@/store";
+
+export type TabType = {
+  id: number;
+  name: string;
+  x: string;
+  y: string;
+  b: string;
+  r: string;
+  type: "底部" | "顶部";
+  link: string;
+};
+
+type MapType = {
+  id: number;
+  name: string;
+  x: string;
+  y: string;
+  ind: number;
+  son: TabType[];
+};
+
+export const mapData1: MapType[] = [
   {
   {
     id: 1,
     id: 1,
     name: "虎门故事",
     name: "虎门故事",
-    x: "20%",
-    y: "20%",
+    x: "37%",
+    y: "6%",
     ind: 21,
     ind: 21,
+    son: [
+      {
+        id: 1.1,
+        name: "虎门故事",
+        x: "20%",
+        y: "10%",
+        b: "auto",
+        r: "auto",
+        type: "底部",
+        link: "https://www.baidu.com/",
+      },
+      {
+        id: 1.2,
+        name: "消烟池",
+        x: "auto",
+        y: "auto",
+        b: "40%",
+        r: "40%",
+        type: "顶部",
+        link: "https://www.baidu.com/",
+      },
+    ],
   },
   },
   {
   {
     id: 2,
     id: 2,
     name: "鸦片战争博物馆",
     name: "鸦片战争博物馆",
-    x: "30%",
-    y: "30%",
+    x: "35%",
+    y: "5.6%",
     ind: 20,
     ind: 20,
+    son: [
+      {
+        id: 2.1,
+        name: "22222-1111",
+        x: "20%",
+        y: "10%",
+        b: "auto",
+        r: "auto",
+        type: "顶部",
+        link: "https://www.baidu.com/",
+      },
+    ],
+  },
+  {
+    id: 3,
+    name: "海战馆",
+    x: "20.3%",
+    y: "44%",
+    ind: 20,
+    son: [
+      {
+        id: 2.1,
+        name: "22222-1111",
+        x: "20%",
+        y: "10%",
+        b: "auto",
+        r: "auto",
+        type: "顶部",
+        link: "https://www.baidu.com/",
+      },
+    ],
   },
   },
 ];
 ];
+// 沙角炮台
+// 林则徐纪念馆旧址
+// 捕鱼台
 
 
 export const maoData2 = [
 export const maoData2 = [
   {
   {
@@ -25,6 +103,7 @@ export const maoData2 = [
     r: "auto",
     r: "auto",
     ind: 21,
     ind: 21,
     type: "left",
     type: "left",
+    link: "https://www.baidu.com/",
   },
   },
   {
   {
     id: 5,
     id: 5,
@@ -35,5 +114,15 @@ export const maoData2 = [
     r: "10%",
     r: "10%",
     ind: 21,
     ind: 21,
     type: "right",
     type: "right",
+    link: "https://www.baidu.com/",
   },
   },
 ];
 ];
+
+// 设置图片加载完成的仓库数据
+export const imgLodingFu = (id: number) => {
+  const oldArr = store.getState().A0layout.imgLodingArr;
+  if (oldArr.includes(id)) {
+  } else {
+    store.dispatch({ type: "layout/imgLoding", payload: [...oldArr, id] });
+  }
+};

+ 75 - 49
pc/src/pages/A0Map/index.module.scss

@@ -2,6 +2,9 @@
   width: 100%;
   width: 100%;
   height: 100%;
   height: 100%;
   position: relative;
   position: relative;
+  transform-style: preserve-3d;
+  perspective: 1000px;
+
 
 
   :global {
   :global {
 
 
@@ -17,23 +20,9 @@
       height: 100%;
       height: 100%;
       display: flex;
       display: flex;
 
 
-      .videoRow {
-        position: absolute;
-        top: 0;
-        left: 0;
-        opacity: 0;
+      img {
         width: 100%;
         width: 100%;
         height: 100%;
         height: 100%;
-
-        &>img {
-          pointer-events: none;
-          width: 100%;
-          height: 100%;
-        }
-      }
-
-      .videoRowAc {
-        opacity: 1;
       }
       }
 
 
     }
     }
@@ -129,7 +118,7 @@
           transform: translateX(-50%);
           transform: translateX(-50%);
           z-index: 11;
           z-index: 11;
           width: 180px;
           width: 180px;
-          height: 120px;
+          height: 180px;
           display: none;
           display: none;
 
 
           .hoverShowBoxM {
           .hoverShowBoxM {
@@ -167,6 +156,7 @@
 
 
 
 
         &:hover {
         &:hover {
+
           .iconImg1 {
           .iconImg1 {
             display: none;
             display: none;
           }
           }
@@ -201,6 +191,7 @@
         width: 27px;
         width: 27px;
         height: 52px;
         height: 52px;
 
 
+
         .ic2Img2 {
         .ic2Img2 {
           display: none;
           display: none;
         }
         }
@@ -221,6 +212,7 @@
           font-size: 16px;
           font-size: 16px;
           text-align: center;
           text-align: center;
           border-radius: 0 6px 0 6px;
           border-radius: 0 6px 0 6px;
+          display: none;
         }
         }
 
 
         .ic2txtBox5 {
         .ic2txtBox5 {
@@ -317,49 +309,83 @@
       }
       }
     }
     }
 
 
-    .mapMain3{
+    .mapMain3 {
+
       // 小图标
       // 小图标
-      .A0iconSmBox{
-        .ic2Img1{
+      .A0iconSmBox {
+        .ic2Img1 {
           display: none;
           display: none;
         }
         }
+
+        .ic2Img2 {
+          display: block;
+        }
+
+        .ic2txtBox {
+          display: block;
+        }
       }
       }
     }
     }
 
 
 
 
     // 云层 动画帧
     // 云层 动画帧
-    .yunBox {
-      pointer-events: none;
+    // .yunBox {
+    //   pointer-events: none;
+    //   position: absolute;
+    //   z-index: 9;
+    //   top: 0;
+    //   left: 0;
+    //   width: 300%;
+    //   height: 100%;
+    //   display: flex;
+
+    //   .yunSon1 {
+    //     position: absolute;
+    //     top: 0;
+    //     left: 0;
+    //     width: 33.33%;
+    //     height: 100%;
+    //     background-image: url('../../assets/img/map/yun2.png');
+    //     background-size: 100% 100%;
+
+    //   }
+
+    //   .yunSon2 {
+    //     position: absolute;
+    //     top: 0;
+    //     left: 33.33%;
+    //     width: 33.33%;
+    //     height: 100%;
+    //     background-image: url('../../assets/img/map/yun1.png');
+    //     background-size: 100% 100%;
+
+    //   }
+
+    //   .yunSon3 {
+    //     position: absolute;
+    //     top: 0;
+    //     left: 66.66%;
+    //     width: 33.33%;
+    //     height: 100%;
+    //     background-image: url('../../assets/img/map/yun1.png');
+    //     background-size: 100% 100%;
+
+    //   }
+
+    // }
+
+    // 左下角的返回
+    .sonToBack {
       position: absolute;
       position: absolute;
-      z-index: 9;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      display: flex;
-
-      .yunSon1 {
-        position: absolute;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        background-image: url('../../assets/img/map/yun2.png');
-        background-size: 100% 100%;
-
+      z-index: 10;
+      bottom: 30px;
+      left: 30px;
+      cursor: pointer;
+      transition: all .3s;
+
+      &:hover {
+        transform: scale(1.1);
       }
       }
-
-      .yunSon2 {
-        position: absolute;
-        top: 0;
-        left: 0;
-        width: 200%;
-        height: 100%;
-        background-image: url('../../assets/img/map/yun1.png');
-        background-size: 100% 100%;
-
-      }
-
     }
     }
   }
   }
 }
 }

+ 83 - 32
pc/src/pages/A0Map/index.tsx

@@ -1,67 +1,86 @@
-import React, { useEffect, useMemo, useRef, useState } from "react";
+import React, { useCallback, useEffect, useRef, useState } from "react";
 import styles from "./index.module.scss";
 import styles from "./index.module.scss";
 import classNames from "classnames";
 import classNames from "classnames";
 import { envUrl } from "@/utils/env";
 import { envUrl } from "@/utils/env";
-import { maoData2, mapData1 } from "./data";
+import { imgLodingFu, maoData2, mapData1 } from "./data";
 import iconImg1 from "@/assets/img/map/icon1.png";
 import iconImg1 from "@/assets/img/map/icon1.png";
 import iconImg1Ac from "@/assets/img/map/icon1Ac.png";
 import iconImg1Ac from "@/assets/img/map/icon1Ac.png";
 import iconImg2 from "@/assets/img/map/icon2.png";
 import iconImg2 from "@/assets/img/map/icon2.png";
 import iconImg2Ac from "@/assets/img/map/icon2Ac.png";
 import iconImg2Ac from "@/assets/img/map/icon2Ac.png";
+import MapSon from "./MapSon";
+import { useSelector } from "react-redux";
+import { RootState } from "@/store";
+import { domShowFu } from "@/utils/domShow";
 
 
 type Props = {
 type Props = {
   type: number;
   type: number;
+  sonChaneType: (val: number) => void;
 };
 };
 
 
-function A0Map({ type }: Props) {
-  const [videoInd, setVidoeInd] = useState(true);
+function A0Map({ type, sonChaneType }: Props) {
+  // 进页面显示加载中
+  useEffect(() => {
+    domShowFu("#AsyncSpinLoding", true);
+  }, []);
 
 
-  const [moveInd, setMoveInd] = useState(0);
+  // 一级地图 图片的加载
+  const imgLodingArr = useSelector(
+    (state: RootState) => state.A0layout.imgLodingArr
+  );
 
 
-  // 30个动画帧div
-  const moveDiv = useMemo(() => {
-    const arr = [];
-
-    for (let i = 0; i <= 30; i++) {
-      arr.push(
-        <div
-          className={classNames("videoRow", moveInd === i ? "videoRowAc" : "")}
-          key={i}
-        >
-          <img src={`${envUrl}/yunMove/yan_${i}.png`} alt="" />
-        </div>
-      );
+  // 控制二级地图的显示
+  const [mapSon, setMapSon] = useState(0);
+
+  // 大图片是否已经加载完
+  const isImgLodingFu = useCallback(() => {
+    let flag = false;
+
+    if (imgLodingArr.includes(mapSon)) {
+      domShowFu("#AsyncSpinLoding", false);
+      flag = true;
     }
     }
-    return arr;
-  }, [moveInd]);
 
 
-  const moveTime = useRef(-1);
+    return flag;
+  }, [imgLodingArr, mapSon]);
 
 
-  useEffect(() => {
-    if (videoInd) {
+  // 开场动画帧的变化
+  const [moveInd, setMoveInd] = useState(0);
+  const moveTime = useRef(-1);
+  const moveYun = useCallback(() => {
+    if (!isImgLodingFu()) {
       clearInterval(moveTime.current);
       clearInterval(moveTime.current);
       let num = 0;
       let num = 0;
       moveTime.current = window.setInterval(() => {
       moveTime.current = window.setInterval(() => {
         setMoveInd(num);
         setMoveInd(num);
         num++;
         num++;
-        if (num > 30) {
+        if (num > 30 || isImgLodingFu()) {
           clearInterval(moveTime.current);
           clearInterval(moveTime.current);
-          setVidoeInd(false);
         }
         }
       }, 50);
       }, 50);
     }
     }
+  }, [isImgLodingFu]);
+
+  useEffect(() => {
+    moveYun();
 
 
     return () => {
     return () => {
       clearInterval(moveTime.current);
       clearInterval(moveTime.current);
     };
     };
-  }, [videoInd]);
+  }, [moveYun]);
+
+  // 鼠标hover
+  const [isHover, setIsHover] = useState(0);
 
 
   return (
   return (
     <div className={styles.A0Map}>
     <div className={styles.A0Map}>
       {/* 开场动画帧 */}
       {/* 开场动画帧 */}
       <div
       <div
-        className={classNames("videoBoxMove", !videoInd ? "videoBoxHide" : "")}
+        className={classNames(
+          "videoBoxMove",
+          isImgLodingFu() ? "videoBoxHide" : ""
+        )}
       >
       >
-        {moveDiv}
+        <img src={`${envUrl}/yunMove/yan_${moveInd}.png`} alt="" />
       </div>
       </div>
 
 
       {/* 一级地图 */}
       {/* 一级地图 */}
@@ -74,6 +93,12 @@ function A0Map({ type }: Props) {
         {/* 定位大图标 */}
         {/* 定位大图标 */}
         {mapData1.map((v) => (
         {mapData1.map((v) => (
           <div
           <div
+            onMouseEnter={() => setIsHover(v.id)}
+            onMouseLeave={() => setIsHover(0)}
+            onClick={() => {
+              setMapSon(v.id);
+              sonChaneType(2);
+            }}
             key={v.id}
             key={v.id}
             className="A0iconBox"
             className="A0iconBox"
             style={{ top: v.y, left: v.x, zIndex: v.ind }}
             style={{ top: v.y, left: v.x, zIndex: v.ind }}
@@ -84,7 +109,12 @@ function A0Map({ type }: Props) {
             <img className="iconImg2" src={iconImg1Ac} alt="" />
             <img className="iconImg2" src={iconImg1Ac} alt="" />
 
 
             {/* 文字标题 */}
             {/* 文字标题 */}
-            <div className="txtBox">
+            <div
+              className="txtBox"
+              hidden={
+                (isHover === 2 && v.id === 1) || (isHover === 1 && v.id === 2)
+              }
+            >
               <div>{v.name}</div>
               <div>{v.name}</div>
             </div>
             </div>
 
 
@@ -103,6 +133,11 @@ function A0Map({ type }: Props) {
         {/* 定位小图标 */}
         {/* 定位小图标 */}
         {maoData2.map((v) => (
         {maoData2.map((v) => (
           <div
           <div
+            onClick={() => {
+              window.open(v.link);
+              // setMapSon(v.id);
+              sonChaneType(3);
+            }}
             key={v.id}
             key={v.id}
             className={classNames(
             className={classNames(
               "A0iconSmBox",
               "A0iconSmBox",
@@ -140,13 +175,29 @@ function A0Map({ type }: Props) {
         ))}
         ))}
 
 
         <div className="mapBac">
         <div className="mapBac">
-          <img src={`${envUrl}/map/1.jpg`} alt="" />
+          <img
+            onLoad={() => imgLodingFu(0)}
+            src={`${envUrl}/map/0.jpg`}
+            alt=""
+          />
         </div>
         </div>
       </div>
       </div>
-      <div className="yunBox">
+
+      {/* 二级地图 */}
+      {mapSon ? <MapSon sId={mapSon} /> : null}
+
+      {/* <div className="yunBox">
         <div className="yunSon1"></div>
         <div className="yunSon1"></div>
         <div className="yunSon2"></div>
         <div className="yunSon2"></div>
-      </div>
+        <div className="yunSon3"></div>
+      </div> */}
+
+      {/* 左下角的返回 */}
+      {mapSon ? (
+        <div className="sonToBack" onClick={() => setMapSon(0)}>
+          <img src={`${envUrl}/map/map${mapSon}.png`} alt="" />
+        </div>
+      ) : null}
     </div>
     </div>
   );
   );
 }
 }

+ 4 - 6
pc/src/pages/A2Main/index.tsx

@@ -3,9 +3,7 @@ import React, { useCallback, useState } from "react";
 import styles from "./index.module.scss";
 import styles from "./index.module.scss";
 import LogoImg from "@/assets/img/logo.png";
 import LogoImg from "@/assets/img/logo.png";
 import classNames from "classnames";
 import classNames from "classnames";
-import GoodsSw from "./GoodsSw";
 import history from "@/utils/history";
 import history from "@/utils/history";
-import KnowLedge from "./KnowLedge";
 import A0Map from "../A0Map";
 import A0Map from "../A0Map";
 import { envData, envDataSonType, envDataType } from "@/utils/env";
 import { envData, envDataSonType, envDataType } from "@/utils/env";
 import Tab1 from "./Tab1";
 import Tab1 from "./Tab1";
@@ -25,7 +23,7 @@ function A2Main() {
     <div className={styles.A2Main}>
     <div className={styles.A2Main}>
       {/* 图片页面 */}
       {/* 图片页面 */}
       <div className="threeBox">
       <div className="threeBox">
-        <A0Map type={type} />
+        <A0Map type={type} sonChaneType={(val)=>setType(val)} />
       </div>
       </div>
 
 
       {/* 左上方logo */}
       {/* 左上方logo */}
@@ -65,9 +63,9 @@ function A2Main() {
           {/* 历史 */}
           {/* 历史 */}
           {type === 1 ? (
           {type === 1 ? (
             <Tab1 data={swData} />
             <Tab1 data={swData} />
-          ) : type === 4 ? // <GoodsSw />
-          null : type === 5 ? // <KnowLedge />
-          null : null}
+          ) : type === 4 ? null : type === // <GoodsSw />
+            5 ? null : null // <KnowLedge />
+          }
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>

+ 7 - 1
pc/src/store/reducer/layout.ts

@@ -13,12 +13,15 @@ const initState = {
     url: "",
     url: "",
     show: false,
     show: false,
   },
   },
+  // 地图大图片加载是否完成
+  imgLodingArr: [] as number[],
 };
 };
 
 
 // 定义 action 类型
 // 定义 action 类型
 type Props =
 type Props =
   | { type: "layout/message"; payload: MessageType }
   | { type: "layout/message"; payload: MessageType }
-  | { type: "layout/lookBigImg"; payload: { url: string; show: boolean } };
+  | { type: "layout/lookBigImg"; payload: { url: string; show: boolean } }
+  | { type: "layout/imgLoding"; payload: number[] };
 // 频道 reducer
 // 频道 reducer
 export default function loginReducer(state = initState, action: Props) {
 export default function loginReducer(state = initState, action: Props) {
   switch (action.type) {
   switch (action.type) {
@@ -28,6 +31,9 @@ export default function loginReducer(state = initState, action: Props) {
     // 所有图片点击预览查看大图
     // 所有图片点击预览查看大图
     case "layout/lookBigImg":
     case "layout/lookBigImg":
       return { ...state, lookBigImg: action.payload };
       return { ...state, lookBigImg: action.payload };
+    // 大图片是否加载完成
+    case "layout/imgLoding":
+      return { ...state, imgLodingArr: action.payload };
     default:
     default:
       return state;
       return state;
   }
   }