我的问题是我将在D3饼图中添加一条折线

问题描述 投票:0回答:1

我的问题是我的图表中的折线没有正确定位在我的代码中给出的切片上的确切数据上

这是我的切片和折线代码,当你将此代码转换为 html 时,它将运行并放置在 W3 学校上,或者将此代码放置在函数上并在单击时调用 html

供参考整个代码 https://observablehq.com/@mast4461/d3-donut-chart-labels 这是一个甜甜圈,但精确的折线将放置在正确的位置,我的图表是 3D 视图中的饼图,我将在图像中附加我的 UI

    var slices = vis
      .append("svg:g")
      .attr("transform", "translate(" + x + "," + y + ")")
      .attr("class", "slice");

    slices
      .selectAll(".innerSlice")
      .data(_data)
      .enter()
      .append("path")
      .attr("class", "innerSlice")
      .style("fill", function (d) {
        return d3.hsl(d.data.color).darker(0.7);
      })
      .attr("d", function (d) {
        return pieInner(d, rx + 0.5, ry + 0.5, h, ir);
      })
      .each(function (d) {
        this._current = d;
      });

    slices
      .selectAll(".topSlice")
      .data(_data)
      .enter()
      .append("path")
      .attr("class", "topSlice")
      .style("fill", function (d) {
        return d.data.color;
      })
      .style("stroke", function (d) {
        return d.data.color;
      })
      .attr("d", function (d) {
        return pieTop(d, rx, ry, ir);
      })
      .each(function (d) {
        this._current = d;
      });

    slices
      .selectAll(".outerSlice")
      .data(_data)
      .enter()
      .append("path")
      .attr("class", "outerSlice")
      .style("fill", function (d) {
        return d3.hsl(d.data.color).darker(0.7);
      })
      .attr("d", function (d) {
        return pieOuter(d, rx - 0.5, ry - 0.5, 40, 5, 50, 100, 0.02);
      })
      .each(function (d) {
        this._current = d;
      });

    slices
      .selectAll(".percent")
      .data(_data)
      .enter()
      .append("text")
      .attr("class", "percent")
      .attr("x", function (d) {
        return 0.6 * rx * Math.cos(0.5 * (d.startAngle + d.endAngle));
      })
      .attr("y", function (d) {
        return 0.6 * ry * Math.sin(0.5 * (d.startAngle + d.endAngle));
      })
      .text(getPercent)
      .each(function (d) {
        this._current = d;
      });

    function pieInner(d, rx, ry, h, ir) {
      var startAngle = d.startAngle < Math.PI ? Math.PI : d.startAngle;
      var endAngle = d.endAngle < Math.PI ? Math.PI : d.endAngle;

      var sx = ir * rx * Math.cos(startAngle),
        sy = ir * ry * Math.sin(startAngle),
        ex = ir * rx * Math.cos(endAngle),
        ey = ir * ry * Math.sin(endAngle);

      var ret = [];
      ret.push(
        "M",
        sx,
        sy,
        "A",
        ir * rx,
        ir * ry,
        "0 0 1",
        ex,
        ey,
        "L",
        ex,
        h + ey,
        "A",
        ir * rx,
        ir * ry,
        "0 0 0",
        sx,
        h + sy,
        "z"
      );
      return ret.join(" ");
    }

    function pieTop(d, rx, ry, ir) {
      if (d.endAngle - d.startAngle == 0) return "M 0 0";
      var sx = rx * Math.cos(d.startAngle),
        sy = ry * Math.sin(d.startAngle),
        ex = rx * Math.cos(d.endAngle),
        ey = ry * Math.sin(d.endAngle);

      var ret = [];
      ret.push(
        "M",
        sx,
        sy,
        "A",
        rx,
        ry,
        "0",
        d.endAngle - d.startAngle > Math.PI ? 1 : 0,
        "1",
        ex,
        ey,
        "L",
        ir * ex,
        ir * ey
      );
      ret.push(
        "A",
        ir * rx,
        ir * ry,
        "0",
        d.endAngle - d.startAngle > Math.PI ? 1 : 0,
        "0",
        ir * sx,
        ir * sy,
        "z"
      );
      return ret.join(" ");
    }

    function pieOuter(d, rx, ry, h) {
      var startAngle = d.startAngle > Math.PI ? Math.PI : d.startAngle;
      var endAngle = d.endAngle > Math.PI ? Math.PI : d.endAngle;

      var sx = rx * Math.cos(startAngle),
        sy = ry * Math.sin(startAngle),
        ex = rx * Math.cos(endAngle),
        ey = ry * Math.sin(endAngle);

      var ret = [];
      ret.push(
        "M",
        sx,
        h + sy,
        "A",
        rx,
        ry,
        "0 0 1",
        ex,
        h + ey,
        "L",
        ex,
        ey,
        "A",
        rx,
        ry,
        "0 0 0",
        sx,
        sy,
        "z"
      );
      return ret.join(" ");
    }
    var radius = 200;
    var arc = d3
      .arc()
      .innerRadius(radius - 100)
      .outerRadius(radius - 50);

    var outerArc = d3
      .arc()
      .innerRadius(radius * 0.9)
      .outerRadius(radius * 0.9);
    // Add the polylines between chart and labels:
    slices
      .selectAll("allPolylines")
      .data(_data)
      .enter()
      .append("polyline")
      .attr("stroke", "black")
      .style("fill", "none")
      .attr("stroke-width", 1)
      .attr("points", function (d) {
        console.log("checkkkshdfkh", d);
      
        var posA = arc.centroid(d) // line insertion in the slice
        var posB = outerArc.centroid(d) // line break: we use the other arc generator that has been built only for that
        var posC = outerArc.centroid(d); // Label position = almost the same as posB
        let tempX= 0.6 * rx * Math.cos(0.5 * (d.startAngle + d.endAngle));
        let tempY= 0.6 * ry * Math.sin(0.5 * (d.startAngle + d.endAngle))
        var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 // we need the angle to see if the X position will be at the extreme right or extreme left
        posC[0] = radius * 0.95 * (midangle < Math.PI ? 1 : -1);
        console.log("checknskdnfknsdf",posA,[tempX,tempY])
        return [posA, posB, posC]

      });

我的用户界面看起来像

我尝试https://observablehq.com/@mast4461/d3-donut-chart-labels并且我尝试了大部分代码,但它不起作用

我希望我的折线基于数据放置在精确的切片上,并且

javascript css d3.js
1个回答
0
投票

d3.arc
和您的 3d 饼图在单位圆上使用不同的起点进行角度计算。需要添加PI/2才能使用
arc.centroid
:

const angle = {startAngle: d.startAngle + Math.PI/2,
               endAngle: d.endAngle + Math.PI/2};       

var posA = arc.centroid(angle);
var posB = outerArc.centroid(angle);
var posC = outerArc.centroid(angle);
© www.soinside.com 2019 - 2024. All rights reserved.