Explorar el Código

更新了main.js中的组件

aamin hace 1 año
padre
commit
ee5b1e69a1

BIN
public/configMultiMedia/music/music1.mp3


BIN
public/configMultiMedia/music/music2.mp3


BIN
src/assets/images/btn-start.png


BIN
src/assets/images/loading.png


BIN
src/assets/images/loding_apng.png


BIN
src/assets/images/startup-title.png


BIN
src/assets/video/startup.mp4


+ 88 - 0
src/components/LongImageSerialFrames.vue

@@ -0,0 +1,88 @@
+<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
+  },
+  loop: {
+    type: Boolean,
+    default: true,
+  }
+})
+
+const frameWidth = ref(props.totalWidth / props.frameNumber)
+console.assert(Number.isInteger(frameWidth.value), `序列帧的每帧宽度不是整数,可能导致播放时抖动!总宽度:${props.totalWidth},帧数:${props.frameNumber},每帧宽度:${frameWidth.value}`)
+
+const emit = defineEmits(['over'])
+
+const frameIdx = ref(0)
+let intervalId = null
+onMounted(() => {
+  intervalId = setInterval(() => {
+    frameIdx.value++
+    if (frameIdx.value === props.frameNumber) {
+      if (props.loop) {
+        frameIdx.value = 0
+      } else {
+        frameIdx.value--
+        clearInterval(intervalId)
+        emit('over')
+      }
+    }
+  }, props.frameDuration)
+})
+onBeforeUnmount(() => {
+  clearInterval(intervalId)
+})
+
+</script>
+
+<style lang="less" scoped>
+.single-long-image-serial-frames {
+  position: absolute;
+  overflow: hidden;
+  > .long-image {
+    position: absolute;
+    height: 100%;
+  }
+}
+</style>

+ 2 - 2
src/main.js

@@ -17,7 +17,7 @@ import VueLazyLoad from 'vue3-lazyload'
 // import OperationTip from '@/components/OperationTip.vue'
 // import HotspotComp from '@/components/HotspotComp.vue'
 // import HotspotForHomepage from '@/components/HotspotForHomepage.vue'
-// import SerialFrames from '@/components/LongImageSerialFrames.vue'
+import SerialFrames from '@/components/LongImageSerialFrames.vue'
 // import BtnSkip from '@/components/BtnSkip.vue'
 // import PaginationComp from '@/components/PaginationComp.vue'
 // import ProgressBar from '@/components/ProgressBar.vue'
@@ -94,7 +94,7 @@ app.use(store)
 //   .component('HotspotForHomepage', HotspotForHomepage)
 //   .component('Swiper', Swiper)
 //   .component('SwiperSlide', SwiperSlide)
-//   .component('SerialFrames', SerialFrames)
+  .component('SerialFrames', SerialFrames)
 //   .component('BtnSkip', BtnSkip)
 //   .component('PaginationComp', PaginationComp)
 //   .component('ProgressBar', ProgressBar)

+ 35 - 0
src/rollFu.js

@@ -0,0 +1,35 @@
+import { ref } from 'vue'
+export default function rollFu() {
+
+  let lastScrollTop = ref(0)
+  // 节流函数
+  function throttle(func, delay) {
+    let inThrottle
+    return function () {
+      const args = arguments
+      const context = this
+      if (!inThrottle) {
+        func.apply(context, args)
+        inThrottle = true
+        setTimeout(() => inThrottle = false, delay)
+      }
+    }
+  }
+
+  // 滚动事件处理器(传入滚动元素和前进后退函数)
+  const handleScroll = throttle(function (element, fu) {
+    const st = element.scrollTop
+    if (st > lastScrollTop.value) {
+      console.log('向下滚动')
+      fu(1)
+    } else {
+      console.log('向上滚动')
+      fu(-1)
+    }
+    lastScrollTop = st <= 0 ? 0 : st // For Firefox
+  }, 100)
+
+  return {
+    handleScroll
+  }
+}

+ 34 - 5
src/views/HomeView.vue

@@ -1,7 +1,16 @@
 <template>
-  <div
-    class="home"
-  >
+  <div class="home">
+    <!-- 背景 -->
+    <div
+      class="bg-mask"
+      :style="{ background: curPageIndex == 2 ? `rgba(85,116,83,0.8)` : `` }"
+    />
+    <!-- 开场动画 -->
+    <Transition name="fade-out">
+      <Startup
+        class="startup"
+      />
+    </Transition>
   </div>
 </template>
 
@@ -9,17 +18,37 @@
 import { ref, computed, watch, onMounted, inject } from "vue"
 import { useRoute, useRouter } from "vue-router"
 import { useStore } from "vuex"
+import Startup from "@/views/StartupView.vue"
+
 
 const route = useRoute()
 const router = useRouter()
 const store = useStore()
 
-const $env = inject('$env')
+const $env = inject("$env")
 </script>
 
 <style lang="less" scoped>
 .home {
   width: 100%;
   height: 100%;
+  > .bg-mask {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background: rgba(60, 89, 71, 0.65);
+    backdrop-filter: blur(
+      calc(
+        22 / v-bind("windowSizeWhenDesignForRef") *
+          v-bind("windowSizeInCssForRef")
+      )
+    );
+  }
+
+  > .startup {
+    z-index: 20;
+  }
 }
-</style>
+</style>

+ 192 - 0
src/views/StartupView.vue

