|
@@ -12,6 +12,7 @@ import { Howl } from "howler";
|
|
|
import { storeData } from "/src/store";
|
|
|
import { api_back } from "/src/helpers/communication";
|
|
|
import Hammer from "hammerjs";
|
|
|
+import { Button, Icon, Popup, Space } from "vant";
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: "viewFigner",
|
|
@@ -33,7 +34,8 @@ export default defineComponent({
|
|
|
realKey: 0,
|
|
|
notes: [] as IFIGNER_INSTRUMENT_Note[],
|
|
|
tones: [] as IFIGNER_INSTRUMENT_Note[],
|
|
|
- activeTone: "",
|
|
|
+ activeTone: {} as IFIGNER_INSTRUMENT_Note,
|
|
|
+ activeToneName: "",
|
|
|
soundFonts: {} as any,
|
|
|
viewIndex: 0,
|
|
|
noteAudio: null as unknown as Howl,
|
|
@@ -46,6 +48,10 @@ export default defineComponent({
|
|
|
startY: 0,
|
|
|
transition: "",
|
|
|
},
|
|
|
+ tipShow: false,
|
|
|
+ tips: [] as IFIGNER_INSTRUMENT_Note[],
|
|
|
+
|
|
|
+ tnoteShow: false,
|
|
|
});
|
|
|
const fingerData = reactive({
|
|
|
relationshipIndex: 0,
|
|
@@ -57,15 +63,16 @@ export default defineComponent({
|
|
|
if (fignerData) {
|
|
|
data.tones = fignerData.tones || [];
|
|
|
if (data.tones.length) {
|
|
|
- data.activeTone = data.tones[0].realName;
|
|
|
+ data.activeTone = data.tones[0];
|
|
|
}
|
|
|
+ data.tips = fignerData.tips || [];
|
|
|
setNotes();
|
|
|
}
|
|
|
};
|
|
|
const setNotes = () => {
|
|
|
const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA];
|
|
|
if (fignerData) {
|
|
|
- data.notes = fignerData[`list${data.activeTone}`];
|
|
|
+ data.notes = fignerData[`list${data.activeTone.realName || ""}`];
|
|
|
}
|
|
|
};
|
|
|
const getFingeringData = async () => {
|
|
@@ -213,104 +220,167 @@ export default defineComponent({
|
|
|
<img src={icons.icon_2_0} />
|
|
|
<span>还原</span>
|
|
|
</div>
|
|
|
- <div class={[styles.item]}>
|
|
|
- <img src={icons.icon_2_1} />
|
|
|
- <span>小技巧</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div id="fingeringContainer" class={styles.fingerContent}>
|
|
|
- <div
|
|
|
- style={{
|
|
|
- transform: `translate3d(${data.transform.x}px,${data.transform.y}px,0px) scale(${data.transform.scale})`,
|
|
|
- transition: data.transform.transition,
|
|
|
- }}
|
|
|
- class={[styles.fingeringContainer]}
|
|
|
- >
|
|
|
- <div class={styles.imgs}>
|
|
|
- <img src={fingerData.subject?.json?.full} />
|
|
|
- {rs.map((key: number | string, index: number) => {
|
|
|
- const nk: string = typeof key === "string" ? key.replace("active-", "") : String(key);
|
|
|
- return <img data-index={nk} src={fingerData.subject?.json?.[nk]} />;
|
|
|
- })}
|
|
|
- </div>
|
|
|
-
|
|
|
<div
|
|
|
- class={[styles.tizhi, canTizhi && styles.canDisplay]}
|
|
|
- onClick={() =>
|
|
|
- (fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)
|
|
|
- }
|
|
|
+ class={[styles.item]}
|
|
|
+ onClick={() => {
|
|
|
+ resetElement();
|
|
|
+ data.tipShow = !data.tipShow;
|
|
|
+ }}
|
|
|
>
|
|
|
- 替指
|
|
|
+ <img src={icons.icon_2_1} />
|
|
|
+ <span>使用说明</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.fingerContent,
|
|
|
+ fingerData.fingeringInfo.orientation === 1 ? styles.fingerBottom : styles.fingerRight,
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <div class={styles.wrapFinger}>
|
|
|
+ <div id="fingeringContainer" class={styles.boxFinger}>
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ transform: `translate3d(${data.transform.x}px,${data.transform.y}px,0px) scale(${data.transform.scale})`,
|
|
|
+ transition: data.transform.transition,
|
|
|
+ }}
|
|
|
+ class={[styles.fingeringContainer]}
|
|
|
+ >
|
|
|
+ <div class={styles.imgs}>
|
|
|
+ <img src={fingerData.subject?.json?.full} />
|
|
|
+ {rs.map((key: number | string, index: number) => {
|
|
|
+ const nk: string =
|
|
|
+ typeof key === "string" ? key.replace("active-", "") : String(key);
|
|
|
+ return <img data-index={nk} src={fingerData.subject?.json?.[nk]} />;
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
|
|
|
- <div class={styles.tones} style={{display: data.tones.length ? '' : 'none'}}>
|
|
|
- {data.tones.map((tone: IFIGNER_INSTRUMENT_Note) => {
|
|
|
- const steps = new Array(Math.abs(tone.step)).fill(1);
|
|
|
- return (
|
|
|
<div
|
|
|
- draggable={false}
|
|
|
- class={styles.note}
|
|
|
- onClick={() => {
|
|
|
- data.activeTone = tone.realName;
|
|
|
- setNotes();
|
|
|
- }}
|
|
|
+ class={[styles.tizhi, canTizhi && styles.canDisplay]}
|
|
|
+ onClick={() =>
|
|
|
+ (fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)
|
|
|
+ }
|
|
|
>
|
|
|
- {data.activeTone === tone.realName ? (
|
|
|
- <img draggable={false} src={icons.icon_btn_ylow} />
|
|
|
- ) : (
|
|
|
- <img draggable={false} src={icons.icon_btn_blue} />
|
|
|
- )}
|
|
|
+ 替指
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.notes}>
|
|
|
+ {/* <Button>
|
|
|
+ <Icon name="arrow-left" />
|
|
|
+ </Button> */}
|
|
|
+ <div class={styles.noteContent}>
|
|
|
+ <div class={styles.noteBox}>
|
|
|
+ {data.notes.map((note: IFIGNER_INSTRUMENT_Note) => {
|
|
|
+ const steps = new Array(Math.abs(note.step)).fill(1);
|
|
|
+ return (
|
|
|
+ <div draggable={false} class={styles.note} onClick={() => noteClick(note)}>
|
|
|
+ {data.realKey === note.realKey ? (
|
|
|
+ <img draggable={false} src={icons.icon_btn_ylow} />
|
|
|
+ ) : (
|
|
|
+ <img draggable={false} src={icons.icon_btn_blue} />
|
|
|
+ )}
|
|
|
|
|
|
- <div class={[styles.noteKey, data.activeTone === tone.realName && styles.keyActive]}>
|
|
|
- {tone.step > 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}
|
|
|
+ <div
|
|
|
+ class={[styles.noteKey, data.realKey === note.realKey && styles.keyActive]}
|
|
|
+ >
|
|
|
+ {note.step > 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}
|
|
|
|
|
|
- <div class={styles.noteName}>
|
|
|
- <sup>{tone.mark && (tone.mark === "rise" ? "#" : "b")}</sup>
|
|
|
- {tone.key}
|
|
|
- </div>
|
|
|
- {tone.step < 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}
|
|
|
+ <div class={styles.noteName}>
|
|
|
+ <sup>{note.mark && (note.mark === "rise" ? "#" : "b")}</sup>
|
|
|
+ {note.key}
|
|
|
+ </div>
|
|
|
+ {note.step < 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {/* <Button size="small" >
|
|
|
+ <Icon name="arrow" />
|
|
|
+ </Button> */}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={[styles.tips, data.tipShow ? "" : styles.tipHidden]}>
|
|
|
+ <div class={styles.tipTitle}>
|
|
|
+ <div class={styles.tipTitleName}>{fingerData.fingeringInfo.code}使用说明</div>
|
|
|
+ <Button class={styles.tipClose} onClick={() => (data.tipShow = false)}>
|
|
|
+ <Icon name="cross" color="#999" />
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ <div class={styles.tipContent}>
|
|
|
+ {data.tips.map((tip, tipIndex) => (
|
|
|
+ <div class={styles.tipItem}>
|
|
|
+ <div class={styles.iconWrap}>
|
|
|
+ <div class={styles.tipItemIcon}>{tipIndex + 1}</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {tip.name}: {tip.realName}
|
|
|
</div>
|
|
|
</div>
|
|
|
- );
|
|
|
- })}
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class={styles.notes}>
|
|
|
- {/* <Button>
|
|
|
- <Icon name="arrow-left" />
|
|
|
- </Button> */}
|
|
|
- <div class={styles.noteContent}>
|
|
|
- <div class={styles.noteBox}>
|
|
|
- {data.notes.map((note: IFIGNER_INSTRUMENT_Note) => {
|
|
|
- const steps = new Array(Math.abs(note.step)).fill(1);
|
|
|
- return (
|
|
|
- <div draggable={false} class={styles.note} onClick={() => noteClick(note)}>
|
|
|
- {data.realKey === note.realKey ? (
|
|
|
- <img draggable={false} src={icons.icon_btn_ylow} />
|
|
|
- ) : (
|
|
|
- <img draggable={false} src={icons.icon_btn_blue} />
|
|
|
- )}
|
|
|
+ <div class={styles.toggleBtn} onClick={() => (data.tnoteShow = true)}>
|
|
|
+ <div>
|
|
|
+ <sup>{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")}</sup>
|
|
|
+ {data.activeTone.name}
|
|
|
+ </div>
|
|
|
+ 调
|
|
|
+ <img src={icons.icon_arrow} />
|
|
|
+ </div>
|
|
|
|
|
|
- <div class={[styles.noteKey, data.realKey === note.realKey && styles.keyActive]}>
|
|
|
- {note.step > 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}
|
|
|
+ <Popup
|
|
|
+ class="tonePopup"
|
|
|
+ v-model:show={data.tnoteShow}
|
|
|
+ position={fingerData.fingeringInfo.orientation === 1 ? "bottom" : "right"}
|
|
|
+ >
|
|
|
+ <div class={styles.tones}>
|
|
|
+ <div class={styles.toneTitle}>
|
|
|
+ <div class={styles.tipTitleName}>移调</div>
|
|
|
+ <Button class={styles.tipClose} onClick={() => (data.tnoteShow = false)}>
|
|
|
+ <Icon name="cross" color="#999" />
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ <div style={{ flex: 1, overflow: "hidden" }}>
|
|
|
+ <div class={styles.toneContent}>
|
|
|
+ {data.tones.map((tone: IFIGNER_INSTRUMENT_Note) => {
|
|
|
+ const steps = new Array(Math.abs(tone.step)).fill(1);
|
|
|
+ return (
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ plain
|
|
|
+ type={data.activeTone.realName === tone.realName ? "primary" : "default"}
|
|
|
+ onClick={() => {
|
|
|
+ data.activeTone = tone;
|
|
|
+ setNotes();
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {/* {tone.step > 0 ? steps.map((n) => <span class={styles.dot}></span>) : null} */}
|
|
|
|
|
|
<div class={styles.noteName}>
|
|
|
- <sup>{note.mark && (note.mark === "rise" ? "#" : "b")}</sup>
|
|
|
- {note.key}
|
|
|
+ <sup>{tone.mark && (tone.mark === "rise" ? "#" : "b")}</sup>
|
|
|
+ {tone.name}
|
|
|
</div>
|
|
|
- {note.step < 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- );
|
|
|
- })}
|
|
|
+ {/* {tone.step < 0 ? steps.map((n) => <span class={styles.dot}></span>) : null} */}
|
|
|
+ </Button>
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.toneAction}>
|
|
|
+ <Button type="primary" round plain onClick={() => (data.tnoteShow = false)}>
|
|
|
+ 取消
|
|
|
+ </Button>
|
|
|
+ <Button type="primary" round onClick={() => (data.tnoteShow = false)}>
|
|
|
+ 确定
|
|
|
+ </Button>
|
|
|
</div>
|
|
|
</div>
|
|
|
- {/* <Button size="small" >
|
|
|
- <Icon name="arrow" />
|
|
|
- </Button> */}
|
|
|
- </div>
|
|
|
+ </Popup>
|
|
|
</div>
|
|
|
);
|
|
|
};
|