import { PropType, computed, defineComponent, onBeforeMount, reactive } from "vue"; import styles from "./index.module.less"; import icons from "./image/icons.json"; import { FIGNER_INSTRUMENT_DATA, IFIGNER_INSTRUMENT_Note } from "/src/view/figner-preview"; import { ITypeFingering, IVocals, getFingeringConfig, subjectFingering, } from "/src/view/fingering/fingering-config"; import { Howl } from "howler"; import { storeData } from "/src/store"; import { api_back } from "/src/helpers/communication"; import { Button, Icon } from "vant"; export default defineComponent({ name: "viewFigner", emits: ["close"], props: { isComponent: { type: Boolean, default: false, }, subject: { type: String as PropType, default: "", }, }, setup(props, { emit }) { const subject = props.subject || "pan-flute"; const data = reactive({ subject: subject, realKey: 0, notes: [] as IFIGNER_INSTRUMENT_Note[], soundFonts: {} as any, viewIndex: 0, }); const fingerData = reactive({ relationshipIndex: 0, subject: null as unknown as ITypeFingering, fingeringInfo: subjectFingering(data.subject), }); const getNotes = () => { const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA]; if (fignerData) { data.notes = fignerData.list; } }; const getFingeringData = async () => { const subject: any = data.subject + (data.viewIndex === 0 ? "" : data.viewIndex); fingerData.subject = await getFingeringConfig(subject); }; const getSounFonts = () => { const pathname = /(192|localhost)/.test(location.origin) ? "/" : location.pathname; for (let i = 0; i < data.notes.length; i++) { const note = data.notes[i]; // console.log("🚀 ~ note:", i) let url = `${pathname}soundfonts/${data.subject}/`; url += note.realName; url += ".mp3"; const noteAudio = new Howl({ src: url, loop: true, }); data.soundFonts[note.realKey] = noteAudio; } // console.log("🚀 ~ data.soundFonts:", data.soundFonts); }; onBeforeMount(() => { getNotes(); getFingeringData(); getSounFonts(); }); const noteClick = (item: IFIGNER_INSTRUMENT_Note, type: "start" | "stop") => { // console.log("🚀 ~ item:", item); const noteAudio = data.soundFonts[item.realKey]; if (type === "start") { data.realKey = item.realKey; if (noteAudio) { noteAudio.play(); } } else { data.realKey = 0; if (noteAudio) { noteAudio.stop(); } } }; /** 返回 */ const handleBack = () => { if (props.isComponent) { console.log("关闭"); emit("close"); return; } // 不在APP中, if (!storeData.isApp) { window.close(); return; } api_back(); }; return () => { const relationship = fingerData.subject?.relationship?.[data.realKey] || []; const rs: number[] = Array.isArray(relationship[1]) ? relationship[fingerData.relationshipIndex] : relationship; const canTizhi = Array.isArray(relationship[1]); return (
{data.subject === "pan-flute" && (
{ data.viewIndex++; if (data.viewIndex > 1) { data.viewIndex = 0; } getFingeringData(); }} > 切换视图
)}
还原
小技巧
{rs.map((key: number | string, index: number) => { const nk: string = typeof key === "string" ? key.replace("active-", "") : String(key); return ; })}
(fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0) } > 替指
{/* */}
{data.notes.map((note: IFIGNER_INSTRUMENT_Note) => { const steps = new Array(Math.abs(note.step)).fill(1); return (
noteClick(note, "start")} onKeyup={() => noteClick(note, "start")} onMouseleave={() => noteClick(note, "stop")} onTouchstart={() => noteClick(note, "start")} onTouchend={() => noteClick(note, "stop")} onTouchcancel={() => noteClick(note, "stop")} > {data.realKey === note.realKey ? ( ) : ( )}
{note.step > 0 ? steps.map((n) => ) : null}
{note.mark && (note.mark === "rise" ? "#" : "b")} {note.key}
{note.step < 0 ? steps.map((n) => ) : null}
); })}
{/* */}
); }; }, });