Browse Source

feat: 跟练模式1.2

TIANYONG 1 year ago
parent
commit
506e0b034c

+ 1 - 0
src/page-instrument/header-top/index.tsx

@@ -83,6 +83,7 @@ export const headTopData = reactive({
         state.isSingleLine = true
         refreshMusicSvg()
       }
+      smoothAnimationState.isShow.value = false;
       toggleFollow();
     }
     headTopData.modeType = "show";

+ 5 - 1
src/state.ts

@@ -13,7 +13,7 @@ import { api_cloudGetMediaStatus, api_createMusicPlayer, api_cloudChangeSpeed, a
 import { verifyCanRepeat, getDuration } from "./helpers/formateMusic";
 import { getMusicSheetDetail } from "./utils/baseApi"
 import { getQuery } from "/src/utils/queryString";
-import { followData } from "/src/view/follow-practice/index"
+import { followData, skipNotePractice } from "/src/view/follow-practice/index"
 import { changeSongSourceByBate } from "/src/view/audio-list"
 import { moveSmoothAnimation, smoothAnimationState, moveSmoothAnimationByPlayTime, moveTranslateXNum, destroySmoothAnimation} from "/src/page-instrument/view-detail/smoothAnimation"
 import { storeData } from "/src/store";
@@ -679,6 +679,10 @@ export const skipNotePlay = async (itemIndex: number, isStart = false) => {
       audioData.progress = itemTime
       state.midiSectionStart = itemTime
     }
+    // 如果是跟练模式
+    if (followData.start) {
+      skipNotePractice()
+    }
   }
 };
 

+ 34 - 6
src/view/follow-practice/index.tsx

@@ -1,5 +1,5 @@
-import { defineComponent, onMounted, onUnmounted, reactive, ref } from "vue";
-import state, { gotoNext, resetPlaybackToStart, followBeatPaly } from "/src/state";
+import { defineComponent, onMounted, onUnmounted, reactive, ref, watch } from "vue";
+import state, { gotoNext, resetPlaybackToStart, followBeatPaly, skipNotePlay } from "/src/state";
 import { IPostMessage } from "/src/utils/native-message";
 import { api_cloudFollowTime, api_cloudToggleFollow } from "/src/helpers/communication";
 import { storeData } from "/src/store";
@@ -87,8 +87,10 @@ const onClear = () => {
 			note.classList.remove("follow-up", "follow-down", "follow-error", "follow-success");
 		}
 		const _note: HTMLElement = document.getElementById(`vf-${item.id}`)!;
+		const stemEl = document.getElementById(`vf-${item.id}-stem`);
 		if (_note) {
-			_note.classList.remove("follow-up", "follow-down");
+			_note.classList.remove("follow-up", "follow-down", "follow-success");
+			stemEl?.classList.remove("follow-up", "follow-down", "follow-success");
 		}
 	});
 };
@@ -213,8 +215,10 @@ const checked = () => {
 				startTime = 0;
 				followData.index = followData.index + 1;
 				setColor(item, "", true);
-				next();
-				checking = false;
+				setTimeout(() => {
+					next();
+					checking = false;
+				}, 3000);
 				return;
 			}
 		}
@@ -236,14 +240,38 @@ const setColor = (item: any, state: "follow-up" | "follow-down" | "", isRight =
 	}
 	const _note: HTMLElement = document.getElementById(`vf-${item.id}`)!;
 	if (_note) {
+		const stemEl = document.getElementById(`vf-${item.id}-stem`)
 		_note.classList.remove("follow-up", "follow-down");
-		state && _note.classList.add(state);
+		stemEl?.classList.remove("follow-up", "follow-down","follow-success");
+		if (state) {
+			_note.classList.add(state);
+			stemEl?.classList.add(state)
+		}
 		if (isRight) {
 			_note.classList.add("follow-success");
+			stemEl?.classList.add("follow-success")
 		}
 	}
 };
 
+// 进度跟练,点击某个音符开始跟练
+export const skipNotePractice = () => {
+	followData.index = state.activeNoteIndex
+	// 清除其它音符的错误提示
+	const noteFollows: HTMLElement[] = Array.from(document.querySelectorAll(".follow-error"));
+	noteFollows.forEach((noteFollow) => {
+		noteFollow?.classList.remove("follow-up", "follow-down", "follow-error");
+	})
+}
+
+// 移动到对应音符的位置
+watch(
+	() => followData.index,
+	() => {
+		skipNotePlay(followData.index);
+	}
+);
+
 export default defineComponent({
 	name: "follow",
 	setup() {

+ 6 - 4
src/view/selection/index.module.less

@@ -228,7 +228,7 @@
             color: rgba(255, 146, 0, 1) !important;
         }
 
-        .vf-note path {
+        path {
             fill: rgba(255, 146, 0, 1) !important;
             stroke: rgba(255, 146, 0, 1) !important;
         }
@@ -245,7 +245,7 @@
             color: rgba(255, 102, 166, 1) !important;
         }
 
-        .vf-note path {
+        path {
             fill: rgba(255, 102, 166, 1) !important;
             stroke: rgba(255, 102, 166, 1) !important;
         }
@@ -259,12 +259,14 @@
 
     .follow-success {
         display: block;
-
+        transform-box: fill-box;
+        transform-origin: center;
+        animation: noteAnimate 1s linear infinite;
         .van-icon-success {
             display: block;
             color: rgba(0, 255, 148, 1);
         }
-        .vf-note path {
+        path {
             fill: rgba(0, 255, 148, 1) !important;
             stroke: rgba(0, 255, 148, 1) !important;
         }

+ 1 - 1
src/view/selection/index.tsx

@@ -173,7 +173,7 @@ export default defineComponent({
 		};
 		/** 是否可以点击音符 */
 		const disableClickNote = computed(() => {
-			return state.sectionStatus || state.modeType !== "practise";
+			return state.sectionStatus || (state.modeType === "evaluating");
 		});
 		// 选段符号
 		const sectionPosData = computed(() => {