瀏覽代碼

Merge branch 'master' of http://192.168.0.115:3000/renyicun/YangZhouDaYunHeDaDu

aamin 1 年之前
父節點
當前提交
a1f43d8050
共有 29 個文件被更改,包括 1322 次插入9 次删除
  1. 14 0
      src/App.vue
  2. 二進制
      src/assets/images/camera-content-1-2-1-hotspot-1-area.png
  3. 二進制
      src/assets/images/camera-content-1-2-1-hotspot-2-area.png
  4. 二進制
      src/assets/images/camera-content-1-2-1-hotspot-3-area.png
  5. 二進制
      src/assets/images/camera-content-1-2-1-hotspot-4-area.png
  6. 二進制
      src/assets/images/camera-content-1-2-2-default-content.png
  7. 二進制
      src/assets/images/camera-content-1-2-2-tab-2-img.jpg
  8. 二進制
      src/assets/images/camera-content-1-2-3-content.png
  9. 二進制
      src/assets/images/camera-content-1-3-1-tab-1-content.png
  10. 二進制
      src/assets/images/camera-content-1-3-1-tab-2-content.png
  11. 二進制
      src/assets/images/camera-content-1-3-3-content.png
  12. 二進制
      src/assets/images/cloud-left-bottom.png
  13. 二進制
      src/assets/images/cloud-right-bottom.png
  14. 二進制
      src/assets/images/cloud-top.png
  15. 二進制
      src/assets/images/cloud2.png
  16. 二進制
      src/assets/images/start-up-bg.jpg
  17. 二進制
      src/assets/images/startup-animation.png
  18. 二進制
      src/assets/videos/scene-change-effect-1.mp4
  19. 二進制
      src/assets/videos/scene-change-effect-2.mp4
  20. 二進制
      src/assets/videos/start-up-video.mp4
  21. 1 0
      src/components/CameraContent-1-1-1.vue
  22. 359 0
      src/components/CameraContent-1-2-1.vue
  23. 283 0
      src/components/CameraContent-1-2-2.vue
  24. 108 0
      src/components/CameraContent-1-2-3.vue
  25. 0 1
      src/components/CameraContent-1-2.vue
  26. 222 0
      src/components/CameraContent-1-3-1.vue
  27. 76 0
      src/components/CameraContent-1-3-2.vue
  28. 76 0
      src/components/CameraContent-1-3-3.vue
  29. 183 8
      src/views/PanoView.vue

+ 14 - 0
src/App.vue

@@ -108,6 +108,20 @@ const store = useStore()
   opacity: 0;
 }
 
