|
@@ -167,6 +167,7 @@ export default defineComponent({
|
|
|
/** 移调类型 */
|
|
|
moveKeyType: "inset" as "inset" | "up" | "down", // 移调类型
|
|
|
activePlayNote: null as any, // 当前演奏音符
|
|
|
+ times: [] as any[], // 节拍器数据
|
|
|
});
|
|
|
const noteTypes = ABC_DATA.types.map((item) => item.value).filter(Boolean);
|
|
|
const accidentals = ABC_DATA.accidentals.map((item) => item.value).filter(Boolean);
|
|
@@ -300,13 +301,16 @@ export default defineComponent({
|
|
|
console.log("开始");
|
|
|
data.playState = true;
|
|
|
var svg = document.querySelector("#paper svg");
|
|
|
- var cursor = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
|
|
- cursor.setAttribute("class", "ABCJS-cursor");
|
|
|
+ let cursor = document.querySelector("#paper svg .ABCJS-cursor");
|
|
|
+ if (!cursor) {
|
|
|
+ cursor = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
|
|
+ cursor.setAttribute("class", "ABCJS-cursor");
|
|
|
+ svg?.appendChild(cursor);
|
|
|
+ }
|
|
|
cursor.setAttributeNS(null, "x1", "0");
|
|
|
cursor.setAttributeNS(null, "y1", "0");
|
|
|
cursor.setAttributeNS(null, "x2", "0");
|
|
|
cursor.setAttributeNS(null, "y2", "0");
|
|
|
- svg?.appendChild(cursor);
|
|
|
},
|
|
|
onBeat: function (beatNumber: any, totalBeats: any, totalTime: any) {
|
|
|
if (!data.playState) return;
|
|
@@ -314,13 +318,17 @@ export default defineComponent({
|
|
|
const time = (beatNumber / totalBeats) * totalTime;
|
|
|
metronomeData.metro.sound(time);
|
|
|
},
|
|
|
- onEvent: (ev: any) => {
|
|
|
+ onEvent: (event: any) => {
|
|
|
+ let ev = event as any;
|
|
|
if (!data.playState) return;
|
|
|
if (ev.measureStart && ev.left === null) return; // this was the second part of a tie across a measure line. Just ignore it.
|
|
|
+
|
|
|
if (popup.selectMearesShow) {
|
|
|
const startTime = data.selectMeasures.startNote?.currentTrackMilliseconds || 0;
|
|
|
+ // const timeNote = data.times.find(
|
|
|
+ // (n) => n.startChar === data.selectMeasures.startNote.startChar
|
|
|
+ // );
|
|
|
const endNote: any = data.selectMeasures.endNote ? data.selectMeasures.endNote : null;
|
|
|
- // console.log("🚀 ~ endNote:", ev.milliseconds , endNote.currentTrackMilliseconds)
|
|
|
if (
|
|
|
ev.milliseconds < startTime ||
|
|
|
(endNote && ev.milliseconds > endNote.currentTrackMilliseconds)
|
|
@@ -328,9 +336,8 @@ export default defineComponent({
|
|
|
const totalTime = (abcData.synthControl as any).visualObj.getTotalTime();
|
|
|
if (totalTime) {
|
|
|
const progress = startTime / 1000 / totalTime;
|
|
|
- nextTick(() => {
|
|
|
- (abcData.synthControl as any).seek(progress);
|
|
|
- });
|
|
|
+ (abcData.synthControl as any).seek(progress);
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -513,6 +520,7 @@ export default defineComponent({
|
|
|
/** 生成曲谱节拍器数据 */
|
|
|
const productMetronomeData = () => {
|
|
|
const times = new ABCJS.TimingCallbacks(abcData.visualObj);
|
|
|
+ data.times = times.noteTimings;
|
|
|
const list: any[] = [];
|
|
|
let meter = abcData.abc.meter || "";
|
|
|
// length - 1是为了去除最后一个空的结束事件
|
|
@@ -625,6 +633,7 @@ export default defineComponent({
|
|
|
|
|
|
if (type === "exit") {
|
|
|
if (!data.isSave) {
|
|
|
+ clearTimeout(saveTimer);
|
|
|
dialog.warning({
|
|
|
maskClosable: true,
|
|
|
autoFocus: false,
|
|
@@ -1423,7 +1432,7 @@ export default defineComponent({
|
|
|
msg.content = "导出失败";
|
|
|
return;
|
|
|
}
|
|
|
- saveAs(res.data.xml, (data.musicName || '曲谱') + ".xml");
|
|
|
+ saveAs(res.data.xml, (data.musicName || "曲谱") + ".xml");
|
|
|
msg.type = "success";
|
|
|
msg.content = "导出成功";
|
|
|
};
|
|
@@ -2053,14 +2062,13 @@ export default defineComponent({
|
|
|
|
|
|
<div class={styles.topLine}></div>
|
|
|
|
|
|
- <div
|
|
|
- style={{ marginLeft: "auto" }}
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => togglePlay("reset")}
|
|
|
- >
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_20.png")} />
|
|
|
- </div>
|
|
|
+ <div style={{ marginLeft: "auto" }} class={styles.topBtn}>
|
|
|
+ <NSpin show={data.loadingAudioSrouce} size="small">
|
|
|
+ <div class={styles.btnImg} onClick={() => togglePlay("reset")}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_20.png")} />
|
|
|
+ </div>
|
|
|
+ </NSpin>
|
|
|
+
|
|
|
<div>重播</div>
|
|
|
</div>
|
|
|
<div class={styles.topBtn}>
|