如图所示:

    

 

画布组件:dashboard.vue

<template>
  <div>
    <canvas ref="canvas" v-if="change" id="canvas" width="600" height="400" style="width: 300px;height: 200px;"></canvas>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        change: true,
        text:['信用极差','信用较差','信用良好','信用极好']
      };
    },
    props: ['score'],
    methods: {
      canvasScore(id, getScore) {
        const vm = this;
        if(this.common.basics.isNull(getScore)){
          getScore  = 999
        }
        let fillText=vm.text[Math.floor(getScore/250)];
        if(this.common.basics.isNull(fillText)){
          fillText = vm.text[3];
        }

        new init(this.$refs.canvas, {
          teamNum: 20,
          radius: 10 / 2,
          fullMarks:1000,
          grade:getScore,
          color:'#44AAC9',
          fillColor:'#ffffff',
          function:function(ctx,options){
            ctx.font = '500 72px microsoft yahei';
            ctx.textAlign = 'center';
            ctx.fillStyle  = '#ffffff';
            ctx.fillText(options.grade, options.circle_x, options.circle_y-20);
            ctx.font = '500 40px microsoft yahei';
            ctx.textAlign = 'center';
            ctx.fillStyle  = '#ffffff';
            ctx.fillText(fillText, options.circle_x, options.circle_y+45);
          }
        })

      }
    },
    mounted() {
      this.canvasScore('canvas', this.score);
    },
    watch: {
      'score'() {
        this.change = false;
        this.$nextTick(() => {
          this.change = true;
          this.$nextTick(() => {
            this.canvasScore('canvas', this.score);
          });
        });
      }
    }
  };

  /**
   * @desc:canvas绘画芝麻分仪表盘
   * @param:canvas canvas自身
   * @param:options  options配置
   * @param:options-width  canvas宽度
   * @param:options-height  canvas高度
   * @param:options-teamNum 小圆的个数
   * @param:options-radius 小圆的直径
   * @param:options-designChartWidth //设计图宽度 默认750
   * @param:options-fillColor //小圆达到指标后的填充颜色
   * @param:options-color //小圆的默认颜色
   * @param:options-fontSzie //字体大小
   * @param:options-fontColor //字体颜色
   * @param:options-fullMarks//总分数
   * @param:options-grade//目标分数
   * @param:options-function//其他操作 函数 接受ctx-canvas 2d options-配置
   */
  function init(canvas, options) {
    if (!options) {
      options = {};
    }
    var cxt = canvas.getContext('2d');
    var clientWidth = document.documentElement.clientWidth;//根据设计图中的canvas画布的占比进行设置
    options.width = 371;//canvas的宽
    options.height = 270;//canvas的高
    var canvasWidth = Math.floor(clientWidth * options.width / (options.designChartWidth ? options.designChartWidth : 750));
    var canvasHeight =  Math.floor(clientWidth * options.height / (options.designChartWidth ? options.designChartWidth : 750));
    canvas.setAttribute('width', canvasWidth*this.getDevicePixelRatio());
    canvas.setAttribute('height', canvasHeight*this.getDevicePixelRatio());
    canvas.style.width = canvasWidth+'px';
    canvas.style.height = canvasHeight+'px';
    options.radius = options.radius || 50 / 10;//小圆的直径
    options.radius = options.radius*this.getDevicePixelRatio()
    options.team_num = options.teamNum || 10;//小圆的个数
    options.circle_r = canvas.getAttribute('width') / 2 - options.radius; // 半径
    options.circle_x = 0 + options.circle_r + options.radius; // 圆心坐标x
    options.circle_y = 0 + options.circle_r + options.radius;//圆心坐标y
    this.loadTeams(cxt, options);
  }
  init.prototype = {
    loadTeams(cxt, options) {//加载布局模拟图
      this.font(cxt, options);
      this.seating(cxt, options);
    },
    font(cxt, options) {//加载图中文案
      if(options.function){
        options.function(cxt, options);
      }
    },
    seating(cxt, options) { //分配小圆座次
      var angle = 230 / options.teamNum; //角度
      var a = options.fullMarks/options.teamNum;//计算每个小圆代表的值
      var team_x = 0, team_y = 0;
      var team_r = options.radius; // options.team_num < 20 ? 10 : Math.sqrt(options.circle_r * options.circle_r * 2 * (1 - Math.cos(changeRadian(angle)))) / 2;
      //余弦定理  计算小圆的最大半径     BC2=AB2+AC2-2×AB×AC×cosα  如果小圆数目小于20个,半径最大30(上限)
      for (var i = 0; i < options.teamNum; i++) {
        team_x = options.circle_x + Math.sin(this.changeRadian((i * angle) + 250.9)) * options.circle_r;  //角度转弧度
        team_y = options.circle_y - Math.cos(this.changeRadian((i * angle) + 250.9)) * options.circle_r;
        cxt.beginPath();
        cxt.arc(team_x, team_y, team_r, 0, 2 * Math.PI);
        if((i+1)*a<=options.grade)cxt.fillStyle = options.fillColor ? options.fillColor : 'red';
        else cxt.fillStyle = options.color ? options.color : '#333333';
        cxt.fill();
      }
    },
    changeRadian(angle) { //角度转换为弧度
      return Math.PI / 180 * angle;
    },
    getDevicePixelRatio (){//避免手机端失帧
      return window.devicePixelRatio || 1;
    }
  }
</script>

<style scoped>

</style>

父组件引用画布组件

      <dashboard class="sizeQuery" :score="this.scoreVal"></dashboard>

 

scoreVal为分数值,从后台获取可得,从而传给画布组件。

此文为原创,不可转发。