|
@@ -1,11 +1,12 @@
|
|
|
-import { showToast, Toast } from "vant";
|
|
|
-import { reactive, watchEffect } from "vue";
|
|
|
+import { showToast } from "vant";
|
|
|
+import { reactive } from "vue";
|
|
|
import { OpenSheetMusicDisplay } from "../osmd-extended/src";
|
|
|
-import _event, { EventEnum } from "./helpers/eventemitter";
|
|
|
import { metronomeData } from "./helpers/metronome";
|
|
|
-import { GradualNote, GradualTimes, GradualVersion, IMode } from "./type";
|
|
|
-import { handleEndBegin, sendEvaluatingOffsetTime } from "./view/evaluating";
|
|
|
+import { GradualNote, GradualTimes, GradualVersion } from "./type";
|
|
|
+import { handleEndBegin, handleStartEvaluat, sendEvaluatingOffsetTime } from "./view/evaluating";
|
|
|
import { IFingering } from "src/view/fingering/fingering-config";
|
|
|
+import { handleStartTick } from "./view/tick";
|
|
|
+import { audioListStart, getAudioCurrentTime, getAudioDuration, setAudioCurrentTime, setAudioPlaybackRate } from "./view/audio-list";
|
|
|
|
|
|
/** 入门 | 进阶 | 大师 */
|
|
|
export type IDifficulty = "BEGINNER" | "ADVANCED" | "PERFORMER";
|
|
@@ -70,10 +71,6 @@ const state = reactive({
|
|
|
activeNoteIndex: 0,
|
|
|
/** 激活的小节 */
|
|
|
activeMeasureIndex: 0,
|
|
|
- /** 原音ref */
|
|
|
- songEl: null as unknown as HTMLAudioElement,
|
|
|
- /** 背景音乐ref */
|
|
|
- backgroundEl: null as unknown as HTMLAudioElement,
|
|
|
/** 选段状态 */
|
|
|
sectionStatus: false,
|
|
|
/** 选段数据 */
|
|
@@ -117,39 +114,14 @@ const state = reactive({
|
|
|
fixtime: 0,
|
|
|
/** 指法信息 */
|
|
|
fingeringInfo: {} as IFingering,
|
|
|
-
|
|
|
- repeatedBeats: 0,
|
|
|
-
|
|
|
- maskStatus: false,
|
|
|
- timesById: {} as any,
|
|
|
-
|
|
|
- activeTick: -1,
|
|
|
- activeTickRepeat: 1,
|
|
|
- showTick: false,
|
|
|
- isSpecialShapedScreen: false,
|
|
|
- notchHeight: 0,
|
|
|
- fixedKey: 0,
|
|
|
- renderLoading: false,
|
|
|
-
|
|
|
- isPauseRecording: false,
|
|
|
- feeShow: false,
|
|
|
- vipShow: false,
|
|
|
- mode: "contact" as IMode,
|
|
|
- activeSpeed: 90 as number, // 当前速度
|
|
|
- baseSpeed: 90 as number, // 基准速度
|
|
|
- activeDetail: null as any,
|
|
|
- // 是否跳过节拍器时间
|
|
|
- skipTick: false,
|
|
|
-
|
|
|
- sectionFlash: false,
|
|
|
- befireSection: null as any,
|
|
|
+ /** 滚动容器的ID */
|
|
|
+ scrollContainer: "musicAndSelection",
|
|
|
/** 是否是打击乐 */
|
|
|
isPercussion: false,
|
|
|
- isAppPlay: false, // 是否是app播放
|
|
|
- partListNames: [] as string[], // 当前曲谱中所有声部名字
|
|
|
-
|
|
|
- midiPlayIniting: false, // midi播放器是否初始化中
|
|
|
-
|
|
|
+ /** 是否重复节拍器的时间 */
|
|
|
+ repeatedBeats: 0,
|
|
|
+ /**当前曲谱中所有声部名字 */
|
|
|
+ partListNames: [] as string[],
|
|
|
/** 渐变速度信息 */
|
|
|
gradual: [] as GradualNote[],
|
|
|
/** 渐变速度版本 */
|
|
@@ -184,7 +156,7 @@ const setStep = () => {
|
|
|
export const onPlay = () => {
|
|
|
setStep();
|
|
|
if (state.modeType === "evaluating") {
|
|
|
- const currentTime = state.songEl?.currentTime || 0;
|
|
|
+ const currentTime = getAudioCurrentTime();
|
|
|
sendEvaluatingOffsetTime(currentTime);
|
|
|
}
|
|
|
};
|
|
@@ -209,32 +181,31 @@ export const onEnded = () => {
|
|
|
* 播放一直触发的事件
|
|
|
*/
|
|
|
const handlePlaying = (_item?: any) => {
|
|
|
- if (state.songEl) {
|
|
|
- const currentTime = state.songEl.currentTime;
|
|
|
- state.playProgress = (currentTime / state.songEl.duration) * 100;
|
|
|
- const item = _item ? _item : getNote(currentTime);
|
|
|
+ const currentTime = getAudioCurrentTime();
|
|
|
+ const duration = getAudioDuration();
|
|
|
+ state.playProgress = (currentTime / duration) * 100;
|
|
|
+ const item = _item ? _item : getNote(currentTime);
|
|
|
|
|
|
- if (item) {
|
|
|
- // 选段状态下
|
|
|
- if (state.sectionStatus && state.section.length === 2) {
|
|
|
- let startItemIndex = state.section[0].index;
|
|
|
- let startXmlIndex = state.section[0].MeasureNumberXML;
|
|
|
- // 开启预备拍
|
|
|
- if (state.sectionFirst) {
|
|
|
- startItemIndex = state.sectionFirst.i;
|
|
|
- startXmlIndex = state.sectionFirst.MeasureNumberXML;
|
|
|
- }
|
|
|
- if (item.MeasureNumberXML < startXmlIndex || item.MeasureNumberXML > state.section[1].MeasureNumberXML) {
|
|
|
- // console.log('选段播放结束')
|
|
|
- skipNotePlay(startItemIndex);
|
|
|
- return;
|
|
|
- }
|
|
|
+ if (item) {
|
|
|
+ // 选段状态下
|
|
|
+ if (state.sectionStatus && state.section.length === 2) {
|
|
|
+ let startItemIndex = state.section[0].index;
|
|
|
+ let startXmlIndex = state.section[0].MeasureNumberXML;
|
|
|
+ // 开启预备拍
|
|
|
+ if (state.sectionFirst) {
|
|
|
+ startItemIndex = state.sectionFirst.i;
|
|
|
+ startXmlIndex = state.sectionFirst.MeasureNumberXML;
|
|
|
+ }
|
|
|
+ if (item.MeasureNumberXML < startXmlIndex || item.MeasureNumberXML > state.section[1].MeasureNumberXML) {
|
|
|
+ // console.log('选段播放结束')
|
|
|
+ skipNotePlay(startItemIndex);
|
|
|
+ return;
|
|
|
}
|
|
|
- gotoNext(item);
|
|
|
}
|
|
|
-
|
|
|
- metronomeData.metro?.sound(currentTime);
|
|
|
+ gotoNext(item);
|
|
|
}
|
|
|
+
|
|
|
+ metronomeData.metro?.sound(currentTime);
|
|
|
};
|
|
|
/** 跳转到指定音符开始播放 */
|
|
|
export const skipNotePlay = (itemIndex: number, isStart = false) => {
|
|
@@ -245,8 +216,7 @@ export const skipNotePlay = (itemIndex: number, isStart = false) => {
|
|
|
}
|
|
|
// console.log("🚀 ~ itemTime:", itemTime);
|
|
|
if (item) {
|
|
|
- state.songEl && (state.songEl.currentTime = itemTime);
|
|
|
- state.backgroundEl && (state.backgroundEl.currentTime = itemTime);
|
|
|
+ setAudioCurrentTime(itemTime)
|
|
|
handlePlaying(item);
|
|
|
}
|
|
|
};
|
|
@@ -255,25 +225,24 @@ export const skipNotePlay = (itemIndex: number, isStart = false) => {
|
|
|
* 切换曲谱播放状态
|
|
|
* @param playState 可选: 默认 undefined, 需要切换的状态 play:播放, paused: 暂停
|
|
|
*/
|
|
|
-export const togglePlay = (playState?: "play" | "paused") => {
|
|
|
+export const togglePlay = async (playState?: "play" | "paused") => {
|
|
|
state.playState = playState ? playState : state.playState === "paused" ? "play" : "paused";
|
|
|
+ if (state.playState === "play" && state.needTick) {
|
|
|
+ const tickend = await handleStartTick();
|
|
|
+ // console.log("🚀 ~ tickend:", tickend)
|
|
|
+ }
|
|
|
if (state.playState == "play") {
|
|
|
// 如果没有选段结束开始播放,清空选段状态
|
|
|
if (state.sectionStatus && state.section.length < 2) {
|
|
|
clearSelection();
|
|
|
}
|
|
|
- state.songEl?.play();
|
|
|
- state.backgroundEl?.play();
|
|
|
- } else {
|
|
|
- state.songEl?.pause();
|
|
|
- state.backgroundEl?.pause();
|
|
|
}
|
|
|
+ audioListStart(state.playState);
|
|
|
};
|
|
|
/** 结束播放 */
|
|
|
export const handleStopPlay = () => {
|
|
|
state.playState = "paused";
|
|
|
- state.songEl?.pause();
|
|
|
- state.backgroundEl?.pause();
|
|
|
+ audioListStart(state.playState);
|
|
|
skipNotePlay(0, true);
|
|
|
};
|
|
|
|
|
@@ -345,8 +314,7 @@ export const handleSetSpeed = (speed: number) => {
|
|
|
console.log("🚀 ~ playbackRate:", speed, state.originSpeed);
|
|
|
|
|
|
// 按照比例设置速度
|
|
|
- state.songEl && (state.songEl.playbackRate = playbackRate);
|
|
|
- state.backgroundEl && (state.backgroundEl.playbackRate = playbackRate);
|
|
|
+ setAudioPlaybackRate(playbackRate);
|
|
|
};
|
|
|
/** 清除选段状态 */
|
|
|
export const clearSelection = () => {
|
|
@@ -399,7 +367,7 @@ export const handleSelection = (item: any) => {
|
|
|
state.sectionToast.message = "请选择结束小节";
|
|
|
}
|
|
|
};
|
|
|
-let offsetTop = 0
|
|
|
+let offsetTop = 0;
|
|
|
/**
|
|
|
* 窗口内滚动到音符的区域
|
|
|
* @param isScroll 可选: 强制滚动到顶部, 默认: false
|
|
@@ -407,9 +375,9 @@ let offsetTop = 0
|
|
|
*/
|
|
|
export const scrollViewNote = () => {
|
|
|
const cursorElement = document.getElementById("cursorImg-0")!;
|
|
|
- const musicAndSelection = document.getElementById("musicAndSelection")!;
|
|
|
+ const musicAndSelection = document.getElementById(state.scrollContainer)!;
|
|
|
if (!cursorElement || !musicAndSelection || offsetTop === cursorElement.offsetTop) return;
|
|
|
- offsetTop = cursorElement.offsetTop
|
|
|
+ offsetTop = cursorElement.offsetTop;
|
|
|
if (cursorElement.offsetTop > 50) {
|
|
|
musicAndSelection.scrollTo({
|
|
|
top: cursorElement.offsetTop - 25,
|
|
@@ -427,4 +395,13 @@ export const scrollViewNote = () => {
|
|
|
export const isRhythmicExercises = () => {
|
|
|
return state.examSongName.indexOf("节奏练习") > -1;
|
|
|
};
|
|
|
+
|
|
|
+/** 重置状态 */
|
|
|
+export const handleRessetState = () => {
|
|
|
+ if (state.modeType === "evaluating") {
|
|
|
+ handleStartEvaluat();
|
|
|
+ } else if (state.modeType === "practise") {
|
|
|
+ togglePlay("paused");
|
|
|
+ }
|
|
|
+};
|
|
|
export default state;
|