瀏覽代碼

文物鉴赏功能 继续

任一存 2 年之前
父節點
當前提交
0a18dc840e

二進制
src/assets/images/desc.png


File diff suppressed because it is too large
+ 9 - 0
src/assets/images/no-data.svg


+ 1 - 0
src/assets/style/my-reset.css

@@ -16,6 +16,7 @@ html {
 body {
   text-align: justify;
   height: 100%;
+  overflow: hidden;
 }
 
 a {

+ 115 - 0
src/components/BackTop.vue

@@ -0,0 +1,115 @@
+<template>
+  <div
+    v-show="isShowBackTopBtn"
+    class="back-top"
+    @click="onClickBackTop"
+  >
+    <slot>
+      <div class="back-top__default">
+        回到顶部
+      </div>
+    </slot>
+  </div>
+</template>
+
+<script>
+const { debounce } = require('@/config/utils.js')
+const TWEEN = require('@tweenjs/tween.js')
+
+export default ({
+  props: {
+    targetId: {
+      type: String,
+      required: true,
+    },
+    triggerDistance: {
+      type: Number,
+      default: 200,
+    }
+  },
+  data() {
+    return {
+      target: null,
+      isShowBackTopBtn: false,
+      isBackingTop: false,
+    }
+  },
+  methods: {
+    onClickBackTop() {
+      if (this.isBackingTop) {
+        return
+      }
+      this.isBackingTop = true
+
+      const tweenTarget = {
+        scrollTop: this.target.scrollTop
+      }
+      new TWEEN.Tween(tweenTarget)
+        .to({ scrollTop: 0 }, 800)
+        .easing(TWEEN.Easing.Quartic.Out)
+        .onUpdate(() => {
+          this.target.scrollTop = tweenTarget.scrollTop
+        })
+        .onComplete(() => {
+          this.isBackingTop = false
+        })
+        .start()
+
+      const animate = (time) => {
+        if (this.isBackingTop) {
+          requestAnimationFrame(animate)
+          TWEEN.update(time)
+        }
+      }
+      requestAnimationFrame(animate)
+
+      // 不想引入tween.js的话,可以用这段简单的匀速滚动代码
+      // const startTime = Date.now()
+      // const totalScroll = this.target.scrollTop
+      // const fn = () => {
+      //   if (this.target.scrollTop === 0) {
+      //     this.isBackingTop = false
+      //     return
+      //   }
+
+      //   const nowTime = Date.now()
+      //   const assumeScrollTop = totalScroll - (nowTime - startTime) * totalScroll / 500
+      //   this.target.scrollTop = assumeScrollTop > 0 ? assumeScrollTop : 0
+      //   requestAnimationFrame(fn)
+      // }
+      // requestAnimationFrame(fn)
+    },
+    onTargetScroll: debounce(function(e) {
+      if (this.isBackingTop) {
+        return
+      }
+      if (e.target.scrollTop >= this.triggerDistance) {
+        this.isShowBackTopBtn = true
+      } else {
+        this.isShowBackTopBtn = false
+      }
+    }),
+  },
+  mounted() {
+    this.target = document.getElementById(this.targetId)
+    if (this.target) {
+      this.target.addEventListener('scroll', this.onTargetScroll, {
+        passive: true,
+      })
+    }
+  },
+  unmounted() {
+    if (this.target) {
+      this.target.removeEventListener('scroll', this.onTargetScroll, {
+        passive: true,
+      })
+    }
+  }
+})
+</script>
+
+<style scoped lang="less">
+.back-top__default {
+  cursor: pointer;
+}
+</style>

+ 2 - 2
src/components/BottomBar.vue

@@ -4,7 +4,7 @@
     class="bottom-bar"
     :class="{collapsed: isCollapsed}"
     :style="{
-      zIndex: $config.zIndex.bottomBar.self,
+      zIndex: $globalConfig.zIndex.bottomBar.self,
     }"
   >
     <img
@@ -80,7 +80,7 @@
     <ShareModal
       v-if="isShowShareModal"
       :style="{
-        zIndex: $config.zIndex.bottomBar.children.shareModal.self,
+        zIndex: $globalConfig.zIndex.bottomBar.children.shareModal.self,
       }"
       @close="isShowShareModal = false"
     />

