import { Icon, Toast } from 'vant' import { defineComponent, watchEffect, TransitionGroup, ref, Ref, reactive } from 'vue' import event from '/src/components/music-score/event' import SettingState from '/src/pages/detail/setting-state' import state from '../state' import runtime, { getFirsrNoteByMeasureListIndex, getBoundingBoxByNote, changeSpeed } from '../runtime' import { getActtiveNoteByTimes, getBoundingBoxByverticalNote, getNoteBySlursStart, setSettionBackground } from '../helpers' import { formatZoom } from '/src/helpers/utils' import styles from './index.module.less' import classNames from 'classnames' import { modelType } from '/src/subpages/colexiu/buttons' import { restPromptData } from '/src/helpers/restPrompt' import { unitTestData } from '/src/subpages/colexiu/unitTest' import { metronomeData } from "/src/helpers/metronome"; const sectionRef: Ref = ref(null) const noteInfoItems = reactive({ duration: false, numerator: false, denominator: false, i: false, time: false, speed: false, }) ;(window as unknown as Window & { setNoteInfoItems: (data: typeof noteInfoItems) => void }).setNoteInfoItems = ( data ) => { for (const key in data) { if (Object.prototype.hasOwnProperty.call(data, key)) { noteInfoItems[key as keyof typeof noteInfoItems] = data[key as keyof typeof noteInfoItems] } } } /** 根据位置去重复 */ const uniqueByPosition = (list: any[]) => { const data: { [key in string]: any } = {} for (const item of list) { if (item && item.start_x) { data[`${item.x}-${item.y}`] = item } } return data } watchEffect(() => { // 监听状态节点选择状态并且开启提示 if (state.sectionStatus) { if (!state.section.length) { state.befireSection = null Toast.clear() Toast({ duration: 0, message: '请选择开始节点', position: 'top' }) } else if (state.section.length === 1) { Toast.clear() Toast({ duration: 0, message: '请选择结束节点', position: 'top' }) } } else { state.section = [] state.sectionBoundingBoxs = [] Toast.clear() } }) export default defineComponent({ name: 'section-box', props: { type: { type: String, default: 'evaluating', }, top: { type: Number, default: 0, }, left: { type: Number, default: 0, }, }, data() { return { sectionTop: 0, sectionLeft: 0, } }, methods: { setSection(evt: MouseEvent) { const activeNote = getActtiveNoteByTimes(evt) if (activeNote && state.section.length < 2) { const sectionLength = state.section.length if (sectionLength === 0) { const note = getNoteBySlursStart(activeNote, true) state.section.push(state.times[note.i - note.si]) } if (sectionLength === 1) { const note = getNoteBySlursStart(activeNote, true, 'end') state.section.push(state.times[note.i - note.si + note.noteLength - 1]) // 选段状态需要重置播放倍率为1 runtime.basePlayRate = 1; const currentItem: any = state.section[0]; const currentSpeed = currentItem?.measureSpeed ? currentItem.measureSpeed : state.activeSpeed; changeSpeed(currentSpeed) } } if (state.section.length === 2) { Toast.clear() setSettionBackground() } }, sectionClick(evt: MouseEvent): void { metronomeData.isClick = true; if (!state.sectionStatus) { if (state.mode !== 'contact' || runtime.evaluatingStatus) { return } event.emit('section-click', evt) } else { // console.log(state.sectionStatus, evt) this.setSection(evt) } }, /** 重复时仅处理一次 */ filterTimes(times: any[]) { const ids: string[] = [] return times.filter((item) => { const has = ids.includes(item.id) ids.push(item.id) return !has }) }, }, mounted() { Toast.clear() state.section = [] this.sectionTop = sectionRef.value?.getBoundingClientRect().top this.sectionLeft = sectionRef.value?.getBoundingClientRect().left }, beforeUnmount() { Toast.clear() state.sectionStatus = false state.section = [] }, render() { const eyeBorderColor = SettingState.sett.eyeProtection ? 'var(--eye-section-border-color)' : 'var(--section-border-color)' const eyeBackground = (item: any) => { if (SettingState.sett.eyeProtection) { return item.before ? 'var(--section-background-color)' : 'var(--eye-section-background-color)' } else { return item.before ? 'var(--eye-section-background-color)' : 'var(--section-background-color)' } } // console.log(uniqueByPosition(Object.values(state.evaluatings)), 'state.evaluatings') // console.log('state.sectionFlash', state.sectionFlash) const activeNumberXml = state.times[runtime.activeIndex]?.noteElement?.sourceMeasure?.MeasureNumberXML || -2 const restMeasure = restPromptData.list.find((n) => { const m = activeNumberXml - n.measureNumberXML return n.allRests && m >= 0 && m < n.multipleRestMeasures }) const restNumber = restMeasure ? activeNumberXml - restMeasure.measureNumberXML + 1 : 0 const img: HTMLElement = document.querySelector('#cursorImg-0')! if (restMeasure){ img && metronomeData.cursorMode === 2 && img.classList.remove('lineHide') } else { img && metronomeData.cursorMode === 2 && img.classList.add('lineHide') } return (
{/* 为每个音符添加一个遮罩方便点击 */} {this.filterTimes(state.times).map((item) => { if (!item.svgElelent) { return null } let bbox: any try { bbox = item.svgElelent.bbox || item.svgElelent.getBoundingBox?.() if (!bbox && item.svgElelent?.attrs?.el) { bbox = item.svgElelent.attrs.el.getBBox() bbox.w = bbox.width < 15 ? 15 : bbox.width bbox.h = bbox.height < 11 ? 11 : bbox.height } } catch (error) { console.log(error) } if (!bbox) { return null } if (SettingState.sett.type === 'jianpu' && item.svgElelent) { if (item.svgElelent.top_y && item.svgElelent.note_height) { bbox.y = item.svgElelent.top_y - item.svgElelent.note_height } } let { x, y, h, w } = bbox let boundingBox = null // let measureBg = false const activeNumberIndex = (item?.noteElement?.sourceMeasure?.measureNumber + 1) || -2; // console.log(activeNumberIndex,'👀👀',metronomeData.activeMetro?.measureNumberXML) if (item.si === 0) { boundingBox = getBoundingBoxByNote(item.noteElement) } return ( <> {item.si === 0 && boundingBox && (
state.section[1]?.noteElement?.sourceMeasure.MeasureNumberXML ? 'rgba(0, 0, 0,.28)' : 'var(--section-background-color)' }` : '', }} onClick={state.sectionStatus ? this.sectionClick : undefined} > {metronomeData.cursorMode === 2 && activeNumberIndex === metronomeData.activeMetro?.measureNumberXML &&
}
)}
v === true) ? 'rgba(255, 255, 255, 0.8)' : '', }} onClick={this.sectionClick} > {noteInfoItems.duration && ( <> {parseInt(item.duration * 100 + '') / 100}
)} {noteInfoItems.time && ( <> {item.time.toFixed(2)}
)} {noteInfoItems.numerator && ( <> {item.noteElement.sourceMeasure.activeTimeSignature.numerator}

)} {noteInfoItems.denominator && ( <> {item.noteElement.sourceMeasure.activeTimeSignature.denominator}

)} {noteInfoItems.i && ( <> {item.i}

)} {noteInfoItems.speed && ( <> {item.speed.toFixed(0)}

)}
) })} {/* 范围的两个括号 */} {state.section.map((item, index) => { const boundingBox = getBoundingBoxByverticalNote(item) let X: number | undefined = undefined try { const bbox = item.svgElelent?.bbox || item.svgElelent?.getBoundingBox && item.svgElelent?.getBoundingBox() X = formatZoom(bbox?.x || (index === 0 ? boundingBox.start_x : boundingBox.end_x)) } catch (error) { console.log(error) } if (!X) { return null } if (index === 0 && boundingBox) { // console.log('左',formatZoom(boundingBox.y) - 5, formatZoom(boundingBox.x),X,SettingState.sett.scoreSize) return (
) } if (index === 1 && boundingBox) { // console.log('右',formatZoom(boundingBox.y - 5), formatZoom(boundingBox.end_x),X) return (
) } return null })} {/* 添加选择背景 */} {state.sectionBoundingBoxs.map((item) => { return (
) })} {/* 分数信息 */} {Object.values(uniqueByPosition(Object.values(state.evaluatings))).map((item: any) => { if (!item) return return (
{this.type === 'evaluating' ? ( {item.score} ) : null}
) })}
{/* 休止符等待 */} {restMeasure && (
{restNumber}
)}
) }, })