Pārlūkot izejas kodu

Merge branch 'feature-tianyong' of http://git.dayaedu.com/tianyong/gym-music-score into hqyDev

黄琪勇 7 mēneši atpakaļ
vecāks
revīzija
d2c4ad7cbc

+ 3 - 1
src/constant/instruments.ts

@@ -201,7 +201,9 @@ const instruments: any = {
 	'Brake Drum': '闸鼓',
 	'Tam-tam': '大锣',
 	Cymbal: '镲',
-	Cymbals: '镲'
+	Cymbals: '镲',
+	Whip: '乐鞭',
+	whip: '乐鞭'
 };
 /** 获取分轨名称 */
 export const getInstrumentName = (name = '') => {

+ 2 - 0
src/constant/instrumentsClassfiy.ts

@@ -197,6 +197,8 @@ const instrumentsClassfiy: any = {
 		"Drums set",
 		"High Bongo",
 		"Timbales",
+		"Whip",
+		"whip"
 	],
 };
 

+ 10 - 0
src/page-instrument/custom-plugins/ExerciseStatistics/index.tsx

@@ -5,6 +5,7 @@ import request from "/src/utils/request";
 import { getSecondRPM } from "/src/utils";
 import state from '/src/state'
 import { headTopData } from "/src/page-instrument/header-top/index";
