|
@@ -14,6 +14,7 @@ type smoothAnimationType = {
|
|
|
canvasCtx: null | undefined | CanvasRenderingContext2D
|
|
|
canvasDomWith: number
|
|
|
canvasDomHeight: number
|
|
|
+ canvasSmoothDom: null | HTMLCanvasElement
|
|
|
smoothAnimationBoxDom: null | HTMLElement
|
|
|
smoothBotDom: null | HTMLElement
|
|
|
osmdCanvasPageDom: null | HTMLElement
|
|
@@ -21,13 +22,14 @@ type smoothAnimationType = {
|
|
|
osdmScrollDomWith: number
|
|
|
osdmScrollDomOffsetLeft: number
|
|
|
selectionBoxDom: null | HTMLElement
|
|
|
+ batePos: pointsPosType
|
|
|
pointsPos: pointsPosType
|
|
|
translateXNum: number
|
|
|
aveSpeed: number
|
|
|
}
|
|
|
|
|
|
-const _numberOfSegments = 58 // 中间切割线的个数
|
|
|
-const _canvasDomHeight = 60
|
|
|
+let _numberOfSegments = 56 // 中间切割线的个数
|
|
|
+const _canvasDomHeight = 60 // canvans 高度
|
|
|
|
|
|
export const smoothAnimationState = {
|
|
|
isShow: ref(false), // 是否显示
|
|
@@ -35,6 +37,7 @@ export const smoothAnimationState = {
|
|
|
canvasCtx: null,
|
|
|
canvasDomWith: 0,
|
|
|
canvasDomHeight: _canvasDomHeight,
|
|
|
+ canvasSmoothDom: null,
|
|
|
smoothAnimationBoxDom: null,
|
|
|
smoothBotDom: null,
|
|
|
osmdCanvasPageDom: null,
|
|
@@ -42,7 +45,8 @@ export const smoothAnimationState = {
|
|
|
osdmScrollDomWith: 0,
|
|
|
osdmScrollDomOffsetLeft: 0,
|
|
|
selectionBoxDom: null,
|
|
|
- pointsPos: [], // 计算之后的点坐标数组
|
|
|
+ batePos: [], // times 直接转换的数组
|
|
|
+ pointsPos: [], // 筛选之后的点坐标数组
|
|
|
translateXNum: 0, // 当前谱面的translateX的距离 谱面的位置信息 由translateX和scrollLeft的偏移一起决定
|
|
|
aveSpeed: 0 // 谱面的一帧的平均速度
|
|
|
} as smoothAnimationType
|
|
@@ -64,11 +68,16 @@ export function initSmoothAnimation() {
|
|
|
createSmoothAnimation()
|
|
|
// 初始化动画数据
|
|
|
const batePos = getPointsPosByBatePos()
|
|
|
- console.log(batePos, "batePos")
|
|
|
+ smoothAnimationState.batePos = batePos
|
|
|
const batePos1 = dataFilter([...batePos])
|
|
|
- const batePos2 = createSmoothCurvePoints(batePos1, undefined, undefined, _numberOfSegments)
|
|
|
- const batePos3 = dataFilter2(batePos, batePos2)
|
|
|
- smoothAnimationState.pointsPos = batePos3
|
|
|
+ console.log(batePos1, "排序之后的数据")
|
|
|
+ // 这里性能优化,对于超级长的曲子,_numberOfSegments值 动态变化
|
|
|
+ const numberOfSegments = parseInt(16000 / batePos1.length + "")
|
|
|
+ _numberOfSegments = Math.max(18, Math.min(_numberOfSegments, numberOfSegments))
|
|
|
+ const batePos2 = createSmoothCurvePoints(batePos1, _numberOfSegments)
|
|
|
+ smoothAnimationState.pointsPos = batePos2
|
|
|
+ // 初始化旋律线
|
|
|
+ initCanvasSmooth()
|
|
|
// 谱面的平均速度(因为可能有反复的情况所以实际距离要加上反复的距离)
|
|
|
const canvasDomPath = batePos.reduce((path, item, index, arr) => {
|
|
|
if (index !== 0) {
|
|
@@ -94,25 +103,28 @@ export function initSmoothAnimation() {
|
|
|
|
|
|
// 排序
|
|
|
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 }) => {
|
|
|
- const noteIdIndex = batePos2.findIndex(item => {
|
|
|
- return noteId === item.noteId && MeasureNumberXML === item.MeasureNumberXML
|
|
|
- })
|
|
|
- arr.push(...batePos2.slice(noteIdIndex, noteIdIndex + _numberOfSegments + 1))
|
|
|
- return arr
|
|
|
- }, [])
|
|
|
+//根据 activeInde和进度 查找转换之后的activeInde
|
|
|
+function dataFindIndex(activeIndex: number, progress: number) {
|
|
|
+ // 百分比转为当前的index 距离个数
|
|
|
+ const progressCalcIndex = Math.round(progress * _numberOfSegments)
|
|
|
+ const { noteId, MeasureNumberXML } = smoothAnimationState.batePos[activeIndex]
|
|
|
+ return (
|
|
|
+ smoothAnimationState.pointsPos.findIndex(item => {
|
|
|
+ return item.noteId === noteId && item.MeasureNumberXML === MeasureNumberXML
|
|
|
+ }) + progressCalcIndex
|
|
|
+ )
|
|
|
}
|
|
|
+
|
|
|
/**
|
|
|
* 销毁
|
|
|
*/
|
|
@@ -125,6 +137,7 @@ export function destroySmoothAnimation() {
|
|
|
canvasCtx: null,
|
|
|
canvasDomWith: 0,
|
|
|
canvasDomHeight: _canvasDomHeight,
|
|
|
+ canvasSmoothDom: null,
|
|
|
smoothAnimationBoxDom: null,
|
|
|
smoothBotDom: null,
|
|
|
osmdCanvasPageDom: null,
|
|
@@ -132,6 +145,7 @@ export function destroySmoothAnimation() {
|
|
|
osdmScrollDomWith: 0,
|
|
|
osdmScrollDomOffsetLeft: 0,
|
|
|
selectionBoxDom: null,
|
|
|
+ batePos: [],
|
|
|
pointsPos: [],
|
|
|
translateXNum: 0,
|
|
|
aveSpeed: 0
|
|
@@ -150,12 +164,7 @@ export function moveSmoothAnimationByPlayTime(time?: number) {
|
|
|
if (currentTime <= state.fixtime) return
|
|
|
if (currentTime > state.times.last()?.endtime) return
|
|
|
// 当休止小节,可能当前音符在谱面上没有实际的音符(没有bbox),所以往后找谱面上有的音符
|
|
|
- let nextIndex = state.activeNoteIndex + 1
|
|
|
- let nextBBox = state.times[nextIndex]?.bbox
|
|
|
- while (!nextBBox && nextIndex < state.times.length) {
|
|
|
- nextIndex += 1
|
|
|
- nextBBox = state.times[nextIndex]?.bbox
|
|
|
- }
|
|
|
+ const nextIndex = state.activeNoteIndex + 1
|
|
|
// 当前的音符和下一个音符之间的时值 (当是最后一个音符的时候,下一个音符的时间取当前音符的endtime)
|
|
|
const noteDuration =
|
|
|
(nextIndex > state.times.length - 1 ? state.times[state.activeNoteIndex]?.endtime : state.times[nextIndex].time) -
|
|
@@ -180,26 +189,19 @@ export function moveSmoothAnimation(progress: number, activeIndex: number, isMov
|
|
|
// if (!smoothAnimationState.isShow.value) {
|
|
|
// return
|
|
|
// }
|
|
|
- // 计算 下一个音符index 在pointsPos 中的距离
|
|
|
- const nextPointsIndex = (activeIndex + 1) * (_numberOfSegments + 1) - 1
|
|
|
- // 百分比转为当前的index 距离个数
|
|
|
- const progressCalcIndex = Math.round(progress * _numberOfSegments)
|
|
|
- // // 当前的index
|
|
|
- const nowIndex = nextPointsIndex - _numberOfSegments + progressCalcIndex
|
|
|
+ const nowIndex = dataFindIndex(activeIndex, progress)
|
|
|
const nowPointsPos = smoothAnimationState.pointsPos[nowIndex]
|
|
|
// 当x的值为null和undefinedde的时候 错误 不走下面的方法
|
|
|
if (!(nowPointsPos?.x != null)) {
|
|
|
console.error(nowPointsPos?.x, "nowPointsPos", nowIndex, activeIndex)
|
|
|
return
|
|
|
}
|
|
|
- smoothAnimationState.canvasCtx?.clearRect(0, 0, smoothAnimationState.canvasDomWith, smoothAnimationState.canvasDomHeight)
|
|
|
// 移动
|
|
|
smoothAnimationMove(
|
|
|
{
|
|
|
- x: nowPointsPos.x - 18,
|
|
|
+ x: nowPointsPos.x - 18, //鸟的大小
|
|
|
y: nowPointsPos.y - 23
|
|
|
},
|
|
|
- smoothAnimationState.pointsPos,
|
|
|
smoothAnimationState.pointsPos.slice(0, nowIndex)
|
|
|
)
|
|
|
// 当移动到屏幕最右边时候 就不进行移动了 存在移动到屏幕最右边时候 有反复的情况需要屏幕移动。所以这里注释掉了
|
|
@@ -288,17 +290,11 @@ export function moveTranslateXNum(translateXNum: number) {
|
|
|
/**
|
|
|
* 进度条和块移动方法
|
|
|
*/
|
|
|
-function smoothAnimationMove(pos: { x: number; y: number }, pointsPos: pointsPosType, progresspointsPos?: pointsPosType) {
|
|
|
+function smoothAnimationMove(pos: { x: number; y: number }, progresspointsPos: pointsPosType) {
|
|
|
smoothAnimationState.smoothBotDom && (smoothAnimationState.smoothBotDom.style.transform = `translate(${pos.x}px, ${pos.y}px)`)
|
|
|
- smoothAnimationState.canvasCtx && drawSmoothCurve(smoothAnimationState.canvasCtx, pointsPos, progresspointsPos)
|
|
|
-}
|
|
|
-/**
|
|
|
- * 计算视口宽度
|
|
|
- */
|
|
|
-export function calcClientWidth() {
|
|
|
- smoothAnimationState.osdmScrollDomWith = smoothAnimationState.osdmScrollDom?.offsetWidth || 0
|
|
|
- smoothAnimationState.osdmScrollDomOffsetLeft = smoothAnimationState.osdmScrollDom?.getBoundingClientRect().left || 0
|
|
|
+ smoothAnimationState.canvasCtx && drawSmoothCurveProgress(smoothAnimationState.canvasCtx, progresspointsPos, "#FFC121")
|
|
|
}
|
|
|
+
|
|
|
/**
|
|
|
* 创建dom
|
|
|
*/
|
|
@@ -328,7 +324,11 @@ function createSmoothAnimation() {
|
|
|
smoothAnimationState.canvasDomWith = osmdCanvasPageDom?.offsetWidth || 0
|
|
|
smoothCanvasDom.width = smoothAnimationState.canvasDomWith
|
|
|
smoothCanvasDom.height = smoothAnimationState.canvasDomHeight
|
|
|
- smoothAnimationState.canvasCtx = smoothCanvasDom.getContext("2d")
|
|
|
+ const ctx = smoothCanvasDom.getContext("2d")!
|
|
|
+ smoothAnimationState.canvasCtx = ctx
|
|
|
+ ctx.imageSmoothingEnabled = true
|
|
|
+ ctx.lineCap = "round"
|
|
|
+ ctx.lineJoin = "round"
|
|
|
// bot
|
|
|
const smoothBotDom = document.createElement("div")
|
|
|
smoothBotDom.className = "smoothBot"
|
|
@@ -343,6 +343,14 @@ function createSmoothAnimation() {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 计算视口宽度
|
|
|
+ */
|
|
|
+export function calcClientWidth() {
|
|
|
+ smoothAnimationState.osdmScrollDomWith = smoothAnimationState.osdmScrollDom?.offsetWidth || 0
|
|
|
+ smoothAnimationState.osdmScrollDomOffsetLeft = smoothAnimationState.osdmScrollDom?.getBoundingClientRect().left || 0
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
* 根据音符获取坐标
|
|
|
*/
|
|
|
function getPointsPosByBatePos(): pointsPosType {
|
|
@@ -351,7 +359,7 @@ function getPointsPosByBatePos(): pointsPosType {
|
|
|
return !item.frequency || item.frequency === -1 ? 0 : item.frequency
|
|
|
})
|
|
|
// 线性频率数据
|
|
|
- const frequencyLineData = quantileScale(frequencyData, 8, _canvasDomHeight - 8)
|
|
|
+ const frequencyLineData = quantileScale(frequencyData, 8, _canvasDomHeight - 8) // 最小值和最大值
|
|
|
const pointsPos = state.times.reduce((posArr: any[], item, index) => {
|
|
|
// 当休止小节,可能当前音符在谱面上没有实际的音符(没有bbox)
|
|
|
if (item.bbox?.x != null && item.noteId != null) {
|
|
@@ -398,150 +406,65 @@ function quantileScale(data: number[], minRange = 0, maxRange = _canvasDomHeight
|
|
|
/**
|
|
|
* 使用传入的曲线的顶点坐标创建平滑曲线的顶点。
|
|
|
* @param {Array} points 曲线顶点坐标数组,
|
|
|
- * @param {Float} tension 密集程度,默认为 0.5
|
|
|
- * @param {Boolean} closed 是否创建闭合曲线,默认为 false
|
|
|
- * @param {Int} numberOfSegments 平滑曲线 2 个顶点间的线段数,默认为 20
|
|
|
+ * @param {Int} numberOfSegments 平滑曲线 2 个顶点间的线段数
|
|
|
* @return {Array} 平滑曲线的顶点坐标数组
|
|
|
*/
|
|
|
-function createSmoothCurvePoints(pointsPos: pointsPosType, tension?: number, closed?: boolean, numberOfSegments?: number) {
|
|
|
- if (pointsPos.length <= 2) {
|
|
|
- return pointsPos
|
|
|
+function createSmoothCurvePoints(points: pointsPosType, numSegments: number) {
|
|
|
+ if (points.length <= 2) {
|
|
|
+ return points
|
|
|
}
|
|
|
- tension = tension ? tension : 0.5
|
|
|
- closed = closed ? true : false
|
|
|
- numberOfSegments = numberOfSegments ? numberOfSegments : 20
|
|
|
- let ps = pointsPos.slice(0),
|
|
|
- result = [],
|
|
|
- x,
|
|
|
- y,
|
|
|
- t1x,
|
|
|
- t2x,
|
|
|
- t1y,
|
|
|
- t2y,
|
|
|
- c1,
|
|
|
- c2,
|
|
|
- c3,
|
|
|
- c4,
|
|
|
- st,
|
|
|
- t,
|
|
|
- i
|
|
|
- if (closed) {
|
|
|
- ps.unshift(pointsPos[pointsPos.length - 1])
|
|
|
- ps.unshift(pointsPos[pointsPos.length - 1])
|
|
|
- ps.push(pointsPos[0])
|
|
|
- } else {
|
|
|
- ps.unshift(pointsPos[0])
|
|
|
- ps.push(pointsPos[pointsPos.length - 1])
|
|
|
- }
|
|
|
- for (i = 1; i < ps.length - 2; i += 1) {
|
|
|
- //console.log(ps[i + 1].MeasureNumberXML, ps[i - 1].MeasureNumberXML, ps[i + 2].MeasureNumberXML, ps[i].MeasureNumberXML)
|
|
|
- t1x = (ps[i + 1].x - ps[i - 1].x) * tension
|
|
|
- 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
|
|
|
- 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,
|
|
|
- // 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)
|
|
|
- c3 = Math.pow(st, 3) - 2 * Math.pow(st, 2) + st
|
|
|
- c4 = Math.pow(st, 3) - Math.pow(st, 2)
|
|
|
- x = c1 * ps[i].x + c2 * ps[i + 1].x + c3 * t1x + c4 * t2x
|
|
|
- y = c1 * ps[i].y + c2 * ps[i + 1].y + c3 * t1y + c4 * t2y
|
|
|
- //console.log(x, y)
|
|
|
- result.push({
|
|
|
- x,
|
|
|
- y,
|
|
|
- // 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
|
|
|
- })
|
|
|
+ const curvePoints = []
|
|
|
+ for (let i = 0; i < points.length - 1; i++) {
|
|
|
+ const p0 = i > 0 ? points[i - 1] : points[i]
|
|
|
+ const p1 = points[i]
|
|
|
+ const p2 = points[i + 1]
|
|
|
+ const p3 = i !== points.length - 2 ? points[i + 2] : points[i + 1]
|
|
|
+ for (let j = 0; j < numSegments; j++) {
|
|
|
+ const t = j / numSegments
|
|
|
+ const t2 = t * t
|
|
|
+ const t3 = t2 * t
|
|
|
+ const x = 0.5 * (2 * p1.x + (-p0.x + p2.x) * t + (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 + (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3)
|
|
|
+ const y = 0.5 * (2 * p1.y + (-p0.y + p2.y) * t + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 + (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3)
|
|
|
+ curvePoints.push({ x, y, MeasureNumberXML: p1.MeasureNumberXML, noteId: p1.noteId })
|
|
|
}
|
|
|
}
|
|
|
- return result
|
|
|
+ return curvePoints
|
|
|
+}
|
|
|
+
|
|
|
+/** 初始化一条完整的旋律线dom */
|
|
|
+function initCanvasSmooth() {
|
|
|
+ const smoothDom = document.createElement("canvas")
|
|
|
+ smoothDom.width = smoothAnimationState.canvasDomWith
|
|
|
+ smoothDom.height = smoothAnimationState.canvasDomHeight
|
|
|
+ const smoothDomCtx = smoothDom.getContext("2d")!
|
|
|
+ smoothDomCtx.imageSmoothingEnabled = true
|
|
|
+ smoothDomCtx.lineCap = "round"
|
|
|
+ smoothDomCtx.lineJoin = "round"
|
|
|
+ // 根据坐标花线
|
|
|
+ drawLines(smoothDomCtx, smoothAnimationState.pointsPos, "rgba(255,255,255,0.6)")
|
|
|
+ smoothAnimationState.canvasSmoothDom = smoothDom
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 根据进度画线
|
|
|
+ */
|
|
|
+function drawSmoothCurveProgress(context: CanvasRenderingContext2D, pointsPos: pointsPosType, color: string) {
|
|
|
+ context.clearRect(0, 0, smoothAnimationState.canvasDomWith, smoothAnimationState.canvasDomHeight)
|
|
|
+ smoothAnimationState.canvasSmoothDom && context.drawImage(smoothAnimationState.canvasSmoothDom, 0, 0)
|
|
|
+ drawLines(context, pointsPos, color)
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* 根据坐标划线
|
|
|
*/
|
|
|
-function drawSmoothCurve(context: CanvasRenderingContext2D, pointsPos: pointsPosType, progresspointsPos?: pointsPosType) {
|
|
|
+function drawLines(context: CanvasRenderingContext2D, pointsPos: pointsPosType, color: string) {
|
|
|
+ if (pointsPos.length === 0) return
|
|
|
context.lineWidth = 2
|
|
|
- context.lineJoin = "round" // 优化锯齿
|
|
|
- context.lineCap = "round" // 优化锯齿
|
|
|
- context.strokeStyle = "rgba(255,255,255,0.6)"
|
|
|
- drawLines(context, pointsPos)
|
|
|
- if (progresspointsPos?.length) {
|
|
|
- context.strokeStyle = "#FFC121"
|
|
|
- drawLines(context, progresspointsPos)
|
|
|
- }
|
|
|
-}
|
|
|
-function drawLines(context: CanvasRenderingContext2D, points: pointsPosType) {
|
|
|
+ context.strokeStyle = color
|
|
|
context.beginPath()
|
|
|
- context.moveTo(points[0].x, points[0].y)
|
|
|
- for (let i = 1; i < points.length - 1; i++) {
|
|
|
- if (Math.abs(points[i].MeasureNumberXML - points[i - 1].MeasureNumberXML) > 1) {
|
|
|
- // 取消反复和跳房子连线
|
|
|
- context.stroke()
|
|
|
- context.beginPath()
|
|
|
- context.moveTo(points[i + 1].x, points[i + 1].y)
|
|
|
- continue
|
|
|
- }
|
|
|
- context.lineTo(points[i].x, points[i].y)
|
|
|
+ context.moveTo(pointsPos[0].x, pointsPos[0].y)
|
|
|
+ for (let i = 1; i < pointsPos.length; i++) {
|
|
|
+ context.lineTo(pointsPos[i].x, pointsPos[i].y)
|
|
|
}
|
|
|
context.stroke()
|
|
|
}
|