|
@@ -31,6 +31,7 @@ import {
|
|
|
NPopselect,
|
|
|
NSelect,
|
|
|
NSpace,
|
|
|
+ NSpin,
|
|
|
useMessage,
|
|
|
} from "naive-ui";
|
|
|
import { LongArrowAltDown, LongArrowAltUp } from "@vicons/fa";
|
|
@@ -161,6 +162,7 @@ export default defineComponent({
|
|
|
const message = useMessage();
|
|
|
const popup = reactive({
|
|
|
instrument: false,
|
|
|
+ selectSubjectShow: false, // 声部弹窗
|
|
|
moveKeyShow: false, // 移调弹窗
|
|
|
speedShow: false, // 节拍弹窗
|
|
|
accidentalsShow: false, // 临时升降记号弹窗
|
|
@@ -203,6 +205,7 @@ export default defineComponent({
|
|
|
addMearseNumber: 1, // 添加小节数量
|
|
|
|
|
|
deleteMearseType: "ing" as "ing" | "finish", // 删除小节类型
|
|
|
+ loadingAudioSrouce: false, // 加载音频资源
|
|
|
});
|
|
|
const noteTypes = ABC_DATA.types.map((item) => item.value).filter(Boolean);
|
|
|
const accidentals = ABC_DATA.accidentals.map((item) => item.value).filter(Boolean);
|
|
@@ -412,6 +415,19 @@ export default defineComponent({
|
|
|
});
|
|
|
};
|
|
|
|
|
|
+ const getAudioSource = async () => {
|
|
|
+ const midiBuffer = new ABCJS.synth.CreateSynth();
|
|
|
+ data.loadingAudioSrouce = true;
|
|
|
+ midiBuffer
|
|
|
+ .init({
|
|
|
+ visualObj: abcData.visualObj,
|
|
|
+ options: abcData.synthOptions,
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ data.loadingAudioSrouce = false;
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
const togglePlay = (type: "play" | "pause" | "reset") => {
|
|
|
console.log("🚀 ~ abcData.synthControl:", abcData.synthControl);
|
|
|
|
|
@@ -502,10 +518,26 @@ export default defineComponent({
|
|
|
const handleChange = async (params: { type: string; value: any }) => {
|
|
|
const type = params.type;
|
|
|
const value = params.value;
|
|
|
- console.log(params);
|
|
|
+ const activeNote =
|
|
|
+ abcData.abc.measures[data.active?.measureIndex]?.notes[data.active?.noteIndex] || null;
|
|
|
+ console.log(params, activeNote);
|
|
|
if (type === "type") {
|
|
|
// 设置音符类型
|
|
|
data.noteType = value;
|
|
|
+ if (activeNote) {
|
|
|
+ activeNote.noteType = value;
|
|
|
+ await handleResetRender();
|
|
|
+ const abcElem: AbcElem = rangeHighlight(data.active.startChar);
|
|
|
+ const active: any = abcElem
|
|
|
+ ? {
|
|
|
+ ...cloneDeep(abcElem),
|
|
|
+ measureIndex: data.active.measureIndex,
|
|
|
+ noteIndex: data.active.noteIndex,
|
|
|
+ isFirstChecked: true,
|
|
|
+ }
|
|
|
+ : null;
|
|
|
+ data.active = active;
|
|
|
+ }
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -591,7 +623,16 @@ export default defineComponent({
|
|
|
}
|
|
|
activeNote.accidental = activeNote.accidental == value ? "" : value;
|
|
|
await handleResetRender();
|
|
|
- rangeHighlight(data.active.startChar);
|
|
|
+ const abcElem: AbcElem = rangeHighlight(data.active.startChar);
|
|
|
+ const active: any = abcElem
|
|
|
+ ? {
|
|
|
+ ...cloneDeep(abcElem),
|
|
|
+ measureIndex: data.active.measureIndex,
|
|
|
+ noteIndex: data.active.noteIndex,
|
|
|
+ isFirstChecked: true,
|
|
|
+ }
|
|
|
+ : null;
|
|
|
+ data.active = active;
|
|
|
}
|
|
|
|
|
|
// 谱号
|
|
@@ -713,8 +754,8 @@ export default defineComponent({
|
|
|
if (!activeNote) return;
|
|
|
const abcElem: any = abcData.visualObj.getElementFromChar(data.active.endChar);
|
|
|
if (data.active.averagepitch != abcElem.averagepitch) {
|
|
|
- message.warning('必须同音高才能添加延音线');
|
|
|
- return
|
|
|
+ message.warning("必须同音高才能添加延音线");
|
|
|
+ return;
|
|
|
}
|
|
|
activeNote.tieline = activeNote.tieline == value ? "" : value;
|
|
|
await handleResetRender();
|
|
@@ -1282,7 +1323,7 @@ export default defineComponent({
|
|
|
<div class={styles.topLine}></div>
|
|
|
|
|
|
<NPopover
|
|
|
- v-model:value={popup.moveKeyShow}
|
|
|
+ v-model:show={popup.selectSubjectShow}
|
|
|
trigger="click"
|
|
|
contentStyle={{ width: "320px" }}
|
|
|
>
|
|
@@ -1303,18 +1344,20 @@ export default defineComponent({
|
|
|
filterable
|
|
|
options={instruments.value}
|
|
|
v-model:value={abcData.synthOptions.program}
|
|
|
- onChange={() => handleResetRender()}
|
|
|
+ onUpdate:value={() => {
|
|
|
+ popup.selectSubjectShow = false;
|
|
|
+ getAudioSource();
|
|
|
+ handleResetRender();
|
|
|
+ togglePlay("pause");
|
|
|
+ togglePlay("reset");
|
|
|
+ }}
|
|
|
></NSelect>
|
|
|
</>
|
|
|
),
|
|
|
}}
|
|
|
</NPopover>
|
|
|
|
|
|
- <NPopover
|
|
|
- v-model:value={popup.moveKeyShow}
|
|
|
- trigger="click"
|
|
|
- contentStyle={{ width: "320px" }}
|
|
|
- >
|
|
|
+ <NPopover v-model:show={popup.moveKeyShow} trigger="click" contentStyle={{ width: "320px" }}>
|
|
|
{{
|
|
|
trigger: () => (
|
|
|
<div class={styles.topBtn}>
|
|
@@ -1595,19 +1638,21 @@ export default defineComponent({
|
|
|
</div>
|
|
|
<div>重播</div>
|
|
|
</div>
|
|
|
- <div class={styles.topBtn} onClick={() => togglePlay(data.playState ? "pause" : "play")}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img
|
|
|
- style={{ display: data.playState ? "" : "none" }}
|
|
|
- class={styles.topBtnIcon}
|
|
|
- src={getImage("icon_21_1.png")}
|
|
|
- />
|
|
|
- <img
|
|
|
- style={{ display: data.playState ? "none" : "" }}
|
|
|
- class={styles.topBtnIcon}
|
|
|
- src={getImage("icon_21.png")}
|
|
|
- />
|
|
|
- </div>
|
|
|
+ <div class={styles.topBtn}>
|
|
|
+ <NSpin show={data.loadingAudioSrouce} size="small">
|
|
|
+ <div class={styles.btnImg} onClick={() => togglePlay(data.playState ? "pause" : "play")}>
|
|
|
+ <img
|
|
|
+ style={{ display: data.playState ? "" : "none" }}
|
|
|
+ class={styles.topBtnIcon}
|
|
|
+ src={getImage("icon_21_1.png")}
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ style={{ display: data.playState ? "none" : "" }}
|
|
|
+ class={styles.topBtnIcon}
|
|
|
+ src={getImage("icon_21.png")}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </NSpin>
|
|
|
<div>{data.playState ? "暂停" : "播放"}</div>
|
|
|
</div>
|
|
|
<div class={[styles.topBtn, styles.btnDisabled]}>
|