@@ -0,0 +1,192 @@
+<template>
+  <div class="startup-view">
+    <span class="font-load-trigger">这是为了尽早触发字体文件加载</span>
+
+    <!-- 背景序列帧 -->
+    <!-- <SerialFrames
+      class="bg-serial-frames"
+      :image-src="require(`@/assets/images/serial-frame-startup.png`)"
+      :total-width="28800 / 900 * windowHeight"
+      :height="windowHeight"
+      :frame-number="48"
+      :frame-duration="1000 / 12"
+    /> -->
+
+    <!-- <img
+      class="bg-serial-frames"
+      src="@/assets/images/loding_apng.png"
+      alt=""
+      draggable="false"
+    > -->
+
+    <img
+      class="title"
+      src="@/assets/images/startup-title.png"
+      alt=""
+      draggable="false"
+    >
+
+    <Transition name="fade-in">
+      <img
+        v-if="isShowLoadingTip"
+        class="loading-tip"
+        src="@/assets/images/loading.png"
+        alt=""
+        draggable="false"
+      >
+    </Transition>
+    <SerialFrames
+      v-if="!isShowLoadingTip"
+      class="btn-start"
+      :class="isStartBtnBlink ? 'animation-show-hide' : ''"
+      :image-src="require(`@/assets/images/btn-start.png`)"
+      :total-width="864 / windowSizeWhenDesignForRef * windowSizeInCssForRef.substring(0, windowSizeInCssForRef.length - 2)"
+      :height="72 / windowSizeWhenDesignForRef * windowSizeInCssForRef.substring(0, windowSizeInCssForRef.length - 2)"
+      :frame-number="12"
+      :loop="false"
+      @over="isStartBtnBlink = true"
+      @click="onClickStart"
+    />
+
+    <Transition name="fade-in">
+      <video
+        v-show="isShowVideo"
+        ref="videoEl"
+        class="transition-video"
+        src="@/assets/videos/startup.mp4"
+        playsinline
+        webkit-playsinline="true"
+        x5-video-player-type="h5"
+        muted
+        @ended="onVideoEnd"
+      />
+    </Transition>
+    <Transition name="fade-in">
+      <BtnSkip
+        v-if="isShowSkip"
+        @click="onVideoEnd"
+      />
+    </Transition>
+  </div>
+</template>
+
+<script setup>
+import useSizeAdapt from "@/useFunctions/useSizeAdapt"
+import { ref, computed, watch, onMounted, inject, nextTick } from "vue"
+import { useRoute, useRouter } from "vue-router"
+import { useStore } from "vuex"
+import { useWindowSize } from '@vueuse/core'
+
+const route = useRoute()
+const router = useRouter()
+const store = useStore()
+
+const $env = inject('$env')
+
+const {
+  windowSizeInCssForRef,
+  windowSizeWhenDesignForRef,
+} = useSizeAdapt()
+
+const { width: windowWidth, height: windowHeight } = useWindowSize()
+
+
+const isShowLoadingTip = ref(true)
+setTimeout(() => {
+  isShowLoadingTip.value = false
+}, 3000)
+const isStartBtnBlink = ref(false)
+
+const isShowVideo = ref(false)
+const isShowSkip = ref(false)
+const videoEl = ref(null)
+function onClickStart() {
+  isShowVideo.value = true
+  const audioEl = document.getElementById('bg-music')
+  nextTick(() => {
+    videoEl.value.play()
+    if (window.location.href.includes('?m=1')) {
+      audioEl.src = './configMultiMedia/music/music2.mp3'
+      audioEl.play()
+    } else {
+      audioEl.play()
+    }
+  })
+  setTimeout(() => {
+    isShowSkip.value = true
+  }, 2000)
+}
+function onVideoEnd() {
+  store.dispatch('recordShownStartup')
+}
+</script>
+
+<style lang="less" scoped>
+.startup-view{
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  background-color: #fff;
+  background-image: url(@/assets/images/startup-bg.jpg);
+  background-size: cover;
+  background-repeat: no-repeat;
+  background-position: center center;
+  >.font-load-trigger{
+    pointer-events: none;
+    opacity: 0;
+    font-family: KaiTi;
+  }
+
+  >.bg-serial-frames{
+    position: absolute;
+    left: 50%;
+    top: 0;
+    transform: translateX(-50%);
+    mix-blend-mode: multiply;
+    width: 100%;
+    height: 100%;
+  }
+
+  >img.title{
+    position: absolute;
+    left: 50%;
+    top: 40%;
+    transform: translate(-50%, -50%);
+    width: calc(152 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+  }
+
+  >.loading-tip{
+    position: absolute;
+    left: 50%;
+    bottom: calc(70 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    transform: translateX(-48%);
+    width: calc(72 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(72 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+  }
+  >.btn-start{
+    position: absolute;
+    left: 50%;
+    bottom: calc(70 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    transform: translateX(-48%);
+  }
+
+  >video.transition-video{
+    position: absolute;
+    left: 50%;
+    top: 0;
+    height: 100%;
+    transform: translateX(-50%);
+  }
+
+  // @keyframes spin {
+  //   0% {
+  //     transform: translate(-50%, -50%) rotate(0deg);
+  //   }
+  //   100% {
+  //     transform: translate(-50%, -50%) rotate(360deg);
+  //   }
+  // }
+}
+</style>