javascript - d3js : how to put circles at the end of an arc

标签 javascript d3.js svg charts

我正在尝试在 d3js 中创建一个圆环图,其中每个圆弧的末端都有一个圆圈。 圆的边缘必须适合圆弧的边缘。

我尝试了附加一个圆圈和一个用标记包裹的圆圈,但都没有成功。

尝试附加标记似乎是最接近所需解决方案的方法,但我无法帮助标记溢出弧形边缘。

代码:

var data = [
  {
    name: "punti",
    count: 3,
    color: "#fff000"
  },
  {
    name: "max",
    count: 7,
    color: "#f8b70a"
  }
];
var totalCount = data.reduce((acc, el) => el.count + acc, 0);
var image_width = 32;
var image_height = 32;
var width = 540,
  height = 540,
  radius = 200,
  outerRadius = radius - 10,
  innerRadius = 100;
var cornerRadius = innerRadius;
var markerRadius = (outerRadius - innerRadius) / 2;
var arc = d3
  .arc()
  .outerRadius(outerRadius)
  .innerRadius(innerRadius)
  .cornerRadius(cornerRadius);

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

var svg = d3
  .select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var pieData = pie(data);
var g = svg
  .selectAll(".arc")
  .data(pieData)
  .enter()
  .append("g");

var path = g
  .append("path")
  .attr("d", arc)
  .style("fill", function(d, i) {
    return d.data.color;
  });

var marker = svg
  .append("defs")
  .append("marker")
  .attr("id", "endmarker")
  .attr("overflow", "visible")
  .append("circle")
  .attr("cy", 0)
  .attr("cx", 0)
  .attr("r", markerRadius)
  .attr("fill", "red");
g.attr("marker-end", "url(#endmarker)");

g
  .append("circle")
  .attr("cx", function(d) {
    let path = d3.select(this.parentNode);
    var x = arc.centroid(d)[0];
    return x;
  })
  .attr("cy", function(d) {
    var y = arc.centroid(d)[1];
    console.log(d3.select(this).attr("cx"));
    return y;
  })
  .attr("fill", d => d.data.color)
  .attr("stroke", "black")
  .attr("r", (outerRadius - innerRadius) / 2);

codepen here

感谢任何愿意提供帮助的人!

最佳答案

假设您希望输出如下: enter image description here

我从 Mike Bostock's Block here which shows how to add circles to rounded Arc Corners 中找到了一些代码.

我为您改编了以下代码,其中执行了相当多的复杂数学运算。

var cornerRadius = (outerRadius - innerRadius)/2;
svg.append("g")
    .style("stroke", "#555")
    .style("fill", "none")
    .attr("class", "corner")
  .selectAll("circle")
    .data(d3.merge(pieData.map(function(d) {
      return [
        {angle: d.startAngle + d.padAngle / 2, radius: outerRadius - cornerRadius, start: +1},
        {angle:   d.endAngle - d.padAngle / 2, radius: outerRadius - cornerRadius, start: -1},
      ];
    })))
  .enter().append("circle")
    .attr("cx", function(d) { return d.start * cornerRadius * Math.cos(d.angle) + Math.sqrt(d.radius * d.radius - cornerRadius * cornerRadius) * Math.sin(d.angle); })
    .attr("cy", function(d) { return d.start * cornerRadius * Math.sin(d.angle) - Math.sqrt(d.radius * d.radius - cornerRadius * cornerRadius) * Math.cos(d.angle); })
    .attr("r", cornerRadius);

显示输出的完整代码段:

<div id="chart"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.12.0/d3.min.js"></script>
<script>
var data = [
  {
    name: "punti",
    count: 3,
    color: "#fff000"
  },
  {
    name: "max",
    count: 7,
    color: "#f8b70a"
  },
];
var totalCount = data.reduce((acc, el) => el.count + acc, 0);
var image_width = 32;
var image_height = 32;
var width = 540,
  height = 540,
  radius = 200,
  outerRadius = radius - 10,
  innerRadius = 100;
var cornerRadius = innerRadius;
var markerRadius = (outerRadius - innerRadius) / 2;
var arc = d3
  .arc()
  .outerRadius(outerRadius)
  .innerRadius(innerRadius)
  .cornerRadius(cornerRadius);

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

var svg = d3
  .select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var pieData = pie(data);
var g = svg
  .selectAll(".arc")
  .data(pieData)
  .enter()
  .append("g");

var path = g
  .append("path")
  .attr("d", arc)
  .style("fill", function(d, i) {
    return d.data.color;
  });

var cornerRadius = (outerRadius - innerRadius)/2;
svg.append("g")
    .style("stroke", "#555")
    .style("fill", "none")
    .attr("class", "corner")
  .selectAll("circle")
    .data(d3.merge(pieData.map(function(d) {
      return [
        {angle: d.startAngle + d.padAngle / 2, radius: outerRadius - cornerRadius, start: +1},
        {angle:   d.endAngle - d.padAngle / 2, radius: outerRadius - cornerRadius, start: -1},
      ];
    })))
  .enter().append("circle")
    .attr("cx", function(d) { return d.start * cornerRadius * Math.cos(d.angle) + Math.sqrt(d.radius * d.radius - cornerRadius * cornerRadius) * Math.sin(d.angle); })
    .attr("cy", function(d) { return d.start * cornerRadius * Math.sin(d.angle) - Math.sqrt(d.radius * d.radius - cornerRadius * cornerRadius) * Math.cos(d.angle); })
    .attr("r", cornerRadius);
  
  
</script>

关于javascript - d3js : how to put circles at the end of an arc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59013408/

相关文章:

javascript - 闭包中的 jquery tmpl

javascript - 用 JavaScript 实现的简单、安全的脚本语言?

javascript - 如何在 LoopBack 框架中为 PersistedModel 禁用某些 HTTP 方法(例如 POST)

javascript - d3 线过滤掉(去除)重复点

svg - 从 svg 图像中去除像素化边缘

JavaScript : Check if object has properties

javascript - 选择id中有双点的元素,报错: "#octo:cat" is not a valid selector

d3.js - 从 d3.js 轴移除凸角以创建平轴

html - 如何在 IE 中隐藏 clipPath

Javascript - 需要仅从 SVG 路径的笔画获取 x 和 y 坐标?