简体   繁体   English

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

[英]D3 v4 - Pie Chart with connectors outside the pie and with dots.

I am trying to change the following example i started out with to edit the lines such that they 我正在尝试更改以下示例,我开始编辑这些行,以便他们

  • start 5px outside the center of the slice 在切片中心外开始5px
  • have a 4px circle around 周围有一个4px的圆圈

The design is as follows. 设计如下。 The main part im struggling with initially is changing the starting point. 我最初挣扎的主要部分是改变起点。 I think the circle will be easy if i can figure that out. 如果我能弄明白的话,我认为这个圈子很容易。

Any suggestions how to achieve this? 任何建议如何实现这一目标?

馅饼示例

 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; } 
 <button class="randomize">c</button> <script src="http://d3js.org/d3.v4.min.js"></script> 

You could make a new arc variable and change the innerradius to a higher value. 您可以创建一个新的arc变量并将内innerradius更改为更高的值。 for example 例如

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

and reference it in the attrTween & mess around with the values 并在attrTween引用它并弄乱值

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

I also added the circles the way you wanted: 我还按照你想要的方式添加了圆圈:

  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();

Here's a fork: 这是一个分叉:

 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM