Browse Source

绘画列表页 序列帧

任一存 1 year ago
parent
commit
4268b9909a

BIN
public/configMultiMedia/paintings-small/墨竹图(一).jpg


BIN
public/configMultiMedia/paintings-small/潇湘竹石图(竹石部分).jpg


BIN
public/configMultiMedia/paintings-thumb/墨竹图(一).jpg


BIN
public/configMultiMedia/paintings-thumb/潇湘竹石图(竹石部分).jpg


BIN
public/configMultiMedia/paintings/墨竹图(一).jpg


BIN
public/configMultiMedia/paintings/潇湘竹石图(竹石部分).jpg


BIN
src/assets/images/home-painting-leaf.png


BIN
src/assets/images/home-painting-stem.png


BIN
src/assets/images/home-painting-stone.png


BIN
src/assets/images/serial-frame-painting-list-bottom.png


BIN
src/assets/images/serial-frame-painting-list-top.png


+ 77 - 0
src/components/LongImageSerialFrames.vue

@@ -0,0 +1,77 @@
+<template>
+  <div
+    class="single-long-image-serial-frames"
+    :style="{
+      width: frameWidth + 'px',
+      height: props.height + 'px',
+    }"
+  >
+    <img
+      class="long-image"
+      :style="{
+        left: `calc(-${frameWidth}px * ${frameIdx})`,
+      }"
+      :src="props.imageSrc"
+      alt=""
+      draggable="false"
+      @dragstart.prevent
+    >
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onBeforeUnmount } from 'vue'
+
+const props = defineProps({
+  imageSrc: {
+    type: String,
+    required: true,
+  },
+  totalWidth: {
+    type: Number,
+    required: true,
+  },
+  height: {
+    type: Number,
+    required: true,
+  },
+  frameNumber: {
+    type: Number,
+    required: true,
+  },
+  frameDuration: {
+    type: Number,
+    default: 41
+  },
+})
+
+const frameWidth = ref(props.totalWidth / props.frameNumber)
+console.assert(Number.isInteger(frameWidth.value), `序列帧的每帧宽度不是整数,会导致播放时抖动!总宽度:${props.totalWidth},帧数:${props.frameNumber},每帧宽度:${frameWidth.value}`)
+
+const frameIdx = ref(0)
+let intervalId = null
+onMounted(() => {
+  intervalId = setInterval(() => {
+    frameIdx.value++
+    if (frameIdx.value === props.frameNumber) {
+      frameIdx.value = 0
+    }
+  }, props.frameDuration)
+})
+onBeforeUnmount(() => {
+  clearInterval(intervalId)
+})
+
+</script>
+
+<style lang="less" scoped>
+.single-long-image-serial-frames {
+  position: absolute;
+  overflow: hidden;
+  pointer-events: none;
+  > .long-image {
+    position: absolute;
+    height: 100%;
+  }
+}
+</style>

+ 2 - 0
src/main.js

@@ -17,6 +17,7 @@ import 'swiper/css/pagination' // 分页器样式
 import BtnBack from '@/components/BtnBack.vue'
 import OperationTip from '@/components/OperationTip.vue'
 import HotspotComp from '@/components/HotspotComp.vue'
+import SerialFrames from '@/components/LongImageSerialFrames.vue'
 
 console.log(`version: ${process.env.VUE_APP_VERSION}`)
 console.log(`Build time: ${process.env.VUE_APP_UPDATE_TIME}`)
@@ -87,6 +88,7 @@ app.use(store)
   .component('HotspotComp', HotspotComp)
   .component('Swiper', Swiper)
   .component('SwiperSlide', SwiperSlide)
+  .component('SerialFrames', SerialFrames)
   .mount('#app')
 
 //  you can reset the default options at any other time

+ 22 - 12
src/views/HomeView.vue

@@ -73,9 +73,7 @@
       >
       <img
         class="painting"
-        :style="{
-          opacity: 1 - Math.max(stemOpacity * 0.5, leafOpacity * 0.5, stoneOpacity * 0.5),
-        }"
+
         src="@/assets/images/home-painting.jpg"
         alt=""
         draggable="false"
@@ -124,7 +122,7 @@
       <HotspotComp
         v-show="isShowHotspot"
         class="hotspot-2"
