소스 검색

文物展示在用户点击热点后自动进行。

任一存 3 년 전
부모
커밋
ac462591b4
1개의 변경된 파일97개의 추가작업 그리고 128개의 파일을 삭제
  1. 97 128
      src/views/HomeView.vue

+ 97 - 128
src/views/HomeView.vue

@@ -77,12 +77,13 @@
         @dragstart.prevent
       >
       <HotSpot
-        v-if="[3].includes(tourState) || ([0].includes(tourState) && maskOpacity === 0)"
+        v-if="[3].includes(tourState) || ([0].includes(tourState))"
         class="hot-spot"
         @click="onClickPeopleFarHotSpot"
       />
     </div>
     <div
+      ref="people-near-wrap"
       class="people-near-wrap"
       :style="{
         left: peopleNearPositionLeft,
@@ -99,7 +100,7 @@
         @click="onClickPeopleNearHotSpot"
       />
       <img
-        v-show="[0, 1].includes(tourState)"
+        v-if="[0, 3].includes(tourState) || ([0].includes(tourState) && maskOpacity === 0)"
         ref="treasure"
         class="treasure"
         :style="{
@@ -122,7 +123,7 @@
     >
 
     <div
-      v-if="[0, 1, 2].includes(tourState) && maskOpacity !== 0"
+      v-if="[0, 1, 2].includes(tourState)"
       class="fade-mask"
       :style="{
         opacity: maskOpacity,
@@ -151,29 +152,21 @@
         @load="onTreasureFrameLoad(index - 1)"
         @error="onTreasureFrameError(index - 1)"
       >
-      <div
-        class="text1"
-        :style="{opacity: text1Opacity}"
-      >
-        <span class="title">宋清瓷团花粉盒</span><br>
-        <span>约公元前1220年<br>口径13.5cm  底径8cm  高6cm</span>
-      </div>
-      <div
-        class="text2"
-        :style="{opacity: text2Opacity}"
-      >
-        此展品为宋代文物。子母口,浅腹,平底,盖面平;盒为子口,内有三个小碟;胎灰白,坚硬,施青色釉,口沿与底部无釉。现收藏于松阳县博物馆。
-      </div>
     </div>
   </div>
 </template>
 
 <script>
+import TWEEN from '@tweenjs/tween.js'
+
+const initialLandscapePositionLeft = '18.491%'
 const initialCloud2PositionLeft = '35%'
 const initialCloud1PositionLeft = '0%'
 const initialCloud3PositionLeft = '55%'
+const initialPeopleFarPositionRight = '15%'
 const initialPeopleNearPositionLeft = '25%'
-const initPeopleFarPositionRight = '15%'
+const initialIntroducePositionLeft = '3.347%'
+
 const landscapeSpeedRate = 0.02
 const cloud2SpeedRate = 0.25
 const cloud1SpeedRate = 0.4
@@ -181,11 +174,14 @@ const cloud3SpeedRate = 0.4
 const peopleFarSpeedRate = 0.4
 const peopleNearSpeedRate = 0.6
 const introduceSpeedRate = 0.6
+
 const translateLengthRightBorder = 9000
-const treasureFadeInProgressRightBorder = 3000
-const treasureDisplayProgressRightBorder = 6000
-const treasureFadeOutProgressRightBorder = 2000
+
+const treasureFadeInDuration = 3000
+const treasureFadeOutDuration = 2000
+
 const treasureFrameTotalNum = 125
+
 const treasureInitialHeightPercent = 9
 const treasureFinalHeightPercent = 116
 
