带有子值指示器和标签的仪表图

时间:2019-06-08 13:18:05

标签: javascript d3.js charts data-visualization

我是d3.js的新手。我要添加子值指标和文本以及工具提示,如所附图像所示。子值指示器的目的是显示一些临界值。如何在针的末尾添加文本? screenshot

我分享了以下代码。请指导我实现这一目标。

JAVASCRIPT:

$$'...'

CSS:

(function () {
  var Needle, arc, arcEndRad, arcStartRad, barWidth, chart, chartInset, degToRad, el, endPadRad, height, i, margin, needle, numSections, padRad, percToDeg, percToRad, percent, radius, ref, sectionIndx, sectionPerc, startPadRad, svg, totalPercent, width;

  percent = .65;
  barWidth = 60;
  numSections = 3;
  // / 2 for HALF circle
  sectionPerc = [0.1, 0.25, 0.15];
  padRad = 0;
  chartInset = 10;
  // start at 270deg
  totalPercent = .75;
  el = d3.select('.chart-gauge');
  margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 20 };
  width = el[0][0].offsetWidth - margin.left - margin.right;
  height = width;
  radius = Math.min(width, height) / 2;
  percToDeg = function (perc) {
    return perc * 360;
  };
  percToRad = function (perc) {
    return degToRad(percToDeg(perc));
  };
  degToRad = function (deg) {
    return deg * Math.PI / 180;
  };
  svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom);
  chart = svg.append('g').attr('transform', `translate(${(width + margin.left) / 2}, ${(height + margin.top) / 2})`);
  // build gauge bg
  for (sectionIndx = i = 1, ref = numSections; 1 <= ref ? i <= ref : i >= ref; sectionIndx = 1 <= ref ? ++i : --i) {
    arcStartRad = percToRad(totalPercent);
    arcEndRad = arcStartRad + percToRad(sectionPerc[sectionIndx-1]);
    totalPercent += sectionPerc[sectionIndx-1];
    startPadRad = 0;
    endPadRad = 0;
    arc = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth).startAngle(arcStartRad + startPadRad).endAngle(arcEndRad - endPadRad);
    chart.append('path').attr('class', `arc chart-color${sectionIndx}`).attr('d', arc);
  }
  Needle = class Needle {
    constructor(len, radius1) {
      this.len = len;
      this.radius = radius1;
    }
    drawOn(el, perc) {
      el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius);
      return el.append('path').attr('class', 'needle').attr('d', this.mkCmd(perc));
    }
    animateOn(el, perc) {
      var self;
      self = this;
      return el.transition().delay(500).ease('elastic').duration(3000).selectAll('.needle').tween('progress', function () {
        return function (percentOfPercent) {
          var progress;
          progress = percentOfPercent * perc;
          return d3.select(this).attr('d', self.mkCmd(progress));
        };
      });
    }
    mkCmd(perc) {
      var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY;
      thetaRad = percToRad(perc / 2); // half circle
      centerX = 0;
      centerY = 0;
      topX = centerX - this.len * Math.cos(thetaRad);
      topY = centerY - this.len * Math.sin(thetaRad);
      leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2);
      leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2);
      rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2);
      rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2);
      return `M ${leftX} ${leftY} L ${topX} ${topY} L ${rightX} ${rightY}`;
    }};
  needle = new Needle(140, 15);
  needle.drawOn(chart, 0);
  needle.animateOn(chart, percent);
}).call(this);
//# sourceURL=coffeescript

HTML:

@import compass

.chart-gauge
  width: 400px
  margin: 10px auto  

.chart-color1
  fill: #D82724

.chart-color2
  fill: #FCBF02

.chart-color3
  fill: #92D14F

.needle,
.needle-center
  fill: #464A4F

.prose
  text-align: center
  font-family: sans-serif
  color: #ababab

谢谢

1 个答案:

答案 0 :(得分:1)

要创建此子值指示符,您只需要设置一个弧形生成器即可接受要设置的百分比值(此处称为subIndicator),并在外半径和内半径中添加填充... < / p>

arc2 = d3.svg.arc()
    .outerRadius(radius - chartInset + 10)
    .innerRadius(radius - chartInset - barWidth - 10)
    .startAngle(percToRad(subIndicator))
    .endAngle(percToRad(subIndicator));

...并使用它来添加新路径:

chart.append('path')
    .attr('d', arc2)
    .style("stroke", "black")
    .style("stroke-width", "2px");

请注意以下事实:给定原始代码的作者设置其功能的方式,量规中的零等于75%。因此,您必须相应地设置百分比值。例如,将子值指标定位在55%:

subIndicator = totalPercent + (55 / 200);

这是一个演示(使用55%的子值指标):

(function () {
  var Needle, arc, arcEndRad, arcStartRad, barWidth, chart, chartInset, degToRad, el, endPadRad, height, i, margin, needle, numSections, padRad, percToDeg, percToRad, percent, radius, ref, sectionIndx, sectionPerc, startPadRad, svg, totalPercent, width, subIndicator;

  percent = .65;

  barWidth = 60;

  numSections = 3;

  // / 2 for HALF circle
  sectionPerc = [0.1, 0.25, 0.15];

  padRad = 0;

  chartInset = 10;

  // start at 270deg
  totalPercent = .75;
  
  subIndicator = totalPercent + (55/200)

  el = d3.select('.chart-gauge');

  margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 20 };


  width = el[0][0].offsetWidth - margin.left - margin.right;

  height = width;

  radius = Math.min(width, height) / 2;

  percToDeg = function (perc) {
    return perc * 360;
  };

  percToRad = function (perc) {
    return degToRad(percToDeg(perc));
  };

  degToRad = function (deg) {
    return deg * Math.PI / 180;
  };

  svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom);

  chart = svg.append('g').attr('transform', `translate(${(width + margin.left) / 2}, ${(height + margin.top) / 2})`);

  // build gauge bg
  for (sectionIndx = i = 1, ref = numSections; 1 <= ref ? i <= ref : i >= ref; sectionIndx = 1 <= ref ? ++i : --i) {
    arcStartRad = percToRad(totalPercent);
    arcEndRad = arcStartRad + percToRad(sectionPerc[sectionIndx-1]);
    totalPercent += sectionPerc[sectionIndx-1];
    startPadRad = 0;
    endPadRad = 0;
    arc = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth).startAngle(arcStartRad + startPadRad).endAngle(arcEndRad - endPadRad);
    chart.append('path').attr('class', `arc chart-color${sectionIndx}`).attr('d', arc);
  }
  
  arc2 = d3.svg.arc().outerRadius(radius - chartInset + 10).innerRadius(radius - chartInset - barWidth - 10).startAngle(percToRad(subIndicator)).endAngle(percToRad(subIndicator));
    chart.append('path').attr('d', arc2).style("stroke", "black").style("stroke-width", "2px");

  Needle = class Needle {
    constructor(len, radius1) {
      this.len = len;
      this.radius = radius1;
    }

    drawOn(el, perc) {
      el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius);
      return el.append('path').attr('class', 'needle').attr('d', this.mkCmd(perc));
    }

    animateOn(el, perc) {
      var self;
      self = this;
      return el.transition().delay(500).ease('elastic').duration(3000).selectAll('.needle').tween('progress', function () {
        return function (percentOfPercent) {
          var progress;
          progress = percentOfPercent * perc;
          return d3.select(this).attr('d', self.mkCmd(progress));
        };
      });
    }

    mkCmd(perc) {
      var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY;
      thetaRad = percToRad(perc / 2); // half circle
      centerX = 0;
      centerY = 0;
      topX = centerX - this.len * Math.cos(thetaRad);
      topY = centerY - this.len * Math.sin(thetaRad);
      leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2);
      leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2);
      rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2);
      rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2);
      return `M ${leftX} ${leftY} L ${topX} ${topY} L ${rightX} ${rightY}`;
    }};



  needle = new Needle(140, 15);

  needle.drawOn(chart, 0);

  needle.animateOn(chart, percent);

}).call(this);

//# sourceURL=coffeescript
.chart-gauge {
  width: 400px;
  margin: 10px auto;
}

.chart-color1 {
  fill: #D82724;
}

.chart-color2 {
  fill: #FCBF02;
}

.chart-color3 {
  fill: #92D14F;
}

.needle,
.needle-center {
  fill: #464A4F;
}

.prose {
  text-align: center;
  font-family: sans-serif;
  color: #ababab;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<div class="chart-gauge"></div>

使用相同的方法来附加子值指标文本。