Explorar o código

Merge branch 'feature-tianyong-newVersion' into ktyq-test-new

TIANYONG hai 9 meses
pai
achega
aa8bb144c5

+ 2 - 2
instrument.html

@@ -53,11 +53,11 @@
   </script>
 
   <script type="module" src="/src/page-instrument/main.ts"></script>
-  <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
+  <!-- <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
   <script>
     // VConsole will be exported to `window.VConsole` by default.
     var vConsole = new window.VConsole();
-  </script>  
+  </script>   -->
 </body>
 
 </html>

+ 22 - 1
src/helpers/customMusicScore.ts

@@ -314,6 +314,10 @@ export const resetFormate = () => {
 		for (let i = 0; i < vftexts.length; i++) {
 			const _text = vftexts[i];
 			for (let j = 0; j < vftexts.length; j++) {
+				if (_text.textContent === 'second time only') {
+					// @ts-ignore
+					_text.style.transform = `translateY(15px)`;
+				}
 				if (_text.parentNode === vftexts[j].parentNode) continue;
 				const result = collisionDetection(_text as SVGAElement, vftexts[j] as SVGAElement);
 				if (result.isCollision) {
@@ -570,9 +574,26 @@ export const resetFormate = () => {
 		}
 
 	}
-	
+	if (!state.isCombineRender) {
+		transSinglePage();
+	}
 	// setTimeout(() => this.resetGlobalText());
 };
+
+// 一行谱时,五线谱/简谱的谱面staffLine,居中显示
+const transSinglePage = () => {
+	if (state.isSingleLine) {
+		const svgPage = document?.getElementById('osmdSvgPage1')?.getBoundingClientRect();
+		const staffLine = document?.querySelector('.staffline')?.getBoundingClientRect();
+		if (svgPage && staffLine && svgPage.height > 130) {
+			// 需要上移的距离
+			const needTransTop = (svgPage.height - staffLine.height) / 2;
+			// @ts-ignore
+			document.getElementById('osmdSvgPage1').style.transform = `translateY(-${needTransTop}px)`;
+		}
+	}
+}
+
 // 技巧文本
 const resetGlobalText = () => {
 	const svg = container.value.querySelector("svg");

+ 4 - 1
src/helpers/formateMusic.ts

@@ -1130,7 +1130,10 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			// console.log('relaEndtime',noteLength, relativeTime)
 			const fixedKey = note.fixedKey || 0;
 			// const svgElement = activeVerticalMeasureList[0]?.vfVoices["1"]?.tickables[si];
-			const svgElement = currenrtVfVoices?.tickables[staveNoteIndex];
+			//const svgElement = currenrtVfVoices?.tickables[staveNoteIndex];
+			// 过滤掉ghostnote
+			const filterTickables = currenrtVfVoices?.tickables?.filter((tickable: any) => tickable.attrs?.type !== "GhostNote")
+			const svgElement = filterTickables?.[staveNoteIndex];
 
 			// console.log('si',si,i)
 			// console.log(note.sourceMeasure.MeasureNumberXML,note,svgElement, NoteRealValue, measureLength)

+ 1 - 1
src/page-instrument/header-top/index.module.less

@@ -34,7 +34,7 @@
         height: 18px;
     }
     &.modeWarnRight {
-        left: "inherit";
+        left: inherit;
         right: 30px;
     }
 }

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

@@ -62,7 +62,7 @@ export default defineComponent({
                                 </div>
                         }
                         {
-                            state.isSingleLine && state.modeType === "practise" &&
+                            state.isSingleLine && state.modeType === "practise" && !state.isCombineRender && !state.isPercussion && 
                                 <div class={styles.cellBox}>
                                 <div class={styles.tit}>旋律线</div>
                                     <Switch v-model={smoothAnimationState.isShow.value}></Switch>

+ 20 - 6
src/page-instrument/simple-detail/index.tsx

@@ -1,5 +1,5 @@
 import { defineComponent, onMounted, onUnmounted, reactive, nextTick } from "vue";
-import state, { getMusicDetail, handleSetSpeed, addNoteBBox, getNote, gotoNext, fillWordColor } from "/src/state";
+import state, { getMusicDetail, handleSetSpeed, addNoteBBox, getNote, gotoNext, fillWordColor, moveSvgDom } from "/src/state";
 import MusicScore from "../../view/music-score";
 import styles from "./index.module.less";
 import { getQuery } from "/src/utils/queryString";
@@ -44,18 +44,32 @@ export default defineComponent({
 			if (resInfo?.api === "api_updateProgress") {
 				console.log('拖动的进度')
 				if (state.playState === 'paused') {
-					detailData.currentTime = resInfo?.content?.currentTime ? resInfo?.content?.currentTime : detailData.currentTime;
+					detailData.currentTime = resInfo?.content?.currentTime ?? detailData.currentTime;
+					// 坐标和小节都改为初始值
+					state.activeNoteIndex = 0
+					state.activeMeasureIndex = state.times[0].MeasureNumberXML;
 					handlePlaying(true);
 				}
 			}
 			// 播放进度
 			if (resInfo?.api === "api_playProgress") {
 				// console.log('播放进度',resInfo)
-				if (resInfo?.content?.currentTime) {
-					if (resInfo?.content?.currentTime < detailData.currentTime) {
+				const currentTime = resInfo?.content?.currentTime
+				if (currentTime) {
+					if (currentTime < detailData.currentTime) {
+						// 坐标和小节都改为初始值
 						state.activeNoteIndex = 0
+						let item = getNote(currentTime) || state.times[0];
+						if(item.i === state.activeNoteIndex){
+							state.activeMeasureIndex = item.MeasureNumberXML;
+						}
+						// 当拖动到MP3节拍器时候 需要手动移动到当前为止
+						const fixtime = state.times[0].fixtime
+						if(currentTime <= fixtime){
+							moveSvgDom(true)
+						}
 					}
-					detailData.currentTime = resInfo?.content?.currentTime
+					detailData.currentTime = currentTime
 				}
 			}
 		};
@@ -134,7 +148,7 @@ export default defineComponent({
 			//detailData.currentTime += 0.03
 			const currentTime = detailData.currentTime;
 			// console.log('👀~播放进度',currentTime)
-			let item = getNote(currentTime);
+			let item = getNote(currentTime) || state.times[0];
 			if (item) {
 				gotoNext(item, skipNote);
 			}

+ 3 - 2
src/page-instrument/view-detail/index.tsx

@@ -87,6 +87,7 @@ export const musicScoreRef = ref();
 export default defineComponent({
   name: "music-list",
   setup() {
+    const browsInfo = browser();
     const query: any = getQuery();
 
     const detailData = reactive({
@@ -105,7 +106,8 @@ export default defineComponent({
         // console.log("🚀 ~ screenData:", screenData.content);
         const { isSpecialShapedScreen, notchHeight } = screenData.content;
         if (isSpecialShapedScreen) {
-          detailData.paddingLeft = 25 + "px";
+          // 安卓取刘海值
+          detailData.paddingLeft = browsInfo.android ? notchHeight : 26 + "px";
         }
       }
     };
@@ -411,7 +413,6 @@ export default defineComponent({
         }
       }
     );
-    const browsInfo = browser();
     const handleOpenFignerView = () => {
       if (!query.modelType) {
         detailData.orientation = state.fingeringInfo.orientation || 0;

+ 6 - 1
src/page-instrument/view-detail/smoothAnimation/index.ts

@@ -81,6 +81,10 @@ export function initSmoothAnimation() {
    window.addEventListener("resize", calcClientWidth)
    // 初始化 只有练习模式 才显示
    state.modeType === "practise" && (smoothAnimationState.isShow.value = true)
+   // 多分轨合并显示、打击乐、节奏练习的曲子不显示旋律线
+   if (state.isCombineRender || state.isPercussion) {
+      smoothAnimationState.isShow.value = false
+   }
    console.log(smoothAnimationState, "一行谱小鸟数据")
 }
 
@@ -460,7 +464,8 @@ function createSmoothCurvePoints(pointsPos: pointsPosType, tension?: number, clo
  */
 function drawSmoothCurve(context: CanvasRenderingContext2D, pointsPos: pointsPosType, progresspointsPos?: pointsPosType) {
    context.lineWidth = 4
-   context.lineJoin = "round" // 优化锯齿
+   context.lineJoin = 'round';// 优化锯齿
+   context.lineCap = 'round'; // 优化锯齿
    context.strokeStyle = "rgba(255,255,255,0.6)"
    drawLines(context, pointsPos)
    if (progresspointsPos?.length) {

+ 1 - 1
src/page-instrument/view-evaluat-report/component/share-top/index.tsx

@@ -61,7 +61,7 @@ export default defineComponent({
       slow: "#FF7B00",
     };
     // console.log("🚀 ~ scoreData:", scoreData.value)
-    const itemType = ref<IItemType>("intonation");
+    const itemType = ref<IItemType>(state.isPercussion ? "cadence" : "intonation");
     /** 返回 */
     const handleBack = () => {
       api_back();

+ 3 - 3
src/state.ts

@@ -382,7 +382,7 @@ const state = reactive({
   /** 激活的note index */
   activeNoteIndex: 0,
   /** 激活的小节 */
-  activeMeasureIndex: 0,
+  activeMeasureIndex: -1,
   /** 选段状态 */
   sectionStatus: false,
   /** 选段数据 */
@@ -1591,7 +1591,7 @@ export const followBeatPaly = () => {
     metroTimer = null
     return;
   }
-  const time = state.measureTime * 1000 / metronomeData.totalNumerator
+  const time = state.measureTime * 1000 / metronomeData.totalNumerator / state.basePlayRate;
   requestAnimationFrame(() => {
     const endTime = Date.now();
     if (endTime - state.beatStartTime < time) {
@@ -1859,7 +1859,7 @@ watch(
 /** 刷新谱面 */
 export const refreshMusicSvg = () => {
   resetBaseRate();
-  state.activeMeasureIndex = 0;
+  state.activeMeasureIndex = -1;
   // 销毁旋律线
   destroySmoothAnimation()
   musicScoreRef.value?.refreshMusicScore()

+ 16 - 1
src/view/follow-practice/index.tsx

@@ -1,5 +1,5 @@
 import { defineComponent, onMounted, onUnmounted, reactive, ref, watch } from "vue";
-import state, { gotoNext, resetPlaybackToStart, followBeatPaly, skipNotePlay } from "/src/state";
+import state, { gotoNext, resetPlaybackToStart, followBeatPaly, skipNotePlay, initSetPlayRate } from "/src/state";
 import { IPostMessage } from "/src/utils/native-message";
 import { api_cloudFollowTime, api_cloudToggleFollow } from "/src/helpers/communication";
 import { storeData } from "/src/store";
@@ -119,6 +119,7 @@ export const handleFollowStart = async () => {
 		followData.start = true;
 		followData.index = 0;
 		followData.list = [];
+		initSetPlayRate();
 		resetPlaybackToStart();
 		openToggleRecord(true);
 		getNoteIndex();
@@ -138,6 +139,18 @@ export const handleFollowEnd = () => {
 	console.log("结束");
 };
 
+// 清除当前音符右侧的音符的颜色状态
+const clearRightNoteColor = () => {
+	const noteId = state.times[state.activeNoteIndex]?.id;
+	const leftVal = document.getElementById(`vf-${noteId}`)?.getBoundingClientRect()?.left || 0;
+	state.times.forEach((item: any) => {
+		const note: HTMLElement = document.getElementById(`vf-${item.id}`)!;
+		if (note?.getBoundingClientRect()?.left > leftVal) {
+			note.classList.remove("follow-up", "follow-down", "follow-error", "follow-success");
+		}
+	});
+}
+
 /**
  * 2024.6.17 新增自动结束跟练模式功能
  * 如果跟练模式,唱完了最后一个有频率的音符,需要自动结束掉跟练模式
@@ -156,6 +169,7 @@ const autoEndFollow = () => {
 		handleFollowEnd()
 		return
 	}
+	clearRightNoteColor();
 }
 
 // 下一个
@@ -265,6 +279,7 @@ export const skipNotePractice = () => {
 	noteFollows.forEach((noteFollow) => {
 		noteFollow?.classList.remove("follow-up", "follow-down", "follow-error");
 	})
+	clearRightNoteColor();
 }
 
 // 移动到对应音符的位置

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

@@ -117,7 +117,7 @@ export default defineComponent({
 			if (state.isSimplePage) {
 				osmd.EngravingRules.PageTopMargin = state.musicRenderType === 'staff' ? 0 : 3;
 				osmd.EngravingRules.PageTopMarginNarrow = 0;
-				osmd.EngravingRules.PageLeftMargin = 0;
+				osmd.EngravingRules.PageLeftMargin = 1;
 				osmd.EngravingRules.PageRightMargin = 0;
 				osmd.EngravingRules.BreathMarkDistance = 0.1; 
 				osmd.EngravingRules.PageBottomMargin = 0;
@@ -219,7 +219,7 @@ export default defineComponent({
 					isInTheGradualRange.value && styles.inGradualRange,
 					state.musicRenderType == EnumMusicRenderType.staff ? "staff" : "jianpuTone",
 					state.isSingleLine && "singleLineMusicBox",
-					!state.isCreateImg ? "blueMusicXml" : ""
+					(!state.isCreateImg && state.musicRenderType === EnumMusicRenderType.staff) ? "blueMusicXml" : ""
 				]}
 			>
 				{slots.default?.()}

+ 1 - 1
src/view/selection/index.module.less

@@ -258,7 +258,7 @@
     }
 
     .follow-success {
-        display: block;
+        // display: block;
         transform-box: fill-box;
         transform-origin: center;
         animation: noteAnimate 1s linear;

+ 2 - 2
src/view/tick/index.tsx

@@ -42,8 +42,8 @@ const tickPlayCb = (i: any, resolve: any, source: any) => {
 		return
 	};
 	tickData.index++;
-	// 当系统节拍器才播放声音
-	if (source && isUseSystemBeat.value) {
+	// 当系统节拍器才播放声音,跟练模式需要播放系统节拍器的声音,评测模式,如果没有伴奏,也需要播放系统节拍器的声音
+	if (source && (isUseSystemBeat.value || state.modeType === 'follow' || (state.modeType === 'evaluating' && !state.accompany)) ) {
 		const beatVolume = state.setting.beatVolume / 100
 		source.volume = beatVolume;
 		if (source.volume <= 0) {