chenlei пре 1 недеља
родитељ
комит
f65454fbe5
32 измењених фајлова са 506 додато и 70 уклоњено
  1. 35 0
      code/public/myData/data.js
  2. 5 0
      code/src/App.tsx
  3. BIN
      code/src/assets/img/bd.png
  4. BIN
      code/src/assets/img/group1-1.png
  5. BIN
      code/src/assets/img/group1.png
  6. BIN
      code/src/assets/img/icon-caidan1-min.png
  7. 52 0
      code/src/components/Z1titie/index.module.scss
  8. 30 1
      code/src/components/Z1titie/index.tsx
  9. BIN
      code/src/pages/A1home/images/diamond-min.png
  10. BIN
      code/src/pages/A1home/images/icon-sy-min.png
  11. BIN
      code/src/pages/A1home/images/zs1-min.png
  12. 58 1
      code/src/pages/A1home/index.module.scss
  13. 25 2
      code/src/pages/A1home/index.tsx
  14. BIN
      code/src/pages/A2show/images/ft-bg-min.png
  15. 155 40
      code/src/pages/A2show/index.module.scss
  16. 27 26
      code/src/pages/A2show/index.tsx
  17. BIN
      code/src/pages/A4scene/images/card-ft-bg-min.png
  18. BIN
      code/src/pages/A4scene/images/play.png
  19. 64 0
      code/src/pages/A4scene/index.module.scss
  20. 53 0
      code/src/pages/A4scene/index.tsx
  21. 2 0
      code/src/types/declaration.d.ts
  22. BIN
      静态资源/staticData/scene/1.jpg
  23. BIN
      静态资源/staticData/scene/1.mp4
  24. BIN
      静态资源/staticData/scene/2.jpg
  25. BIN
      静态资源/staticData/scene/2.mp4
  26. BIN
      静态资源/staticData/scene/3.jpg
  27. BIN
      静态资源/staticData/scene/3.mp4
  28. BIN
      静态资源/staticData/scene/4.jpg
  29. BIN
      静态资源/staticData/scene/4.mp4
  30. BIN
      静态资源/staticData/scene/5.jpg
  31. BIN
      静态资源/staticData/scene/5.mp4
  32. BIN
      静态资源/staticData/show/fan2-min.png

+ 35 - 0
code/public/myData/data.js

@@ -1,6 +1,41 @@
 const serverUrl = 'https://houseoss.4dkankan.com/project/chuGuoYuJian/staticData/'
 // const serverUrl = 'http://192.168.20.55:8080/staticData/'
 
