D3 v4 - 饼图外面有饼干和圆点的饼图。

时间:2018-01-30 16:41:56

标签: javascript d3.js

我正在尝试更改以下示例,我开始编辑这些行,以便他们

  • 在切片中心外开始5px
  • 有一个4px的圈子

设计如下。我最初挣扎的主要部分是改变起点。如果我能弄明白的话,我认为这个圈子很容易。

有任何建议如何实现这一目标?

Pie Example

outfile
var svg = d3.select("body")
  .append("svg")
  .append("g")

var isDount = false;

svg.append("g")
  .attr("class", "slices");
svg.append("g")
  .attr("class", "labels");
svg.append("g")
  .attr("class", "lines");

var width = 200,
  height = 200,
  radius = Math.min(width, height) / 2,
  transitionSpeed = 600;

var pie = d3.pie()
  .sort(null)
  .value(function(d) {
    return d.value;
  });

var arc = d3.arc()
  .outerRadius(radius * 0.8)
  .innerRadius(isDount ? radius * 0.4 : 0);

var outerArc = d3.arc()
  .innerRadius(radius * 0.9)
  .outerRadius(isDount ? radius * 0.9 : 0);

svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var key = function(d) {
  return d.data.label;
};

var color = d3.scaleOrdinal()
  .domain(["Lorem ipsum", "dolor sit", "amet", "consectetur"]) //, "adipisicing", "elit", "sed", "do", "eiusmod", "tempor", "incididunt"
  .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

function randomData() {
  var labels = color.domain();
  return labels.map(function(label) {
    return {
      label: label,
      value: Math.random()
    }
  });
}

change(randomData());

d3.select(".randomize")
  .on("click", function() {
    change(randomData());
  });

function change(data) {

  /* ------- PIE SLICES -------*/
  var slice = svg.select(".slices").selectAll("path.slice")
    .data(pie(data), key);

  slice.enter()
    .insert("path")
    .style("fill", function(d) {
      return color(d.data.label);
    })
    .attr("class", "slice")
    .merge(slice)
    .transition().duration(transitionSpeed)
    .attrTween("d", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        return arc(interpolate(t));
      };
    })

  slice.exit()
    .remove();

  /* ------- TEXT LABELS -------*/

  var text = svg.select(".labels").selectAll("text")
    .data(pie(data), key);

  function midAngle(d) {
    return d.startAngle + (d.endAngle - d.startAngle) / 2;
  }

  text.enter()
    .append("text")
    .attr("dy", ".35em")
    .text(function(d) {
      console.log(d3.format('.3f')(d.data.value))
      var showValue = true;
      return showValue ? d3.format('.3f')(d.data.value) : d.data.label;
    })
    .merge(text)
    .transition().duration(transitionSpeed)
    .attrTween("transform", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        var d2 = interpolate(t);
        var pos = outerArc.centroid(d2);
        pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
        return "translate(" + pos + ")";
      };
    })
    .styleTween("text-anchor", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        var d2 = interpolate(t);
        return midAngle(d2) < Math.PI ? "start" : "end";
      };
    });

  text.exit()
    .remove();

  /* ------- SLICE TO TEXT POLYLINES -------*/

  var polyline = svg.select(".lines").selectAll("polyline")
    .data(pie(data), key);

  polyline.enter()
    .append("polyline")
    .merge(polyline)
    .transition().duration(transitionSpeed)
    .attrTween("points", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        var d2 = interpolate(t);
        var pos = outerArc.centroid(d2);
        pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
        return [arc.centroid(d2), outerArc.centroid(d2), pos];
      };
    });

  polyline.exit()
    .remove();
};
body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  width: 960px;
  height: 500px;
  position: relative;
}

svg {
  width: 100%;
  height: 100%;
}

path.slice {
  stroke-width: 2px;
}

polyline {
  opacity: .3;
  stroke: black;
  stroke-width: 1px;
  fill: none;
}

.labels text {
  font-size: 12px;
}

1 个答案:

答案 0 :(得分:3)

您可以制作新的arc变量并将innerradius更改为更高的值。例如

    var arc2 = d3.arc()
  .outerRadius(radius * 0.8 -10)
  .innerRadius(isDount ? radius * 0.4 : 0);

并在attrTween&amp;弄乱了价值观

return [arc2.centroid(d2), outerArc.centroid(d2), pos];

我还按照您想要的方式添加了圈子:

  var circles = svg.selectAll(".circles")
    .data(pie(data));

  circles = circles.enter()
    .append("circle")
    .attr("class","circles")
    .attr("r",3)
    .attr("fill","#999")
    .merge(circles)

  circles.transition().duration(transitionSpeed)
    .attrTween("transform", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        var d2 = interpolate(t);
        var pos = outerArc.centroid(d2);
        pos[0] = radius * .95 * (midAngle(d2) < Math.PI ? 1 : -1);
        return "translate("+ circlesArc.centroid(d2) +")";
      };
    })
  circles.exit().remove();

