<template> <div class="loader-wrapper" :class="{ loaded: !loading, mask: maskReadyRef }" :style="visibleStyle" @touchmove.prevent @mousewheel.prevent > <div class="loader"> <p class="tip">{{tip}}</p> <p class="percent">{{percent}}%</p> <p class="progress"> <div :style="progressStyle"></div> </p> </div> <!-- <div class="loader-section section-top"></div> <div class="loader-section section-bottom"></div> --> <MaskVue ref="maskRef" @end="onEnd"/> <audio :src="entranceAudio" style="max-width: 1px;max-height: 1px;" ref="entranceAudioRef" ></audio> </div> </template> <script setup> import { computed, onMounted, ref, watch } from "vue" import MaskVue from "./Mask.vue"; const entranceAudio = './audios/entrance.mp3'; const props = defineProps({ tip: { type: String, default: 'loading...' }, percent: { type: Number, default: 0 }, loading: Boolean }) const elRef = ref(); const maskRef = ref(); const maskReadyRef = ref(false); const progressStyle = computed(() => ({ width: `${props.percent}%` })); const visibleStyle = ref({}) const entranceAudioRef = ref() const entranceAudioReady = ref(false) const onEnd = () => { visibleStyle.value = { display: 'none' } } const onTouchMove = (e) => { // 禁止滚动 e.preventDefault(); } const playMask = () => { if (maskReadyRef.value && entranceAudioReady.value) { entranceAudioRef.value.play(); maskRef.value.start(); } } watch(() => props.loading, (newVal, oldVal) => { if (oldVal && !newVal) { maskReadyRef.value = true; playMask(); } }) onMounted(() => { document.addEventListener("WeixinJSBridgeReady", function () { entranceAudioReady.value = true; playMask(); }, false); }) </script> <style lang="less" scoped> @bg-color: #D7DDD3; @tip-color: #933D33; @text-color: #fff; .loader-wrapper { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 100; overflow: hidden; background: @bg-color; .loader { display: block; position: relative; z-index: 11; color: @tip-color; font-size: 2em; text-align: center; padding-top: 200px; .percent { color: @text-color; } .progress { box-sizing: border-box; padding: 0 2em; & > div { width: 0%; height: 2px; background: @tip-color; border-radius: 50%; } } } .loader-section { position: fixed; left: 0; width: 100%; height: 51%; background: @bg-color; z-index: 10; } .section-top { top: 0; } .section-bottom { bottom: 0; } &.loaded.mask { // visibility: hidden; // transform: translateX(-100%); // transition: all 0.3s 1s ease-out; .loader { opacity: 0; transition: all 0.3s ease-out; } .section-top { transform: translateY(-100%); transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); } .section-bottom { transform: translateY(100%); transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); } } } </style>