Kaynağa Gözat

长图序列帧相关代码提取成一个组件

任一存 3 yıl önce
ebeveyn
işleme
ca87524abe

+ 91 - 0
src/components/SingleLongImageSerialFrames.vue

@@ -0,0 +1,91 @@
+<template>
+  <div
+    class="single-long-image-serial-frames"
+  >
+    <img
+      class="long-image"
+      :style="{
+        transitionDuration: transitionDuration + 'ms',
+        transitionTimingFunction: `steps(${frameNumber - 1}, jump-end)`,
+        left: status === 'initial' ? 0 : `calc(-100% * ${frameNumber - 1})`
+      }"
+      :src="imageSrc"
+      alt=""
+      @dragstart.prevent
+    >
+    <HotSpot
+      class="hot-spot"
+      :style="{
+        left: hotSpotCenterPosLeft,
+        top: hotSpotCenterPosTop,
+      }"
+      @click="onClickHotSpot"
+    />
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    imageSrc: {
+      type: String,
+      required: true,
+    },
+    frameNumber: {
+      type: Number,
+      required: true,
+    },
+    transitionDuration: {
+      type: Number,
+      default: 2500,
+    },
+    hotSpotCenterPosLeft: {
+      type: String,
+      default: '50%'
+    },
+    hotSpotCenterPosTop: {
+      type: String,
+      default: '50%',
+    },
+  },
+  data() {
+    return {
+      status: 'initial', // 'initial', 'variant'
+      isChanging: false,
+    }
+  },
+  methods: {
+    onClickHotSpot() {
+      if (this.isChanging) {
+        return
+      } else {
+        if (this.status === 'initial') {
+          this.status = 'variant'
+        } else {
+          this.status = 'initial'
+        }
+        this.isChanging = true
+        setTimeout(() => {
+          this.isChanging = false
+        }, 2500)
+      }
+    },
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.single-long-image-serial-frames {
+  position: absolute;
+  overflow: hidden;
+  > .long-image {
+    position: absolute;
+    height: 100%;
+    transition-property: left;
+  }
+  > .hot-spot {
+    position: absolute;
+    transform: translate(-50%, -50%);
+  }
+}
+</style>

+ 2 - 0
src/main.js

@@ -5,6 +5,7 @@ import store from './store'
 import HotSpot from '@/components/HotSpot.vue'
 import SerialFrames from '@/components/SerialFrames.vue'
 import TreasureDisplay from '@/components/TreasureDisplay.vue'
+import SingleLongImageSerialFrames from '@/components/SingleLongImageSerialFrames.vue'
 
 createApp(App)
   .use(store)
@@ -12,4 +13,5 @@ createApp(App)
   .component('HotSpot', HotSpot)
   .component('SerialFrames', SerialFrames)
   .component('TreasureDisplay', TreasureDisplay)
+  .component('SingleLongImageSerialFrames', SingleLongImageSerialFrames)
   .mount('#app')

+ 7 - 54
src/views/HomeView.vue

@@ -63,25 +63,17 @@
       src="@/assets/cloud3.png"
       alt=""
     >
-    <div
+    <SingleLongImageSerialFrames
       class="people-far-wrap"
       :style="{
         right: peopleFarPositionRight,
       }"
-    >
-      <img
-        class="people-far"
-        :class="peopleFarColorStatus"
-        src="@/assets/people-far-serial-frame-400-600-60.png"
-        alt=""
-        @dragstart.prevent
-      >
-      <HotSpot
-        v-if="canMoveCamera"
-        class="hot-spot"
-        @click="onClickPeopleFarHotSpot"
-      />
-    </div>
+      :image-src="require('@/assets/people-far-serial-frame-400-600-60.png')"
+      :frame-number="60"
+      :transition-duration="2500"
+      :hot-spot-center-pos-left="'55%'"
+      :hot-spot-center-pos-top="'34.5%'"
+    />
     <div
       ref="people-near-wrap"
       class="people-near-wrap"
@@ -154,10 +146,6 @@ export default {
       peopleFarPositionRight: config.initialPeopleFarPositionRight,
       peopleNearPositionLeft: config.initialPeopleNearPositionLeft,
       introducePositionLeft: config.initialIntroducePositionLeft,
-
-      // 远处人物变色相关
-      peopleFarColorStatus: 'no-color', // 'no-color', 'color'
-      isPeopleFarColorChanging: false,
     }
   },
   watch: {
@@ -246,21 +234,6 @@ export default {
       this.lastAnimationTimeStamp = timeStamp
       this.animationFrameId = requestAnimationFrame(this.animationFrameTask)
     },
-    onClickPeopleFarHotSpot() {
-      if (this.isPeopleFarColorChanging) {
-        return
-      } else {
-        if (this.peopleFarColorStatus === 'no-color') {
-          this.peopleFarColorStatus = 'color'
-        } else {
-          this.peopleFarColorStatus = 'no-color'
-        }
-        this.isPeopleFarColorChanging = true
-        setTimeout(() => {
-          this.isPeopleFarColorChanging = false
-        }, 2500)
-      }
-    },
     onClickPeopleNearHotSpot() {
       this.$refs['treasure-display'].startDisplay()
     },
@@ -312,26 +285,6 @@ export default {
     top: 14%;
     height: 750px;
     width: 500px;
-    overflow: hidden;
-    > .people-far {
-      position: absolute;
-      height: 100%;
-      transition-property: left;
-      transition-duration: 2.5s;
-      transition-timing-function: steps(59, jump-end);
-      &.no-color {
-        left: 0;
-      }
-      &.color {
-        left: calc(-100% * 59)
-      }
-    }
-    > .hot-spot {
-      position: absolute;
-      left: 55%;
-      transform: translateX(-50%);
-      top: 31%;
-    }
   }
   > .people-near-wrap {
     position: absolute;