@@ -209,32 +205,36 @@ export default {
       // 镜头平移相关
       translateLength: 0,
       paperPositionLeft: 0,
-      landscapePositionLeft: '18.491%',
+      landscapePositionLeft: initialLandscapePositionLeft,
       cloud2PositionLeft: initialCloud2PositionLeft,
       cloud1PositionLeft: initialCloud1PositionLeft,
       cloud3PositionLeft: initialCloud3PositionLeft,
-      peopleFarPositionRight: initPeopleFarPositionRight,
+      peopleFarPositionRight: initialPeopleFarPositionRight,
       peopleNearPositionLeft: initialPeopleNearPositionLeft,
-      introducePositionLeft: '3.347%',
+      introducePositionLeft: initialIntroducePositionLeft,
 
       // 文物淡入相关
-      treasureFadeInProgress: 0,
-      treasureFadeInProgressRightBorder,
+      treasureFadeInProgress: {
+        value: 0,
+      },
       treasureFadeInInitialLeft: 0,
       treasureFadeInInitialTop: 0,
       treasureFadeInFinalLeft: 0,
       treasureFadeInFinalTop: 0,
       treasureInitialHeightPercent,
+      treasureFadeInTween: null,
 
       // 文物展示相关
-      treasureDisplayProgress: 0,
       treasureFrameTotalNum,
       treasureFrameCurNum: 0,
       treasureFrameStateList: new Array(treasureFrameTotalNum),
+      treasureFrameIntervalId: null,
 
       // 文物淡出相关
-      treasureFadeOutProgress: 0,
-      treasureFadeOutProgressRightBorder,
+      treasureFadeOutProgress: {
+        value: 0,
+      },
+      treasureFadeOutTween: null,
 
       // 远处人物变色相关
       peopleFarColorStatus: 'no-color', // 'no-color', 'color'
@@ -244,16 +244,16 @@ export default {
   computed: {
     treasureOpacity() {
       if (this.tourState === 0) {
-        if (this.treasureFadeInProgress > treasureFadeInProgressRightBorder / 2) {
+        if (this.treasureFadeInProgress.value > 50) {
           return 1
         } else {
-          return this.treasureFadeInProgress / (treasureFadeInProgressRightBorder / 2)
+          return this.treasureFadeInProgress.value / 50
         }
       } else if (this.tourState === 2) {
-        if (this.treasureFadeOutProgress < treasureFadeOutProgressRightBorder / 2) {
+        if (this.treasureFadeOutProgress.value < 50) {
           return 1
         } else {
-          return 1 - (this.treasureFadeOutProgress - treasureFadeOutProgressRightBorder / 2) / (treasureFadeOutProgressRightBorder / 2)
+          return 1 - (this.treasureFadeOutProgress.value - 50) / 50
         }
       } else {
         return 0
@@ -261,62 +261,53 @@ export default {
     },
     maskOpacity() {
       if (this.tourState === 0) {
-        if (this.treasureFadeInProgress > treasureFadeInProgressRightBorder / 2) {
+        if (this.treasureFadeInProgress.value > 50) {
           return 1
         } else {
-          return this.treasureFadeInProgress / (treasureFadeInProgressRightBorder / 2)
+          return this.treasureFadeInProgress.value / 50
         }
       } else if (this.tourState === 2) {
-        if (this.treasureFadeOutProgress < treasureFadeOutProgressRightBorder / 2) {
-          return 1
-        } else {
-          return 1 - (this.treasureFadeOutProgress - treasureFadeOutProgressRightBorder / 2) / (treasureFadeOutProgressRightBorder / 2)
-        }
-      } else {
-        return 1
-      }
-    },
-    text1Opacity() {
-      if (this.tourState === 1) {
-        if (this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.1) {
-          return this.treasureDisplayProgress / (treasureDisplayProgressRightBorder * 0.1)
-        } else if (this.treasureDisplayProgress >= treasureDisplayProgressRightBorder * 0.1 && this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.4) {
-          return 1
-        } else if (this.treasureDisplayProgress >= treasureDisplayProgressRightBorder * 0.4 && this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.5) {
-          return 1 - (this.treasureDisplayProgress - treasureDisplayProgressRightBorder * 0.4) / (treasureDisplayProgressRightBorder * (0.5 - 0.4))
-        } else {
-          return 0
-        }
+        return (100 - this.treasureFadeOutProgress.value) / 100
       } else {
         return 0
       }
     },
-    text2Opacity() {
-      if (this.tourState === 1) {
-        if (this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.5) {
-          return 0
-        } else if (this.treasureDisplayProgress >= treasureDisplayProgressRightBorder * 0.5 && this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.6) {
-          return (this.treasureDisplayProgress - treasureDisplayProgressRightBorder * 0.5) / (treasureDisplayProgressRightBorder * (0.6 - 0.5))
-        } else if (this.treasureDisplayProgress >= treasureDisplayProgressRightBorder * 0.6 && this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.9) {
-          return 1
-        } else {
-          return 1 - (this.treasureDisplayProgress - treasureDisplayProgressRightBorder * 0.9) / (treasureDisplayProgressRightBorder * (1 - 0.9))
+  },
+  watch: {
+    tourState: {
+      handler(vNew, vOld) {
+        if (vOld === 0 && vNew === 1) {
+          this.treasureFrameIntervalId = setInterval(() => {
+            const frameNumBackup = this.treasureFrameCurNum
+            this.treasureFrameCurNum++
+            if (this.treasureFrameCurNum === this.treasureFrameTotalNum) {
+              clearInterval(this.treasureFrameIntervalId)
+              this.treasureFrameCurNum = 0
+              this.tourState = 2
+              return
+            }
+
+            while (this.treasureFrameStateList[this.treasureFrameCurNum] === false) {
+              this.treasureFrameCurNum++
+            }
+            if (this.treasureFrameStateList[this.treasureFrameCurNum] === undefined) {
+              this.treasureFrameCurNum = frameNumBackup
+            }
+          }, 41)
+        } else if (vOld === 1 && vNew === 2) {
+          this.treasureFadeOutTween.start()
         }
-      } else {
-        return 0
       }
     },
-  },
-  watch: {
-    treasureFadeInProgress: {
+    'treasureFadeInProgress.value': {
       handler(vNew, vOld) {
-        if (vOld < this.treasureFadeInProgressRightBorder && vNew >= this.treasureFadeInProgressRightBorder && this.tourState === 0) {
+        if (vOld < 100 && vNew === 100 && this.tourState === 0) {
           this.tourState = 1
         }
-        if (this.treasureFadeInProgress > treasureFadeInProgressRightBorder / 2) {
-          this.$refs.treasure.style.left = this.treasureFadeInInitialLeft + (this.treasureFadeInProgress - treasureFadeInProgressRightBorder / 2) / (treasureFadeInProgressRightBorder / 2) * (this.treasureFadeInFinalLeft - this.treasureFadeInInitialLeft) + 'px'
-          this.$refs.treasure.style.top = this.treasureFadeInInitialTop + (this.treasureFadeInProgress - treasureFadeInProgressRightBorder / 2) / (treasureFadeInProgressRightBorder / 2) * (this.treasureFadeInFinalTop - this.treasureFadeInInitialTop) + 'px'
-          this.$refs.treasure.style.transform = `translate(-50%, -50%) scale(${1 + (this.treasureFadeInProgress - treasureFadeInProgressRightBorder / 2) / (treasureFadeInProgressRightBorder / 2) * (treasureFinalHeightPercent / this.treasureInitialHeightPercent - 1)})`
+        if (this.treasureFadeInProgress.value > 50) {
+          this.$refs.treasure.style.left = this.treasureFadeInInitialLeft + (this.treasureFadeInProgress.value - 50) / 50 * (this.treasureFadeInFinalLeft - this.treasureFadeInInitialLeft) + 'px'
+          this.$refs.treasure.style.top = this.treasureFadeInInitialTop + (this.treasureFadeInProgress.value - 50) / 50 * (this.treasureFadeInFinalTop - this.treasureFadeInInitialTop) + 'px'
+          this.$refs.treasure.style.transform = `translate(-50%, -50%) scale(${1 + (this.treasureFadeInProgress.value - 50) / 50 * (treasureFinalHeightPercent / this.treasureInitialHeightPercent - 1)})`
         } else {
           this.$refs.treasure.style.left = this.treasureFadeInInitialLeft + 'px'
           this.$refs.treasure.style.top = this.treasureFadeInInitialTop + 'px'
@@ -324,49 +315,42 @@ export default {
         }
       }
     },
-    treasureDisplayProgress: {
+    'treasureFadeOutProgress.value': {
       handler(vNew, vOld) {
-        // 更新toureState
-        if (vOld > 0 && vNew <= 0 && this.tourState === 1) {
-          this.tourState = 0
-        } else if (vOld < treasureDisplayProgressRightBorder && vNew >= treasureDisplayProgressRightBorder && this.tourState === 1) {
-          this.tourState = 2
-        }
-
-        let idealCurNum = Math.round(this.treasureDisplayProgress / treasureDisplayProgressRightBorder * treasureFrameTotalNum)
-
-        while (this.treasureFrameStateList[idealCurNum] === false) {
-          idealCurNum--
-        }
-        this.treasureFrameCurNum = idealCurNum
-      }
-    },
-    treasureFadeOutProgress: {
-      handler(vNew, vOld) {
-        if (vOld > 0 && vNew <= 0 && this.tourState === 2) {
-          this.tourState = 1
-        } else if (vOld < this.treasureFadeOutProgressRightBorder && vNew >= this.treasureFadeOutProgressRightBorder && this.tourState === 2) {
+        if (vOld < 100 && vNew >= 100 && this.tourState === 2) {
           this.tourState = 3
         }
       }
     },
     translateLength: {
       handler(vNew, vOld) {
-        // const rightBorder = window.innerWidth * 2
-
         this.paperPositionLeft = `${vNew * landscapeSpeedRate}px`
         this.landscapePositionLeft = `calc(18.491% + ${vNew * landscapeSpeedRate}px)`
         this.cloud2PositionLeft = `calc(${initialCloud2PositionLeft} + ${vNew * cloud2SpeedRate}px)`
         this.cloud1PositionLeft = `calc(${initialCloud1PositionLeft} + ${vNew * cloud1SpeedRate}px)`
         this.cloud3PositionLeft = `calc(${initialCloud3PositionLeft} + ${vNew * cloud3SpeedRate}px)`
-        this.peopleFarPositionRight = `calc(${initPeopleFarPositionRight} - ${vNew * peopleFarSpeedRate}px)`
+        this.peopleFarPositionRight = `calc(${initialPeopleFarPositionRight} - ${vNew * peopleFarSpeedRate}px)`
         this.peopleNearPositionLeft = `calc(${initialPeopleNearPositionLeft} + ${vNew * peopleNearSpeedRate}px)`
         this.introducePositionLeft = `calc(3.347% + ${vNew * introduceSpeedRate}px)`
       }
     },
   },
   mounted() {
-    this.animationFrameId = requestAnimationFrame(this.inertanceEffect)
+    const that = this
+    this.animationFrameId = requestAnimationFrame(this.animationFrameTask)
+
+    this.treasureFadeInTween = new TWEEN.Tween(that.treasureFadeInProgress)
+    this.treasureFadeInTween.to({
+      value: 100,
+    }, treasureFadeInDuration)
+    this.treasureFadeInTween.easing(TWEEN.Easing.Linear.None)
+
+    this.treasureFadeOutTween = new TWEEN.Tween(that.treasureFadeOutProgress)
+    this.treasureFadeOutTween.to({
+      value: 100,
+    }, treasureFadeOutDuration)
+    this.treasureFadeOutTween.easing(TWEEN.Easing.Linear.None)
+
   },
   unmounted() {
     cancelAnimationFrame(this.animationFrameId)
@@ -405,7 +389,7 @@ export default {
         }
       }
     },
-    inertanceEffect() {
+    animationFrameTask() {
       const timeStamp = Date.now()
       const timeElapsed = timeStamp - this.lastAnimationTimeStamp
 
@@ -433,8 +417,10 @@ export default {
         }
       }
 
+      TWEEN.update()
+
       this.lastAnimationTimeStamp = timeStamp
-      this.animationFrameId = requestAnimationFrame(this.inertanceEffect)
+      this.animationFrameId = requestAnimationFrame(this.animationFrameTask)
     },
     onClickPeopleFarHotSpot() {
       if (this.isPeopleFarColorChanging) {
@@ -452,10 +438,18 @@ export default {
       }
     },
     onClickPeopleNearHotSpot() {
+      if (this.tourState !== 3) {
+        return
+      }
+
+      // 计算淡入过渡的起始终止位置
       this.treasureFadeInInitialLeft = this.$refs.treasure.offsetLeft
       this.treasureFadeInInitialTop = this.$refs.treasure.offsetTop
-      this.treasureFadeInFinalLeft = window.innerWidth / 2 - this.$refs.treasure.offsetParent.offsetLeft
-      this.treasureFadeInFinalTop = window.innerHeight / 2 - this.$refs.treasure.offsetParent.offsetTop
+      this.treasureFadeInFinalLeft = window.innerWidth / 2 - this.$refs['people-near-wrap'].offsetLeft
+      this.treasureFadeInFinalTop = window.innerHeight / 2 - this.$refs['people-near-wrap'].offsetTop
+      this.tourState = 0
+
+      this.treasureFadeInTween.start()
     },
     onTreasureFrameLoad(idx) {
       this.treasureFrameStateList[idx] = true
@@ -583,31 +577,6 @@ export default {
       height: 100%;
       object-fit: cover;
     }
-    > .text1 {
-      color: #fff;
-      position: absolute;
-      top: 5%;
-      left: 3%;
-      .title {
-        font-size: 24px;
-        font-weight: bold;
-        line-height: 2;
-
-      }
-      span {
-        font-size: 18px;
-        line-height: 1.5;
-      }
-    }
-    > .text2 {
-      color: #fff;
-      position: absolute;
-      bottom: 5%;
-      right: 3%;
-      width: 30%;
-      font-size: 18px;
-      line-height: 1.5;
-    }
   }
   @media screen and (max-height: 810px) {
     .people-far-wrap {