|
@@ -1,1060 +0,0 @@
|
|
-import { PropType, computed, defineComponent, nextTick, onBeforeMount, onMounted, onUnmounted, reactive, ref } from "vue";
|
|
|
|
-import styles from "./index.module.less";
|
|
|
|
-import icons from "./image/icons.json";
|
|
|
|
-import { FIGNER_INSTRUMENT_DATA, FIGNER_INSTRUMENT_REALKEY, IFIGNER_INSTRUMENT_Note } from "/src/view/figner-preview";
|
|
|
|
-import { ITypeFingering, IVocals, getFingeringConfig, mappingVoicePart, subjectFingering } from "/src/view/fingering/fingering-config";
|
|
|
|
-import { Howl } from "howler";
|
|
|
|
-import { storeData } from "/src/store";
|
|
|
|
-import { api_back, api_cloudLoading, api_setRequestedOrientation, api_setStatusBarVisibility, isSpecialShapedScreen } from "/src/helpers/communication";
|
|
|
|
-import Hammer from "hammerjs";
|
|
|
|
-import { Button, Icon, Loading, Popover, Popup, Progress, Space } from "vant";
|
|
|
|
-// import GuideIndex from "./guide/guide-index";
|
|
|
|
-import qs from "query-string";
|
|
|
|
-import { getQuery } from "/src/utils/queryString";
|
|
|
|
-import { browser } from "/src/utils";
|
|
|
|
-import { usePageVisibility } from "@vant/use";
|
|
|
|
-import { watch } from "vue";
|
|
|
|
-import icon_loading_img from "./image/icon_loading_img.png";
|
|
|
|
-import state, { IPlatform } from "/src/state";
|
|
|
|
-
|
|
|
|
-export default defineComponent({
|
|
|
|
- name: "viewFigner",
|
|
|
|
- emits: ["close"],
|
|
|
|
- props: {
|
|
|
|
- show: {
|
|
|
|
- type: Boolean,
|
|
|
|
- default: true,
|
|
|
|
- },
|
|
|
|
- // isComponent: {
|
|
|
|
- // type: Boolean,
|
|
|
|
- // default: false,
|
|
|
|
- // },
|
|
|
|
- // subject: {
|
|
|
|
- // type: String as PropType<IVocals>,
|
|
|
|
- // default: "",
|
|
|
|
- // },
|
|
|
|
- },
|
|
|
|
- setup(props, { emit }) {
|
|
|
|
- const query = getQuery();
|
|
|
|
- const browsInfo = browser();
|
|
|
|
- const code = query.subjectCode || mappingVoicePart(storeData.user?.subjectId, "INSTRUMENT");
|
|
|
|
- const subject = code || "pan-flute";
|
|
|
|
-
|
|
|
|
- // 设置屏幕方向
|
|
|
|
- api_setRequestedOrientation(["hulusi-flute", "piccolo"].includes(subject) ? 1 : 0);
|
|
|
|
-
|
|
|
|
- const data = reactive({
|
|
|
|
- loading: true,
|
|
|
|
- subject: subject as any,
|
|
|
|
- realKey: 0,
|
|
|
|
- notes: [] as IFIGNER_INSTRUMENT_Note[],
|
|
|
|
- tones: [] as IFIGNER_INSTRUMENT_Note[],
|
|
|
|
- activeTone: {} as IFIGNER_INSTRUMENT_Note,
|
|
|
|
- popupActiveTone: {} as IFIGNER_INSTRUMENT_Note,
|
|
|
|
- activeToneName: "",
|
|
|
|
- soundFonts: {} as any,
|
|
|
|
- viewIndex: 0,
|
|
|
|
- viewTotal: 1,
|
|
|
|
- noteAudio: null as unknown as Howl,
|
|
|
|
- transform: {
|
|
|
|
- scale: 1,
|
|
|
|
- x: 0,
|
|
|
|
- y: 0,
|
|
|
|
- startScale: 1,
|
|
|
|
- startX: 0,
|
|
|
|
- startY: 0,
|
|
|
|
- transition: "",
|
|
|
|
- },
|
|
|
|
- tipShow: false,
|
|
|
|
- tips: [] as IFIGNER_INSTRUMENT_Note[],
|
|
|
|
- tnoteShow: false,
|
|
|
|
- loadingSoundFonts: true,
|
|
|
|
- loadingSoundProgress: 0,
|
|
|
|
-
|
|
|
|
- huaweiPad: navigator?.userAgent?.includes("UAWEIVRD-W09") ? true : false,
|
|
|
|
- paddingTop: "",
|
|
|
|
- paddingLeft: "",
|
|
|
|
-
|
|
|
|
- subjects: [
|
|
|
|
- {
|
|
|
|
- text: "排箫",
|
|
|
|
- value: "pan-flute",
|
|
|
|
- className: "",
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- text: "陶笛",
|
|
|
|
- value: "ocarina",
|
|
|
|
- className: "",
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- text: "葫芦丝",
|
|
|
|
- value: "hulusi-flute",
|
|
|
|
- className: "",
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- text: "竖笛",
|
|
|
|
- value: "piccolo",
|
|
|
|
- className: "",
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- text: "口风琴",
|
|
|
|
- value: "melodica",
|
|
|
|
- className: "",
|
|
|
|
- },
|
|
|
|
- ],
|
|
|
|
- fingeringModeList: [
|
|
|
|
- {
|
|
|
|
- text: "指法模式",
|
|
|
|
- value: "fingeringMode",
|
|
|
|
- className: styles.selected,
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- text: "听音模式",
|
|
|
|
- value: "listenMode",
|
|
|
|
- className: "",
|
|
|
|
- },
|
|
|
|
- ],
|
|
|
|
- fingeringMode: "fingeringMode" as "fingeringMode" | "listenMode", // 模式
|
|
|
|
- noteType: "all" as "#c" | "all", // 音调
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const fingerData = reactive({
|
|
|
|
- relationshipIndex: 0,
|
|
|
|
- subject: null as unknown as ITypeFingering,
|
|
|
|
- fingeringInfo: subjectFingering(data.subject),
|
|
|
|
- });
|
|
|
|
- // if (!props.isComponent) {
|
|
|
|
- // state.fingeringInfo = fingerData.fingeringInfo;
|
|
|
|
- // }
|
|
|
|
-
|
|
|
|
- const getAPPData = async (type: "top" | "left") => {
|
|
|
|
- const screenData = await isSpecialShapedScreen();
|
|
|
|
- if (screenData?.content) {
|
|
|
|
- // console.log("🚀 ~ screenData:", screenData.content);
|
|
|
|
- const { isSpecialShapedScreen, notchHeight } = screenData.content;
|
|
|
|
- if (isSpecialShapedScreen) {
|
|
|
|
- if (type === "top") {
|
|
|
|
- data.paddingTop = 25 + "px";
|
|
|
|
- }
|
|
|
|
- if (type === "left") {
|
|
|
|
- data.paddingLeft = 25 + "px";
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const getHeadTop = () => {
|
|
|
|
- if (!browsInfo.ios && fingerData.fingeringInfo.orientation === 1) {
|
|
|
|
- getAPPData("top");
|
|
|
|
- }
|
|
|
|
- if (!browsInfo.ios && fingerData.fingeringInfo.orientation === 0) {
|
|
|
|
- getAPPData("left");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const getNotes = () => {
|
|
|
|
- const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA];
|
|
|
|
- if (fignerData) {
|
|
|
|
- data.tones = fignerData.tones || [];
|
|
|
|
- if (data.tones.length) {
|
|
|
|
- data.activeTone = data.tones[0];
|
|
|
|
- data.popupActiveTone = data.tones[0];
|
|
|
|
- }
|
|
|
|
- data.tips = fignerData.tips || [];
|
|
|
|
- setNotes();
|
|
|
|
- setTimeout(() => {
|
|
|
|
- data.loading = false;
|
|
|
|
- }, 600);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- const setNotes = () => {
|
|
|
|
- const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA];
|
|
|
|
- if (fignerData) {
|
|
|
|
- const tempNotes = fignerData[`list${data.activeTone.realName || ""}`];
|
|
|
|
- const appendNote: any = [];
|
|
|
|
- tempNotes.forEach((note: any) => {
|
|
|
|
- note.steps = new Array(Math.abs(note.step)).fill(1);
|
|
|
|
- if (FIGNER_INSTRUMENT_REALKEY.includes(note.realKey)) {
|
|
|
|
- appendNote.push(note);
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- // 判断是音符状态
|
|
|
|
- data.notes = data.noteType === "#c" ? appendNote : tempNotes;
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- const getFingeringData = async () => {
|
|
|
|
- const subject: any = data.subject + (data.viewIndex === 0 ? "" : data.viewIndex);
|
|
|
|
- console.log("🚀 ~ subject:", subject);
|
|
|
|
- fingerData.subject = await getFingeringConfig(subject);
|
|
|
|
- };
|
|
|
|
- const createAudio = (url: string) => {
|
|
|
|
- return new Promise((resolve) => {
|
|
|
|
- const noteAudio = new Howl({
|
|
|
|
- src: url,
|
|
|
|
- loop: true,
|
|
|
|
- onload: () => {
|
|
|
|
- resolve(noteAudio);
|
|
|
|
- },
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
- const getSounFonts = async () => {
|
|
|
|
- const pathname = /(192|localhost)/.test(location.origin) ? "/" : location.pathname;
|
|
|
|
- data.loadingSoundFonts = true;
|
|
|
|
- data.loadingSoundProgress = 0;
|
|
|
|
- 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";
|
|
|
|
- data.soundFonts[note.realKey] = await createAudio(url);
|
|
|
|
- data.loadingSoundProgress = Math.floor(((i + 1) / data.notes.length) * 100);
|
|
|
|
- }
|
|
|
|
- data.loadingSoundProgress = 100;
|
|
|
|
- api_cloudLoading();
|
|
|
|
- data.loadingSoundFonts = false;
|
|
|
|
- // console.log("🚀 ~ data.soundFonts:", data.soundFonts);
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const selectSubjectType = (subject: string) => {
|
|
|
|
- data.subjects.forEach((item: any) => {
|
|
|
|
- if (item.value === subject) {
|
|
|
|
- item.className = styles.selected;
|
|
|
|
- } else {
|
|
|
|
- item.className = "";
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- onBeforeMount(() => {
|
|
|
|
- getNotes();
|
|
|
|
-
|
|
|
|
- if (["pan-flute", "ocarina"].includes(data.subject)) {
|
|
|
|
- data.viewIndex = 1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- selectSubjectType(data.subject);
|
|
|
|
- // const o: any = {
|
|
|
|
- // "pan-flute": 2,
|
|
|
|
- // ocarina: 2,
|
|
|
|
- // piccolo: 2,
|
|
|
|
- // "hulusi-flute": 2,
|
|
|
|
- // };
|
|
|
|
- // data.viewTotal = o[data.subject] || 1;
|
|
|
|
- getFingeringData();
|
|
|
|
- getSounFonts();
|
|
|
|
- getHeadTop();
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const noteClick = (item: IFIGNER_INSTRUMENT_Note) => {
|
|
|
|
- if (data.noteAudio) {
|
|
|
|
- data.noteAudio.stop();
|
|
|
|
- if (data.realKey === item.realKey) {
|
|
|
|
- data.realKey = 0;
|
|
|
|
- data.noteAudio = null as unknown as Howl;
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- data.realKey = item.realKey;
|
|
|
|
- data.noteAudio = data.soundFonts[item.realKey];
|
|
|
|
- data.noteAudio.play();
|
|
|
|
- };
|
|
|
|
- const handleStop = () => {
|
|
|
|
- if (data.noteAudio) {
|
|
|
|
- data.noteAudio.stop();
|
|
|
|
- data.realKey = 0;
|
|
|
|
- data.noteAudio = null as unknown as Howl;
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- /** 返回 */
|
|
|
|
- const handleBack = () => {
|
|
|
|
- handleStop();
|
|
|
|
- // if (props.isComponent) {
|
|
|
|
- // console.log("关闭");
|
|
|
|
- // emit("close");
|
|
|
|
- // return;
|
|
|
|
- // } else {
|
|
|
|
- // // if (fingerData.fingeringInfo.orientation === 0) {
|
|
|
|
- // // api_setRequestedOrientation(1);
|
|
|
|
- // // }
|
|
|
|
- // }
|
|
|
|
- // 不在APP中,
|
|
|
|
- if (!storeData.isApp) {
|
|
|
|
- window.close();
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- api_back();
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- onMounted(() => {
|
|
|
|
- loadElement();
|
|
|
|
- api_setStatusBarVisibility();
|
|
|
|
- });
|
|
|
|
- const loadElement = () => {
|
|
|
|
- const fingeringContainer = document.getElementById("fingeringContainer");
|
|
|
|
- // console.log("🚀 ~ fingeringContainer:", fingeringContainer);
|
|
|
|
- const mc = new Hammer.Manager(fingeringContainer as HTMLElement);
|
|
|
|
- mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
|
|
|
|
- mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get("pan")]);
|
|
|
|
- // mc.get("pan").set({ direction: Hammer.DIRECTION_ALL });
|
|
|
|
- // mc.get("pinch").set({ enable: true });
|
|
|
|
- mc.on("panstart pinchstart", function (ev) {
|
|
|
|
- data.transform.transition = "";
|
|
|
|
- });
|
|
|
|
- mc.on("panmove pinchmove", function (ev) {
|
|
|
|
- if (ev.type === "pinchmove") {
|
|
|
|
- // console.log("🚀 ~ ev:", ev.type, ev.scale, ev.deltaX, ev.deltaY);
|
|
|
|
- data.transform.scale = ev.scale * data.transform.startScale;
|
|
|
|
- data.transform.x = data.transform.startX + ev.deltaX;
|
|
|
|
- data.transform.y = data.transform.startY + ev.deltaY;
|
|
|
|
- }
|
|
|
|
- if (ev.type === "panmove") {
|
|
|
|
- // console.log("🚀 ~ ev:", ev.type, ev.deltaX, ev.deltaY);
|
|
|
|
- data.transform.x = data.transform.startX + ev.deltaX;
|
|
|
|
- data.transform.y = data.transform.startY + ev.deltaY;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- //
|
|
|
|
- mc.on("hammer.input", function (ev) {
|
|
|
|
- // console.log("🚀 ~ ev:", ev.type, ev.isFinal);
|
|
|
|
- if (ev.isFinal) {
|
|
|
|
- data.transform.startScale = data.transform.scale;
|
|
|
|
- data.transform.startX = data.transform.x;
|
|
|
|
- data.transform.startY = data.transform.y;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
- const resetElement = () => {
|
|
|
|
- data.transform.transition = "all 0.3s";
|
|
|
|
- nextTick(() => {
|
|
|
|
- data.transform.scale = 1;
|
|
|
|
- data.transform.x = 0;
|
|
|
|
- data.transform.y = 0;
|
|
|
|
- data.transform.startScale = 1;
|
|
|
|
- data.transform.startX = 0;
|
|
|
|
- data.transform.startY = 0;
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const pageVisible = usePageVisibility();
|
|
|
|
- watch(
|
|
|
|
- () => pageVisible.value,
|
|
|
|
- (val) => {
|
|
|
|
- if (val === "hidden") {
|
|
|
|
- console.log("页面隐藏停止播放");
|
|
|
|
- handleStop();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- );
|
|
|
|
- /** 课件播放 */
|
|
|
|
- const changePlay = (res: any) => {
|
|
|
|
- if (res?.data?.api === "setPlayState") {
|
|
|
|
- handleStop();
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const noteBoxRef = ref();
|
|
|
|
- const scrollNoteBox = (type: "left" | "right") => {
|
|
|
|
- const width = noteBoxRef.value.offsetWidth / 2;
|
|
|
|
- (noteBoxRef.value as unknown as HTMLElement).scrollBy({
|
|
|
|
- left: type === "left" ? -width : width,
|
|
|
|
- behavior: "smooth",
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const playStatus = reactive({
|
|
|
|
- gamut: false, // 是否播放音阶
|
|
|
|
- answer: false, // 是否显示答案
|
|
|
|
- action: false, // 是否开始播放
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- /** 音符切换 */
|
|
|
|
- const noteChangeShow = () => {
|
|
|
|
- // 播放音阶时不能切换
|
|
|
|
- if (playStatus.gamut) return;
|
|
|
|
- // 开始答题不能切换
|
|
|
|
- if (playStatus.action) return;
|
|
|
|
- if (data.noteType === "all") {
|
|
|
|
- data.noteType = "#c";
|
|
|
|
- } else {
|
|
|
|
- data.noteType = "all";
|
|
|
|
- }
|
|
|
|
- getNotes();
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // 开始播放音阶
|
|
|
|
- const onGamutPlayOrPause = async () => {
|
|
|
|
- if (playStatus.gamut) {
|
|
|
|
- playStatus.gamut = false;
|
|
|
|
- gaumntPause();
|
|
|
|
- } else {
|
|
|
|
- // 不管当前显示在哪个音老师滚动到开始位置
|
|
|
|
- (noteBoxRef.value as unknown as HTMLElement).scroll({
|
|
|
|
- left: 0,
|
|
|
|
- top: 0,
|
|
|
|
- behavior: "smooth",
|
|
|
|
- });
|
|
|
|
- playStatus.gamut = true;
|
|
|
|
- const notes = data.notes;
|
|
|
|
- let step = 7;
|
|
|
|
- for (let i = 0; i < notes.length; i++) {
|
|
|
|
- if (!playStatus.gamut) return false;
|
|
|
|
-
|
|
|
|
- if (i % 8 === 0 && i !== 0) {
|
|
|
|
- scrollNoteBox("right");
|
|
|
|
- step = notes[i].step;
|
|
|
|
- }
|
|
|
|
- await gaumtPlay(notes[i]);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // // 处理播放到最后一个
|
|
|
|
- setTimeout(() => {
|
|
|
|
- playStatus.gamut = false;
|
|
|
|
- gaumntPause();
|
|
|
|
- }, 667);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- const gaumtPlay = (note: any, status?: boolean) => {
|
|
|
|
- return new Promise((resolve) => {
|
|
|
|
- setTimeout(() => {
|
|
|
|
- if (playStatus.gamut || status) {
|
|
|
|
- noteClick(note);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- resolve(note);
|
|
|
|
- }, 667);
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
- const gaumntPause = () => {
|
|
|
|
- if (data.noteAudio) {
|
|
|
|
- data.noteAudio.stop();
|
|
|
|
- data.realKey = 0;
|
|
|
|
- data.noteAudio = null as unknown as Howl;
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- /** 开始播放 */
|
|
|
|
- const playAction = reactive({
|
|
|
|
- exampleAnser: {} as any, // 示例声音
|
|
|
|
- standardAnswer: {} as any, // 标准答案key
|
|
|
|
- showAnswerLoading: false, // 显示按答案中
|
|
|
|
- listenModeStatus: false, // 听音模式
|
|
|
|
- listenLock: false,
|
|
|
|
- /** 0: 未答,1: 答对,2: 答错 */
|
|
|
|
- userAnswerStatus: 0 as 0 | 1 | 2, // 用户回答状态
|
|
|
|
- userAnswer: {} as any, // 用户答的数据
|
|
|
|
- });
|
|
|
|
- const onActionPlay = async () => {
|
|
|
|
- if (playAction.listenLock) return;
|
|
|
|
- playStatus.action = true;
|
|
|
|
- playStatus.answer = true;
|
|
|
|
- // 先暂停播放声音
|
|
|
|
- gaumntPause();
|
|
|
|
- if (data.fingeringMode === "fingeringMode") {
|
|
|
|
- onFingeringMode();
|
|
|
|
- } else if (data.fingeringMode === "listenMode") {
|
|
|
|
- if (playAction.listenModeStatus) {
|
|
|
|
- playAction.listenLock = true;
|
|
|
|
- await fingeringPlay(playAction.standardAnswer);
|
|
|
|
- gaumntPause();
|
|
|
|
- playAction.listenLock = false;
|
|
|
|
- } else {
|
|
|
|
- onListenMode();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // 指法模式
|
|
|
|
- const fingeringPlay = (note: any, timer = 1500) => {
|
|
|
|
- return new Promise((resolve) => {
|
|
|
|
- noteClick(note);
|
|
|
|
- setTimeout(() => {
|
|
|
|
- resolve(note);
|
|
|
|
- }, timer);
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
- const onFingeringMode = () => {
|
|
|
|
- const randomIndex = Math.floor(Math.random() * data.notes.length);
|
|
|
|
- playAction.standardAnswer = data.notes[randomIndex];
|
|
|
|
- data.realKey = data.notes[randomIndex].realKey;
|
|
|
|
- };
|
|
|
|
- // 听音模式
|
|
|
|
- const onListenMode = async () => {
|
|
|
|
- playAction.listenModeStatus = true; // 是否开始听音
|
|
|
|
- playAction.listenLock = true; // 锁
|
|
|
|
- let randomIndex = Math.floor(Math.random() * data.notes.length);
|
|
|
|
- playAction.exampleAnser = data.notes[randomIndex];
|
|
|
|
- data.realKey = playAction.exampleAnser.realKey;
|
|
|
|
- scrollAnswer();
|
|
|
|
- await fingeringPlay(playAction.exampleAnser);
|
|
|
|
- data.realKey = 0;
|
|
|
|
- playAction.exampleAnser = {};
|
|
|
|
- gaumntPause();
|
|
|
|
- setTimeout(async () => {
|
|
|
|
- randomIndex = Math.floor(Math.random() * data.notes.length);
|
|
|
|
- playAction.standardAnswer = data.notes[randomIndex];
|
|
|
|
- await fingeringPlay(data.notes[randomIndex]);
|
|
|
|
- gaumntPause();
|
|
|
|
- playAction.listenLock = false;
|
|
|
|
- }, 1000);
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // 显示答案
|
|
|
|
- const onShowAnswer = async () => {
|
|
|
|
- if (data.fingeringMode === "fingeringMode") {
|
|
|
|
- playAction.showAnswerLoading = true;
|
|
|
|
- scrollAnswer();
|
|
|
|
- ressetMode();
|
|
|
|
- } else if (data.fingeringMode === "listenMode") {
|
|
|
|
- if (playAction.listenLock) return;
|
|
|
|
- playAction.showAnswerLoading = true;
|
|
|
|
- scrollAnswer(playAction.standardAnswer.realKey);
|
|
|
|
- await fingeringPlay(playAction.standardAnswer);
|
|
|
|
- ressetMode(true, 0);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- // 滚动到对应答案位置
|
|
|
|
- const scrollAnswer = (realKey?: any) => {
|
|
|
|
- const index = data.notes.findIndex((item: any) => item.realKey === realKey || data.realKey);
|
|
|
|
- const activeDom = document.querySelectorAll(".note-class")[index] as any;
|
|
|
|
- if (activeDom) {
|
|
|
|
- const aWidth = activeDom.offsetWidth;
|
|
|
|
- const width = noteBoxRef.value.offsetWidth - aWidth;
|
|
|
|
- const wLeft = noteBoxRef.value.offsetLeft;
|
|
|
|
- const aLeft = Math.max(activeDom?.offsetLeft - aWidth, 0);
|
|
|
|
-
|
|
|
|
- console.log(aLeft - wLeft - width / 2);
|
|
|
|
- (noteBoxRef.value as unknown as HTMLElement).scroll({
|
|
|
|
- left: aLeft - wLeft - width / 2,
|
|
|
|
- top: 0,
|
|
|
|
- behavior: "smooth",
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const ressetMode = (status = true, timer = 2000) => {
|
|
|
|
- // 2秒钟后重置
|
|
|
|
- setTimeout(() => {
|
|
|
|
- gaumntPause();
|
|
|
|
- if (status) {
|
|
|
|
- playAction.standardAnswer = {};
|
|
|
|
- playAction.showAnswerLoading = false;
|
|
|
|
- playAction.userAnswerStatus = 0;
|
|
|
|
- playAction.userAnswer = {};
|
|
|
|
- playAction.listenModeStatus = false;
|
|
|
|
- playStatus.action = false;
|
|
|
|
- playStatus.answer = false;
|
|
|
|
- data.realKey = 0;
|
|
|
|
- } else {
|
|
|
|
- playAction.userAnswerStatus = 0;
|
|
|
|
- playAction.userAnswer = {};
|
|
|
|
- }
|
|
|
|
- }, timer);
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- /** 滚轮缩放 */
|
|
|
|
- const handleWheel = (e: WheelEvent) => {
|
|
|
|
- e.preventDefault();
|
|
|
|
- if (e.deltaY > 0) {
|
|
|
|
- data.transform.scale -= 0.1;
|
|
|
|
- if (data.transform.scale <= 0.5) {
|
|
|
|
- data.transform.scale = 0.5;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- data.transform.scale += 0.1;
|
|
|
|
- if (data.transform.scale >= 2) {
|
|
|
|
- data.transform.scale = 2;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- onMounted(() => {
|
|
|
|
- window.addEventListener("message", changePlay);
|
|
|
|
- const fingeringContainer = document.getElementById("fingeringContainer");
|
|
|
|
- fingeringContainer?.addEventListener("wheel", handleWheel);
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- onUnmounted(() => {
|
|
|
|
- window.removeEventListener("message", changePlay);
|
|
|
|
- const fingeringContainer = document.getElementById("fingeringContainer");
|
|
|
|
- fingeringContainer?.removeEventListener("wheel", handleWheel);
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const containerBox = computed(() => {
|
|
|
|
- if (state.platform === IPlatform.PC || query.modelType) {
|
|
|
|
- return {
|
|
|
|
- paddingTop: "1rem",
|
|
|
|
- paddingBottom: "",
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
- if (data.subject === "hulusi-flute") {
|
|
|
|
- return {
|
|
|
|
- paddingTop: "2.6rem",
|
|
|
|
- paddingBottom: ".6rem",
|
|
|
|
- };
|
|
|
|
- } else if (data.subject === "piccolo") {
|
|
|
|
- return {
|
|
|
|
- paddingTop: "3.5rem",
|
|
|
|
- paddingBottom: ".6rem",
|
|
|
|
- };
|
|
|
|
- } else if (data.subject === "pan-flute") {
|
|
|
|
- return {
|
|
|
|
- paddingTop: "0",
|
|
|
|
- paddingBottom: "0",
|
|
|
|
- };
|
|
|
|
- } else if (data.subject === "ocarina") {
|
|
|
|
- return {
|
|
|
|
- paddingTop: "1rem",
|
|
|
|
- paddingBottom: "0",
|
|
|
|
- };
|
|
|
|
- } else if (data.subject === "melodica") {
|
|
|
|
- return {
|
|
|
|
- paddingTop: "2.8rem",
|
|
|
|
- paddingBottom: "1rem",
|
|
|
|
- };
|
|
|
|
- } else {
|
|
|
|
- return {
|
|
|
|
- paddingTop: "",
|
|
|
|
- paddingBottom: "",
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const listenText = computed(() => {
|
|
|
|
- if (data.fingeringMode === "fingeringMode") {
|
|
|
|
- if (playStatus.action) {
|
|
|
|
- return "换一换";
|
|
|
|
- } else {
|
|
|
|
- return "开始";
|
|
|
|
- }
|
|
|
|
- } else if (data.fingeringMode === "listenMode") {
|
|
|
|
- if (playStatus.action) {
|
|
|
|
- return "再听一遍";
|
|
|
|
- } else {
|
|
|
|
- return "开始听音";
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return "开始听音";
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const modeText = computed(() => {
|
|
|
|
- let text = "";
|
|
|
|
- data.fingeringModeList.forEach((item: any) => {
|
|
|
|
- if (item.value === data.fingeringMode) {
|
|
|
|
- text = item.text;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- return text;
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const resultImg = (note: any) => {
|
|
|
|
- if (data.realKey === note.realKey && !playStatus.action) {
|
|
|
|
- return {
|
|
|
|
- icon: icons.icon_btn_ylow,
|
|
|
|
- status: false,
|
|
|
|
- };
|
|
|
|
- } else if (playAction.exampleAnser.realKey === note.realKey) {
|
|
|
|
- return {
|
|
|
|
- icon: icons.icon_btn_ylow,
|
|
|
|
- status: false,
|
|
|
|
- };
|
|
|
|
- } else if (playAction.standardAnswer.realKey === note.realKey) {
|
|
|
|
- // 没有开始答题
|
|
|
|
- if (!playStatus.action) {
|
|
|
|
- return {
|
|
|
|
- icon: icons.icon_btn_ylow,
|
|
|
|
- status: false,
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
- // 显示答案中
|
|
|
|
- if (playAction.showAnswerLoading) {
|
|
|
|
- return {
|
|
|
|
- icon: icons.icon_btn_green,
|
|
|
|
- status: true,
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
- // 用户答对
|
|
|
|
- if (playAction.userAnswerStatus === 1) {
|
|
|
|
- return {
|
|
|
|
- icon: icons.icon_btn_green,
|
|
|
|
- status: true,
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- // 用户答错
|
|
|
|
- if (playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey) {
|
|
|
|
- return {
|
|
|
|
- icon: icons.icon_btn_red,
|
|
|
|
- status: true,
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return {
|
|
|
|
- icon: icons.icon_btn_blue,
|
|
|
|
- status: true,
|
|
|
|
- };
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const relactionObj = computed(() => {
|
|
|
|
- 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 {
|
|
|
|
- rs,
|
|
|
|
- canTizhi,
|
|
|
|
- };
|
|
|
|
- });
|
|
|
|
- return () => {
|
|
|
|
- return (
|
|
|
|
- <div class={[styles.fingerBox, state.platform !== IPlatform.PC && !query.modelType && fingerData.fingeringInfo.orientation === 1 ? styles.fingerBottom : styles.fingerRight]}>
|
|
|
|
- <div
|
|
|
|
- class={styles.head}
|
|
|
|
- style={{
|
|
|
|
- paddingTop: data.paddingTop ? data.paddingTop : "",
|
|
|
|
- paddingLeft: data.paddingLeft ? data.paddingLeft : "",
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- <div class={styles.left}>
|
|
|
|
- <button class={[styles.backBtn]} onClick={() => handleBack()}>
|
|
|
|
- <img src={icons.icon_back} />
|
|
|
|
- </button>
|
|
|
|
- <Popover
|
|
|
|
- placement="bottom"
|
|
|
|
- class={styles.popoverContainer}
|
|
|
|
- actions={data.subjects}
|
|
|
|
- onSelect={(val: any) => {
|
|
|
|
- //
|
|
|
|
- selectSubjectType(val.value);
|
|
|
|
- const _url =
|
|
|
|
- location.origin +
|
|
|
|
- location.pathname +
|
|
|
|
- "#/view-figner-listen?" +
|
|
|
|
- qs.stringify({
|
|
|
|
- ...query,
|
|
|
|
- _t: new Date().valueOf(),
|
|
|
|
- subjectCode: val.value,
|
|
|
|
- });
|
|
|
|
- location.href = _url;
|
|
|
|
- window.location.reload();
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- {{
|
|
|
|
- reference: () => (
|
|
|
|
- <div
|
|
|
|
- class={styles.baseBtn}
|
|
|
|
- onClick={() => {
|
|
|
|
- //
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- <img src={icons.icon_change_instrument} />
|
|
|
|
- <span>切换乐器</span>
|
|
|
|
- </div>
|
|
|
|
- ),
|
|
|
|
- }}
|
|
|
|
- </Popover>
|
|
|
|
- </div>
|
|
|
|
- <div class={styles.rightBtn}>
|
|
|
|
- <Popover
|
|
|
|
- placement="bottom"
|
|
|
|
- class={styles.popoverContainer}
|
|
|
|
- actions={data.fingeringModeList}
|
|
|
|
- onSelect={(val: any) => {
|
|
|
|
- //
|
|
|
|
- if (playAction.listenLock) return;
|
|
|
|
- data.fingeringModeList.forEach((item: any) => {
|
|
|
|
- if (item.value === val.value) {
|
|
|
|
- item.className = styles.selected;
|
|
|
|
- } else {
|
|
|
|
- item.className = styles.normal;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- data.fingeringMode = val.value;
|
|
|
|
-
|
|
|
|
- // 重置
|
|
|
|
- ressetMode(true, 0);
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- {{
|
|
|
|
- reference: () => (
|
|
|
|
- <div class={styles.baseBtn}>
|
|
|
|
- <img src={icons.icon_mode} />
|
|
|
|
- <span>{modeText.value}</span>
|
|
|
|
- </div>
|
|
|
|
- ),
|
|
|
|
- }}
|
|
|
|
- </Popover>
|
|
|
|
-
|
|
|
|
- <div class={styles.baseBtn} onClick={() => resetElement()}>
|
|
|
|
- <img src={icons.icon_2_0} />
|
|
|
|
- <span>还原</span>
|
|
|
|
- </div>
|
|
|
|
- <div
|
|
|
|
- class={styles.baseBtn}
|
|
|
|
- onClick={() => {
|
|
|
|
- resetElement();
|
|
|
|
- data.tipShow = !data.tipShow;
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- <img src={icons.icon_2_1} />
|
|
|
|
- <span>使用说明</span>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- <div class={styles.fingerContent}>
|
|
|
|
- <div class={styles.wrapFinger}>
|
|
|
|
- <div
|
|
|
|
- id="fingeringContainer"
|
|
|
|
- class={styles.boxFinger}
|
|
|
|
- style={{
|
|
|
|
- paddingTop: containerBox.value.paddingTop,
|
|
|
|
- paddingBottom: containerBox.value.paddingBottom,
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- <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?.full1} />
|
|
|
|
- {relactionObj.value.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 style={{ left: data.viewIndex == 2 ? "0" : "64%" }} class={[styles.tizhi, relactionObj.value.canTizhi && styles.canDisplay]} onClick={() => (fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)}>
|
|
|
|
- 替指
|
|
|
|
- </div>
|
|
|
|
- <div id="finger-note-2" style={{ left: "50%", transform: "translateX(-50%)" }} class={styles.tizhi} onClick={() => (fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)}></div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- <div
|
|
|
|
- class={styles.notes}
|
|
|
|
- style={{
|
|
|
|
- paddingLeft: data.paddingLeft ? data.paddingLeft : "",
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- <Button class={styles.noteBtn} onClick={() => scrollNoteBox("left")}>
|
|
|
|
- <Icon name="arrow-left" />
|
|
|
|
- </Button>
|
|
|
|
- <div class={[styles.noteContent, browsInfo.ios ? "" : styles.noteContentWrap, data.huaweiPad && styles.huaweiPad]}>
|
|
|
|
- <div draggable={false} class={styles.note} onClick={noteChangeShow}>
|
|
|
|
- <img draggable={false} src={icons.icon_btn_orange} />
|
|
|
|
- <div class={[styles.noteKey]}>
|
|
|
|
- <div class={[styles.noteName, styles.noteFixed]}>{data.noteType === "all" ? "全按键" : "C调"}</div>
|
|
|
|
- <span class={styles.dotFixed}></span>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- <div ref={noteBoxRef} id="noteBox1" class={styles.noteBox}>
|
|
|
|
- {data.notes.map((note: any, index: number) => (
|
|
|
|
- <div
|
|
|
|
- id={index == 0 ? "finger-note-0" : ""}
|
|
|
|
- draggable={false}
|
|
|
|
- class={[styles.note, "note-class"]}
|
|
|
|
- key={note.realKey}
|
|
|
|
- onClick={async () => {
|
|
|
|
- // 判断是否在播放音阶
|
|
|
|
- if (playStatus.gamut) return;
|
|
|
|
- if (playAction.listenLock) return;
|
|
|
|
- if (playStatus.action) {
|
|
|
|
- playAction.userAnswer = note;
|
|
|
|
- // 判断用户答题
|
|
|
|
- playAction.userAnswerStatus = note.realKey === playAction.standardAnswer.realKey ? 1 : 2;
|
|
|
|
- if (data.fingeringMode === "listenMode") {
|
|
|
|
- playAction.listenLock = true;
|
|
|
|
- data.realKey = note.realKey;
|
|
|
|
- await fingeringPlay(note, 1000);
|
|
|
|
- ressetMode(note.realKey === playAction.standardAnswer.realKey ? true : false, 0);
|
|
|
|
- data.realKey = 0;
|
|
|
|
- playAction.listenLock = false;
|
|
|
|
- } else {
|
|
|
|
- ressetMode(note.realKey === playAction.standardAnswer.realKey ? true : false);
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- noteClick(note);
|
|
|
|
- }
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- <img draggable={false} src={resultImg(note).icon} />
|
|
|
|
-
|
|
|
|
- {playStatus.action && ((playAction.showAnswerLoading && playAction.standardAnswer.realKey === note.realKey) || (playAction.userAnswerStatus === 1 && playAction.userAnswer.realKey === note.realKey)) ? <span class={styles.showAnswer}></span> : ""}
|
|
|
|
- {playStatus.action && playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey ? <span class={[styles.showAnswer, styles.errorAnswer]}></span> : ""}
|
|
|
|
-
|
|
|
|
- <div
|
|
|
|
- class={[
|
|
|
|
- styles.noteKey,
|
|
|
|
- ((data.realKey === note.realKey && !playStatus.action) ||
|
|
|
|
- (playStatus.action && ((playAction.showAnswerLoading && playAction.standardAnswer.realKey === note.realKey) || (playAction.userAnswerStatus === 1 && playAction.userAnswer.realKey === note.realKey))) ||
|
|
|
|
- (playStatus.action && playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey)) &&
|
|
|
|
- styles.keyActive,
|
|
|
|
- ]}
|
|
|
|
- >
|
|
|
|
- {/* 显示对应的点 */}
|
|
|
|
- {note.step > 0 ? note.steps.map((n: any) => <span class={styles.dot}></span>) : null}
|
|
|
|
-
|
|
|
|
- <div class={styles.noteName}>
|
|
|
|
- <sup>{note.mark && (note.mark === "rise" ? "#" : "b")}</sup>
|
|
|
|
- {note.key}
|
|
|
|
- </div>
|
|
|
|
- {/* 显示对应的点 */}
|
|
|
|
- {note.step < 0 ? note.steps.map((n: any) => <span class={styles.dot}></span>) : null}
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- ))}
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- <Button class={styles.noteBtn} onClick={() => scrollNoteBox("right")}>
|
|
|
|
- <Icon name="arrow" />
|
|
|
|
- </Button>
|
|
|
|
- </div>
|
|
|
|
- <div class={styles.optionBtns}>
|
|
|
|
- {/* , styles.disabled */}
|
|
|
|
- <Button class={[styles.oBtn, styles.gamut, playStatus.action && styles.disabled]} round onClick={onGamutPlayOrPause}>
|
|
|
|
- {playStatus.gamut ? "暂停" : "播放音阶"}
|
|
|
|
- </Button>
|
|
|
|
- <Button class={[styles.oBtn, styles.play, playStatus.gamut && styles.disabled]} round onClick={onActionPlay}>
|
|
|
|
- {listenText.value}
|
|
|
|
- </Button>
|
|
|
|
- <Button class={[styles.oBtn, styles.success, !playStatus.answer && styles.disabled]} round onClick={onShowAnswer}>
|
|
|
|
- 显示答案
|
|
|
|
- </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" size={19} color="#fff" />
|
|
|
|
- </Button>
|
|
|
|
- </div>
|
|
|
|
- <div class={styles.iconBook}></div>
|
|
|
|
- <div class={styles.tipContentbox}>
|
|
|
|
- <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>
|
|
|
|
- {data.loadingSoundFonts && (
|
|
|
|
- <div class={styles.loading}>
|
|
|
|
- <div class={styles.loadingWrap}>
|
|
|
|
- <img class={styles.loadingIcon} src={icon_loading_img} />
|
|
|
|
- <Progress percentage={data.loadingSoundProgress} />
|
|
|
|
- <div class={styles.loadingTip}>加载中,请稍后…</div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- )}
|
|
|
|
- </div>
|
|
|
|
- {!!data.tones.length && (
|
|
|
|
- <>
|
|
|
|
- {fingerData.fingeringInfo.name == "hulusi-flute" ? (
|
|
|
|
- <div id="finger-note-1" class={[styles.toggleBtn, styles.toggleBtnhulusi]} onClick={() => (data.tnoteShow = true)}>
|
|
|
|
- <div>
|
|
|
|
- 全按作
|
|
|
|
- <div class={[styles.noteKey]}>
|
|
|
|
- {data.activeTone.step > 0 ? <span class={styles.dot}></span> : null}
|
|
|
|
-
|
|
|
|
- <div class={styles.noteName}>
|
|
|
|
- <sup>{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")}</sup>
|
|
|
|
- {data.activeTone.key}
|
|
|
|
- </div>
|
|
|
|
- {data.activeTone.step < 0 ? <span class={styles.dot}></span> : null}
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- <img src={icons.icon_arrow} />
|
|
|
|
- </div>
|
|
|
|
- ) : (
|
|
|
|
- <div id="finger-note-1" class={styles.toggleBtn} onClick={() => (data.tnoteShow = true)}>
|
|
|
|
- <div style={{ marginTop: "-4px" }}>
|
|
|
|
- <sup>{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")}</sup>
|
|
|
|
- {data.activeTone.name}
|
|
|
|
- </div>
|
|
|
|
- 调
|
|
|
|
- <img src={icons.icon_arrow} />
|
|
|
|
- </div>
|
|
|
|
- )}
|
|
|
|
- </>
|
|
|
|
- )}
|
|
|
|
-
|
|
|
|
- <Popup class="tonePopup" v-model:show={data.tnoteShow} position={state.platform !== IPlatform.PC && !query.modelType && 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" size={19} color="#fff" />
|
|
|
|
- </Button>
|
|
|
|
- </div>
|
|
|
|
- <div class={styles.tipContentbox}>
|
|
|
|
- <div class={styles.tipContent}>
|
|
|
|
- <div class={styles.tipWrap}>
|
|
|
|
- <Space size={0} class={styles.toneContent}>
|
|
|
|
- {data.tones.map((tone: IFIGNER_INSTRUMENT_Note) => {
|
|
|
|
- const steps = new Array(Math.abs(tone.step)).fill(1);
|
|
|
|
- return (
|
|
|
|
- <Button
|
|
|
|
- class={[fingerData.fingeringInfo.name == "hulusi-flute" && styles.hulusiBtn]}
|
|
|
|
- round
|
|
|
|
- plain
|
|
|
|
- type={data.popupActiveTone.realName === tone.realName ? "primary" : "default"}
|
|
|
|
- onClick={() => {
|
|
|
|
- data.popupActiveTone = tone;
|
|
|
|
- setNotes();
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- {fingerData.fingeringInfo.name == "hulusi-flute" ? (
|
|
|
|
- <div style={{ display: "flex", alignItems: "center" }}>
|
|
|
|
- 全按作
|
|
|
|
- <div class={[styles.noteKey, styles.hulusiNoteKey]}>
|
|
|
|
- {tone.step > 0 ? <span class={styles.dot}></span> : null}
|
|
|
|
- <div class={styles.noteName} style={{ fontSize: "0.25rem" }}>
|
|
|
|
- <sup>{tone.mark && (tone.mark === "rise" ? "#" : "b")}</sup>
|
|
|
|
- {tone.key}
|
|
|
|
- </div>
|
|
|
|
- {tone.step < 0 ? <span class={styles.dot}></span> : null}
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- ) : (
|
|
|
|
- <div class={styles.noteName}>
|
|
|
|
- <sup>{tone.mark && (tone.mark === "rise" ? "#" : "b")}</sup>
|
|
|
|
- {tone.name}
|
|
|
|
- </div>
|
|
|
|
- )}
|
|
|
|
- </Button>
|
|
|
|
- );
|
|
|
|
- })}
|
|
|
|
- </Space>
|
|
|
|
- </div>
|
|
|
|
- <div class={styles.toneAction}>
|
|
|
|
- <img onClick={() => (data.tnoteShow = false)} src={icons.icon_action_cancel} />
|
|
|
|
- <img
|
|
|
|
- onClick={() => {
|
|
|
|
- data.activeTone = data.popupActiveTone;
|
|
|
|
- setNotes();
|
|
|
|
- data.tnoteShow = false;
|
|
|
|
- }}
|
|
|
|
- src={icons.icon_action_confirm}
|
|
|
|
- />
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </Popup>
|
|
|
|
-
|
|
|
|
- {/* {props.show && !data.loading && !data.loadingSoundFonts && <GuideIndex showGuide={false} list={["finger"]} />} */}
|
|
|
|
- </div>
|
|
|
|
- );
|
|
|
|
- };
|
|
|
|
- },
|
|
|
|
-});
|
|
|