Canvas实现雷达图效果

1,100 阅读1分钟

Canvas-雷达图效果.gif Canvas-雷达图效果.gif

代码地址:gitee.com/zyjun/desig…

一、使用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()
    }
    
    思路1.png
  • 开启定时移动逻辑
    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)
    }
    

页面实现整体效果: 测评结果.png