+import { followData } from "/src/view/follow-practice/index"
 
 // 练习统计
 export default defineComponent({
@@ -42,6 +43,15 @@ export default defineComponent({
                 handleStop()
             }
         })
+		// 监听跟练播放
+		watch(() => state.hasFollowResult, () => {
+			console.log('跟练录音11111',state.hasFollowResult,followData.start)
+            if (followData.practiceStart && state.hasFollowResult){
+                handleStart()
+            } else if (!followData.practiceStart) {
+                handleStop()
+            }
+        })		
 		onMounted(() => {
 			getTime();
 		});

+ 22 - 8
src/state.ts

@@ -595,6 +595,8 @@ const state = reactive({
   headTopHeight: 0,
   /** 是否是自动重播,练习模式开启自动重播时,播放前不需要再次计算播放倍率了,还是按照上次的播放倍率播放音频 */
   isAutoRePlay: false,
+  /** 跟练,是否收到了录音的回调 */
+  hasFollowResult: false,  
 });
 const browserInfo = browser();
 let offset_duration = 0;
@@ -639,7 +641,9 @@ export const onPlay = () => {
 /** 播放模式结束自动重播 */
 const autoResetPlay = () => {
   if (state.modeType !== "practise") return;
-  skipNotePlay(0, true);
+  // 如果是选段需要跳转到预备小节或者选段内的第一小节,否则跳转到第一小节
+  const targetIdx = state.section.length === 2 ? state.sectionFirst?.i || state.section[1].i : 0;
+  skipNotePlay(targetIdx, true);
   // 没有开启自动重播, 不是练习模式
   if (!state.setting.repeatAutoPlay) return;
   offsetTop = 0;
@@ -1356,7 +1360,7 @@ export const hanldeDirectSelection = (list: any[]) => {
     console.log('选段小节', state.section)
   }, 0);
 };
-let offsetTop = 0;
+let offsetTop = 0, musicScrollTop = 0;
 /**
  * 窗口内滚动到音符的区域
  * @param isScroll 可选: 强制滚动到顶部, 默认: false
@@ -1368,24 +1372,34 @@ export const scrollViewNote = (resetTop?: boolean) => {
     return;
   }
   const noteId = state.times[state.activeNoteIndex].id;
-  if (!noteId) {
-    return;
-  }
+  // if (!noteId) {
+  //   return;
+  // }
   const domId = "vf" + noteId;
-  const cursorElement: any = document.querySelector(`[data-vf=${domId}]`)?.parentElement;
+  // 合并休止小节没有音符,取小节的位置,否则取音符指针位置
+  const cursorElement: any = !noteId && state.times[state.activeNoteIndex]?.totalMultipleRestMeasures ? document.querySelector(`.measureIndex_${state.activeMeasureIndex}`) : document.querySelector(`[data-vf=${domId}]`)?.parentElement;
   const musicAndSelection = document.getElementById(state.scrollContainer)!;
   if (!state.headTopHeight) {
     state.headTopHeight = document.querySelector('.headHeight')?.getBoundingClientRect()?.height || 100;
   }
-  // console.log('滑动',cursorElement.offsetTop,offsetTop, cursorElement, )
-  if (!cursorElement || !musicAndSelection || offsetTop === cursorElement.offsetTop || Math.abs(offsetTop - cursorElement.offsetTop) < 30) return;
+  // console.log('滑动',musicAndSelection?.scrollTop, musicScrollTop)
+  if (!cursorElement || !musicAndSelection) {
+    return
+  }
+  if (Math.abs(musicAndSelection?.scrollTop - musicScrollTop) > 30) {
+    // 手动滑动谱面,重新播放需要滚动到对应位置
+  } else {
+    if (offsetTop === cursorElement.offsetTop || Math.abs(offsetTop - cursorElement.offsetTop) < 30) return;
+  }
   offsetTop = cursorElement.offsetTop;
   if (offsetTop > (state.headTopHeight + 30)) {
+    musicScrollTop = (offsetTop - state.headTopHeight - 30) * state.musicZoom
     musicAndSelection.scrollTo({
       top: (offsetTop - state.headTopHeight - 30) * state.musicZoom,
       behavior: "smooth",
     });
   } else {
+    musicScrollTop = 0
     musicAndSelection.scrollTo({
       top: 0,
       behavior: "smooth",

+ 2 - 0
src/view/follow-practice/index.tsx

@@ -115,6 +115,7 @@ export const handleFollowStart = async () => {
 		followData.practiceStart = false;
 	} else {
 		followData.dontAccredit = false;
+		state.hasFollowResult = true;
 		// 从头开始跟练,跟练模式开始前,增加播放系统节拍器
 		if (state.activeNoteIndex === 0) {
 			const tickend = await handleStartTick();
@@ -150,6 +151,7 @@ export const handleFollowEnd = () => {
 	onClear();
 	followData.start = false;
 	followData.practiceStart = false;
+	state.hasFollowResult = false
 	openToggleRecord(false);
 	followData.index = 0;
 	console.log("结束");

+ 3 - 2
src/view/music-score/index.tsx

@@ -1,5 +1,5 @@
 import { computed, defineComponent, onMounted, reactive, ref, onUnmounted } from "vue";
-import { formatXML, onlyVisible } from "../../helpers/formateMusic";
+import { formatXML, onlyVisible, getCustomInfo } from "../../helpers/formateMusic";
 // // @ts-ignore
 import { OpenSheetMusicDisplay } from "/osmd-extended/src";
 import state, { EnumMusicRenderType, IPlatform, resetCursorPosition } from "/src/state";
@@ -73,7 +73,8 @@ export default defineComponent({
 				downloadXmlStr.value = await fetch(state.xmlUrl).then((response) => response.text())
 			}
 			const xmlStr = downloadXmlStr.value;
-			const xml = formatXML(xmlStr);
+			const parseXmlInfo = getCustomInfo(xmlStr);
+			const xml = formatXML(parseXmlInfo.parsedXML);
 			musicData.score = state.isCombineRender ? xml : onlyVisible(xml, state.partIndex);
 			if (state.gradualTimes) {
 				state.gradual = getGradualLengthByXml(xml);

+ 2 - 0
src/view/selection/index.tsx

@@ -147,6 +147,7 @@ export default defineComponent({
 							selectData.measureHeight = staveBbox.height
 							let compareVal = staveBbox.height - minMeasureHeigt
 							compareVal = compareVal > 0 ? compareVal : 0
+							selectData.measureHeight = staveBbox.height - compareVal
 							noteItem.staveBox = {
 								left: staveBbox.x - parentLeft + "px",
 								// top: ((item.stave.y || 0) - 5) * state.zoom + "px",
@@ -309,6 +310,7 @@ export default defineComponent({
 											styles.position,
 											// scoreItem ? `scoreItemLeve${scoreItem.leve}` : "", // 去掉评测小节得分的背景色
 											(state.platform === IPlatform.PC && state.zoom > 0.8) ? styles.linePC : '',
+											`measureIndex_${item.MeasureNumberXML}`
 										]}
 										style={item.staveBox}
 										onClick={() => handleSelection(item)}