+const MODEL_LIST = [
+  { name: '玉剑简介', page: 'show' },
+  { name: '佩戴方式', page: 'wear' },
+  { name: '使用场景', page: 'scene' },
+  { name: '三维模型', page: 'model' }
+]
+
+const VIDEO_LIST = [
+  {
+    name: '祭祀场景',
+    videoPath: 'scene/1.mp4',
+    coverPath: 'scene/1.jpg'
+  },
+  {
+    name: '早朝场景',
+    videoPath: 'scene/2.mp4',
+    coverPath: 'scene/2.jpg'
+  },
+  {
+    name: '文人雅集',
+    videoPath: 'scene/3.mp4',
+    coverPath: 'scene/3.jpg'
+  },
+  {
+    name: '外交场景',
+    videoPath: 'scene/4.mp4',
+    coverPath: 'scene/4.jpg'
+  },
+  {
+    name: '军事演练',
+    videoPath: 'scene/5.mp4',
+    coverPath: 'scene/5.jpg'
+  },
+]
+
 // 剑本身
 const myInfoTemp1 = [
   {

+ 5 - 0
code/src/App.tsx

@@ -15,6 +15,7 @@ const A1home = React.lazy(() => import('./pages/A1home'))
 const A2show = React.lazy(() => import('./pages/A2show'))
 const A3wear = React.lazy(() => import('./pages/A3wear'))
 const A0model = React.lazy(() => import('./pages/A0model'))
+const A4scene = React.lazy(() => import('./pages/A4scene'))
 
 export default function App() {
   // 从仓库中获取查看图片的信息
@@ -46,6 +47,10 @@ export default function App() {
       element: <A0model />
     },
     {
+      path: '/scene',
+      element: <A4scene />
+    },
+    {
       index: true,
       element: <A1home />
     },

BIN
code/src/assets/img/bd.png


BIN
code/src/assets/img/group1-1.png


BIN
code/src/assets/img/group1.png


BIN
code/src/assets/img/icon-caidan1-min.png


+ 52 - 0
code/src/components/Z1titie/index.module.scss

@@ -27,5 +27,57 @@
       height: 34px;
       width: auto;
     }
+
+    .Z1menu {
+      position: absolute;
+      top: 30px;
+      right: 15px;
+      z-index: 10;
+
+      img {
+        width: 30px;
+        height: auto;
+      }
+    }
+    .Z1menuList {
+      position: absolute;
+      top: 36px;
+      right: 0;
+      padding: 0 5px;
+      border-radius: 3px;
+      background: rgba(182,139,60,0.8);
+      border: 1px solid #FFFDDC;
+      opacity: 0;
+      visibility: hidden;
+      transform: translateY(-10px);
+      transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
+
+      &.Z1menuListShow {
+        opacity: 1;
+        visibility: visible;
+        transform: translateY(0);
+      }
+
+      li {
+        position: relative;
+        height: 41px;
+        color: #FFFDDC;
+        line-height: 12px;
+        text-align: center;
+        white-space: nowrap;
+        line-height: 40px;
+
+        &:not(:last-child)::after {
+          content: '';
+          position: absolute;
+          left: 50%;
+          transform: translateX(-50%);
+          bottom: 0;
+          width: 49px;
+          height: 1px;
+          background: url('../../assets/img/bd.png') no-repeat center / contain;
+        }
+      }
+    }
   }
 }

+ 30 - 1
code/src/components/Z1titie/index.tsx

@@ -1,5 +1,6 @@
-import React from 'react'
+import React, { useState } from 'react'
 import styles from './index.module.scss'
+import history from '@/utils/history'
 
 type Props = {
   title: string
@@ -8,6 +9,17 @@ type Props = {
 }
 
 function Z1titie({ title, toHome, backFu }: Props) {
+  const [showMenu, setShowMenu] = useState(false)
+
+  const toggleMenu = () => {
+    setShowMenu(!showMenu)
+  }
+
+  const handleMenuClick = (page: string) => {
+    setShowMenu(false)
+    history.push(page)
+  }
+
   return (
     <div className={styles.Z1titie} id='Z1titie'>
       <img className='Z1_1' src={`${serverUrl}home/titlel.png`} alt='' />
@@ -36,6 +48,23 @@ function Z1titie({ title, toHome, backFu }: Props) {
           onClick={() => backFu()}
         />
       ) : null}
+
+      {backFu || toHome ? (
+        <div className='Z1menu'>
+          <img 
+            src={require('@/assets/img/icon-caidan1-min.png')} 
+            alt='' 
+            onClick={toggleMenu}
+            style={{ cursor: 'pointer' }}
+          />
+
+          <ul className={`Z1menuList ${showMenu ? 'Z1menuListShow' : ''}`}>
+            {MODEL_LIST.map(item => (
+              <li key={item.name} onClick={() => handleMenuClick(item.page)}>{item.name}</li>
+            ))}
+          </ul>
+        </div>
+      ) : null}
     </div>
   )
 }

BIN
code/src/pages/A1home/images/diamond-min.png


BIN
code/src/pages/A1home/images/icon-sy-min.png


BIN
code/src/pages/A1home/images/zs1-min.png


+ 58 - 1
code/src/pages/A1home/index.module.scss

@@ -32,5 +32,62 @@
       letter-spacing: 6px;
       color: #faf6d3;
     }
