|
@@ -625,49 +625,112 @@ export default defineComponent({
|
|
|
};
|
|
|
|
|
|
/** 生成曲谱节拍器数据 */
|
|
|
- const productMetronomeData = () => {
|
|
|
+ const productMetronomeData = async () => {
|
|
|
const times = new ABCJS.TimingCallbacks(abcData.visualObj);
|
|
|
data.times = times.noteTimings;
|
|
|
const list: any[] = [];
|
|
|
let meter = abcData.abc.meter || "";
|
|
|
- // length - 1是为了去除最后一个空的结束事件
|
|
|
- for (let i = 0; i < times.noteTimings.length - 1; i++) {
|
|
|
- const timeNote = times.noteTimings[i];
|
|
|
- const abcNote = getNextNote(timeNote.startChar as number);
|
|
|
- let indexStr: any = abcNote.chord?.find((n) => n.position === "left")?.name || "";
|
|
|
- indexStr = indexStr.split(".").map((n: string) => Number(n));
|
|
|
- if (indexStr.length === 2) {
|
|
|
- const measure = abcData.abc.measures[indexStr[0]];
|
|
|
- // 如果小节里面有拍号,后面一直延用这个拍号,以此类推, ps: 下个版本
|
|
|
- // if (measure.meter){
|
|
|
- // meter = measure.meter;
|
|
|
- // }
|
|
|
- const reg = new RegExp(/M:(\d+)\/\d+/);
|
|
|
- const numerator = Number(meter.match(reg)?.[1]);
|
|
|
- // console.log("🚀 ~ reg:", meter.match(reg)?.[1], abcData.abc.meter)
|
|
|
- // console.log("🚀 ~ measure:", measure)
|
|
|
- const note = measure.notes[indexStr[1]];
|
|
|
- list.push({
|
|
|
- ...note,
|
|
|
- timeNote,
|
|
|
- abcNote,
|
|
|
- measure: {
|
|
|
- numerator,
|
|
|
- },
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- // console.log("abcData.abc.measures", list);
|
|
|
- if (!metronomeData.metro) {
|
|
|
- metronomeData.metro = new Metronome();
|
|
|
- }
|
|
|
- try {
|
|
|
- metronomeData.activeIndex = -1;
|
|
|
- metronomeData.metro.init(list);
|
|
|
- } catch (error) {
|
|
|
- console.log("🚀 ~ 生成节拍器数据错误:", error);
|
|
|
- }
|
|
|
+
|
|
|
+ // 分帧计算:每帧处理 100 条数据(可根据性能调整)
|
|
|
+ const chunkSize = 5;
|
|
|
+ const totalItems = times.noteTimings.length - 1; // 去掉最后一个空事件
|
|
|
+ let currentIndex = 0;
|
|
|
+
|
|
|
+ // 使用 Promise 包装,方便 await 等待计算完成
|
|
|
+ await new Promise<void>((resolve) => {
|
|
|
+ const processChunk = () => {
|
|
|
+ const endIndex = Math.min(currentIndex + chunkSize, totalItems);
|
|
|
+
|
|
|
+ // 处理当前 chunk 的数据
|
|
|
+ for (let i = currentIndex; i < endIndex; i++) {
|
|
|
+ const timeNote = times.noteTimings[i];
|
|
|
+ const abcNote = getNextNote(timeNote.startChar as number);
|
|
|
+ let indexStr: any = abcNote.chord?.find((n) => n.position === "left")?.name || "";
|
|
|
+ indexStr = indexStr.split(".").map((n: string) => Number(n));
|
|
|
+
|
|
|
+ if (indexStr.length === 2) {
|
|
|
+ const measure = abcData.abc.measures[indexStr[0]];
|
|
|
+ const reg = new RegExp(/M:(\d+)\/\d+/);
|
|
|
+ const numerator = Number(meter.match(reg)?.[1]);
|
|
|
+ const note = measure.notes[indexStr[1]];
|
|
|
+ list.push({
|
|
|
+ ...note,
|
|
|
+ timeNote,
|
|
|
+ abcNote,
|
|
|
+ measure: {
|
|
|
+ numerator,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ currentIndex = endIndex;
|
|
|
+
|
|
|
+ // 如果还有数据,继续下一帧处理
|
|
|
+ if (currentIndex < totalItems) {
|
|
|
+ requestAnimationFrame(processChunk);
|
|
|
+ } else {
|
|
|
+ // 所有数据处理完成,初始化 Metronome
|
|
|
+ if (!metronomeData.metro) {
|
|
|
+ metronomeData.metro = new Metronome();
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ metronomeData.activeIndex = -1;
|
|
|
+ metronomeData.metro.init(list);
|
|
|
+ } catch (error) {
|
|
|
+ console.log("🚀 ~ 生成节拍器数据错误:", error);
|
|
|
+ }
|
|
|
+ resolve(); // 完成 Promise
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 开始处理
|
|
|
+ requestAnimationFrame(processChunk);
|
|
|
+ });
|
|
|
};
|
|
|
+ // const productMetronomeData = () => {
|
|
|
+ // const times = new ABCJS.TimingCallbacks(abcData.visualObj);
|
|
|
+ // data.times = times.noteTimings;
|
|
|
+ // const list: any[] = [];
|
|
|
+ // let meter = abcData.abc.meter || "";
|
|
|
+ // // length - 1是为了去除最后一个空的结束事件
|
|
|
+ // for (let i = 0; i < times.noteTimings.length - 1; i++) {
|
|
|
+ // const timeNote = times.noteTimings[i];
|
|
|
+ // const abcNote = getNextNote(timeNote.startChar as number);
|
|
|
+ // let indexStr: any = abcNote.chord?.find((n) => n.position === "left")?.name || "";
|
|
|
+ // indexStr = indexStr.split(".").map((n: string) => Number(n));
|
|
|
+ // if (indexStr.length === 2) {
|
|
|
+ // const measure = abcData.abc.measures[indexStr[0]];
|
|
|
+ // // 如果小节里面有拍号,后面一直延用这个拍号,以此类推, ps: 下个版本
|
|
|
+ // // if (measure.meter){
|
|
|
+ // // meter = measure.meter;
|
|
|
+ // // }
|
|
|
+ // const reg = new RegExp(/M:(\d+)\/\d+/);
|
|
|
+ // const numerator = Number(meter.match(reg)?.[1]);
|
|
|
+ // // console.log("🚀 ~ reg:", meter.match(reg)?.[1], abcData.abc.meter)
|
|
|
+ // // console.log("🚀 ~ measure:", measure)
|
|
|
+ // const note = measure.notes[indexStr[1]];
|
|
|
+ // list.push({
|
|
|
+ // ...note,
|
|
|
+ // timeNote,
|
|
|
+ // abcNote,
|
|
|
+ // measure: {
|
|
|
+ // numerator,
|
|
|
+ // },
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // // console.log("abcData.abc.measures", list);
|
|
|
+ // if (!metronomeData.metro) {
|
|
|
+ // metronomeData.metro = new Metronome();
|
|
|
+ // }
|
|
|
+ // try {
|
|
|
+ // metronomeData.activeIndex = -1;
|
|
|
+ // metronomeData.metro.init(list);
|
|
|
+ // } catch (error) {
|
|
|
+ // console.log("🚀 ~ 生成节拍器数据错误:", error);
|
|
|
+ // }
|
|
|
+ // };
|
|
|
|
|
|
// 高亮选中的音符
|
|
|
const rangeHighlight = (startChar: number) => {
|
|
@@ -1769,6 +1832,7 @@ export default defineComponent({
|
|
|
rect.setAttribute("fill", "#fff");
|
|
|
svg.prepend(rect);
|
|
|
if (svg) {
|
|
|
+ console.log(svg.outerHTML, 'svg.outerHTML')
|
|
|
const _canvas = svg2canvas(svg.outerHTML);
|
|
|
if (isUrl) {
|
|
|
// document.body.appendChild(_canvas);
|
|
@@ -1782,8 +1846,13 @@ export default defineComponent({
|
|
|
el.dispatchEvent(event);
|
|
|
} else {
|
|
|
_canvas.toBlob(async (blob) => {
|
|
|
- const pngUrl = await api_uploadFile(blob, data.musicId + ".png");
|
|
|
- resolve(pngUrl);
|
|
|
+ if(blob) {
|
|
|
+ const pngUrl = await api_uploadFile(blob, data.musicId + ".png");
|
|
|
+ resolve(pngUrl);
|
|
|
+ } else {
|
|
|
+ // reject('bolb is null')
|
|
|
+ resolve('')
|
|
|
+ }
|
|
|
}, "image/png");
|
|
|
}
|
|
|
}
|
|
@@ -2031,14 +2100,16 @@ export default defineComponent({
|
|
|
|
|
|
// 取消
|
|
|
const onCancelExport = async () => {
|
|
|
- data = Object.assign(data, importTemp.value.data);
|
|
|
- abcData = Object.assign(abcData, importTemp.value.abcData);
|
|
|
- clearInterval(importTemp.value.timer);
|
|
|
- // 判断是否有编号,有则取消
|
|
|
- if (importTemp.value.importFileId) {
|
|
|
- await api_musicalScoreConversionRecordRemove(importTemp.value.importFileId);
|
|
|
- }
|
|
|
- data.loadingAudioSrouce2 = false;
|
|
|
+ requestAnimationFrame(async () => {
|
|
|
+ data = Object.assign(data, importTemp.value.data);
|
|
|
+ abcData = Object.assign(abcData, importTemp.value.abcData);
|
|
|
+ clearInterval(importTemp.value.timer);
|
|
|
+ // 判断是否有编号,有则取消
|
|
|
+ if (importTemp.value.importFileId) {
|
|
|
+ await api_musicalScoreConversionRecordRemove(importTemp.value.importFileId);
|
|
|
+ }
|
|
|
+ data.loadingAudioSrouce2 = false;
|
|
|
+ })
|
|
|
};
|
|
|
|
|
|
/** 设置选段小节 */
|