|
@@ -1328,20 +1328,17 @@ export default defineComponent({
|
|
|
};
|
|
|
|
|
|
const downPng = async () => {
|
|
|
- await handleResetRender();
|
|
|
- const paper = document.getElementById("paper");
|
|
|
+ abcData.abc.title = `T:${data.musicName}`;
|
|
|
+ abcData.abc.creator = `R:${data.creator}`;
|
|
|
+ const paper = document.getElementById("exportPng");
|
|
|
if (!paper) return;
|
|
|
+ const abc = renderMeasures(abcData.abc, { hiddenIndex: true, showTitle: true, showCreator: true });
|
|
|
+ ABCJS.renderAbc(paper, abc, abcData.abcOptions);
|
|
|
const svg: any = paper.children[0]?.cloneNode(true);
|
|
|
- const annotation = svg.querySelectorAll(".abcjs-annotation");
|
|
|
- annotation.forEach((n: HTMLElement) => {
|
|
|
- n.remove();
|
|
|
- });
|
|
|
const svgBox = paper.getBoundingClientRect();
|
|
|
- console.log("🚀 ~ svgBox:", svgBox);
|
|
|
svg.setAttribute("width", `${svgBox.width * 3}`);
|
|
|
svg.setAttribute("height", `${svgBox.height * 3}`);
|
|
|
const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
|
- console.log("🚀 ~ svg:", svg);
|
|
|
rect.setAttribute("x", "0");
|
|
|
rect.setAttribute("y", "0");
|
|
|
rect.setAttribute("width", `${svgBox.width * 10}`);
|
|
@@ -1462,866 +1459,908 @@ export default defineComponent({
|
|
|
};
|
|
|
|
|
|
return () => (
|
|
|
- <div class={styles.container}>
|
|
|
- <div class={styles.containerTop} onKeyup={(e: Event) => e.stopPropagation()}>
|
|
|
- <div class={styles.topWrap}>
|
|
|
- <div class={styles.topBtn} onClick={() => handleChange({ type: "exit", value: "exit" })}>
|
|
|
- <div class={[styles.btnImg]}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_-1.png")} />
|
|
|
+ <>
|
|
|
+ <div class={styles.container}>
|
|
|
+ <div class={styles.containerTop} onKeyup={(e: Event) => e.stopPropagation()}>
|
|
|
+ <div class={styles.topWrap}>
|
|
|
+ <div class={styles.topBtn} onClick={() => handleChange({ type: "exit", value: "exit" })}>
|
|
|
+ <div class={[styles.btnImg]}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_-1.png")} />
|
|
|
+ </div>
|
|
|
+ <div>退出</div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.topBtn}>
|
|
|
+ <FileBtn
|
|
|
+ onSelect={(val: IFileBtnType) => {
|
|
|
+ if (val === "newMusic") {
|
|
|
+ handleCreateMusic();
|
|
|
+ } else if (val === "save") {
|
|
|
+ handleSaveMusic();
|
|
|
+ } else if (["xml"].includes(val)) {
|
|
|
+ handleExport();
|
|
|
+ } else if (val === "upload") {
|
|
|
+ } else if (["png", "midi", "wav"].includes(val)) {
|
|
|
+ handleDownFile(val);
|
|
|
+ } else if (val === "print") {
|
|
|
+ }
|
|
|
+ // else if (val === "exit") {
|
|
|
+
|
|
|
+ // }
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <div>文件</div>
|
|
|
</div>
|
|
|
- <div>退出</div>
|
|
|
- </div>
|
|
|
- <div class={styles.topBtn}>
|
|
|
- <FileBtn
|
|
|
- onSelect={(val: IFileBtnType) => {
|
|
|
- if (val === "newMusic") {
|
|
|
- handleCreateMusic();
|
|
|
- } else if (val === "save") {
|
|
|
- handleSaveMusic();
|
|
|
- } else if (["xml"].includes(val)) {
|
|
|
- handleExport();
|
|
|
- } else if (val === "upload") {
|
|
|
- } else if (["png", "midi", "wav"].includes(val)) {
|
|
|
- handleDownFile(val);
|
|
|
- } else if (val === "print") {
|
|
|
- }
|
|
|
- // else if (val === "exit") {
|
|
|
-
|
|
|
- // }
|
|
|
- }}
|
|
|
- />
|
|
|
- <div>文件</div>
|
|
|
- </div>
|
|
|
|
|
|
- <div class={styles.topLine}></div>
|
|
|
+ <div class={styles.topLine}></div>
|
|
|
|
|
|
- <div class={styles.topBtn} onClick={() => handleChange({ type: "dot", value: ">" })}>
|
|
|
- <div class={[styles.btnImg, noteComputed.value.dot === ">" && styles.btnImgActive]}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_1.png")} />
|
|
|
+ <div class={styles.topBtn} onClick={() => handleChange({ type: "dot", value: ">" })}>
|
|
|
+ <div class={[styles.btnImg, noteComputed.value.dot === ">" && styles.btnImgActive]}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_1.png")} />
|
|
|
+ </div>
|
|
|
+ <div>附点</div>
|
|
|
</div>
|
|
|
- <div>附点</div>
|
|
|
- </div>
|
|
|
|
|
|
- <div class={styles.topLine}></div>
|
|
|
+ <div class={styles.topLine}></div>
|
|
|
+
|
|
|
+ {ABC_DATA.accidentals.map((item) => (
|
|
|
+ <div
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => handleChange({ type: "accidentals", value: item.value })}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.btnImg,
|
|
|
+ noteComputed.value.accidental === item.value && styles.btnImgActive,
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <img class={styles.topBtnIcon} src={item.icon} />
|
|
|
+ </div>
|
|
|
+ <div class={styles.btnName}>{item.name}</div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+
|
|
|
+ <div class={styles.topLine}></div>
|
|
|
|
|
|
- {ABC_DATA.accidentals.map((item) => (
|
|
|
<div
|
|
|
class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "accidentals", value: item.value })}
|
|
|
+ onClick={() => handleChange({ type: "tie", value: ABC_DATA.tie[0].value })}
|
|
|
>
|
|
|
<div
|
|
|
class={[
|
|
|
styles.btnImg,
|
|
|
- noteComputed.value.accidental === item.value && styles.btnImgActive,
|
|
|
+ noteComputed.value.tieline === ABC_DATA.tie[0].value && styles.btnImgActive,
|
|
|
]}
|
|
|
>
|
|
|
- <img class={styles.topBtnIcon} src={item.icon} />
|
|
|
+ <img class={styles.topBtnIcon} src={ABC_DATA.tie[0].icon} />
|
|
|
</div>
|
|
|
- <div class={styles.btnName}>{item.name}</div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
-
|
|
|
- <div class={styles.topLine}></div>
|
|
|
-
|
|
|
- <div
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "tie", value: ABC_DATA.tie[0].value })}
|
|
|
- >
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.btnImg,
|
|
|
- noteComputed.value.tieline === ABC_DATA.tie[0].value && styles.btnImgActive,
|
|
|
- ]}
|
|
|
- >
|
|
|
- <img class={styles.topBtnIcon} src={ABC_DATA.tie[0].icon} />
|
|
|
+ <div>{ABC_DATA.tie[0].name}</div>
|
|
|
</div>
|
|
|
- <div>{ABC_DATA.tie[0].name}</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "tie", value: ABC_DATA.tie[1].value })}
|
|
|
- >
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.btnImg,
|
|
|
- ABC_DATA.tie[1].value.includes(noteComputed.value.tie) && styles.btnImgActive,
|
|
|
- ]}
|
|
|
- >
|
|
|
- <img class={styles.topBtnIcon} src={ABC_DATA.tie[1].icon} />
|
|
|
- </div>
|
|
|
- <div>{ABC_DATA.tie[1].name}</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class={styles.topLine}></div>
|
|
|
|
|
|
- {ABC_DATA.play.slice(0, 4).map((item) => (
|
|
|
<div
|
|
|
- class={[styles.topBtn]}
|
|
|
- onClick={() => handleChange({ type: "play", value: item.value })}
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => handleChange({ type: "tie", value: ABC_DATA.tie[1].value })}
|
|
|
>
|
|
|
<div
|
|
|
class={[
|
|
|
styles.btnImg,
|
|
|
- noteComputed.value.play?.includes(item.value) && styles.btnImgActive,
|
|
|
+ ABC_DATA.tie[1].value.includes(noteComputed.value.tie) && styles.btnImgActive,
|
|
|
]}
|
|
|
>
|
|
|
- <img class={styles.topBtnIcon} src={item.icon} />
|
|
|
+ <img class={styles.topBtnIcon} src={ABC_DATA.tie[1].icon} />
|
|
|
</div>
|
|
|
- <div>{item.name}</div>
|
|
|
+ <div>{ABC_DATA.tie[1].name}</div>
|
|
|
</div>
|
|
|
- ))}
|
|
|
|
|
|
- <NPopover
|
|
|
- class={styles.popupWrap}
|
|
|
- showArrow={false}
|
|
|
- trigger="click"
|
|
|
- contentStyle={{ width: "400px" }}
|
|
|
- >
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div class={styles.topDownArrow}>
|
|
|
- <img src={getImage("icon_arrow.png")} />
|
|
|
+ <div class={styles.topLine}></div>
|
|
|
+
|
|
|
+ {ABC_DATA.play.slice(0, 4).map((item) => (
|
|
|
+ <div
|
|
|
+ class={[styles.topBtn]}
|
|
|
+ onClick={() => handleChange({ type: "play", value: item.value })}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.btnImg,
|
|
|
+ noteComputed.value.play?.includes(item.value) && styles.btnImgActive,
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <img class={styles.topBtnIcon} src={item.icon} />
|
|
|
</div>
|
|
|
- ),
|
|
|
- default: () => (
|
|
|
- <NGrid cols={4} yGap={8}>
|
|
|
- {ABC_DATA.play.slice(4).map((item) => (
|
|
|
- <NGi>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.btnItem,
|
|
|
- noteComputed.value.play?.includes(item.value) && styles.btnItemActive,
|
|
|
- ]}
|
|
|
- onClick={() => {
|
|
|
- data.morePlay = false;
|
|
|
- handleChange({ type: "play", value: item.value });
|
|
|
- }}
|
|
|
- >
|
|
|
- <div class={styles.btnItemIcon}>
|
|
|
- <TheIcon iconClassName={item.icon} />
|
|
|
+ <div>{item.name}</div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+
|
|
|
+ <NPopover
|
|
|
+ class={styles.popupWrap}
|
|
|
+ showArrow={false}
|
|
|
+ trigger="click"
|
|
|
+ contentStyle={{ width: "400px" }}
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div class={styles.topDownArrow}>
|
|
|
+ <img src={getImage("icon_arrow.png")} />
|
|
|
+ </div>
|
|
|
+ ),
|
|
|
+ default: () => (
|
|
|
+ <NGrid cols={4} yGap={8}>
|
|
|
+ {ABC_DATA.play.slice(4).map((item) => (
|
|
|
+ <NGi>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.btnItem,
|
|
|
+ noteComputed.value.play?.includes(item.value) && styles.btnItemActive,
|
|
|
+ ]}
|
|
|
+ onClick={() => {
|
|
|
+ data.morePlay = false;
|
|
|
+ handleChange({ type: "play", value: item.value });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div class={styles.btnItemIcon}>
|
|
|
+ <TheIcon iconClassName={item.icon} />
|
|
|
+ </div>
|
|
|
+ <div>{item.name}</div>
|
|
|
</div>
|
|
|
- <div>{item.name}</div>
|
|
|
- </div>
|
|
|
- </NGi>
|
|
|
- ))}
|
|
|
- </NGrid>
|
|
|
- ),
|
|
|
- }}
|
|
|
- </NPopover>
|
|
|
-
|
|
|
- <div class={styles.topLine}></div>
|
|
|
-
|
|
|
- <NDropdown
|
|
|
- trigger="click"
|
|
|
- options={ABC_DATA.slus as any}
|
|
|
- labelField="name"
|
|
|
- keyField="value"
|
|
|
- onSelect={(val) => {
|
|
|
- console.log(val);
|
|
|
- handleChange({ type: "slus", value: val });
|
|
|
- }}
|
|
|
- >
|
|
|
- <div class={[styles.topBtn]}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_13.png")} />
|
|
|
+ </NGi>
|
|
|
+ ))}
|
|
|
+ </NGrid>
|
|
|
+ ),
|
|
|
+ }}
|
|
|
+ </NPopover>
|
|
|
+
|
|
|
+ <div class={styles.topLine}></div>
|
|
|
+
|
|
|
+ <NDropdown
|
|
|
+ trigger="click"
|
|
|
+ options={ABC_DATA.slus as any}
|
|
|
+ labelField="name"
|
|
|
+ keyField="value"
|
|
|
+ onSelect={(val) => {
|
|
|
+ console.log(val);
|
|
|
+ handleChange({ type: "slus", value: val });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div class={[styles.topBtn]}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_13.png")} />
|
|
|
+ </div>
|
|
|
+ <div>连音</div>
|
|
|
</div>
|
|
|
- <div>连音</div>
|
|
|
- </div>
|
|
|
- </NDropdown>
|
|
|
+ </NDropdown>
|
|
|
|
|
|
- <div class={[styles.topBtn, styles.btnDisabled]}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_14.png")} />
|
|
|
+ <div class={[styles.topBtn, styles.btnDisabled]}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_14.png")} />
|
|
|
+ </div>
|
|
|
+ <div>翻转</div>
|
|
|
</div>
|
|
|
- <div>翻转</div>
|
|
|
- </div>
|
|
|
|
|
|
- <div class={styles.topLine}></div>
|
|
|
+ <div class={styles.topLine}></div>
|
|
|
|
|
|
- <NPopover
|
|
|
- class={styles.popupWrap}
|
|
|
- showArrow={false}
|
|
|
- v-model:show={popup.selectSubjectShow}
|
|
|
- trigger="click"
|
|
|
- contentStyle={{ width: "320px" }}
|
|
|
- >
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div class={styles.topBtn}>
|
|
|
- <div class={styles.btnImg} onClick={() => (popup.instrument = true)}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_25.png")} />
|
|
|
+ <NPopover
|
|
|
+ class={styles.popupWrap}
|
|
|
+ showArrow={false}
|
|
|
+ v-model:show={popup.selectSubjectShow}
|
|
|
+ trigger="click"
|
|
|
+ contentStyle={{ width: "320px" }}
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div class={styles.topBtn}>
|
|
|
+ <div class={styles.btnImg} onClick={() => (popup.instrument = true)}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_25.png")} />
|
|
|
+ </div>
|
|
|
+ <div>选择声部</div>
|
|
|
</div>
|
|
|
- <div>选择声部</div>
|
|
|
- </div>
|
|
|
- ),
|
|
|
- default: () => (
|
|
|
- <>
|
|
|
- <div class={styles.btnLineTitle}>选择声部</div>
|
|
|
-
|
|
|
- <NSelect
|
|
|
- filterable
|
|
|
- options={instruments.value}
|
|
|
- v-model:value={abcData.synthOptions.program}
|
|
|
- onUpdate:value={async () => {
|
|
|
- abcData.synthControl.disable(true);
|
|
|
- data.playState = false;
|
|
|
- await loadMiniMp3();
|
|
|
- resetMidi(true);
|
|
|
- popup.selectSubjectShow = false;
|
|
|
- }}
|
|
|
- ></NSelect>
|
|
|
- </>
|
|
|
- ),
|
|
|
- }}
|
|
|
- </NPopover>
|
|
|
-
|
|
|
- <NPopover
|
|
|
- class={styles.popupWrap}
|
|
|
- showArrow={false}
|
|
|
- v-model:show={popup.moveKeyShow}
|
|
|
- trigger="click"
|
|
|
- contentStyle={{ width: "320px" }}
|
|
|
- >
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div class={styles.topBtn}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_15.png")} />
|
|
|
+ ),
|
|
|
+ default: () => (
|
|
|
+ <>
|
|
|
+ <div class={styles.btnLineTitle}>选择声部</div>
|
|
|
+
|
|
|
+ <NSelect
|
|
|
+ filterable
|
|
|
+ options={instruments.value}
|
|
|
+ v-model:value={abcData.synthOptions.program}
|
|
|
+ onUpdate:value={async () => {
|
|
|
+ abcData.synthControl.disable(true);
|
|
|
+ data.playState = false;
|
|
|
+ await loadMiniMp3();
|
|
|
+ resetMidi(true);
|
|
|
+ popup.selectSubjectShow = false;
|
|
|
+ }}
|
|
|
+ ></NSelect>
|
|
|
+ </>
|
|
|
+ ),
|
|
|
+ }}
|
|
|
+ </NPopover>
|
|
|
+
|
|
|
+ <NPopover
|
|
|
+ class={styles.popupWrap}
|
|
|
+ showArrow={false}
|
|
|
+ v-model:show={popup.moveKeyShow}
|
|
|
+ trigger="click"
|
|
|
+ contentStyle={{ width: "320px" }}
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div class={styles.topBtn}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_15.png")} />
|
|
|
+ </div>
|
|
|
+ <div>移调</div>
|
|
|
</div>
|
|
|
- <div>移调</div>
|
|
|
- </div>
|
|
|
- ),
|
|
|
- default: () => (
|
|
|
- <>
|
|
|
- <div class={styles.btnLineTitle}>移调方式</div>
|
|
|
-
|
|
|
- <NSpace>
|
|
|
- <NButton
|
|
|
- secondary
|
|
|
- type={data.moveKeyType === "inset" ? "primary" : "default"}
|
|
|
- onClick={() => (data.moveKeyType = "inset")}
|
|
|
- >
|
|
|
- <NIcon component={GripLinesVertical} />
|
|
|
- 最靠近
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- secondary
|
|
|
- type={data.moveKeyType === "down" ? "primary" : "default"}
|
|
|
- onClick={() => (data.moveKeyType = "down")}
|
|
|
- >
|
|
|
- <NIcon component={LongArrowAltDown} />
|
|
|
- 向下移调
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- secondary
|
|
|
- type={data.moveKeyType === "up" ? "primary" : "default"}
|
|
|
- onClick={() => (data.moveKeyType = "up")}
|
|
|
- >
|
|
|
- <NIcon component={LongArrowAltUp} />
|
|
|
- 向上移调
|
|
|
- </NButton>
|
|
|
- </NSpace>
|
|
|
-
|
|
|
- <div class={styles.btnLineTitle}>目标音调</div>
|
|
|
-
|
|
|
- <NGrid cols={5} yGap={8}>
|
|
|
- {ABC_DATA.key
|
|
|
- .sort((a, b) => b.step - a.step)
|
|
|
- .map((item) => (
|
|
|
- <NGi>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.btnItem,
|
|
|
- abcData.abc.key === item.value && styles.btnItemActive,
|
|
|
- ]}
|
|
|
- onClick={() => handleMoveKey(item)}
|
|
|
- >
|
|
|
- <div class={[styles.btnItemIcon]}>
|
|
|
- <TheIcon iconClassName={item.icon} />
|
|
|
+ ),
|
|
|
+ default: () => (
|
|
|
+ <>
|
|
|
+ <div class={styles.btnLineTitle}>移调方式</div>
|
|
|
+
|
|
|
+ <NSpace>
|
|
|
+ <NButton
|
|
|
+ secondary
|
|
|
+ type={data.moveKeyType === "inset" ? "primary" : "default"}
|
|
|
+ onClick={() => (data.moveKeyType = "inset")}
|
|
|
+ >
|
|
|
+ <NIcon component={GripLinesVertical} />
|
|
|
+ 最靠近
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ secondary
|
|
|
+ type={data.moveKeyType === "down" ? "primary" : "default"}
|
|
|
+ onClick={() => (data.moveKeyType = "down")}
|
|
|
+ >
|
|
|
+ <NIcon component={LongArrowAltDown} />
|
|
|
+ 向下移调
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ secondary
|
|
|
+ type={data.moveKeyType === "up" ? "primary" : "default"}
|
|
|
+ onClick={() => (data.moveKeyType = "up")}
|
|
|
+ >
|
|
|
+ <NIcon component={LongArrowAltUp} />
|
|
|
+ 向上移调
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
+
|
|
|
+ <div class={styles.btnLineTitle}>目标音调</div>
|
|
|
+
|
|
|
+ <NGrid cols={5} yGap={8}>
|
|
|
+ {ABC_DATA.key
|
|
|
+ .sort((a, b) => b.step - a.step)
|
|
|
+ .map((item) => (
|
|
|
+ <NGi>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.btnItem,
|
|
|
+ abcData.abc.key === item.value && styles.btnItemActive,
|
|
|
+ ]}
|
|
|
+ onClick={() => handleMoveKey(item)}
|
|
|
+ >
|
|
|
+ <div class={[styles.btnItemIcon]}>
|
|
|
+ <TheIcon iconClassName={item.icon} />
|
|
|
+ </div>
|
|
|
+ <div class={styles.btnItemName}>{item.name}</div>
|
|
|
</div>
|
|
|
- <div class={styles.btnItemName}>{item.name}</div>
|
|
|
- </div>
|
|
|
- </NGi>
|
|
|
- ))}
|
|
|
- </NGrid>
|
|
|
- </>
|
|
|
- ),
|
|
|
- }}
|
|
|
- </NPopover>
|
|
|
-
|
|
|
- <NPopover
|
|
|
- class={styles.popupWrap}
|
|
|
- showArrow={false}
|
|
|
- v-model:value={popup.speedShow}
|
|
|
- trigger="click"
|
|
|
- placement="bottom"
|
|
|
- displayDirective="show"
|
|
|
- >
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div class={[styles.topBtn]}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_16.png")} />
|
|
|
+ </NGi>
|
|
|
+ ))}
|
|
|
+ </NGrid>
|
|
|
+ </>
|
|
|
+ ),
|
|
|
+ }}
|
|
|
+ </NPopover>
|
|
|
+
|
|
|
+ <NPopover
|
|
|
+ class={styles.popupWrap}
|
|
|
+ showArrow={false}
|
|
|
+ v-model:value={popup.speedShow}
|
|
|
+ trigger="click"
|
|
|
+ placement="bottom"
|
|
|
+ displayDirective="show"
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div class={[styles.topBtn]}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_16.png")} />
|
|
|
+ </div>
|
|
|
+ <div>速度调整</div>
|
|
|
</div>
|
|
|
- <div>速度调整</div>
|
|
|
- </div>
|
|
|
- ),
|
|
|
- default: () => <TheSpeed onChange={(val) => handleChange(val)} />,
|
|
|
- }}
|
|
|
- </NPopover>
|
|
|
-
|
|
|
- <NPopover
|
|
|
- class={styles.popupWrap}
|
|
|
- showArrow={false}
|
|
|
- v-model:show={popup.staffShow}
|
|
|
- trigger="click"
|
|
|
- placement="bottom"
|
|
|
- contentStyle={{ width: "320px" }}
|
|
|
- >
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div class={[styles.topBtn]}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_17.png")} />
|
|
|
+ ),
|
|
|
+ default: () => <TheSpeed onChange={(val) => handleChange(val)} />,
|
|
|
+ }}
|
|
|
+ </NPopover>
|
|
|
+
|
|
|
+ <NPopover
|
|
|
+ class={styles.popupWrap}
|
|
|
+ showArrow={false}
|
|
|
+ v-model:show={popup.staffShow}
|
|
|
+ trigger="click"
|
|
|
+ placement="bottom"
|
|
|
+ contentStyle={{ width: "320px" }}
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div class={[styles.topBtn]}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_17.png")} />
|
|
|
+ </div>
|
|
|
+ <div>谱面显示</div>
|
|
|
</div>
|
|
|
- <div>谱面显示</div>
|
|
|
- </div>
|
|
|
- ),
|
|
|
- default: () => (
|
|
|
- <>
|
|
|
- <div class={styles.btnLineTitle}>乐谱大小</div>
|
|
|
-
|
|
|
- <NSpace>
|
|
|
- <NButton
|
|
|
- type={abcData.abcOptions.staffwidth === 1200 ? "primary" : "default"}
|
|
|
- secondary
|
|
|
- onClick={() => {
|
|
|
- abcData.abcOptions.staffwidth = 1200;
|
|
|
- handleResetRender();
|
|
|
- }}
|
|
|
- >
|
|
|
- 小
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- type={abcData.abcOptions.staffwidth === 800 ? "primary" : "default"}
|
|
|
- secondary
|
|
|
- onClick={() => {
|
|
|
- abcData.abcOptions.staffwidth = 800;
|
|
|
- handleResetRender();
|
|
|
- }}
|
|
|
- >
|
|
|
- 中
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- type={abcData.abcOptions.staffwidth === 400 ? "primary" : "default"}
|
|
|
- secondary
|
|
|
- onClick={() => {
|
|
|
- abcData.abcOptions.staffwidth = 400;
|
|
|
- handleResetRender();
|
|
|
- }}
|
|
|
- >
|
|
|
- 大
|
|
|
- </NButton>
|
|
|
- </NSpace>
|
|
|
-
|
|
|
- <div class={styles.btnLineTitle}>小节数</div>
|
|
|
-
|
|
|
- <NSpace vertical>
|
|
|
- <NInputNumber
|
|
|
- min={1}
|
|
|
- v-model:value={(abcData.abcOptions.wrap as any).preferredMeasuresPerLine}
|
|
|
- placeholder="请输入小节数"
|
|
|
- onUpdate:value={() => {
|
|
|
- handleResetRender();
|
|
|
- }}
|
|
|
- />
|
|
|
+ ),
|
|
|
+ default: () => (
|
|
|
+ <>
|
|
|
+ <div class={styles.btnLineTitle}>乐谱大小</div>
|
|
|
|
|
|
- {/* <NSpace style={{ marginTop: "20px" }} align="center" wrap={false} wrapItem={false}>
|
|
|
- <NButton style={{ width: "48%" }} round onClick={() => (popup.staffShow = false)}>
|
|
|
- 取消
|
|
|
+ <NSpace>
|
|
|
+ <NButton
|
|
|
+ type={abcData.abcOptions.staffwidth === 1200 ? "primary" : "default"}
|
|
|
+ secondary
|
|
|
+ onClick={() => {
|
|
|
+ abcData.abcOptions.staffwidth = 1200;
|
|
|
+ handleResetRender();
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 小
|
|
|
</NButton>
|
|
|
<NButton
|
|
|
- style={{ width: "48%" }}
|
|
|
- round
|
|
|
- type="primary"
|
|
|
+ type={abcData.abcOptions.staffwidth === 800 ? "primary" : "default"}
|
|
|
+ secondary
|
|
|
+ onClick={() => {
|
|
|
+ abcData.abcOptions.staffwidth = 800;
|
|
|
+ handleResetRender();
|
|
|
+ }}
|
|
|
>
|
|
|
- 确定
|
|
|
+ 中
|
|
|
</NButton>
|
|
|
- </NSpace> */}
|
|
|
- </NSpace>
|
|
|
- </>
|
|
|
- ),
|
|
|
- }}
|
|
|
- </NPopover>
|
|
|
-
|
|
|
- <NPopover
|
|
|
- class={styles.popupWrap}
|
|
|
- showArrow={false}
|
|
|
- v-model:show={popup.barShow}
|
|
|
- trigger="click"
|
|
|
- placement="bottom"
|
|
|
- contentStyle={{ width: "320px" }}
|
|
|
- >
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div class={[styles.topBtn]}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_18.png")} />
|
|
|
- </div>
|
|
|
- <div>添加小节</div>
|
|
|
- </div>
|
|
|
- ),
|
|
|
- default: () => (
|
|
|
- <>
|
|
|
- <div class={styles.btnLineTitle}>添加方式</div>
|
|
|
-
|
|
|
- <NSpace>
|
|
|
- <NButton
|
|
|
- type={data.addMearseType === "pre" ? "primary" : "default"}
|
|
|
- secondary
|
|
|
- onClick={() => (data.addMearseType = "pre")}
|
|
|
- >
|
|
|
- 当前小节前
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- type={data.addMearseType === "next" ? "primary" : "default"}
|
|
|
- secondary
|
|
|
- onClick={() => (data.addMearseType = "next")}
|
|
|
- >
|
|
|
- 当前小节后
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- type={data.addMearseType === "finish" ? "primary" : "default"}
|
|
|
- secondary
|
|
|
- onClick={() => (data.addMearseType = "finish")}
|
|
|
- >
|
|
|
- 曲谱末尾
|
|
|
- </NButton>
|
|
|
- </NSpace>
|
|
|
+ <NButton
|
|
|
+ type={abcData.abcOptions.staffwidth === 400 ? "primary" : "default"}
|
|
|
+ secondary
|
|
|
+ onClick={() => {
|
|
|
+ abcData.abcOptions.staffwidth = 400;
|
|
|
+ handleResetRender();
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 大
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
|
|
|
- <div class={styles.btnLineTitle}>小节数</div>
|
|
|
+ <div class={styles.btnLineTitle}>小节数</div>
|
|
|
|
|
|
- <NSpace vertical>
|
|
|
- <NInputNumber
|
|
|
- min={1}
|
|
|
- v-model:value={data.addMearseNumber}
|
|
|
- placeholder="请输入小节数"
|
|
|
- />
|
|
|
+ <NSpace vertical>
|
|
|
+ <NInputNumber
|
|
|
+ min={1}
|
|
|
+ v-model:value={(abcData.abcOptions.wrap as any).preferredMeasuresPerLine}
|
|
|
+ placeholder="请输入小节数"
|
|
|
+ onUpdate:value={() => {
|
|
|
+ handleResetRender();
|
|
|
+ }}
|
|
|
+ />
|
|
|
|
|
|
- <NSpace style={{ marginTop: "20px" }} align="center" wrap={false} wrapItem={false}>
|
|
|
- <NButton style={{ width: "48%" }} round onClick={() => (popup.barShow = false)}>
|
|
|
+ {/* <NSpace style={{ marginTop: "20px" }} align="center" wrap={false} wrapItem={false}>
|
|
|
+ <NButton style={{ width: "48%" }} round onClick={() => (popup.staffShow = false)}>
|
|
|
取消
|
|
|
</NButton>
|
|
|
<NButton
|
|
|
style={{ width: "48%" }}
|
|
|
round
|
|
|
type="primary"
|
|
|
- onClick={() => handleAddMearse()}
|
|
|
>
|
|
|
确定
|
|
|
</NButton>
|
|
|
+ </NSpace> */}
|
|
|
</NSpace>
|
|
|
- </NSpace>
|
|
|
- </>
|
|
|
- ),
|
|
|
- }}
|
|
|
- </NPopover>
|
|
|
-
|
|
|
- <NPopover
|
|
|
- class={styles.popupWrap}
|
|
|
- v-model:show={popup.mearseDeleteShow}
|
|
|
- trigger="click"
|
|
|
- placement="bottom"
|
|
|
- >
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div class={[styles.topBtn]}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_19.png")} />
|
|
|
+ </>
|
|
|
+ ),
|
|
|
+ }}
|
|
|
+ </NPopover>
|
|
|
+
|
|
|
+ <NPopover
|
|
|
+ class={styles.popupWrap}
|
|
|
+ showArrow={false}
|
|
|
+ v-model:show={popup.barShow}
|
|
|
+ trigger="click"
|
|
|
+ placement="bottom"
|
|
|
+ contentStyle={{ width: "320px" }}
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div class={[styles.topBtn]}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_18.png")} />
|
|
|
+ </div>
|
|
|
+ <div>添加小节</div>
|
|
|
</div>
|
|
|
- <div>删除小节</div>
|
|
|
- </div>
|
|
|
- ),
|
|
|
- default: () => (
|
|
|
- <>
|
|
|
- <div class={styles.btnLineTitle}>删除方式</div>
|
|
|
+ ),
|
|
|
+ default: () => (
|
|
|
+ <>
|
|
|
+ <div class={styles.btnLineTitle}>添加方式</div>
|
|
|
|
|
|
- <NSpace vertical>
|
|
|
<NSpace>
|
|
|
<NButton
|
|
|
- type={data.deleteMearseType === "ing" ? "primary" : "default"}
|
|
|
+ type={data.addMearseType === "pre" ? "primary" : "default"}
|
|
|
secondary
|
|
|
- onClick={() => (data.deleteMearseType = "ing")}
|
|
|
+ onClick={() => (data.addMearseType = "pre")}
|
|
|
>
|
|
|
- 当前选中小节
|
|
|
+ 当前小节前
|
|
|
</NButton>
|
|
|
<NButton
|
|
|
- type={data.deleteMearseType === "finish" ? "primary" : "default"}
|
|
|
+ type={data.addMearseType === "next" ? "primary" : "default"}
|
|
|
secondary
|
|
|
- onClick={() => (data.deleteMearseType = "finish")}
|
|
|
+ onClick={() => (data.addMearseType = "next")}
|
|
|
>
|
|
|
- 末尾空白小节
|
|
|
+ 当前小节后
|
|
|
</NButton>
|
|
|
- </NSpace>
|
|
|
-
|
|
|
- <NSpace style={{ marginTop: "20px" }} align="center" wrap={false} wrapItem={false}>
|
|
|
<NButton
|
|
|
- style={{ width: "48%" }}
|
|
|
- round
|
|
|
- onClick={() => (popup.mearseDeleteShow = false)}
|
|
|
+ type={data.addMearseType === "finish" ? "primary" : "default"}
|
|
|
+ secondary
|
|
|
+ onClick={() => (data.addMearseType = "finish")}
|
|
|
>
|
|
|
- 取消
|
|
|
+ 曲谱末尾
|
|
|
</NButton>
|
|
|
- <NButton
|
|
|
- style={{ width: "48%" }}
|
|
|
- round
|
|
|
- type="primary"
|
|
|
- onClick={() => handleDeleteMearse()}
|
|
|
+ </NSpace>
|
|
|
+
|
|
|
+ <div class={styles.btnLineTitle}>小节数</div>
|
|
|
+
|
|
|
+ <NSpace vertical>
|
|
|
+ <NInputNumber
|
|
|
+ min={1}
|
|
|
+ v-model:value={data.addMearseNumber}
|
|
|
+ placeholder="请输入小节数"
|
|
|
+ />
|
|
|
+
|
|
|
+ <NSpace
|
|
|
+ style={{ marginTop: "20px" }}
|
|
|
+ align="center"
|
|
|
+ wrap={false}
|
|
|
+ wrapItem={false}
|
|
|
>
|
|
|
- 确定
|
|
|
- </NButton>
|
|
|
+ <NButton
|
|
|
+ style={{ width: "48%" }}
|
|
|
+ round
|
|
|
+ onClick={() => (popup.barShow = false)}
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ style={{ width: "48%" }}
|
|
|
+ round
|
|
|
+ type="primary"
|
|
|
+ onClick={() => handleAddMearse()}
|
|
|
+ >
|
|
|
+ 确定
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
</NSpace>
|
|
|
- </NSpace>
|
|
|
- </>
|
|
|
- ),
|
|
|
- }}
|
|
|
- </NPopover>
|
|
|
-
|
|
|
- <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")} />
|
|
|
+ </>
|
|
|
+ ),
|
|
|
+ }}
|
|
|
+ </NPopover>
|
|
|
+
|
|
|
+ <NPopover
|
|
|
+ class={styles.popupWrap}
|
|
|
+ v-model:show={popup.mearseDeleteShow}
|
|
|
+ trigger="click"
|
|
|
+ placement="bottom"
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div class={[styles.topBtn]}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_19.png")} />
|
|
|
+ </div>
|
|
|
+ <div>删除小节</div>
|
|
|
+ </div>
|
|
|
+ ),
|
|
|
+ default: () => (
|
|
|
+ <>
|
|
|
+ <div class={styles.btnLineTitle}>删除方式</div>
|
|
|
+
|
|
|
+ <NSpace vertical>
|
|
|
+ <NSpace>
|
|
|
+ <NButton
|
|
|
+ type={data.deleteMearseType === "ing" ? "primary" : "default"}
|
|
|
+ secondary
|
|
|
+ onClick={() => (data.deleteMearseType = "ing")}
|
|
|
+ >
|
|
|
+ 当前选中小节
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ type={data.deleteMearseType === "finish" ? "primary" : "default"}
|
|
|
+ secondary
|
|
|
+ onClick={() => (data.deleteMearseType = "finish")}
|
|
|
+ >
|
|
|
+ 末尾空白小节
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
+
|
|
|
+ <NSpace
|
|
|
+ style={{ marginTop: "20px" }}
|
|
|
+ align="center"
|
|
|
+ wrap={false}
|
|
|
+ wrapItem={false}
|
|
|
+ >
|
|
|
+ <NButton
|
|
|
+ style={{ width: "48%" }}
|
|
|
+ round
|
|
|
+ onClick={() => (popup.mearseDeleteShow = false)}
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ style={{ width: "48%" }}
|
|
|
+ round
|
|
|
+ type="primary"
|
|
|
+ onClick={() => handleDeleteMearse()}
|
|
|
+ >
|
|
|
+ 确定
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
+ </NSpace>
|
|
|
+ </>
|
|
|
+ ),
|
|
|
+ }}
|
|
|
+ </NPopover>
|
|
|
+
|
|
|
+ <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>重播</div>
|
|
|
</div>
|
|
|
- <div>重播</div>
|
|
|
- </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 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
|
|
|
+ id="selectMearesBtn"
|
|
|
+ class={[styles.topBtn]}
|
|
|
+ onClick={() => (popup.selectMearesShow = !popup.selectMearesShow)}
|
|
|
+ >
|
|
|
+ <div class={[styles.btnImg, popup.selectMearesShow && styles.btnImgActive]}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_22.png")} />
|
|
|
</div>
|
|
|
- </NSpin>
|
|
|
- <div>{data.playState ? "暂停" : "播放"}</div>
|
|
|
- </div>
|
|
|
- <div
|
|
|
- id="selectMearesBtn"
|
|
|
- class={[styles.topBtn]}
|
|
|
- onClick={() => (popup.selectMearesShow = !popup.selectMearesShow)}
|
|
|
- >
|
|
|
- <div class={[styles.btnImg, popup.selectMearesShow && styles.btnImgActive]}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_22.png")} />
|
|
|
+ <div>选段</div>
|
|
|
</div>
|
|
|
- <div>选段</div>
|
|
|
- </div>
|
|
|
|
|
|
- <div class={[styles.topBtn, styles.btnDisabled]}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_23.png")} />
|
|
|
+ <div class={[styles.topBtn, styles.btnDisabled]}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_23.png")} />
|
|
|
+ </div>
|
|
|
+ <div>节拍器</div>
|
|
|
</div>
|
|
|
- <div>节拍器</div>
|
|
|
- </div>
|
|
|
- <div class={[styles.topBtn]} onClick={() => (popup.settingShow = true)}>
|
|
|
- <div class={styles.btnImg}>
|
|
|
- <img class={styles.topBtnIcon} src={getImage("icon_24.png")} />
|
|
|
+ <div class={[styles.topBtn]} onClick={() => (popup.settingShow = true)}>
|
|
|
+ <div class={styles.btnImg}>
|
|
|
+ <img class={styles.topBtnIcon} src={getImage("icon_24.png")} />
|
|
|
+ </div>
|
|
|
+ <div>设置</div>
|
|
|
</div>
|
|
|
- <div>设置</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div class={styles.content}>
|
|
|
- <div class={styles.slide}>
|
|
|
- <Collapse v-model={data.slide} elevation={false} divider={false}>
|
|
|
- <CollapseItem title="音符时值" name="note">
|
|
|
- <div class={styles.wrapBox}>
|
|
|
- {ABC_DATA.types.map((item) => (
|
|
|
- <div
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "type", value: item.value })}
|
|
|
- >
|
|
|
- <div class={[styles.btnImg, data.noteType === item.value && styles.btnImgActive]}>
|
|
|
- <TheIcon iconClassName={item.icon} />
|
|
|
- </div>
|
|
|
- <div>{item.name}</div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- <div class={styles.topBtn} onClick={() => handleChange({ type: "note", value: "z" })}>
|
|
|
- <div
|
|
|
- class={[styles.btnImg, noteComputed.value.content === "z" && styles.btnImgActive]}
|
|
|
- >
|
|
|
- <img style={{ width: "20px", height: "20px" }} src={getImage("icon_rest.png")} />
|
|
|
- </div>
|
|
|
- <div>休止符</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class={styles.topBtn} onClick={() => handleChange({ type: "segno", value: " " })}>
|
|
|
- <div
|
|
|
- class={[styles.btnImg, noteComputed.value.segno === " " && styles.btnImgActive]}
|
|
|
- >
|
|
|
- {/* <img style={{ width: "20px", height: "20px" }} src={getImage("icon_rest.png")} /> */}
|
|
|
- </div>
|
|
|
- <div>分割</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </CollapseItem>
|
|
|
-
|
|
|
- <CollapseItem title="拍号" name="meter">
|
|
|
- <div class={styles.wrapBox}>
|
|
|
- {ABC_DATA.meter.map((item) => (
|
|
|
- <div
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "meter", value: item.value })}
|
|
|
- >
|
|
|
- <div class={[styles.btnImg]}>
|
|
|
- <TheIcon iconClassName={item.icon} />
|
|
|
+ <div class={styles.content}>
|
|
|
+ <div class={styles.slide}>
|
|
|
+ <Collapse v-model={data.slide} elevation={false} divider={false}>
|
|
|
+ <CollapseItem title="音符时值" name="note">
|
|
|
+ <div class={styles.wrapBox}>
|
|
|
+ {ABC_DATA.types.map((item) => (
|
|
|
+ <div
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => handleChange({ type: "type", value: item.value })}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class={[styles.btnImg, data.noteType === item.value && styles.btnImgActive]}
|
|
|
+ >
|
|
|
+ <TheIcon iconClassName={item.icon} />
|
|
|
+ </div>
|
|
|
+ <div>{item.name}</div>
|
|
|
</div>
|
|
|
- <div>{item.name}</div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- </CollapseItem>
|
|
|
-
|
|
|
- <CollapseItem title="力度记号" name="dynamics">
|
|
|
- <div class={styles.wrapBox}>
|
|
|
- {ABC_DATA.dynamics.slice(0, 8).map((item) => (
|
|
|
+ ))}
|
|
|
<div
|
|
|
class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "dynamics", value: item.value })}
|
|
|
+ onClick={() => handleChange({ type: "note", value: "z" })}
|
|
|
>
|
|
|
<div
|
|
|
class={[
|
|
|
styles.btnImg,
|
|
|
- noteComputed.value.dynamics === item.value && styles.btnImgActive,
|
|
|
+ noteComputed.value.content === "z" && styles.btnImgActive,
|
|
|
]}
|
|
|
>
|
|
|
- <TheIcon iconClassName={item.icon} size={["2em", "2em"]} />
|
|
|
+ <img style={{ width: "20px", height: "20px" }} src={getImage("icon_rest.png")} />
|
|
|
</div>
|
|
|
- <div>{item.name}</div>
|
|
|
+ <div>休止符</div>
|
|
|
</div>
|
|
|
- ))}
|
|
|
- <div
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "dynamics", value: ABC_DATA.dynamics[8].value })}
|
|
|
- >
|
|
|
+
|
|
|
<div
|
|
|
- class={[
|
|
|
- styles.btnImg,
|
|
|
- ABC_DATA.dynamics[8].value.includes(noteComputed.value.dynamics) &&
|
|
|
- styles.btnImgActive,
|
|
|
- ]}
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => handleChange({ type: "segno", value: " " })}
|
|
|
>
|
|
|
- <TheIcon iconClassName={ABC_DATA.dynamics[8].icon} size={["2em", "2em"]} />
|
|
|
+ <div
|
|
|
+ class={[styles.btnImg, noteComputed.value.segno === " " && styles.btnImgActive]}
|
|
|
+ >
|
|
|
+ {/* <img style={{ width: "20px", height: "20px" }} src={getImage("icon_rest.png")} /> */}
|
|
|
+ </div>
|
|
|
+ <div>分割</div>
|
|
|
</div>
|
|
|
- <div>{ABC_DATA.dynamics[8].name}</div>
|
|
|
</div>
|
|
|
- <div
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "dynamics", value: ABC_DATA.dynamics[9].value })}
|
|
|
- >
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.btnImg,
|
|
|
- ABC_DATA.dynamics[9].value.includes(noteComputed.value.dynamics) &&
|
|
|
- styles.btnImgActive,
|
|
|
- ]}
|
|
|
- >
|
|
|
- <TheIcon iconClassName={ABC_DATA.dynamics[9].icon} size={["2em", "2em"]} />
|
|
|
- </div>
|
|
|
- <div>{ABC_DATA.dynamics[9].name}</div>
|
|
|
+ </CollapseItem>
|
|
|
+
|
|
|
+ <CollapseItem title="拍号" name="meter">
|
|
|
+ <div class={styles.wrapBox}>
|
|
|
+ {ABC_DATA.meter.map((item) => (
|
|
|
+ <div
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => handleChange({ type: "meter", value: item.value })}
|
|
|
+ >
|
|
|
+ <div class={[styles.btnImg]}>
|
|
|
+ <TheIcon iconClassName={item.icon} />
|
|
|
+ </div>
|
|
|
+ <div>{item.name}</div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </CollapseItem>
|
|
|
- <CollapseItem title="反复与跳跃" name="repeat">
|
|
|
- <div class={styles.wrapBox}>
|
|
|
- {ABC_DATA.repeat.map((item) => (
|
|
|
+ </CollapseItem>
|
|
|
+
|
|
|
+ <CollapseItem title="力度记号" name="dynamics">
|
|
|
+ <div class={styles.wrapBox}>
|
|
|
+ {ABC_DATA.dynamics.slice(0, 8).map((item) => (
|
|
|
+ <div
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => handleChange({ type: "dynamics", value: item.value })}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.btnImg,
|
|
|
+ noteComputed.value.dynamics === item.value && styles.btnImgActive,
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <TheIcon iconClassName={item.icon} size={["2em", "2em"]} />
|
|
|
+ </div>
|
|
|
+ <div>{item.name}</div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
<div
|
|
|
- class={[styles.topBtn, styles.longTopBtn]}
|
|
|
- onClick={() => handleChange({ type: "repeat", value: item.value })}
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() =>
|
|
|
+ handleChange({ type: "dynamics", value: ABC_DATA.dynamics[8].value })
|
|
|
+ }
|
|
|
>
|
|
|
<div
|
|
|
class={[
|
|
|
styles.btnImg,
|
|
|
- measureComputed.value.repeat === item.value && styles.btnImgActive,
|
|
|
+ ABC_DATA.dynamics[8].value.includes(noteComputed.value.dynamics) &&
|
|
|
+ styles.btnImgActive,
|
|
|
]}
|
|
|
>
|
|
|
- <TheIcon iconClassName={item.icon} size={["5em", "1em"]} />
|
|
|
+ <TheIcon iconClassName={ABC_DATA.dynamics[8].icon} size={["2em", "2em"]} />
|
|
|
</div>
|
|
|
- <div>{item.name}</div>
|
|
|
+ <div>{ABC_DATA.dynamics[8].name}</div>
|
|
|
</div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- </CollapseItem>
|
|
|
- <CollapseItem title="小节线" name="line">
|
|
|
- <div class={styles.wrapBox}>
|
|
|
- {ABC_DATA.bar.map((item) => (
|
|
|
<div
|
|
|
class={styles.topBtn}
|
|
|
- onClick={() => {
|
|
|
- data.morePlay = false;
|
|
|
- handleChange({ type: "barline", value: item.value });
|
|
|
- }}
|
|
|
+ onClick={() =>
|
|
|
+ handleChange({ type: "dynamics", value: ABC_DATA.dynamics[9].value })
|
|
|
+ }
|
|
|
>
|
|
|
<div
|
|
|
class={[
|
|
|
styles.btnImg,
|
|
|
- measureComputed.value.barline === item.value && styles.btnImgActive,
|
|
|
+ ABC_DATA.dynamics[9].value.includes(noteComputed.value.dynamics) &&
|
|
|
+ styles.btnImgActive,
|
|
|
]}
|
|
|
>
|
|
|
- <TheIcon iconClassName={item.icon} size={["2em", "2em"]} />
|
|
|
+ <TheIcon iconClassName={ABC_DATA.dynamics[9].icon} size={["2em", "2em"]} />
|
|
|
</div>
|
|
|
- <div>{item.name}</div>
|
|
|
+ <div>{ABC_DATA.dynamics[9].name}</div>
|
|
|
</div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- </CollapseItem>
|
|
|
+ </div>
|
|
|
+ </CollapseItem>
|
|
|
+ <CollapseItem title="反复与跳跃" name="repeat">
|
|
|
+ <div class={styles.wrapBox}>
|
|
|
+ {ABC_DATA.repeat.map((item) => (
|
|
|
+ <div
|
|
|
+ class={[styles.topBtn, styles.longTopBtn]}
|
|
|
+ onClick={() => handleChange({ type: "repeat", value: item.value })}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.btnImg,
|
|
|
+ measureComputed.value.repeat === item.value && styles.btnImgActive,
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <TheIcon iconClassName={item.icon} size={["5em", "1em"]} />
|
|
|
+ </div>
|
|
|
+ <div>{item.name}</div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </CollapseItem>
|
|
|
+ <CollapseItem title="小节线" name="line">
|
|
|
+ <div class={styles.wrapBox}>
|
|
|
+ {ABC_DATA.bar.map((item) => (
|
|
|
+ <div
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => {
|
|
|
+ data.morePlay = false;
|
|
|
+ handleChange({ type: "barline", value: item.value });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.btnImg,
|
|
|
+ measureComputed.value.barline === item.value && styles.btnImgActive,
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <TheIcon iconClassName={item.icon} size={["2em", "2em"]} />
|
|
|
+ </div>
|
|
|
+ <div>{item.name}</div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </CollapseItem>
|
|
|
|
|
|
- <CollapseItem title="谱号" name="clef">
|
|
|
- <div class={styles.wrapBox}>
|
|
|
- {ABC_DATA.clef.map((item) => (
|
|
|
- <div
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "clef", value: item.value })}
|
|
|
- >
|
|
|
- <div class={[styles.btnImg]}>
|
|
|
- <TheIcon iconClassName={item.icon} />
|
|
|
+ <CollapseItem title="谱号" name="clef">
|
|
|
+ <div class={styles.wrapBox}>
|
|
|
+ {ABC_DATA.clef.map((item) => (
|
|
|
+ <div
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => handleChange({ type: "clef", value: item.value })}
|
|
|
+ >
|
|
|
+ <div class={[styles.btnImg]}>
|
|
|
+ <TheIcon iconClassName={item.icon} />
|
|
|
+ </div>
|
|
|
+ <div>{item.name}</div>
|
|
|
</div>
|
|
|
- <div>{item.name}</div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- </CollapseItem>
|
|
|
- <CollapseItem title="调号" name="key">
|
|
|
- <div class={styles.wrapBox}>
|
|
|
- {ABC_DATA.key.map((item) => (
|
|
|
- <div
|
|
|
- class={styles.topBtn}
|
|
|
- onClick={() => handleChange({ type: "key", value: item.value })}
|
|
|
- >
|
|
|
- <div class={[styles.btnImg]}>
|
|
|
- <TheIcon iconClassName={item.icon} />
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </CollapseItem>
|
|
|
+ <CollapseItem title="调号" name="key">
|
|
|
+ <div class={styles.wrapBox}>
|
|
|
+ {ABC_DATA.key.map((item) => (
|
|
|
+ <div
|
|
|
+ class={styles.topBtn}
|
|
|
+ onClick={() => handleChange({ type: "key", value: item.value })}
|
|
|
+ >
|
|
|
+ <div class={[styles.btnImg]}>
|
|
|
+ <TheIcon iconClassName={item.icon} />
|
|
|
+ </div>
|
|
|
+ <div>{item.name}</div>
|
|
|
</div>
|
|
|
- <div>{item.name}</div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- </CollapseItem>
|
|
|
- </Collapse>
|
|
|
- </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </CollapseItem>
|
|
|
+ </Collapse>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class={styles.box}>
|
|
|
- <div class={styles.titleBox}>
|
|
|
- <div class={styles.titleName} style={{ width: "50%", margin: "0 auto" }}>
|
|
|
- <NInput
|
|
|
- onKeyup={(e: Event) => e.stopPropagation()}
|
|
|
- v-model:value={data.musicName}
|
|
|
- placeholder="曲谱名称"
|
|
|
- />
|
|
|
+ <div class={styles.box}>
|
|
|
+ <div class={styles.titleBox}>
|
|
|
+ <div class={styles.titleName} style={{ width: "50%", margin: "0 auto" }}>
|
|
|
+ <NInput
|
|
|
+ onKeyup={(e: Event) => e.stopPropagation()}
|
|
|
+ v-model:value={data.musicName}
|
|
|
+ placeholder="曲谱名称"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div style={{ width: "30%", margin: "10px 0 0 auto" }}>
|
|
|
+ <NInput
|
|
|
+ onKeyup={(e: Event) => e.stopPropagation()}
|
|
|
+ v-model:value={data.creator}
|
|
|
+ placeholder="曲谱作者"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div style={{ width: "30%", margin: "10px 0 0 auto" }}>
|
|
|
- <NInput
|
|
|
- onKeyup={(e: Event) => e.stopPropagation()}
|
|
|
- v-model:value={data.creator}
|
|
|
- placeholder="曲谱作者"
|
|
|
+ <div id="paper"></div>
|
|
|
+ {!data.loading && (
|
|
|
+ <Keys
|
|
|
+ show={data.active ? true : false}
|
|
|
+ instrumentCode={abcData.abc.subjectCode}
|
|
|
+ onClick={(val) => handleChange(val)}
|
|
|
/>
|
|
|
- </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* <textarea ref={textAreaRef} class={styles.value} id="abc"></textarea> */}
|
|
|
+ <div id="audio" style={{ display: "none" }}></div>
|
|
|
+ <div id="warnings"></div>
|
|
|
+
|
|
|
+ <p class="beat"></p>
|
|
|
+ <pre class="clicked-info"></pre>
|
|
|
+ <pre class="feedback"></pre>
|
|
|
+ <div id="container"></div>
|
|
|
+ {data.loadingAudioSrouce && (
|
|
|
+ <div class={styles.loading}>
|
|
|
+ <NSpin></NSpin>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
</div>
|
|
|
- <div id="paper"></div>
|
|
|
- {!data.loading && (
|
|
|
- <Keys
|
|
|
- show={data.active ? true : false}
|
|
|
- instrumentCode={abcData.abc.subjectCode}
|
|
|
- onClick={(val) => handleChange(val)}
|
|
|
- />
|
|
|
- )}
|
|
|
-
|
|
|
- {/* <textarea ref={textAreaRef} class={styles.value} id="abc"></textarea> */}
|
|
|
- <div id="audio" style={{ display: "none" }}></div>
|
|
|
- <div id="warnings"></div>
|
|
|
-
|
|
|
- <p class="beat"></p>
|
|
|
- <pre class="clicked-info"></pre>
|
|
|
- <pre class="feedback"></pre>
|
|
|
- <div id="container"></div>
|
|
|
- {data.loadingAudioSrouce && (
|
|
|
- <div class={styles.loading}>
|
|
|
- <NSpin></NSpin>
|
|
|
- </div>
|
|
|
- )}
|
|
|
</div>
|
|
|
+ <div ref={downRef}></div>
|
|
|
+
|
|
|
+ <TheSetting v-model:show={popup.settingShow} />
|
|
|
+
|
|
|
+ {data.selectMeasures.state && (
|
|
|
+ <UseDraggable
|
|
|
+ initialValue={{ x: data.selectMeasures.x, y: data.selectMeasures.y }}
|
|
|
+ class={[styles.selectMearesBox, !popup.selectMearesShow && styles.selectMearesHidden]}
|
|
|
+ >
|
|
|
+ <div onKeyup={(e: Event) => e.stopPropagation()}>
|
|
|
+ <NSpace justify="space-between">
|
|
|
+ <div class={styles.btnLineTitle}>输入小节范围</div>
|
|
|
+ <NButton
|
|
|
+ circle
|
|
|
+ quaternary
|
|
|
+ size="small"
|
|
|
+ onClick={() => (popup.selectMearesShow = false)}
|
|
|
+ >
|
|
|
+ <NIcon size={16} component={<Close />} />
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
+ <NSpace align="center" wrap={false} wrapItem={false}>
|
|
|
+ <div class={styles.mearesInput}>
|
|
|
+ <NInputNumber
|
|
|
+ min={1}
|
|
|
+ max={data.selectMeasures.max}
|
|
|
+ bordered={false}
|
|
|
+ placeholder="开始小节"
|
|
|
+ showButton={false}
|
|
|
+ onUpdate:value={(val) => handleSetSelectMeares(val, "start")}
|
|
|
+ ></NInputNumber>
|
|
|
+ -
|
|
|
+ <NInputNumber
|
|
|
+ min={data.selectMeasures.start}
|
|
|
+ max={data.selectMeasures.max}
|
|
|
+ bordered={false}
|
|
|
+ placeholder="结束小节"
|
|
|
+ showButton={false}
|
|
|
+ onUpdate:value={(val) => handleSetSelectMeares(val, "end")}
|
|
|
+ ></NInputNumber>
|
|
|
+ </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>
|
|
|
+ </NSpace>
|
|
|
+ </div>
|
|
|
+ </UseDraggable>
|
|
|
+ )}
|
|
|
</div>
|
|
|
- <div ref={downRef}></div>
|
|
|
-
|
|
|
- <TheSetting v-model:show={popup.settingShow} />
|
|
|
-
|
|
|
- {data.selectMeasures.state && (
|
|
|
- <UseDraggable
|
|
|
- initialValue={{ x: data.selectMeasures.x, y: data.selectMeasures.y }}
|
|
|
- class={[styles.selectMearesBox, !popup.selectMearesShow && styles.selectMearesHidden]}
|
|
|
- >
|
|
|
- <div onKeyup={(e: Event) => e.stopPropagation()}>
|
|
|
- <NSpace justify="space-between">
|
|
|
- <div class={styles.btnLineTitle}>输入小节范围</div>
|
|
|
- <NButton circle quaternary size="small" onClick={() => (popup.selectMearesShow = false)}>
|
|
|
- <NIcon size={16} component={<Close />} />
|
|
|
- </NButton>
|
|
|
- </NSpace>
|
|
|
- <NSpace align="center" wrap={false} wrapItem={false}>
|
|
|
- <div class={styles.mearesInput}>
|
|
|
- <NInputNumber
|
|
|
- min={1}
|
|
|
- max={data.selectMeasures.max}
|
|
|
- bordered={false}
|
|
|
- placeholder="开始小节"
|
|
|
- showButton={false}
|
|
|
- onUpdate:value={(val) => handleSetSelectMeares(val, "start")}
|
|
|
- ></NInputNumber>
|
|
|
- -
|
|
|
- <NInputNumber
|
|
|
- min={data.selectMeasures.start}
|
|
|
- max={data.selectMeasures.max}
|
|
|
- bordered={false}
|
|
|
- placeholder="结束小节"
|
|
|
- showButton={false}
|
|
|
- onUpdate:value={(val) => handleSetSelectMeares(val, "end")}
|
|
|
- ></NInputNumber>
|
|
|
- </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>
|
|
|
- </NSpace>
|
|
|
- </div>
|
|
|
- </UseDraggable>
|
|
|
- )}
|
|
|
- </div>
|
|
|
+ <div class={styles.exportPng}>
|
|
|
+ <div id="exportPng"></div>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
);
|
|
|
},
|
|
|
});
|