+
+    .A1mask {
+      position: absolute;
+      inset: 0;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      gap: 34px;
+      background-size: 100% 100%;
+      opacity: 0;
+      visibility: hidden;
+      transition: opacity 0.5s ease-in-out, visibility 0.5s ease-in-out;
+
+      &.A1maskShow {
+        opacity: 1;
+        visibility: visible;
+      }
+
+      &::after,
+      &::before {
+        content: '';
+        width: 40px;
+        height: 23px;
+        background: url('./images/zs1-min.png') no-repeat center / contain;
+      }
+      &::after {
+        transform: rotate(180deg);
+      }
+      ul {
+        display: flex;
+        flex-direction: column;
+        gap: 80px;
+
+        li {
+          position: relative;
+          width: 217px;
+          height: 40px;
+          text-align: center;
+          line-height: 40px;
+          font-size: 19px;
+          color: #2D0C05;
+          background: url('./images/icon-sy-min.png') no-repeat center / contain;
+        
+          &:not(:last-child)::after {
+            content: '';
+            position: absolute;
+            bottom: -43px;
+            left: 50%;
+            transform: translateX(-50%);
+            width: 9px;
+            height: 9px;
+            background: url('./images/diamond-min.png') no-repeat center / contain;
+          }
+        }
+      }
+    }
   }
-}
+}

+ 25 - 2
code/src/pages/A1home/index.tsx

