Просмотр исходного кода

更新加载条 和兼容性处理

黄琪勇 1 год назад
Родитель
Сommit
49539cbd9b

+ 2 - 2
src/helpers/metronome.ts

@@ -179,8 +179,8 @@ class Metronome {
 	};
 	// 播放
 	playAudio = () => {
-		/* 如果是 评测模式且不为MIDI  不运行节拍器播放 */
-		if (state.modeType === "practise" && state.playMode !== "MIDI") {
+		/* 如果是 评测模式且不为MIDI并且节拍器资源加载成功的时候  不运行节拍器播放频*/
+		if (state.audioBetaDone && state.modeType === "practise" && state.playMode !== "MIDI") {
 			return
 		}
 		if (!metronomeData.initPlayerState || state.playState === 'paused') return;

+ 4 - 2
src/state.ts

@@ -445,6 +445,8 @@ const state = reactive({
   midiSectionStart: 0,
   /** 音频文件是否加载完成 */
   audioDone: false,
+  /** 节拍文件是否加载成功 */
+  audioBetaDone: false,
   /** 谱面svgdom节点 */
   osmdSvgDom: null as any,
   /** 滚动容器dom */
@@ -654,7 +656,7 @@ export const skipNotePlay = async (itemIndex: number, isStart = false) => {
 /* 还原音频源 */
 watch(()=>state.playState,()=>{
   // 播放之前  当为评测模式和不为MIDI时候按  是否禁用节拍器  切换音源
-  if (state.playState==='paused' && state.modeType === "practise" && state.playMode !== "MIDI") {
+  if (state.audioBetaDone && state.playState==='paused' && state.modeType === "practise" && state.playMode !== "MIDI") {
     console.log("还原音源")
     changeSongSourceByBate(true)
   }
@@ -670,7 +672,7 @@ export const togglePlay = async (playState?: "play" | "paused", sourceType?: str
     return
   }
   // 播放之前  当为评测模式和不为MIDI时候按  是否禁用节拍器  切换音源
-  if ((playState ? playState : state.playState === "paused" ? "play" : "paused") ==='play' && state.modeType === "practise" && state.playMode !== "MIDI") {
+  if (state.audioBetaDone && (playState ? playState : state.playState === "paused" ? "play" : "paused") ==='play' && state.modeType === "practise" && state.playMode !== "MIDI") {
     console.log("设置音源")
     changeSongSourceByBate(metronomeData.disable)
   }

BIN
src/view/audio-list/icon_loading_img.png


+ 61 - 0
src/view/audio-list/index.module.less

@@ -4,4 +4,65 @@
     bottom: 0;
     width: 100%;
     z-index: -1000000;
+}
+
+.loading {
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    z-index: 10000;
+    background: rgba(0, 0, 0, .6);
+}
+
+.loadingWrap {
+    position: relative;
+    width: 295px;
+    padding: 21px 17px;
+    background: rgba(135, 135, 135, .72);
+    border-radius: 24px;
+
+    .loadingIcon {
+        position: absolute;
+        left: 50%;
+        top: -35px;
+        transform: translateX(-50%);
+        width: 216px;
+    }
+
+    .loadingTip {
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        bottom: -35px;
+        color: #fff;
+        font-size: 13px;
+        font-weight: 400px;
+    }
+
+    :global {
+        .van-progress {
+            height: 7px;
+        }
+
+        .van-progress__portion {
+            background: linear-gradient(180deg, #3CD6F9 0%, #1CACF1 100%);
+            border: 1px solid rgba(255, 255, 255, .5);
+        }
+
+        .van-progress__pivot {
+            top: 0;
+            color: transparent;
+            background-color: transparent;
+            width: 35px;
+            height: 37px;
+            background-image: url('./image/icon_loading_head.png');
+            background-repeat: no-repeat;
+            background-size: 100% 100%;
+        }
+    }
 }

+ 67 - 49
src/view/audio-list/index.tsx

@@ -17,6 +17,7 @@ import Crunker from "../../utils/crunker"
 const crunker = new Crunker()
 import tickWav from "/src/assets/tick.mp3";
 import tockWav from "/src/assets/tock.mp3";
+import Loading from "./loading"
 
 export const audioData = reactive({
 	songEle: null as unknown as HTMLAudioElement,
@@ -233,11 +234,11 @@ export default defineComponent({
 				onEnded();
 			}
 		}
-
-		onMounted(async () => {
-			if (state.playMode !== "MIDI") {
-				/* 合并节拍到音频 */
-				const [musicBuff,accompanyBuff,tickWavBuff,tockWavBuff] = await crunker.fetchAudio(state.music+'?v='+Date.now(), state.accompany+'?v='+Date.now(), tickWav, tockWav)
+		// 合成节拍器音源
+		function loadMergeAudioBetas() {
+			console.time("音频加载时间")
+			return crunker.fetchAudio(state.music+'?v='+Date.now(), state.accompany+'?v='+Date.now(), tickWav, tockWav).then(([musicBuff,accompanyBuff,tickWavBuff,tockWavBuff])=>{
+				console.timeEnd("音频加载时间")
 				const beats:AudioBuffer[] = []
 				const beatsTime:number[] = []
 				metronomeData.metroMeasure.map(Measures=>{
@@ -251,47 +252,61 @@ export default defineComponent({
 				const musicBuffMeg = crunker.mergeAudioBuffers([musicBuff,...beats],[0,...beatsTime])
 				const accompanyBuffMeg = crunker.mergeAudioBuffers([accompanyBuff,...beats],[0,...beatsTime])
 				console.timeEnd("音频合并时间")
+				return [musicBuffMeg,accompanyBuffMeg]
+			}).then(([musicBuffMeg,accompanyBuffMeg])=>{
 				console.time("音频audioDom生成时间")
 				const musicAudio = crunker.exportAudioElement(musicBuffMeg)
 				const accompanyAudio = crunker.exportAudioElement(accompanyBuffMeg)
 				console.timeEnd("音频audioDom生成时间")
-				if (musicAudio) {
-					musicAudio.addEventListener("play", onPlay);
-					musicAudio.addEventListener("ended", onEnded);
-					accompanyAudio && (accompanyAudio.muted = true);
-				} else if (accompanyAudio) {
-					accompanyAudio.addEventListener("play", onPlay);
-					accompanyAudio.addEventListener("ended", onEnded);
-				}
-				Promise.all([createAudio(state.music), createAudio(state.accompany)]).then(
-					([music, accompany]) => {
-						state.audioDone = true;
-						// console.log(music, accompany);
-						if (music) {
-							audioData.songEle = music;
-						}
-						if (accompany) {
-							audioData.backgroundEle = accompany;
-						}
-						if (music) {
-							music.addEventListener("play", onPlay);
-							music.addEventListener("ended", onEnded);
-							accompany && (accompany.muted = true);
-						} else if (accompany) {
-							accompany.addEventListener("play", onPlay);
-							accompany.addEventListener("ended", onEnded);
-						}
-						Object.assign(audioData.songCollection,{
-							songEle:music,
-							backgroundEle:accompany,
-							beatSongEle:musicAudio,
-							bateBackgroundEle:accompanyAudio
-						})
+				return [musicAudio,accompanyAudio]
+			})
+		}
+		// 加载普通音源
+		function loadAudio(){
+			return Promise.all([createAudio(state.music), createAudio(state.accompany)])
+		}
+		onMounted(async () => {
+			if (state.playMode !== "MIDI") {
+				console.time("加载资源耗时")
+				// 不带节拍的音源
+				const [music, accompany] = await loadAudio()
+				try {
+					// 带节拍的音源
+					const [musicAudio,accompanyAudio] = await loadMergeAudioBetas()
+					console.log("音频合成成功66666666")
+					state.audioBetaDone = true;
+					if (musicAudio) {
+						musicAudio.addEventListener("play", onPlay);
+						musicAudio.addEventListener("ended", onEnded);
+						accompanyAudio && (accompanyAudio.muted = true);
+					} else if (accompanyAudio) {
+						accompanyAudio.addEventListener("play", onPlay);
+						accompanyAudio.addEventListener("ended", onEnded);
 					}
-				);
-
+					Object.assign(audioData.songCollection,{
+						songEle:music,
+						backgroundEle:accompany,
+						beatSongEle:musicAudio,
+						bateBackgroundEle:accompanyAudio
+					})
+				} catch (err) {
+					console.log("音频合成失败7777777:",err)
+				}
+				state.audioDone = true;
+				audioData.backgroundEle = accompany!;
+				audioData.songEle = music!;
+				if (music) {
+					music.addEventListener("play", onPlay);
+					music.addEventListener("ended", onEnded);
+					accompany && (accompany.muted = true);
+				} else if (accompany) {
+					accompany.addEventListener("play", onPlay);
+					accompany.addEventListener("ended", onEnded);
+				}
+				console.timeEnd("加载资源耗时")
 				api_playProgress(progress);
 			} else {
+				state.audioDone = true;
 				const songEndTime = state.times[state.times.length - 1 || 0]?.endtime || 0
 				audioData.duration = songEndTime
 				// 监听midi播放进度
@@ -307,16 +322,19 @@ export default defineComponent({
 
 		// console.log(state.playMode, state.midiUrl);
 		return () => (
-			<div class={styles.audioList}>
-				{state.playMode === "MIDI" && state.speed != 0 && (
-					<iframe
-						style={{ display: "none" }}
-						ref={midiRef}
-						src={`/midi/index.html`}
-						onLoad={handleLoad}
-					/>
-				)}
-			</div>
+			<>
+				<Loading/>
+				<div class={styles.audioList}>
+					{state.playMode === "MIDI" && state.speed != 0 && (
+						<iframe
+							style={{ display: "none" }}
+							ref={midiRef}
+							src={`/midi/index.html`}
+							onLoad={handleLoad}
+						/>
+					)}
+				</div>
+			</>
 		);
 	},
 });

+ 39 - 0
src/view/audio-list/loading.tsx

@@ -0,0 +1,39 @@
+import { defineComponent, ref } from "vue"
+import icon_loading_img from "./icon_loading_img.png"
+import { Progress } from "vant"
+import styles from "./index.module.less"
+import state from "/src/state"
+
+export default defineComponent({
+   name: "loading",
+   setup() {
+      function fakeLoadingProgress(duration = 2000, callback: (num: number) => void) {
+         let startTime = Date.now()
+         let progress = 0
+         const timer = setInterval(() => {
+            let timePassed = Date.now() - startTime
+            if (timePassed >= duration) {
+               clearInterval(timer)
+               callback(96) // 进度完成
+               return
+            }
+            progress = Math.min(100, (timePassed / duration) * 100)
+            callback(progress)
+         }, 300)
+      }
+      const loadingProress = ref(0)
+      fakeLoadingProgress(2000, num => {
+         loadingProress.value = num
+      })
+      return () =>
+         !state.audioDone && (
+            <div class={styles.loading}>
+               <div class={styles.loadingWrap}>
+                  <img class={styles.loadingIcon} src={icon_loading_img} />
+                  <Progress percentage={loadingProress.value} />
+                  <div class={styles.loadingTip}>音频资源加载中,请稍后</div>
+               </div>
+            </div>
+         )
+   }
+})