Ver Fonte

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

TIANYONG há 6 meses atrás
pai
commit
61ea581024

+ 6 - 5
src/helpers/calcSpeed.ts

@@ -1,4 +1,5 @@
 import { OpenSheetMusicDisplay, SourceMeasure } from "/osmd-extended/src";
+import { onlyVisible } from "/src/helpers/formateMusic";
 
 export const noteDuration = {
 	"1/2": 2,
@@ -113,8 +114,8 @@ export type GradualItem = {
  * @param xml 始终按照第一分谱进行减慢速度的计算
  */
 export const getGradualLengthByXml = (xml: string) => {
-	// const firstPartXml = onlyVisible(xml, 0)
-	const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
+	const firstPartXml = onlyVisible(xml, 0)
+	const xmlParse = new DOMParser().parseFromString(firstPartXml, "text/xml");
 	const measures = Array.from(xmlParse.querySelectorAll("measure"));
 	const notes = Array.from(xmlParse.querySelectorAll("note"));
 	const words = Array.from(xmlParse.querySelectorAll("words"));
@@ -159,13 +160,13 @@ export const getGradualLengthByXml = (xml: string) => {
 	// 结尾处手动插入一个音符节点
 	eles.push({
 		ele: notes[notes.length - 1],
-		index: notes.length,
+		index: notes.length-1,
 		noteInMeasureIndex: 0,
 		textContent: "",
 		type: "metronome",
 		allDuration: 1,
-		leftDuration: 1,
-		measureIndex: measures.length,
+		leftDuration: 0,
+		measureIndex: measures.length-1,
 	});
 
 	const gradualNotes: GradualNote[] = [];

+ 49 - 8
src/helpers/customMusicScore.ts

@@ -268,6 +268,18 @@ export const limitSingleSvgPageHeight = () => {
 
 }
 
+const isElementInViewport = (el: any) => {
+    const rect = el.getBoundingClientRect();
+    return (
+        rect.top >= 0 &&
+        rect.left >= 0 &&
+        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
+        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
+    );
+}
+const isNumeric = (str: any) => {
+	return /^\d+$/.test(str);
+  }
 // 谱面优化
 export const resetFormate = () => {
 	container.value = document.getElementById('scrollContainer')
@@ -296,14 +308,23 @@ export const resetFormate = () => {
 		const paths: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure > .vf-stave path"));
 		const dotModifiers: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure .vf-stopDot"));
 		const staves: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure > .vf-stave"));
+		const numberVfTexts = Array.from((container.value as HTMLElement).querySelectorAll(".vf-text > text")); 
 
 		// 获取第一个线谱的y轴坐标
 		const firstLinePathY = paths[0]?.getBBox().y || 0
+		// D.C循环标记没有显示完全修复
 		// 反复标记 和 小节碰撞
-		const repetWord = ["To Coda", "D.S. al Coda", "Coda"];
+		const repetWord = ["To Coda", "D.S. al Coda", "Coda", "D.C."];
 		texts
 			.filter((n) => repetWord.includes(n.textContent || ""))
 			.forEach((t) => {
+				// console.log('文本123',t.textContent,'是否在可视区域内',isElementInViewport(t))
+				// D.C循环标记不在可视区域内,需要修复移动其位置信息
+				if (t.textContent?.includes('D.C')) {
+					if (!isElementInViewport(t)) {
+						t.style.transform = `translateX(-40px)`;
+					}
+				}
 				vfbeams.forEach((curve) => {
 					const result = collisionDetection(t, curve);
 					const prePath: SVGAElement = t?.previousSibling as unknown as SVGAElement;
@@ -430,13 +451,14 @@ export const resetFormate = () => {
 				label.textContent = labelText.replace('#','♯')
 			}
 		});
-		dotModifiers.forEach((group: any) => {
-			if (state.musicRenderType === 'fixedTone') {
-				group.setAttribute('transform', 'translate(3,-12)')
-			} else {
-				group.setAttribute('transform', 'translate(3,-7)')
-			}
-		});
+		// numberVfTexts.forEach((label: any) => {
+		// 	const labelText = label.textContent as string
+		// 	if (isNumeric(labelText)) {
+		// 		const _y = Number(label.getAttribute("y"))
+		// 		const endY = firstLinePathY ? firstLinePathY - musicalDistance : _y
+		// 		label.setAttribute("y", endY)
+		// 	}
+		// })
 		const vftextBottom = Array.from(staffline.querySelectorAll(".vf-text > text")).filter((n: any) => n.getBBox().y > stafflineCenter);
 		const vflineBottom = Array.from(staffline.querySelectorAll(".vf-line")).filter((n: any) => n.getBBox().y > stafflineCenter);
 		// 去重
@@ -614,6 +636,25 @@ export const resetFormate = () => {
 			state.vfmeasures = state.vfmeasures.concat(vfmeasures);
 		}
 
+		dotModifiers.forEach((group: any) => {
+			let parent = group?.parentElement; // 获取父元素
+			// 如果需要找更外层的祖先元素,可以一直迭代
+			while (parent && !parent.classList?.contains('vf-measure') && parent.tagName !== 'body' && parent) { // 假设你想找到最外层的 DIV
+				parent = parent.parentElement;
+			}
+			const parentY = parent?.querySelector('.vf-custom-bg').getBoundingClientRect()?.y || 0;
+			const dotY = group?.getBoundingClientRect()?.y || 0;
+			const distanceY = parentY - dotY;
+			const translateY = 15 - distanceY;
+			// console.log('距离111',translateY)
+			group.setAttribute('transform', `translate(3,${-translateY})`)
+			// if (state.musicRenderType === 'fixedTone') {
+			// 	// group.setAttribute('transform', 'translate(3,-12)')
+			// } else {
+			// 	// group.setAttribute('transform', 'translate(3,-7)')
+			// }
+		});
+
 	}
 	if (!state.isCombineRender && state.isSingleLine) {
 		transSinglePage();

+ 15 - 9
src/helpers/formateMusic.ts

@@ -826,7 +826,6 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 	let multipleRestMeasures = 0;
 	let staveNoteIndex = 0;
 	let staveIndex = 0;
-	let xmlNoteTime = 0  // xml上面的音符时间
 	let xmlMp3BeatFixTime = 0 // xml上节拍器的时间
 
 	let preNoteEndTime = 0; // 上一个音符的结束时间
@@ -1122,8 +1121,8 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 					// 范围内小节
 					const inFiestOrLastMeasure = first.closedMeasureIndex !== measureListIndex && last.closedMeasureIndex !== measureListIndex;
 					if (inTheFirstMeasure || inTheLastMeasure || inFiestOrLastMeasure) {
-						const startTime = state.gradualTimes[first.measureIndex];
-						const endTime = state.gradualTimes[last.measureIndex];
+						const startTime = state.gradualTimes[first.measureIndex+1];
+						const endTime = state.gradualTimes[last.measureIndex+1];
 						if (startTime && endTime) {
 							const times = continuous - first.leftDuration / first.allDuration + last.leftDuration / last.allDuration;
 							const diff = dayjs(tranTime(endTime)).diff(dayjs(tranTime(startTime)), "millisecond");
@@ -1264,9 +1263,8 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 				const allowRange = Math.abs(_notes[idx+1]?.note?.noteTimeInfo?.[0]?.begin - _notes[idx-1]?.note?.noteTimeInfo?.[0]?.end) < 10;
 				if (allowRange) {
 					note.maxNoteNum = note.maxNoteNum - 1;
-					// 唱名时间补齐,唱名上一个音符的结束时候,也需要补上这个时间
-					allNotes[allNotes.length-1].xmlNoteEndTime = retain(xmlNoteTime + noteLength)
-					xmlNoteTime += noteLength
+					// 唱名时间补齐,当删除这个音符的时候,上个音符的持续时间要加上这个音符的时间
+					allNotes[allNotes.length - 1].noteLengthTime += noteLength
 					continue;
 				}
 			}
@@ -1348,14 +1346,14 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 				maxNoteNum: note.maxNoteNum, // 当前小节音符最多的分轨的音符数量
 				// repeatIdx: iterator.repeatIdx || 0, // 标记是第几遍循环,从0开始
 				repeatIdx: filterRepeatIdx,
-				xmlNoteTime: retain(xmlNoteTime), // xml上音符开始时间 唱名用
-				xmlNoteEndTime: retain(xmlNoteTime + noteLength), //xml上音符结束时间 唱名用
+				noteLengthTime: noteLength, //当前音符时长
+				xmlNoteTime: 0, // xml上音符开始时间 唱名用
+				xmlNoteEndTime: 0, //xml上音符结束时间 唱名用
 				xmlMp3BeatFixTime,  //xml上节拍器的时间
 				notBeatFixtime: state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime, // 不含节拍器的fixtime值 唱名用
 				notBeatTime: state.isEvxml && evNoteStartTime ? retain(evNoteStartTime) : retain(relativeTime + (state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime)), // 不含节拍器的 音符开始时间
 				notBeatEndTime: state.isEvxml && evNoteEndTime ? retain(evNoteEndTime) : retain(relaEndtime + (state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime)) // 不含节拍器的 音符结束时间
 			};
-			xmlNoteTime += noteLength
 			// 如果是妙极客的曲子,并且第二遍循环播放需要等待时间,并且是第二遍循环的第一个小节的第一个音符
 			// if (state.isEvxml && state.secondEvXmlBeginTime && nodeDetail.i > 0 && nodeDetail.MeasureNumberXML === 1 && nodeDetail.noteId === 0) {
 			// 	nodeDetail.time = nodeDetail.time + state.secondEvXmlBeginTime;
@@ -1415,6 +1413,14 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 	const sortArray = allNotes.sort((a, b) => a.relativeTime - b.relativeTime).map((item, index) => Object.assign(item,{i:index}));
 	// const sortArray = allNotes.sort((a, b) => a.time - b.time).map((item, index) => ({ ...item, i: index }));
 	// const sortArray = allNotes.map((item, index) => ({ ...item, i: index }));
+	// 给 xmlNoteTime 和 xmlNoteEndTime 赋值
+	let xmlNoteTime = 0
+	sortArray.map(item => {
+		const noteLengthTime = item.noteLengthTime
+		item.xmlNoteTime = retain(xmlNoteTime)
+		item.xmlNoteEndTime = retain(xmlNoteTime + noteLengthTime)
+		xmlNoteTime += noteLengthTime
+	})
 	console.timeEnd("音符跑完时间");
 	try {
 		osmd.cursor.reset();

+ 2 - 2
src/page-instrument/header-top/index.tsx

@@ -156,7 +156,7 @@ function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPla
   // 演奏向演唱切
   if (oldPlayType === "play" && playType === "sing") {
     if (playSource === "mingSong") {
-      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间
+      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间  注意这修改了之后给总控平台的时值也需要改
       state.fixtime = difftime;
       state.times.map((item) => {
         item.time = item.xmlNoteTime + difftime;
@@ -228,7 +228,7 @@ function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPla
     // 演唱之间切换
     // 切到唱名时候
     if (playSource === "mingSong") {
-      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间
+      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间  注意这修改了之后给总控平台的时值也需要改
       state.fixtime = difftime;
       state.times.map((item) => {
         item.time = item.xmlNoteTime + difftime;

+ 8 - 7
src/page-instrument/view-detail/index.tsx

@@ -250,7 +250,7 @@ export default defineComponent({
       // 需要向外面(iframe)派发计时器数据的时候触发
       if (query.isbeatTimes) {
         const { isOpenMetronome, isSingOpenMetronome } = state;
-        const { xmlMp3BeatFixTime } = state.times[0];
+        const { xmlMp3BeatFixTime, difftime } = state.times[0];
         const singBeatTime: number[][] = [];
         const beatTime = metronomeData.metroMeasure.map((metroMeasure) => {
           const singBeat: number[] = [];
@@ -268,11 +268,11 @@ export default defineComponent({
           return beatTimeItem;
         });
         //改为唱名
-        state.fixtime = 0;
+        state.fixtime = difftime;
         state.times.map((item) => {
-          item.time = item.xmlNoteTime;
-          item.endtime = item.xmlNoteEndTime;
-          item.fixtime = 0;
+          item.time = item.xmlNoteTime + difftime;
+          item.endtime = item.xmlNoteEndTime + difftime;
+          item.fixtime = difftime;
         });
         metronomeData.metro.calculation(state.times);
         const mingBeatTime: number[][] = metronomeData.metroMeasure.map((metroMeasure) => {
@@ -281,11 +281,12 @@ export default defineComponent({
           });
           return beatTimeItem;
         });
-        console.log("webApi_beatTimes", { beatTime, singBeatTime, mingBeatTime });
+        const webApi_beatTimes = { beatTime, singBeatTime, mingBeatTime, isBeatTime:!state.evXmlBeginArr.length, isSingBeatTime:!state.evXmlBeginArr.length, isMingBeatTime:!state.evXmlBeginArr.length }
+        console.log("webApi_beatTimes", webApi_beatTimes);
         window.parent.postMessage(
           {
             api: "webApi_beatTimes",
-            data: JSON.stringify({ beatTime, singBeatTime, mingBeatTime }),
+            data: JSON.stringify(webApi_beatTimes),
           },
           "*"
         );

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

@@ -368,7 +368,7 @@ function getPointsPosByBatePos(): pointsPosType {
    const frequencyLineData = quantileScale(frequencyData, 8, _canvasDomHeight - 8) // 最小值和最大值
    const pointsPos = state.times.reduce((posArr: any[], item, index) => {
       // 当休止小节,可能当前音符在谱面上没有实际的音符(没有bbox)
-      if (item.bbox?.x != null && item.noteId != null) {
+      if (item.bbox?.x != null && ![-Infinity, Infinity].includes(item.bbox?.x) && item.noteId != null) {
          posArr.push({
             noteId: item.noteId,
             MeasureNumberXML: item.MeasureNumberXML,
@@ -381,7 +381,7 @@ function getPointsPosByBatePos(): pointsPosType {
             // 这里当第一个音符noteId为null,找不到前一个noteId,所以兼容一下
             noteId: item.noteId != null ? item.noteId : (posArr[posArr.length - 1]?.noteId != null ? posArr[posArr.length - 1]?.noteId : -1) + 0.01, // 这里+0.01 是制造一个假id
             MeasureNumberXML: item.MeasureNumberXML,
-            x: item.bbox?.x != null ? item.bbox.x : posArr[posArr.length - 1]?.x || 10,
+            x: item.bbox?.x != null && ![-Infinity, Infinity].includes(item.bbox?.x) ? item.bbox.x : posArr[posArr.length - 1]?.x || 10,
             y: _canvasDomHeight - frequencyLineData[index]
          })
       }

+ 3 - 8
src/state.ts

@@ -1434,12 +1434,12 @@ function initMusicSource(data: any, tracks: string[], partIndex: number) {
         // 总谱渲染
         state.isCombineRender = true
         state.partListNames = tracks
-        // 总谱演唱模式是 范唱
+        // 总谱演唱模式是 范唱,取scoreAudioFileUrl字段
         fanSongObj = musicSheetAccompanimentList.find((item: any) => {
           return item.audioPlayType === "SING"
         })
-        // 先取scoreAudioFileUrl的值
-        if(fanSongObj?.scoreAudioFileUrl){
+        // 先取scoreAudioFileUrl的值 如果 没有就是空
+        if(fanSongObj){
           fanSongObj.audioFileUrl = fanSongObj.scoreAudioFileUrl
           fanSongObj.audioBeatMixUrl = fanSongObj.scoreAudioBeatMixUrl
         }
@@ -1447,11 +1447,6 @@ function initMusicSource(data: any, tracks: string[], partIndex: number) {
         accompanyObj = musicSheetAccompanimentList.find((item: any) => {
           return item.audioPlayType === "PLAY"
         })
-        // 先取scoreAudioFileUrl的值
-        if(accompanyObj?.scoreAudioFileUrl){
-          accompanyObj.audioFileUrl = accompanyObj.scoreAudioFileUrl
-          accompanyObj.audioBeatMixUrl = accompanyObj.scoreAudioBeatMixUrl
-        }
         track = "总谱"
         index = 999
         musicalInstrumentId = ''

+ 3 - 3
vite.config.ts

@@ -76,9 +76,9 @@ export default defineConfig({
         // target: "https://kt.colexiu.com",
         // target: "https://test.lexiaoya.cn",
         // target: "https://kt.colexiu.com",
-        // target: "https://test.resource.colexiu.com", // 内容平台开发环境,内容平台开发,需在url链接上加上isCbs=true
-        target: "https://test.kt.colexiu.com",
-        //target: "https://mec.colexiu.com",
+        target: "https://test.resource.colexiu.com", // 内容平台开发环境,内容平台开发,需在url链接上加上isCbs=true
+        // target: "https://test.kt.colexiu.com",
+        // target: "https://mec.colexiu.com",
         changeOrigin: true,
         rewrite: (path) => path.replace(/^\/instrument/, ""),
       },