Canvas-雷达图效果.gif
一、使用Canvas实现原理
这里最难的就是坐标系旋转后的坐标使用。其他就是利用数学公式等计算一些数据。
还有就是一步一步的调试,最终才能实现想要的效果。
如果光看已经完成的代码可能体会不到具体的逻辑关系,实现了效果后就是对代码的不断优化。
- 绘制图形部分代码
painting() { this.ctx.restore() this.ctx.clearRect(0, 0, this.canvasInfo.width, this.canvasInfo.height) this.ctx.save() this.ctx.translate(this.centerX, this.centerX) this.ctx.rotate(45 * Math.PI / 180) this.ctx.lineWidth = 0.7; this.ctx.strokeStyle = "#CACACA"; this.strokeRect(1, 1) this.strokeFillRect(4 / 5, 4 / 5, "#F6F8FC") this.strokeFillRect(3 / 5, 3 / 5, "#FFFFFF") this.strokeFillRect(2 / 5, 2 / 5, "#F6F8FC") this.strokeFillRect(1 / 5, 1 / 5, "#FFFFFF") this.strokeLine(-this.outX, -this.outX, this.outX, this.outX) this.strokeLine(-this.outX, this.outX, this.outX, -this.outX) let pData = this.strokeValueLine(0.5, 0.3, 0.7, 0.5, "#FF8E5E") this.strokeValueLine(0.2, 0.4, 0.5, 0.3, "#195497") this.movePointProcess(pData) this.movePoint(this.curStepLine) return this }
- 1.将画布中心点作为坐标中心
- 2.将画布旋转45°
- 3.绘制最外面的边框
- 4.绘制里面的带颜色的正方形
- 5.绘制两个坐标轴线
- 6.绘制数值线圈⚪及线条
- 7.使用timer执行移动点逻辑
- 将雷达图四个点坐标转换成路径坐标
movePointProcess({p1, p2, p3, p4}) { let lines = [{s: p1, e: p2}, {s: p2, e: p3}, {s: p3, e: p4}, {s: p4, e: p1}] let linesSteps = [] for (let i = 0; i < lines.length; i++) { let {s, e} = lines[i] let distance = this.getDistanceLine(s, e)//获取开始点和结束点的直线距离 let stepNum = Math.floor(distance / 1)//将距离除以单步距离得到对应的总步数 let xSpan, ySpan xSpan = this.getDistanceAxis(s.x, e.x) / stepNum//获取开始点和结束点在x轴上的距离-除以总步数-得到每一步对应的x轴距离 ySpan = this.getDistanceAxis(s.y, e.y) / stepNum//获取开始点和结束点在y轴上的距离-除以总步数-得到每一步对应的y轴距离 linesSteps.push({s, e, xSpan, ySpan, stepNum}) } this.linesSteps = linesSteps }
- 绘制移动的点
movePoint({s, e, xSpan, ySpan, stepNum}) { this.ctx.save() this.curStep.step += 1 this.ctx.fillStyle = "#FF8E5E" this.ctx.shadowOffsetX = 3 this.ctx.shadowOffsetY = 3 this.ctx.shadowColor = 'rgba(100, 100, 100, 0.8)' this.ctx.shadowBlur = 2 this.ctx.beginPath() let potX = e.x > s.x ? s.x + this.curStep.step * xSpan : s.x - this.curStep.step * xSpan let potY = e.y > s.y ? s.y + this.curStep.step * ySpan : s.y - this.curStep.step * ySpan this.ctx.arc(potX, potY, 3, 0, 2 * Math.PI) this.ctx.closePath(); this.ctx.fill() this.ctx.restore() }
- 开启定时移动逻辑
startTimer() { if (this.curStepLine.stepNum === 0) this.curStepLine = this.linesSteps[0] console.log(this.linesSteps, this.curStepLine) this.moveTimer = setInterval(() => { // debugger if (this.curStep.step >= this.curStepLine.stepNum) {//如果走到线条最后,开始走下一条线路 if (this.curStep.lineIndex == 3) this.curStep.lineIndex = 0 else this.curStep.lineIndex += 1 this.curStep.step = 0 this.curStepLine = this.linesSteps[this.curStep.lineIndex] } this.painting() }, 30) }
页面实现整体效果: