skin-blue

vue 使用canvas仿芝麻分信用表

如图所示:

    

 

画布组件: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为分数值,从后台获取可得,从而传给画布组件。

此文为原创,不可转发。
posted on 2018-12-12 14:49  执着慕晚的流年  阅读(877)  评论(0编辑  收藏  举报
 

分类:

技术点:

相关文章: