import { computed, defineComponent, onMounted, reactive, Transition, nextTick, watch } from "vue"; import state, { EnumMusicRenderType, handleSelection, skipNotePlay, IPlatform } from "/src/state"; import styles from "./index.module.less"; import { metronomeData } from "/src/helpers/metronome"; import { evaluatingData } from "../evaluating"; import { leveByScoreMeasureIcons } from "../evaluating/evaluatResult"; import { Icon, showToast } from "vant"; import MoveMusicScore, { moveData, renderForMoveData } from "../plugins/move-music-score"; import { useRoute } from "vue-router"; import { getQuery } from "/src/utils/queryString"; const selectData = reactive({ notes: [] as any[], staves: [] as any[], measureHeight: 0 as number, // 小节高度 }); /** 计算点击层数据 */ const calcNoteData = () => { const musicContainer = document.getElementById("musicAndSelection")?.getBoundingClientRect() || { x: 0, y: 0, }; const parentLeft = musicContainer.x || 0; const parentTop = musicContainer.y || 0; const notes = state.times; const notesList: string[] = []; const MeasureNumberXMLList: number[] = []; let minMeasureHeigt: number = 0; for (let i = 0; i < notes.length; i++) { const item = notes[i]; // console.log("🚀 ~ item:", item) const noteItem = { ...item, index: item.i, bbox: null as any, staveBox: null as any, }; if (!notesList.includes(item.noteId)) { let staveBbox: any = {}; if (item.stave?.attrs?.id) { const staveEle = document.querySelector(`#${item.stave.attrs.id}`); staveBbox = staveEle?.parentElement?.parentElement?.getBoundingClientRect?.() || { x: 0, width: 0, }; // console.log("🚀 ~ staveBbox:", staveBbox.height) } if (item.svgElement) { const noteEle = document.querySelector(`#vf-${item.svgElement?.attrs?.id}`); if (noteEle) { const noteBbox = noteEle.getBoundingClientRect?.() || { x: 0, width: 0 }; if (state.musicRenderType !== EnumMusicRenderType.staff) { noteItem.bbox = { left: noteBbox.x - parentLeft - noteBbox.width / 4 + "px", top: noteBbox.y - parentTop - noteBbox.height + "px", width: noteBbox.width * 1.5 + "px", height: noteBbox.height * 3 + "px", }; const noteHead = noteEle.querySelector(".vf-numbered-note-head"); const noteHeadBbox = noteHead?.getBoundingClientRect?.(); if (noteHeadBbox) { item.bbox = { left: noteHeadBbox.x - parentLeft - noteHeadBbox.width / 4, width: noteHeadBbox.width * 1.5, } } } else { noteItem.bbox = { left: noteBbox.x - parentLeft - noteBbox.width / 4 + "px", top: staveBbox.y - parentTop + "px", width: noteBbox.width * 1.5 + "px", height: staveBbox.height + "px", }; } } if (selectData.notes.find((item:any) => item.id === noteItem.id)) { // } else { selectData.notes.push(noteItem); } // selectData.notes.push(noteItem); notesList.push(item.noteId); } } if (!MeasureNumberXMLList.includes(item.MeasureNumberXML)) { if (item.stave) { if (item.stave?.attrs?.id) { const staveEle = document.querySelector(`#${item.stave.attrs.id}`); const list = [ Array.from(staveEle?.querySelectorAll(".vf-clef") || []), Array.from(staveEle?.querySelectorAll(".vf-keysignature") || []), Array.from(staveEle?.getElementsByTagName("text") || []), ].flat(); try { if (list.length) { // console.log("🚀 ~ list:", list) list.forEach((_el: any) => { _el?.style?.setProperty("display", "none"); }); } } catch (error) {} const staveBbox = staveEle?.getBoundingClientRect?.() || { x: 0, width: 0, y: 0, height: 0 }; if (i === 0) { minMeasureHeigt = staveBbox.height } try { if (list.length) { list.forEach((_el: any) => { _el?.style?.removeProperty("display"); }); } } catch (error) {} // console.log("🚀 ~ staveEle:", staveBbox.height) selectData.measureHeight = staveBbox.height let compareVal = staveBbox.height - minMeasureHeigt compareVal = compareVal > 0 ? compareVal : 0 noteItem.staveBox = { left: staveBbox.x - parentLeft + "px", // top: ((item.stave.y || 0) - 5) * state.zoom + "px", top: staveBbox.y - parentTop + compareVal + "px", width: staveBbox.width + "px", height: staveBbox.height - compareVal + "px", // background: 'rgba(0,0,0,.2)' }; selectData.staves.push(noteItem); } MeasureNumberXMLList.push(item.MeasureNumberXML); } else { if (item.multipleRestMeasures) { const preItem = selectData.staves.find( (n: any) => n.MeasureNumberXML === item.MeasureNumberXML - 1 ); if (preItem?.staveBox) { noteItem.staveBox = { left: preItem.staveBox.left, top: preItem.staveBox.top, width: preItem.staveBox.width, // height: preItem.staveBox.height, }; selectData.staves.push(noteItem); MeasureNumberXMLList.push(item.MeasureNumberXML); } } } } } console.log("🚀 ~ selectData.notes:", selectData.notes, selectData.staves); }; /** 重新计算 */ export const recalculateNoteData = () => { selectData.notes = []; selectData.staves = []; calcNoteData(); }; export default defineComponent({ name: "selection", setup() { const route = useRoute(); const query: any = { ...getQuery(), ...route.query, }; /** 是否可以点击音符 */ const disableClickNote = computed(() => { return state.sectionStatus || state.modeType !== "practise"; }); // 选段符号 const sectionPosData = computed(() => { if(state.sectionStatus) { return state.section.map(((item,index) => { if(index === 0){ const currItem = selectData.staves.find(stave => { return stave.MeasureNumberXML === item.MeasureNumberXML }) return currItem && { left: currItem.staveBox.left, top: currItem.staveBox.top, height: selectData.measureHeight + 'px' // 小节的高度 } } else { // 实际的结束位置 const actualEndIndex = state.userChooseEndIndex > item.MeasureNumberXML ? state.userChooseEndIndex : item.MeasureNumberXML const currItem = selectData.staves.find(stave => { return stave.MeasureNumberXML === actualEndIndex }) return currItem && { left: parseFloat(currItem.staveBox.left)+parseFloat(currItem.staveBox.width)+"px", top: currItem.staveBox.top, height: selectData.measureHeight + 'px' } } })) } return [] }) onMounted(() => { selectData.notes = []; selectData.staves = []; calcNoteData(); // 初始化谱面可移动的元素位置 try { moveData.partIndex = state.partIndex + "" nextTick(() => renderForMoveData()) } catch (error) {} }); return () => (