+.fade-in-out-slow-enter-active {
+  transition: opacity 1.5s;
+}
+.fade-in-out-slow-leave-active {
+  transition: opacity 1.5s;
+  pointer-events: none;
+}
+.fade-in-out-slow-enter-from {
+  opacity: 0;
+}
+.fade-in-out-slow-leave-to {
+  opacity: 0;
+}
+
 // 不断渐变显隐 animation
 .animation-show-hide {
   animation: show-hide 1.8s infinite;

二進制
src/assets/images/camera-content-1-2-1-hotspot-1-area.png


二進制
src/assets/images/camera-content-1-2-1-hotspot-2-area.png


二進制
src/assets/images/camera-content-1-2-1-hotspot-3-area.png


二進制
src/assets/images/camera-content-1-2-1-hotspot-4-area.png


二進制
src/assets/images/camera-content-1-2-2-default-content.png


二進制
src/assets/images/camera-content-1-2-2-tab-2-img.jpg


二進制
src/assets/images/camera-content-1-2-3-content.png


二進制
src/assets/images/camera-content-1-3-1-tab-1-content.png


二進制
src/assets/images/camera-content-1-3-1-tab-2-content.png


二進制
src/assets/images/camera-content-1-3-3-content.png


二進制
src/assets/images/cloud-left-bottom.png


二進制
src/assets/images/cloud-right-bottom.png


二進制
src/assets/images/cloud-top.png


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


二進制
src/assets/images/start-up-bg.jpg


二進制
src/assets/images/startup-animation.png


二進制
src/assets/videos/scene-change-effect-1.mp4


二進制
src/assets/videos/scene-change-effect-2.mp4


二進制
src/assets/videos/start-up-video.mp4


+ 1 - 0
src/components/CameraContent-1-1-1.vue

@@ -500,6 +500,7 @@ const displayingHotspotIdx = ref(-1)
       >button.hotspot.active{
         >.label{
           display: flex;
+          pointer-events: none;
         }
         >.deco{
           display: initial;

File diff suppressed because it is too large
+ 359 - 0
src/components/CameraContent-1-2-1.vue


File diff suppressed because it is too large
+ 283 - 0
src/components/CameraContent-1-2-2.vue


+ 108 - 0
src/components/CameraContent-1-2-3.vue

@@ -0,0 +1,108 @@
+
+<template>
+  <div class="camera-content-1-1">
+    <button
+      class="return"
+      @click="emit('close')"
+    />
+    <div class="content-wrap">
+      <div class="left">
+        <img
+          class="content"
+          src="@/assets/images/camera-content-1-2-3-content.png"
+          alt=""
+          draggable="false"
+        >
+      </div>
+      <div class="right">
+        <video
+          src="@/assets/videos/start-up-video.mp4"
+          controls
+          playsinline
+          webkit-playsinline="true"
+          x5-video-player-type="h5"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, watch, onMounted } from "vue"
+import { useRoute, useRouter } from "vue-router"
+import { useStore } from "vuex"
+
+const {
+  windowSizeInCssForRef,
+  windowSizeWhenDesignForRef,
+} = useSizeAdapt(1920, 970)
+
+const route = useRoute()
+const router = useRouter()
+const store = useStore()
+
+const emit = defineEmits(['close'])
+
+</script>
+
+<style lang="less" scoped>
+.camera-content-1-1{
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0,0,0,0.45);
+  backdrop-filter: blur(60px);
+  >button.return{
+    position: absolute;
+    width: 58px;
+    height: 58px;
+    left: 42px;
+    top: 68px;
+    background-image: url(@/assets/images/btn-return.png);
+    background-size: contain;
+    background-repeat: no-repeat;
+    background-position: center center;
+  }
+  >.content-wrap{
+    position: absolute;
+    left: 50%;
+    top: 54%;
+    width: calc(1920 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(723 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    transform: translate(-50%, -50%);
+    background-image: url(@/assets/images/camera-content-1-1-3-bg.png);
+    background-size: cover;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    justify-content: space-evenly;
+    align-items: center;
+    >.left{
+      flex: 0 0 auto;
+      width: calc(818 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      height: calc(438 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      >img.content{
+        width: 100%;
+      }
+    }
+    >.right{
+      flex: 0 0 auto;
+      position: relative;
+      width: calc(818 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      height: calc(438 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      >video{
+        position: absolute;
+        left: 0;
+        top: 0;
+        width: 100%;
+        height: 100%;
+        background: rgba(145,129,117,0.25);
+        border: 1px solid #FFE88B;
+        padding: calc(25 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      }
+    }
+  }
+}
+</style>

+ 0 - 1
src/components/CameraContent-1-2.vue

@@ -1 +0,0 @@
-

+ 222 - 0
src/components/CameraContent-1-3-1.vue

@@ -0,0 +1,222 @@
+
+<template>
+  <div class="camera-content-1-2-2">
+    <button
+      class="return"
+      @click="emit('close')"
+    />
+    <div class="content-wrap">
+      <h1>大都城内的寺庙建筑</h1>
+      <div class="tabbar">
+        <button
+          :class="{
+            active: activeTabIdx === 1
+          }"
+          @click="activeTabIdx = 1"
+        >
+          大圣寿万安寺
+        </button>
+        <div class="splitter" />
+        <button
+          :class="{
+            active: activeTabIdx === 2
+          }"
+          @click="activeTabIdx = 2"
+        >
+          大庆寿寺
+        </button>
+      </div>
+      <div
+        v-if="activeTabIdx === 1"
+        class="tab-content tab-1-content"
+      >
+        <img
+          class=""
+          src="@/assets/images/camera-content-1-3-1-tab-1-content.png"
+          alt=""
+          draggable="false"
+        >
+      </div>
+      <div
+        v-if="activeTabIdx === 2"
+        class="tab-content tab-2-content"
+      >
+        <img
+          class=""
+          src="@/assets/images/camera-content-1-3-1-tab-2-content.png"
+          alt=""
+          draggable="false"
+        >
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, watch, onMounted } from "vue"
+import { useRoute, useRouter } from "vue-router"
+import { useStore } from "vuex"
+
+const {
+  windowSizeInCssForRef,
+  windowSizeWhenDesignForRef,
+} = useSizeAdapt(1920, 970)
+
+const route = useRoute()
+const router = useRouter()
+const store = useStore()
+
+const emit = defineEmits(['close'])
+
+const activeTabIdx = ref(1)
+
+</script>
+
+<style lang="less" scoped>
+.camera-content-1-2-2{
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0,0,0,0.45);
+  backdrop-filter: blur(60px);
+  >button.return{
+    position: absolute;
+    width: 58px;
+    height: 58px;
+    left: 42px;
+    top: 68px;
+    background-image: url(@/assets/images/btn-return.png);
+    background-size: contain;
+    background-repeat: no-repeat;
+    background-position: center center;
+  }
+  >.content-wrap{
+    position: absolute;
+    left: 50%;
+    top: 54%;
+    width: calc(1585 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(819 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    transform: translate(-50%, -50%);
+    background-image: url(@/assets/images/camera-content-1-1-2-bg.png);
+    background-size: cover;
+    background-repeat: no-repeat;
+    background-position: center center;
+    >h1{
+      position: absolute;
+      left: calc(163 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      top: calc(180 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      font-size: calc(40 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      font-family: Source Han Serif CN;
+      color: #FBF7DC;
+      line-height: calc(47 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      writing-mode: vertical-lr;
+      letter-spacing: 0.3em;
+    }
+    >.tabbar{
+      position: absolute;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      left: calc(373 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      top: calc(42 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      >button {
+        width: calc(46 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        padding-top: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        padding-bottom: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        writing-mode: vertical-lr;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        background: #AC997F;
+        box-shadow: 3px 4px 9px 0px rgba(0,0,0,0.25);
+      }
+      >button.active{
+        background: linear-gradient(322deg, #C69D49 0%, #F8E6A9 68%);
+      }
+      >.splitter{
+        // position: absolute;
+        // left: 50%;
+        // top: 50%;
+        // transform: translate(-50%, -50%);
+        width: calc(34 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        height: 1px;
+        background-color: #FFF3C3;
+      }
+    }
+    >.tab-content{
+      position: absolute;
+      left: calc(450 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      top: calc(42 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      width: calc(950 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      height: calc(750 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+    >.default-content{
+      padding: calc(40 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'))
+    }
+    >.tab-1-content{
+      >img{
+        width: 95%;
+      }
+      >div.table{
+        position: absolute;
+        left: 0;
+        top: 0;
+        width: 100%;
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        >h3{
+          width: calc(528 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          height: calc(64 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          background-image: url(@/assets/images/camera-content-1-1-2-tab-1-table-title.png);
+          background-size: cover;
+          background-repeat: no-repeat;
+          background-position: center center;
+          font-size: calc(28 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-family: Source Han Serif CN;
+          font-weight: 600;
+          color: #6A3906;
+          line-height: calc(33 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          letter-spacing: calc(5 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          margin-bottom: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+        >img.table-img{
+          width: calc(931 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          height: calc(528 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+      }
+      >button.change-page{
+        position: absolute;
+        width: calc(60 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        height: calc(60 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        right: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        bottom: calc(50 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        background-size: cover;
+        background-repeat: no-repeat;
+        background-position: center center;
+      }
+    }
+    >.tab-2-content{
+      padding-top: calc(50 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      padding-bottom: calc(50 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      display: flex;
+      flex-direction: column;
+      justify-content: space-evenly;
+      align-items: center;
+      >img{
+        object-fit: contain;
+      }
+    }
+  }
+}
+</style>

+ 76 - 0
src/components/CameraContent-1-3-2.vue

@@ -0,0 +1,76 @@
+
+<template>
+  <div class="camera-content-1-1">
+    <button
+      class="return"
+      @click="emit('close')"
+    />
+    <div class="content-wrap">
+      <img
+        class="content"
+        src="@/assets/images/camera-content-1-3-3-content.png"
+        alt=""
+        draggable="false"
+      >
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, watch, onMounted } from "vue"
+import { useRoute, useRouter } from "vue-router"
+import { useStore } from "vuex"
+
+const {
+  windowSizeInCssForRef,
+  windowSizeWhenDesignForRef,
+} = useSizeAdapt(1920, 970)
+
+const route = useRoute()
+const router = useRouter()
+const store = useStore()
+
+const emit = defineEmits(['close'])
+
+</script>
+
+<style lang="less" scoped>
+.camera-content-1-1{
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0,0,0,0.45);
+  backdrop-filter: blur(60px);
+  >button.return{
+    position: absolute;
+    width: 58px;
+    height: 58px;
+    left: 42px;
+    top: 68px;
+    background-image: url(@/assets/images/btn-return.png);
+    background-size: contain;
+    background-repeat: no-repeat;
+    background-position: center center;
+  }
+  >.content-wrap{
+    position: absolute;
+    left: 50%;
+    top: 54%;
+    width: calc(1920 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(723 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    transform: translate(-50%, -50%);
+    background-image: url(@/assets/images/camera-content-1-1-3-bg.png);
+    background-size: cover;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    justify-content: space-evenly;
+    align-items: center;
+    >img.content{
+      width: 90%;
+    }
+  }
+}
+</style>

+ 76 - 0
src/components/CameraContent-1-3-3.vue

@@ -0,0 +1,76 @@
+
+<template>
+  <div class="camera-content-1-1">
+    <button
+      class="return"
+      @click="emit('close')"
+    />
+    <div class="content-wrap">
+      <img
+        class="content"
+        src="@/assets/images/camera-content-1-3-3-content.png"
+        alt=""
+        draggable="false"
+      >
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, watch, onMounted } from "vue"
+import { useRoute, useRouter } from "vue-router"
+import { useStore } from "vuex"
+
+const {
+  windowSizeInCssForRef,
+  windowSizeWhenDesignForRef,
+} = useSizeAdapt(1920, 970)
+
+const route = useRoute()
+const router = useRouter()
+const store = useStore()
+
+const emit = defineEmits(['close'])
+
+</script>
+
+<style lang="less" scoped>
+.camera-content-1-1{
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0,0,0,0.45);
+  backdrop-filter: blur(60px);
+  >button.return{
+    position: absolute;
+    width: 58px;
+    height: 58px;
+    left: 42px;
+    top: 68px;
+    background-image: url(@/assets/images/btn-return.png);
+    background-size: contain;
+    background-repeat: no-repeat;
+    background-position: center center;
+  }
+  >.content-wrap{
+    position: absolute;
+    left: 50%;
+    top: 54%;
+    width: calc(1920 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(723 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    transform: translate(-50%, -50%);
+    background-image: url(@/assets/images/camera-content-1-1-3-bg.png);
+    background-size: cover;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    justify-content: space-evenly;
+    align-items: center;
+    >img.content{
+      width: 90%;
+    }
+  }
+}
+</style>

+ 183 - 8
src/views/PanoView.vue

@@ -152,6 +152,59 @@
       class="camera-content"
       @close="showingContentIdx = 0"
     />
+
+    <transition name="fade-in-out-slow">
+      <video
+        v-show="isShowEffectVideo1"
+        ref="sceneChangeEffectVideo1"
+        class="sceneChangeEffectVideo"
+        load="lazy"
+        src="@/assets/videos/scene-change-effect-1.mp4"
+        playsinline
+        webkit-playsinline="true"
+        x5-video-player-type="h5"
+        @ended="onEffectVideoEnd"
+      />
+    </transition>
+    <transition name="fade-in-out-slow">
+      <video
+        v-show="isShowEffectVideo2"
+        ref="sceneChangeEffectVideo2"
+        class="sceneChangeEffectVideo"
+        src="@/assets/videos/scene-change-effect-2.mp4"
+        playsinline
+        webkit-playsinline="true"
+        x5-video-player-type="h5"
+        @ended="onEffectVideoEnd"
+      />
+    </transition>
+    <transition name="cloud-top">
+      <img
+        v-if="isShowEffectCloud"
+        class="cloud cloud-top"
+        src="@/assets/images/cloud-top.png"
+        alt=""
+        draggable="false"
+      >
+    </transition>
+    <transition name="cloud-left-bottom">
+      <img
+        v-if="isShowEffectCloud"
+        class="cloud-left-bottom"
+        src="@/assets/images/cloud-left-bottom.png"
+        alt=""
+        draggable="false"
+      >
+    </transition>
+    <transition name="cloud-right-bottom">
+      <img
+        v-if="isShowEffectCloud"
+        class="cloud-right-bottom"
+        src="@/assets/images/cloud-right-bottom.png"
+        alt=""
+        draggable="false"
+      >
+    </transition>
   </div>
 </template>
 
@@ -211,15 +264,30 @@ const btnOnTrack3Name = computed(() => {
   return currentCameraList.value[cameraIdx.value].contentPageBtnNameList[2]
 })
 
-const CameraContent1 = defineAsyncComponent(() =>
+let CameraContent1 = defineAsyncComponent(() =>
   import(`@/components/CameraContent-${Number(route.query.sceneIdx) + 1}-${Number(route.query.cameraIdx) + 1}-1.vue`)
 )
-const CameraContent2 = defineAsyncComponent(() =>
+let CameraContent2 = defineAsyncComponent(() =>
   import(`@/components/CameraContent-${Number(route.query.sceneIdx) + 1}-${Number(route.query.cameraIdx) + 1}-2.vue`)
 )
-const CameraContent3 = defineAsyncComponent(() =>
+let CameraContent3 = defineAsyncComponent(() =>
   import(`@/components/CameraContent-${Number(route.query.sceneIdx) + 1}-${Number(route.query.cameraIdx) + 1}-3.vue`)
 )
+onBeforeRouteUpdate((to, from) => {
+  console.log('to: ', to)
+  if (to.name === route.name) {
+    CameraContent1 = defineAsyncComponent(() =>
+      import(`@/components/CameraContent-${Number(route.query.sceneIdx) + 1}-${Number(route.query.cameraIdx) + 1}-1.vue`)
+    )
+    CameraContent2 = defineAsyncComponent(() =>
+      import(`@/components/CameraContent-${Number(route.query.sceneIdx) + 1}-${Number(route.query.cameraIdx) + 1}-2.vue`)
+    )
+    CameraContent3 = defineAsyncComponent(() =>
+      import(`@/components/CameraContent-${Number(route.query.sceneIdx) + 1}-${Number(route.query.cameraIdx) + 1}-3.vue`)
+    )
+  }
+})
+
 
 const {
   windowSizeInCssForRef,
@@ -274,14 +342,40 @@ const currentCameraList = computed(() => {
 
 const mouseEnterCameraItemIdx = ref(-1)
 
+const sceneChangeEffectVideo1 = ref(null)
+const sceneChangeEffectVideo2 = ref(null)
+const isShowEffectVideo1 = ref(false)
+const isShowEffectVideo2 = ref(false)
+const isShowEffectCloud = ref(false)
 function onClickNextCamera() {
+  if (sceneIdx.value === 0) {
+    isShowEffectVideo1.value = true
+    setTimeout(() => {
+      sceneChangeEffectVideo1.value.play()
+    }, 1000)
+  } else if (sceneIdx.value === 1) {
+    isShowEffectVideo2.value = true
+    setTimeout(() => {
+      sceneChangeEffectVideo2.value.play()
+    }, 1000)
+  }
+}
+function onEffectVideoEnd() {
+  isShowEffectCloud.value = true
   router.push({
     name: route.name,
     query: {
-      sceneIdx: sceneIdx.value + 1,
-      cameraIdx: cameraIdx.value,
+      sceneIdx: Number(route.query.sceneIdx) + 1,
+      cameraIdx: 0,
     }
   })
+  setTimeout(() => {
+    isShowEffectVideo1.value = false
+    isShowEffectVideo2.value = false
+  }, 1000)
+  setTimeout(() => {
+    isShowEffectCloud.value = false
+  }, 2500)
 }
 
 /**
@@ -420,9 +514,9 @@ onMounted(() => {
 
 onBeforeRouteUpdate((to, from) => {
   console.log('to: ', to)
-  // if (to.name === route.name) {
-  //   loadScene(Number(to.query.sceneIdx), Number(to.query.cameraIdx))
-  // }
+  if (to.name === route.name) {
+    loadScene(Number(to.query.sceneIdx), Number(to.query.cameraIdx))
+  }
 })
 </script>
 
@@ -684,6 +778,87 @@ onBeforeRouteUpdate((to, from) => {
   >.camera-content{
     z-index: 10;
   }
+  >video.sceneChangeEffectVideo{
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background-color: black;
+    z-index: 11;
+  }
+
+  .cloud-top{
+    position: absolute;
+    width: 100%;
+    top: 0;
+    left: 0;
+    z-index: 12;
+  }
+  .cloud-top-enter-active {
+    transition: all 1.5s;
+  }
+  .cloud-top-leave-active {
+    transition: all 1.5s;
+    pointer-events: none;
+  }
+  .cloud-top-enter-from {
+    opacity: 0;
+    translate: 0 -100%;
+  }
+  .cloud-top-leave-to {
+    opacity: 0;
+    top: -50%;
+    translate: 0 -100%;
+  }
+
+  .cloud-left-bottom{
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    height: 70%;
+    z-index: 12;
+  }
+  .cloud-left-bottom-enter-active {
+    transition: all 1.5s;
+  }
+  .cloud-left-bottom-leave-active {
+    transition: all 1.5s;
+    pointer-events: none;
+  }
+  .cloud-left-bottom-enter-from {
+    opacity: 0;
+    translate: -100% 100%;
+  }
+  .cloud-left-bottom-leave-to {
+    opacity: 0;
+    pointer-events: none;
+    translate: -100% 100%;
+  }
+
+  .cloud-right-bottom{
+    position: absolute;
+    right: 0;
+    bottom: 0;
+    height: 95%;
+    z-index: 12;
+  }
+  .cloud-right-bottom-enter-active {
+    transition: all 1.5s;
+  }
+  .cloud-right-bottom-leave-active {
+    transition: all 1.5s;
+    pointer-events: none;
+  }
+  .cloud-right-bottom-enter-from {
+    opacity: 0;
+    translate: 100% 100%;
+  }
+  .cloud-right-bottom-leave-to {
+    opacity: 0;
+    pointer-events: none;
+    translate: 100% 100%;
+  }
 }
 @keyframes character-default-animation {
   0% {