@@ -1,9 +1,19 @@
-import React from 'react'
+import React, { useState } from 'react'
 import styles from './index.module.scss'
 import Z1titie from '@/components/Z1titie'
 import history from '@/utils/history'
 
 function A1home() {
+  const [showMask, setShowMask] = useState(false)
+
+  const handleStartClick = () => {
+    setShowMask(true)
+  }
+
+  const handleMaskClick = (index: number) => {
+    history.push(MODEL_LIST[index].page)
+  }
+
   return (
     <div className={styles.A1home}>
       {/* 点击开始 */}
@@ -18,13 +28,26 @@ function A1home() {
         <img className='A1jian' src={`${serverUrl}home/jian.png`} alt='' />
 
         <div
-          onClick={() => history.push('/show')}
           style={{ backgroundImage: `url(${serverUrl}home/btnBac.png)` }}
           className='A1btn'
+          onClick={handleStartClick}
         >
           点击开始
         </div>
       </div>
+
+      <div 
+        className={`A1mask ${showMask ? 'A1maskShow' : ''}`}
+        style={{ backgroundImage: `url(${serverUrl}home/start.jpg)` }}
+      >
+        <ul>
+          {MODEL_LIST.map((item, index) => (
+            <li key={index} onClick={() => handleMaskClick(index)}>
+              {item.name}
+            </li>
+          ))}
+        </ul>
+      </div>
     </div>
   )
 }

BIN
code/src/pages/A2show/images/ft-bg-min.png


+ 155 - 40
code/src/pages/A2show/index.module.scss

@@ -7,32 +7,78 @@
     .A2txt {
       margin-top: 8px;
       text-align: center;
-      letter-spacing: 2px;
-      font-size: 14px;
-      color: #e7e3c5;
+      letter-spacing: 3px;
+      font-size: 12px;
+      color: #FFFDDC;
       & > p {
         margin-bottom: 5px;
       }
     }
 
-    .A2rBtn {
+    .A2labelLeft,
+    .A2labelRight {
       position: absolute;
-      right: 15px;
-      top: 50%;
-      transform: translateY(-50%);
-      z-index: 10;
-      .A2rBtnRow {
-        margin-bottom: 15px;
-        color: var(--themeColor2);
-        & > img {
-          width: 50px;
-          height: auto;
-        }
-        & > p {
-          margin-top: 3px;
-          text-align: center;
-          font-size: 12px;
-        }
+      left: 50%;
+      transform: translateX(-50%);
+      font-size: 12px;
+      font-weight: bold;
+      color: #FFFDDC;
+      text-shadow: 0px 0px 3px #FCE9AC;
+
+      &::before {
+        content: '';
+        position: absolute;
+        top: 50%;
+        left: -14px;
+        transform: translateY(-50%);
+        width: 12px;
+        height: 12px;
+        background: url('../../assets/img/group1.png') no-repeat center / contain;
+      }
+      &::after {
+        content: '';
+        position: absolute;
+        left: -21px;
+        bottom: -20px;
+        width: 91px;
+        height: 20px;
+        background: url('../../assets/img/group1-1.png') no-repeat center / contain;
+      }
+    }
+    .A2labelLeft {
+      &.js {
+        top: -20px;
+        left: calc(50% - 75px);
+      }
+      &.jg {
+        top: 50px;
+        left: calc(50% - 80px);
+      }
+      &.yz {
+        top: -20px;
+        left: calc(50% - 80px);
+      }
+      &.yb {
+        bottom: 60px;
+        left: calc(50% - 80px);
+      }
+    }
+    .A2labelRight {
+      &::after {
+        left: -50px;
+        transform: rotateY(180deg);
+      }
+      &.jj {
+        top: 0;
+        left: calc(50% + 75px);
+      }
+      &.js {
+        top: 100px;
+        left: calc(50% + 80px);
+      }
+      &.jq {
+        top: 80px;
+        left: calc(50% + 80px);
       }
     }
     .A2rotate {
@@ -51,9 +97,10 @@
       backface-visibility: hidden;
       -webkit-transform: translateZ(0);
       transform: translateZ(0);
+      z-index: 9;
       .A2rotate1 {
         position: absolute;
-        top: 42%;
+        top: 50%;
         left: 50%;
         width: 100%;
         height: 60%;
@@ -64,11 +111,19 @@
       .A2rotate2 {
         opacity: 0.3;
         transform: translate(-50%, -50%) rotateY(195deg) translateZ(300px);
+      
+        img:last-child {
+          position: absolute;
+          top: -35px;
+          left: 50%;
+          transform: translateX(-50%);
+          z-index: -1;
+        }
       }
     }
     .A2rotateShow {
-      transform: translate3d(0, 0, 0) rotateY(-196deg);
-      -webkit-transform: translate3d(0, 0, 0) rotateY(-196deg); /* 增加Webkit前缀 */
+      transform: translate3d(0, 0, 0) rotateY(-195deg);
+      -webkit-transform: translate3d(0, 0, 0) rotateY(-195deg); /* 增加Webkit前缀 */
       .A2rotate1 {
         opacity: 0.3;
       }
@@ -77,6 +132,12 @@
       }
     }
 
+    .A2cut1 {
+      position: absolute;
+      left: 20%;
+      bottom: 25%;
+      width: 60%;
+    }
     .A2cut {
       width: 60%;
       left: 20%;
@@ -119,25 +180,79 @@
         color: var(--themeColor);
       }
     }
-    .A2btn {
+
+    .A2bottom {
       position: absolute;
-      z-index: 20;
-      bottom: 3%;
-      left: 10%;
-      width: 80%;
-      height: 5%;
+      bottom: 50px;
+      left: 0;
+      right: 0;
       display: flex;
-      justify-content: space-between;
-      & > div {
-        width: 48%;
-        height: 100%;
-        background-size: 100% 100%;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        color: #2d0c05;
-        font-size: 18px;
-        letter-spacing: 2px;
+      justify-content: center;
+      gap: 40px;
+      height: 69px;
+      background: url('./images/ft-bg-min.png') no-repeat center / contain;
+    }
+    // 下面按钮
+    .A2btm {
+      position: absolute;
+      bottom: 93px;
+      left: 0;
+      right: 0;
+      height: 120px;
+      padding-top: 0px;
+      position: relative;
+      .A2btmRow {
+        position: absolute;
+        top: 12%;
+        left: 9%;
+        text-align: center;
+        & > div {
+          width: 50px;
+          height: 50px;
+          position: relative;
+          & > img {
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            transition: opacity 0.3s;
+            opacity: 1;
+            position: absolute;
+            width: 46px;
+            height: 46px;
+            &:nth-of-type(2) {
+              width: 100%;
+              height: 100%;
+              opacity: 0;
+            }
+          }
+        }
+        .A2btmAc {
+          & > img {
+            opacity: 0;
+            &:nth-of-type(2) {
+              opacity: 1;
+            }
+          }
+        }
+        & > p {
+          margin-top: 3px;
+          text-align: center;
+          font-size: 12px;
+          transition: all 0.3s;
+          color: #FFFDDC;
+        }
+        &:nth-of-type(2) {
+          top: 26%;
+          left: 32%;
+        }
+        &:nth-of-type(3) {
+          top: 26%;
+          left: 55%;
+        }
+        &:nth-of-type(4) {
+          top: 12%;
+          left: 78%;
+        }
       }
     }
   }

+ 27 - 26
code/src/pages/A2show/index.tsx

@@ -6,11 +6,6 @@ import classNames from 'classnames'
 import history from '@/utils/history'
 import A2info from './A2info'
 
-const btnArr = [
-  { name: '三维模型', page: 'model' },
-  { name: '佩戴方式', page: 'wear' }
-]
-
 function A2show() {
   const [rotate, setRotate] = useState(false)
 
@@ -26,32 +21,34 @@ function A2show() {
 
       <div className='A2txt'>
         <p>春秋中晚期 | 藏于十堰市博物馆</p>
-        <p>湖北省郧县五峰乡肖家河村乔家院墓地出土</p>
-      </div>
-
-      {/* 右侧图标 */}
-      <div className='A2rBtn'>
-        {myInfo1.map(item => (
-          <div className='A2rBtnRow' key={item.id} onClick={() => setOpen(item.title)}>
-            <img src={`${serverUrl}show/${item.id}.png`} alt='' />
-            <p>{item.title}</p>
-          </div>
-        ))}
+        {/* <p>湖北省郧县五峰乡肖家河村乔家院墓地出土</p> */}
       </div>
 
       {/* 2张图片伪3D效果 */}
       <div className={classNames('A2rotate', rotate ? 'A2rotateShow' : '')}>
         <div className='A2rotate1'>
+          {!rotate && <>
+            <div className='A2labelLeft js'>剑首</div>
+            <div className='A2labelLeft jg'>剑格</div>
+            <div className='A2labelRight jj'>剑茎</div>
+            <div className='A2labelRight js'>剑身</div>
+          </>}
           <img src={`${serverUrl}show/zheng.png`} alt='' />
         </div>
         <div className='A2rotate1 A2rotate2'>
+          {rotate && <>
+            <div className='A2labelLeft yz'>玉璏</div>
+            <div className='A2labelLeft yb'>玉镖</div>
+            <div className='A2labelRight jq'>剑鞘</div>
+          </>}
           <img src={`${serverUrl}show/fan.png`} alt='' />
+          <img src={`${serverUrl}show/fan2-min.png`} alt='' />
         </div>
       </div>
 
       {/* 切换 */}
+      <img className='A2cut1' src={`${serverUrl}show/xian2.png`} alt='' />
       <div className='A2cut' onClick={() => setRotate(!rotate)}>
-        <img className='A2cut1' src={`${serverUrl}show/xian2.png`} alt='' />
         <img className='A2cut2' src={`${serverUrl}show/xian.png`} alt='' />
         <div className={classNames('A2cut3', rotate ? 'A2cut3Ac' : '')}>
@@ -63,15 +60,19 @@ function A2show() {
         </div>
       </div>
 
-      {/* 底部按钮 */}
-      <div className='A2btn'>
-        {btnArr.map(item => (
-          <div
-            onClick={() => history.push(item.page)}
-            style={{ backgroundImage: `url(${serverUrl}show/btn.png)` }}
-            key={item.name}
-          >
-            {item.name}
+      <div className='A2btm'>
+        <img src={`${serverUrl}show/info/xian.png`} alt='' />
+
+        {myInfo1.map(item => (
+          <div key={item.id} className='A2btmRow' onClick={() => setOpen(item.title)}>
+            <div>
+              <img src={`${serverUrl}show/${item.id}.png`} alt='' />
+              <img src={`${serverUrl}show/${item.id}ac.png`} alt='' />
+            </div>
+
+            <p>
+              {item.title}
+            </p>
           </div>
         ))}
       </div>

BIN
code/src/pages/A4scene/images/card-ft-bg-min.png


BIN
code/src/pages/A4scene/images/play.png


+ 64 - 0
code/src/pages/A4scene/index.module.scss

@@ -0,0 +1,64 @@
+.A4scene {
+  display: flex;
+  flex-direction: column;
+
+  :global {
+    .A4sceneList {
+      flex: 1;
+      display: flex;
+      flex-direction: column;
+      margin-top: 25px;
+      padding: 0 20px 25px;
+      overflow-y: auto;
+      gap: 20px;
+
+      .A4sceneCard {
+        flex-shrink: 0;
+        position: relative;
+        height: 188px;
+        overflow: hidden;
+        border-radius: 7px;
+        background-size: cover;
+        background-position: center;
+        background-repeat: no-repeat;
+        box-shadow: 0px 0 7px 0px rgba(0,0,0,0.6);
+      }
+      .A4sceneCardFt {
+        position: absolute;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        padding: 0 12px;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        height: 43px;
+        color: #FCE9AC;
+        font-size: 15px;
+        font-weight: bold;
+        background: url('./images/card-ft-bg-min.png') no-repeat center / cover;
+      
+        &::after {
+          content: '';
+          width: 23px;
+          height: 23px;
+          background: url('./images/play.png') no-repeat center / cover;
+        }
+      }
+    }
+  }
+}
+
+.A4sceneVideoMask {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 0 20px;
+  
+  :global {
+    video {
+      width: 100%;
+      object-fit: cover;
+    }
+  }
+}

+ 53 - 0
code/src/pages/A4scene/index.tsx

@@ -0,0 +1,53 @@
+import React, { useState } from 'react'
+import styles from './index.module.scss'
+import Z1titie from '@/components/Z1titie'
+import history from '@/utils/history'
+import { Mask } from 'antd-mobile'
+
+function A4scene() {
+  const [visible, setVisible] = useState(false)
+  const [videoPath, setVideoPath] = useState('')
+
+  return (
+    <div
+      className={styles.A4scene}
+      style={{ backgroundImage: `url(${serverUrl}show/bac.jpg)` }}
+    >
+      <Z1titie
+        title='使用场景'
+        backFu={() => {
+          history.push('/show')
+        }}
+      />
+
+      <ul className='A4sceneList'>
+        {VIDEO_LIST.map(item => (
+          <li className='A4sceneCard'
+            key={item.name}
+            style={{ backgroundImage: `url(${serverUrl}${item.coverPath})` }}
+            onClick={() => {
+              setVisible(true)
+              setVideoPath(serverUrl + item.videoPath)
+            }}
+          >
+          <div className='A4sceneCardFt'>
+              <p>{item.name}</p>
+            </div>
+          </li>
+        ))}
+      </ul>
+
+      <Mask className={styles.A4sceneVideoMask}
+        visible={visible}
+        destroyOnClose
+        onMaskClick={() => setVisible(false)}
+      >
+        <video src={videoPath} controls autoPlay />
+      </Mask>
+    </div>
+  )
+}
+
+const MemoA4scene = React.memo(A4scene)
+
+export default MemoA4scene

+ 2 - 0
code/src/types/declaration.d.ts

@@ -11,3 +11,5 @@ declare module 'braft-utils'
 declare const serverUrl: string
 declare const myInfoTemp1
 declare const myInfoTemp2
+declare const MODEL_LIST: { name: string; page: string }[]
+declare const VIDEO_LIST: { name: string; videoPath: string; coverPath: string }[]

BIN
静态资源/staticData/scene/1.jpg


BIN
静态资源/staticData/scene/1.mp4


BIN
静态资源/staticData/scene/2.jpg


BIN
静态资源/staticData/scene/2.mp4


BIN
静态资源/staticData/scene/3.jpg


BIN
静态资源/staticData/scene/3.mp4


BIN
静态资源/staticData/scene/4.jpg


BIN
静态资源/staticData/scene/4.mp4


BIN
静态资源/staticData/scene/5.jpg


BIN
静态资源/staticData/scene/5.mp4


BIN
静态资源/staticData/show/fan2-min.png