Selaa lähdekoodia

更新旋律线算法

黄琪勇 10 kuukautta sitten
vanhempi
commit
d280843f7a
1 muutettua tiedostoa jossa 104 lisäystä ja 62 poistoa
  1. 104 62
      src/page-instrument/view-detail/smoothAnimation/index.ts

+ 104 - 62
src/page-instrument/view-detail/smoothAnimation/index.ts

@@ -7,7 +7,7 @@ import state from "/src/state"
 import "./index.less"
 import Bird from "./bird"
 
-type pointsPosType = { x: number; y: number; MeasureNumberXML: number }[]
+type pointsPosType = { x: number; y: number; MeasureNumberXML: number; noteId: number }[]
 type smoothAnimationType = {
    isShow: Ref<boolean>
    canvasDom: null | HTMLCanvasElement
@@ -64,7 +64,10 @@ export function initSmoothAnimation() {
    // 初始化动画数据
    const batePos = getPointsPosByBatePos()
    console.log(batePos, "batePos")
-   smoothAnimationState.pointsPos = createSmoothCurvePoints(batePos, undefined, undefined, _numberOfSegments)
+   const batePos1 = dataFilter([...batePos])
+   const batePos2 = createSmoothCurvePoints(batePos1, undefined, undefined, _numberOfSegments)
+   const batePos3 = dataFilter2(batePos, batePos2)
+   smoothAnimationState.pointsPos = batePos3
    // 谱面的平均速度(因为可能有反复的情况所以实际距离要加上反复的距离)
    const canvasDomPath = batePos.reduce((path, item, index, arr) => {
       if (index !== 0) {
@@ -88,6 +91,27 @@ export function initSmoothAnimation() {
    console.log(smoothAnimationState, "一行谱小鸟数据")
 }
 
+// 排序
+function dataFilter(batePos: pointsPosType) {
+   const filterData = batePos.filter((item, index, array) => {
+      return array.findIndex(i => i.noteId === item.noteId) === index
+   })
+   // 先按 音符排序  因为音符可能有重复id
+   const sortedData = filterData.sort((a, b) => a.noteId - b.noteId)
+   // 再按 小节排序
+   return sortedData.sort((a, b) => a.MeasureNumberXML - b.MeasureNumberXML)
+}
+
+//给原始数据赋值
+function dataFilter2(batePos1: pointsPosType, batePos2: pointsPosType) {
+   return batePos1.reduce((arr: pointsPosType, { noteId, MeasureNumberXML }, index) => {
+      const noteIdIndex = batePos2.findIndex(item => {
+         return noteId === item.noteId && MeasureNumberXML === item.MeasureNumberXML
+      })
+      arr.push(...batePos2.slice(noteIdIndex, noteIdIndex + _numberOfSegments + 1))
+      return arr
+   }, [])
+}
 /**
  * 销毁
  */
@@ -163,6 +187,10 @@ export function moveSmoothAnimation(progress: number, activeIndex: number, isMov
    let nowIndex = nextPointsIndex - _numberOfSegments + progressCalcIndex
    const nowPointsPos = smoothAnimationState.pointsPos[nowIndex]
    smoothAnimationState.canvasCtx?.clearRect(0, 0, smoothAnimationState.canvasDomWith, smoothAnimationState.canvasDomHeight)
+   if (!nowPointsPos?.x) {
+      console.error(nowPointsPos?.x, "nowPointsPos", nowIndex, activeIndex)
+      return
+   }
    // 移动
    smoothAnimationMove(
       {
@@ -320,17 +348,26 @@ function getPointsPosByBatePos(): pointsPosType {
    const frequencyData = state.times.map(item => {
       return !item.frequency || item.frequency === -1 ? 0 : item.frequency
    })
-   console.log(frequencyData,"没线性化之前的数据")
    // 线性频率数据
    const frequencyLineData = quantileScale(frequencyData, 6, 74)
    const pointsPos = state.times.reduce((posArr: any[], item, index) => {
-      // 当休止小节,可能当前音符在谱面上没有实际的音符(没有bbox),所以往后找谱面上有的音符
-      if (item.bbox) {
+      // 当休止小节,可能当前音符在谱面上没有实际的音符(没有bbox)
+      if (item.bbox?.x != null && item.noteId != null) {
          posArr.push({
+            noteId: item.noteId,
             MeasureNumberXML: item.MeasureNumberXML,
             x: item.bbox.x,
             y: 80 - frequencyLineData[index]
          })
+      } else {
+         // 连续休止小节 noteId 可能为 null,所以这里取上一个音符的id
+         posArr.push({
+            // 这里当第一个音符noteId为null,找不到前一个noteId,所以兼容一下
+            noteId: item.noteId != null ? item.noteId : (posArr[posArr.length - 1]?.noteId != null ? posArr[posArr.length - 1]?.noteId : -1) + 0.01, // 这里+0.01 是制造一个假id
+            MeasureNumberXML: item.MeasureNumberXML,
+            x: item.bbox?.x != null ? item.bbox.x : posArr[posArr.length - 1]?.x || 10,
+            y: 80 - frequencyLineData[index]
+         })
       }
       return posArr
    }, [])
@@ -338,7 +375,8 @@ function getPointsPosByBatePos(): pointsPosType {
    const extendPoint = {
       ...pointsPos[pointsPos.length - 1]
    }
-   extendPoint.MeasureNumberXML++
+   extendPoint.MeasureNumberXML += 100 // 防止MeasureNumberXML重复
+   extendPoint.noteId += 100 // 防止noteId重复
    // 当总长度减30小于最后一个音符时候,取最后一个音符加15
    extendPoint.x = smoothAnimationState.canvasDomWith - 30 > extendPoint.x ? smoothAnimationState.canvasDomWith - 30 : extendPoint.x + 15
    pointsPos.push(extendPoint)
@@ -399,62 +437,63 @@ function createSmoothCurvePoints(pointsPos: pointsPosType, tension?: number, clo
       t2x = (ps[i + 2].x - ps[i].x) * tension
       t1y = (ps[i + 1].y - ps[i - 1].y) * tension
       t2y = (ps[i + 2].y - ps[i].y) * tension
-      // 当中途出现反复 刚开始反复时候 53 52 22 52  (22)中途值会变小 这里强行拉大 防止算法平均值出现很大偏差
-      if (ps[i + 1].MeasureNumberXML - ps[i + 2].MeasureNumberXML > 1) {
-         const nowNumberXML = ps[i + 1].MeasureNumberXML + 1
-         //在当前值的情况下 向前一位
-         let index = ps.findIndex(item => {
-            return nowNumberXML === item.MeasureNumberXML
-         })
-         // 查询不到index时候取当前值
-         index === -1 && (index = i + 1)
-         t2x = (ps[index].x - ps[i].x) * tension
-      }
-      // 当中途出现反复 结束反复时候 22 53 22 22  (53)中途值会变大 这里强行缩小 防止算法平均值出现很大偏差
-      if (ps[i - 1].MeasureNumberXML - ps[i].MeasureNumberXML > 1) {
-         //在当前值的情况下 向后一位
-         const nowNumberXML = ps[i].MeasureNumberXML - 1
-         let index = ps.findIndex((item, index) => {
-            return nowNumberXML === item.MeasureNumberXML && nowNumberXML !== ps[index + 1]?.MeasureNumberXML
-         })
-         // 查询不到index时候取当前值
-         index === -1 && (index = i)
-         t1x = (ps[i + 1].x - ps[index].x) * tension
-      }
-      // 当中途出现跳房子 刚开始跳房子时候 35 35 54 35  (54)中途值会变大 这里强行缩小 防止算法平均值出现很大偏差
-      if (ps[i + 1].MeasureNumberXML - ps[i + 2].MeasureNumberXML < -1) {
-         const nowNumberXML = ps[i + 1].MeasureNumberXML + 1
-         //在当前值的情况下 向前一位
-         let index = ps.findIndex(item => {
-            return nowNumberXML === item.MeasureNumberXML
-         })
-         // 查询不到index时候取当前值
-         index === -1 && (index = i + 1)
-         t2x = (ps[index].x - ps[i].x) * tension
-      }
-      // 当中途出现跳房子 结束跳房子时候 54 35 54 54  (35)中途值会变小 这里强行拉大 防止算法平均值出现很大偏差
-      if (ps[i - 1].MeasureNumberXML - ps[i].MeasureNumberXML < -1) {
-         const nowNumberXML = ps[i].MeasureNumberXML - 1
-         let index = ps.findIndex((item, index) => {
-            return nowNumberXML === item.MeasureNumberXML && nowNumberXML !== ps[index + 1]?.MeasureNumberXML
-         })
-         // 查询不到index时候取当前值
-         index === -1 && (index = i)
-         t1x = (ps[i + 1].x - ps[index].x) * tension
-      }
-      const nowMeasureNumberXML = pointsPos[i - 1].MeasureNumberXML
-      const nextMeasureNumberXML = pointsPos[i].MeasureNumberXML
+      // // 当中途出现反复 刚开始反复时候 53 52 22 52  (22)中途值会变小 这里强行拉大 防止算法平均值出现很大偏差
+      // if (ps[i + 1].MeasureNumberXML - ps[i + 2].MeasureNumberXML > 1) {
+      //    const nowNumberXML = ps[i + 1].MeasureNumberXML + 1
+      //    //在当前值的情况下 向前一位
+      //    let index = ps.findIndex(item => {
+      //       return nowNumberXML === item.MeasureNumberXML
+      //    })
+      //    // 查询不到index时候取当前值
+      //    index === -1 && (index = i + 1)
+      //    t2x = (ps[index].x - ps[i].x) * tension
+      // }
+      // // 当中途出现反复 结束反复时候 22 53 22 22  (53)中途值会变大 这里强行缩小 防止算法平均值出现很大偏差
+      // if (ps[i - 1].MeasureNumberXML - ps[i].MeasureNumberXML > 1) {
+      //    //在当前值的情况下 向后一位
+      //    const nowNumberXML = ps[i].MeasureNumberXML - 1
+      //    let index = ps.findIndex((item, index) => {
+      //       return nowNumberXML === item.MeasureNumberXML && nowNumberXML !== ps[index + 1]?.MeasureNumberXML
+      //    })
+      //    // 查询不到index时候取当前值
+      //    index === -1 && (index = i)
+      //    t1x = (ps[i + 1].x - ps[index].x) * tension
+      // }
+      // // 当中途出现跳房子 刚开始跳房子时候 35 35 54 35  (54)中途值会变大 这里强行缩小 防止算法平均值出现很大偏差
+      // if (ps[i + 1].MeasureNumberXML - ps[i + 2].MeasureNumberXML < -1) {
+      //    const nowNumberXML = ps[i + 1].MeasureNumberXML + 1
+      //    //在当前值的情况下 向前一位
+      //    let index = ps.findIndex(item => {
+      //       return nowNumberXML === item.MeasureNumberXML
+      //    })
+      //    // 查询不到index时候取当前值
+      //    index === -1 && (index = i + 1)
+      //    t2x = (ps[index].x - ps[i].x) * tension
+      // }
+      // // 当中途出现跳房子 结束跳房子时候 54 35 54 54  (35)中途值会变小 这里强行拉大 防止算法平均值出现很大偏差
+      // if (ps[i - 1].MeasureNumberXML - ps[i].MeasureNumberXML < -1) {
+      //    const nowNumberXML = ps[i].MeasureNumberXML - 1
+      //    let index = ps.findIndex((item, index) => {
+      //       return nowNumberXML === item.MeasureNumberXML && nowNumberXML !== ps[index + 1]?.MeasureNumberXML
+      //    })
+      //    // 查询不到index时候取当前值
+      //    index === -1 && (index = i)
+      //    t1x = (ps[i + 1].x - ps[index].x) * tension
+      // }
+      // const nowMeasureNumberXML = pointsPos[i - 1].MeasureNumberXML
+      // const nextMeasureNumberXML = pointsPos[i].MeasureNumberXML
       for (t = 0; t <= numberOfSegments; t++) {
-         // 小于1时候是反复   大于1是跳房子  不画曲线  停留
-         if (nextMeasureNumberXML - nowMeasureNumberXML < 0 || nextMeasureNumberXML - nowMeasureNumberXML > 1) {
-            //console.log(x, y)
-            result.push({
-               x: x as number,
-               y: y as number,
-               MeasureNumberXML: nowMeasureNumberXML
-            })
-            continue
-         }
+         // // 小于1时候是反复   大于1是跳房子  不画曲线  停留
+         // if (nextMeasureNumberXML - nowMeasureNumberXML < 0 || nextMeasureNumberXML - nowMeasureNumberXML > 1) {
+         //    //console.log(x, y)
+         //    result.push({
+         //       x: x as number,
+         //       y: y as number,
+         //       MeasureNumberXML: nowMeasureNumberXML,
+         //       noteId: pointsPos[i - 1].noteId
+         //    })
+         //    continue
+         // }
          st = t / numberOfSegments
          c1 = 2 * Math.pow(st, 3) - 3 * Math.pow(st, 2) + 1
          c2 = -(2 * Math.pow(st, 3)) + 3 * Math.pow(st, 2)
@@ -466,7 +505,10 @@ function createSmoothCurvePoints(pointsPos: pointsPosType, tension?: number, clo
          result.push({
             x,
             y,
-            MeasureNumberXML: t === numberOfSegments ? nextMeasureNumberXML : nowMeasureNumberXML
+            // MeasureNumberXML: t === numberOfSegments ? nextMeasureNumberXML : nowMeasureNumberXML,
+            // noteId: t === numberOfSegments ? pointsPos[i].noteId : pointsPos[i - 1].noteId
+            MeasureNumberXML: pointsPos[i - 1].MeasureNumberXML,
+            noteId: pointsPos[i - 1].noteId
          })
       }
    }