-        @click="isShowPaintingDetail = true"
+        @click="showBigPainting"
       />
       <HotspotComp
         v-show="isShowHotspot"
@@ -215,7 +213,7 @@
         @close="isShowHotspotDetail1 = false"
       />
     </Transition>
-    <Transition name="fade-in-out">
+    <!-- <Transition name="fade-in-out">
       <PaintingDetail
         v-if="isShowPaintingDetail"
         :thumb="require(`@/assets/images/home-painting.jpg`)"
@@ -231,7 +229,7 @@
         class="hotspot-detail painting-detail"
         @close="isShowPaintingDetail = false"
       />
-    </Transition>
+    </Transition> -->
     <Transition name="fade-in-out">
       <HotspotDetail3
         v-if="isShowHotspotDetail3"
@@ -243,14 +241,15 @@
 </template>
 
 <script setup>
-import { ref, computed, watch, onMounted, inject } from "vue"
+import { ref, computed, watch, onMounted, inject, onBeforeUnmount } from "vue"
 import { useRoute, useRouter } from "vue-router"
 import { useStore } from "vuex"
 import Startup from '@/views/StartupView.vue'
 import useSizeAdapt from "@/useFunctions/useSizeAdapt"
 import HotspotDetail1 from '@/views/HotspotDetail1.vue'
-import PaintingDetail from '@/views/PaintingDetail.vue'
+// import PaintingDetail from '@/views/PaintingDetail.vue'
 import HotspotDetail3 from '@/views/HotspotDetail3.vue'
+import { api as viewerApi } from 'v-viewer'
 
 const route = useRoute()
 const router = useRouter()
@@ -272,10 +271,14 @@ const summaryDesc = configText.homepagePaintingSummary
 
 const scrollerEl = ref(null)
 const scrollerElScrollTop = ref(0)
+function onScroll() {
+  scrollerElScrollTop.value = scrollerEl.value.scrollTop
+}
 onMounted(() => {
-  scrollerEl.value.addEventListener('scroll', (e) => {
-    scrollerElScrollTop.value = scrollerEl.value.scrollTop
-  })
+  scrollerEl.value.addEventListener('scroll', onScroll)
+})
+onBeforeUnmount(() => {
+  scrollerEl.value.addEventListener('scroll', onScroll)
 })
 
 const isShowOperationTip = ref(true)
@@ -429,8 +432,15 @@ const isShowHotspot = computed(() => {
 })
 
 const isShowHotspotDetail1 = ref(false)
-const isShowPaintingDetail = ref(false)
+// const isShowPaintingDetail = ref(false)
 const isShowHotspotDetail3 = ref(false)
+
+function showBigPainting() {
+  viewerApi({
+    images: [require(`@/assets/images/home-painting-big.jpg`)],
+  })
+}
+
 </script>
 
 <style lang="less" scoped>

+ 32 - 0
src/views/PaintingList.vue

@@ -2,6 +2,24 @@
   <div
     class="painting-list"
   >
+    <!-- 背景图 -->
+    <SerialFrames
+      class="bg-serial-frames-top"
+      :image-src="require(`@/assets/images/serial-frame-painting-list-top.png`)"
+      :total-width="19404"
+      :height="1272"
+      :frame-number="33"
+      :frame-duration="50"
+    />
+    <SerialFrames
+      class="bg-serial-frames-bottom"
+      :image-src="require(`@/assets/images/serial-frame-painting-list-bottom.png`)"
+      :total-width="19404"
+      :height="1272"
+      :frame-number="33"
+      :frame-duration="50"
+    />
+
     <ul
       ref="menuEl"
     >
@@ -255,6 +273,20 @@ watch(menuElScrollLeft, (v) => {
   width: 100%;
   height: 100%;
   background-color: rgba(121, 143, 108, 1);
+  >.bg-serial-frames-top{
+    position: absolute;
+    top: 0;
+    right: 0;
+    transform: translate(0, 0) scale(0.6);
+    transform-origin: top right;
+  }
+  >.bg-serial-frames-bottom{
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    transform: translate(-62%, 11%) scale(1);
+    transform-origin: bottom left;
+  }
   >ul{
     position: absolute;
     left: 0;