这是一个分叉:

var svg = d3.select("body")
  .append("svg")
  .append("g")

var isDount = false;

svg.append("g")
  .attr("class", "slices");
svg.append("g")
  .attr("class", "labels");
svg.append("g")
  .attr("class", "lines");

var width = 200,
  height = 200,
  radius = Math.min(width, height) / 2,
  transitionSpeed = 600,
  outerRadius = height / 2 - 20;

var pie = d3.pie()
  .sort(null)
  .value(function(d) {
    return d.value;
  });

var arc = d3.arc()
  .outerRadius(radius * 0.8 -10)
  .innerRadius(isDount ? radius * 0.4 : 0);
  
var arc2 = d3.arc()
  .outerRadius(radius * 0.8 -10)
  .innerRadius(radius * 0.9)

var outerArc = d3.arc()
  .innerRadius(radius * .99)
  .outerRadius(radius * .99);
  
var circlesArc = d3.arc()
  .innerRadius(radius * 0.8)
  .outerRadius(radius * 0.8);

svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var key = function(d) {
  return d.data.label;
};

var color = d3.scaleOrdinal()
  .domain(["Lorem ipsum", "dolor sit", "amet", "consectetur"]) //, "adipisicing", "elit", "sed", "do", "eiusmod", "tempor", "incididunt"
  .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

function randomData() {
  var labels = color.domain();
  return labels.map(function(label) {
    return {
      label: label,
      value: Math.random()
    }
  });
}

change(randomData());

d3.select(".randomize")
  .on("click", function() {
    change(randomData());
  });

function change(data) {

  /* ------- PIE SLICES -------*/
  var slice = svg.select(".slices").selectAll("path.slice")
    .data(pie(data), key);

  slice.enter()
    .insert("path")
    .style("fill", function(d) {
      return color(d.data.label);
    })
    .attr("class", "slice")
    .merge(slice)
    .transition().duration(transitionSpeed)
    .attrTween("d", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        return arc(interpolate(t));
      };
    })

  slice.exit()
    .remove();

  /* ------- TEXT LABELS -------*/

  var text = svg.select(".labels").selectAll("text")
    .data(pie(data), key);

  function midAngle(d) {
    return d.startAngle + (d.endAngle - d.startAngle) / 2;
  }

  text.enter()
    .append("text")
    .attr("dy", ".35em")
    .text(function(d) {
      console.log(d3.format('.3f')(d.data.value))
      var showValue = true;
      return showValue ? d3.format('.3f')(d.data.value) : d.data.label;
    })
    .merge(text)
    .transition().duration(transitionSpeed)
    .attrTween("transform", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        var d2 = interpolate(t);
        var pos = outerArc.centroid(d2);
        pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
        return "translate(" + pos + ")";
      };
    })
    .styleTween("text-anchor", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        var d2 = interpolate(t);
        return midAngle(d2) < Math.PI ? "start" : "end";
      };
    });

  text.exit()
    .remove();

  /* ------- SLICE TO TEXT POLYLINES -------*/

  var polyline = svg.select(".lines").selectAll("polyline")
    .data(pie(data), key);

  polyline.enter()
    .append("polyline")
    .merge(polyline)
    .transition().duration(transitionSpeed)
    .attrTween("points", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        var d2 = interpolate(t);
        var pos = outerArc.centroid(d2);
        pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
        return [arc2.centroid(d2), outerArc.centroid(d2), pos];
      };
    });

  polyline.exit()
    .remove();
    
  var circles = svg.selectAll(".circles")
    .data(pie(data));

  circles = circles.enter()
    .append("circle")
    .attr("class","circles")
    .attr("r",3)
    .attr("fill","#999")
    .merge(circles)

  circles.transition().duration(transitionSpeed)
    .attrTween("transform", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        var d2 = interpolate(t);
        var pos = outerArc.centroid(d2);
        pos[0] = radius * .95 * (midAngle(d2) < Math.PI ? 1 : -1);
        return "translate("+ circlesArc.centroid(d2) +")";
      };
    })
  circles.exit().remove();
};
body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  width: 960px;
  height: 500px;
  position: relative;
}

svg {
  width: 100%;
  height: 100%;
}

path.slice {
  stroke-width: 2px;
}

polyline {
  opacity: .3;
  stroke: black;
  stroke-width: 1px;
  fill: none;
}

.labels text {
  font-size: 12px;
}
<button class="randomize">c</button>
<script src="https://d3js.org/d3.v4.min.js"></script>