+ 9 - 1
src/components/RelicItem.vue

@@ -20,6 +20,10 @@
     <div
       v-if="relicImage && relicTitle"
       class="relic-info"
+      :style="{
+        zIndex: $globalConfig.zIndex.relicInfo.self,
+      }"
+      @click="onClickRelicInfo"
     >
       <img
         class="relic-image"
@@ -56,6 +60,11 @@ export default {
       default: ''
     },
   },
+  methods: {
+    onClickRelicInfo() {
+      this.$router.push({ name: 'RelicDetail' })
+    }
+  },
 }
 </script>
 
@@ -78,7 +87,6 @@ export default {
       height: 1.67rem;
       border-radius: 50%;
       background-color: #BC945B;
-      background-color: red;
     }
     .curvy-line {
       height: 100%;

+ 9 - 1
src/config.js

@@ -5,8 +5,16 @@ export default {
       self: '3',
       children: {},
     },
+    relicInfo: {
+      self: '2',
+      children: {},
+    },
+    relicDetail: {
+      self: '4',
+      clildren: {},
+    },
     bottomBar: {
-      self: '3',
+      self: '5',
       children: {
         shareModal: {
           self: '1',

+ 1 - 1
src/main.js

@@ -19,7 +19,7 @@ if (uaInfo.browser && uaInfo.browser.name === 'Safari') {
   Vue.prototype.$isSafari = true
 }
 
-Vue.prototype.$config = globalConfig
+Vue.prototype.$globalConfig = globalConfig
 
 const idealWindowInnerWidth = 2436 // 设计稿的宽度
 const idealRootFontSize = 24 // 设计稿里选择的根元素尺寸

+ 13 - 1
src/router/index.js

@@ -2,6 +2,7 @@ import Vue from 'vue'
 import VueRouter from 'vue-router'
 import HomeView from '../views/HomeView.vue'
 import RelicsAppr from "@/views/RelicsAppr.vue"
+import RelicDetail from "@/views/RelicDetail.vue"
 
 Vue.use(VueRouter)
 
@@ -18,7 +19,18 @@ const routes = [
     meta: {
       isShowBottomBar: true,
       canFullScreen: false,
-    }
+    },
+    children: [
+      {
+        path: './relic-detail',
+        name: 'RelicDetail',
+        component: RelicDetail,
+        meta: {
+          isShowBottomBar: true,
+          canFullScreen: false,
+        }
+      },
+    ]
   },
   {
     path: '/about',

+ 214 - 0
src/views/RelicDetail.vue

@@ -0,0 +1,214 @@
+<template>
+  <div class="relic-detail">
+    <div
+      v-if="!isShowDesc"
+      class="preview"
+    >
+      <h1>{{ title }}</h1>
+      <iframe
+        v-if="dimNumber === 3"
+        :src="iframeSrc"
+        frameborder="0"
+        class="display-3d"
+      />
+      <img
+        v-if="dimNumber === 2"
+        class="photo"
+        :src="imageList[0]"
+        alt=""
+        draggable="false"
+      >
+      <div class="btn-group">
+        <button
+          @click="isShowDesc = true"
+        >
+          <img
+            src="@/assets/images/desc.png"
+            alt="详情"
+            draggable="false"
+          >
+        </button>
+        <button
+          @click="$router.go(-1)"
+        >
+          <img
+            src="@/assets/images/close.png"
+            alt="关闭"
+            draggable="false"
+          >
+        </button>
+      </div>
+    </div>
+    <article
+      v-if="isShowDesc"
+      class="desc"
+    >
+      <button
+        class="close-btn"
+        @click="isShowDesc = false"
+      >
+        <img
+          src="@/assets/images/close.png"
+          alt="关闭"
+          draggable="false"
+        >
+      </button>
+      <img
+        class="photo"
+        :src="imageList[0]"
+        alt=""
+        draggable="false"
+      >
+      <h1>{{ title }}</h1>
+      <ul>
+        <li
+          v-for="(item, index) in detailInfo"
+          :key="index"
+          class="desc-item"
+        >
+          {{ item.key }}:{{ item.value }}
+        </li>
+      </ul>
+    </article>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    id: {
+      type: String,
+      default: '',
+    },
+  },
+  data() {
+    return {
+      title: '',
+      dimNumber: 0,
+      desc: '',
+      iframeSrc: '',
+      imageList: [],
+      detailInfo: [],
+
+      isShowDesc: false,
+    }
+  },
+  mounted() {
+    this.title = `i'm title`
+    this.dimNumber = 2
+    this.desc = 'skfdksdfgkljsldf'
+    this.iframeSrc = 'https://4dscene.4dage.com/culturalrelics/NSRDYT/Model2.html?m=nsr03'
+    this.imageList = ['https://4dkk-culture.oss-cn-shenzhen.aliyuncs.com/one_day_in_southern_song_dynasty/cdn_data/%E4%BA%8C%E7%BB%B4%E6%96%87%E7%89%A9%E7%83%AD%E7%82%B9%E5%9B%BE%E7%89%87%E7%B4%A0%E6%9D%90/%E4%B8%B4%E5%AE%89%E5%BA%9C%E8%A1%8C%E7%94%A8%E9%92%B1%E7%89%8C/%E4%B8%B4%E5%AE%89%E5%BA%9C%E8%A1%8C%E7%94%A8%E9%92%B1%E7%89%8C1.jpg']
+    this.detailInfo = [
+      {
+        key: 'a',
+        value: 'b',
+      },
+      {
+        key: 'a',
+        value: 'b',
+      },
+    ]
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.relic-detail {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(246,239,217,0.8);
+  backdrop-filter: blur(1.04rem);
+  > .preview {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-evenly;
+    align-items: center;
+    padding: 0 1.67rem 5rem 1.67rem;
+    > h1 {
+      font-size: 2rem;
+      font-weight: bold;
+      color: #930909;
+      line-height: 2.34rem;
+      width: 60%;
+      align-self: flex-start;
+      flex: 0 0 auto;
+    }
+    > iframe {
+      width: 100%;
+      height: 60%;
+    }
+    > .photo {
+      width: 100%;
+      max-height: 60%;
+      object-fit: contain;
+    }
+    .btn-group {
+      flex: 0 0 auto;
+      > button {
+        width: 6.25rem;
+        height: 6.25rem;
+        > img {
+          width: 100%;
+          height: 100%;
+        }
+        &:nth-of-type(2) {
+          margin-left: 4.38rem;
+        }
+      }
+    }
+  }
+  > .desc {
+    position: absolute;
+    left: 4.7rem;
+    right: 4.7rem;
+    top: 9.75rem;
+    bottom: 14rem;
+    background: #930909;
+    border-top: solid 0.78rem #CEA763;
+    border-bottom: solid 0.78rem #CEA763;
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+    padding: 2.92rem 3rem;
+    .close-btn {
+      position: absolute;
+      top: 0;
+      right: 0;
+      width: 6.25rem;
+      height: 6.25rem;
+      transform: translate(50%, -50%);
+      > img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+    .photo {
+      width: 100%;
+      max-height: 40%;
+      object-fit: contain;
+    }
+    > h1 {
+      margin-top: 2.29rem;
+      font-size: 2rem;
+      font-weight: bold;
+      color: #CEA763;
+      line-height: 2.34rem;
+    }
+    > ul {
+      margin-top: 1.29rem;
+      > li {
+        font-size: 1.67rem;
+        color: #FFFFFF;
+        line-height: 2.92rem;
+        display: block;
+      }
+    }
+  }
+}
+</style>

+ 117 - 6
src/views/RelicsAppr.vue

@@ -3,7 +3,7 @@
     <div
       class="top-bar"
       :style="{
-        zIndex: $config.zIndex.topBar.self
+        zIndex: $globalConfig.zIndex.topBar.self
       }"
     >
       <div class="left-wrap">
@@ -46,7 +46,7 @@
           </div>
           <button
             class="begin-input"
-            @click="isShowInput = true"
+            @click="onClickFakeInput"
           >
             <img
               src="@/assets/images/search.png"
@@ -81,7 +81,10 @@
               draggable="false"
             >
           </button>
-          <input type="text">
+          <input
+            ref="search-input"
+            type="text"
+          >
           <button
             class="cancel"
             @click="isShowInput = false"
@@ -92,7 +95,10 @@
       </div>
     </div>
 
-    <div class="relics-list">
+    <div
+      v-if="currentDim === 3"
+      class="relics-list-3d"
+    >
       <RelicItem
         v-for="index in 10"
         :key="index"
@@ -104,6 +110,42 @@
         class="relic-item"
       />
     </div>
+
+    <ul
+      v-if="currentDim === 2"
+      class="relics-list-2d"
+    >
+      <li
+        v-for="index in 10"
+        :key="index"
+        @click="onClick2dItem"
+      >
+        <div class="img-wrap">
+          <img
+            :src="require(`@/assets/images/button-to-panos.png`)"
+            alt=""
+            draggable="false"
+          >
+        </div>
+        <div class="img-title">
+          jllklllkkklklklk ljkljlj ljljkljkljkljkljk lkjkljlkklljl ksdfjsjfiksfkl skdfjkl
+        </div>
+      </li>
+    </ul>
+
+    <div
+      v-if="!hasData"
+      class="no-data"
+    >
+      <img
+        src="@/assets/images/no-data.svg"
+        alt=""
+        draggable="false"
+      >
+      <div>暂时没有数据<br>请试一下其他关键字</div>
+    </div>
+
+    <router-view :style="{zIndex: $globalConfig.zIndex.relicDetail.self}" />
   </div>
 </template>
 
@@ -142,9 +184,23 @@ export default {
       isShowInput: false,
     }
   },
+  computed: {
+    hasData() {
+      return true
+    }
+  },
   methods: {
+    onClickFakeInput() {
+      this.isShowInput = true
+      this.$nextTick(() => {
+        this.$refs['search-input'].focus()
+      })
+    },
     onClickOutside() {
       this.isShowSelections = false
+    },
+    onClick2dItem() {
+      this.$router.push({ name: 'RelicDetail' })
     }
   }
 }
@@ -152,7 +208,7 @@ export default {
 
 <style lang="less" scoped>
 .relics-appr {
-  // position: relative;
+  position: relative;
   height: 100%;
   width: 100%;
   background-image: url(@/assets/images/relics-background.png);
@@ -265,6 +321,9 @@ export default {
           flex: 1 0 auto;
           width: 1px;
           height: 100%;
+          margin-left: 1.08rem;
+          color: #D9D9D9;
+          font-size: 1.67rem;
         }
         .cancel {
           flex: 0 0 auto;
@@ -275,11 +334,63 @@ export default {
     }
 
   }
-  .relics-list {
+  .relics-list-3d {
     width: 100%;
     padding: 9rem 0 14rem 0;
     > .relic-item {
     }
   }
+  ul.relics-list-2d {
+    width: 100%;
+    padding: 9rem 0 4rem 0;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 1.9rem;
+    > li {
+      width: 20.83rem;
+      height: 19.33rem;
+      background: #FFFFFF;
+      box-shadow: 0rem 0rem 0.33rem 0rem rgba(0,0,0,0.15);
+      border-radius: 0.42rem 0.42rem 0.42rem 0.42rem;
+      .img-wrap {
+        padding: 1.17rem;
+        background: linear-gradient(180deg, #D3D3D3 0%, #EDEDED 100%);
+        width: 100%;
+        height: 13.33rem;
+        img {
+          width: 100%;
+          height: 100%;
+          object-fit: contain;
+        }
+      }
+      .img-title {
+        display: -webkit-box;
+        -webkit-box-orient: vertical;
+        -webkit-line-clamp: 2;
+        overflow: hidden;
+        padding: 0.54rem 1.05rem;
+        font-size: 1.67rem;
+        color: #666666;
+        line-height: 2.5rem;
+      }
+    }
+  }
+  .no-data {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    > img {
+      width: 22.92rem;
+      height: 20.83rem;
+    }
+    > div {
+      margin-top: 0.96rem;
+      text-align: center;
+      font-size: 1.67rem;
+      color: #666666;
+      line-height: 2.5rem;
+    }
+  }
 }
 </style>