从D3 v3更新,没有错误,但输出SVG路径不可见

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

我正在使用基于 D3 版本 3 构建的代码并尝试更新它。我已经完成了所有更明显的更新 -

  • d3.layout.pie()
    =>
    d3.pie()
  • d3.svg.arc()
    =>
    d3.arc()
  • d3.scale.ordinal()
    =>
    d3.scaleOrdinal()

但是我最终得到了一个带有空白路径的 SVG

<path class="slice" style="fill: rgb(0, 128, 0);"></path>

这是 JS:

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

const svg = d3.select(".donut")
    .append("svg")
    .append("g")

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

const pie = d3.pie()
    .sort(null)
    .value((d) => d.value);

const arc = d3.arc()
    .outerRadius(radius * .9)
    .innerRadius(radius * 0.6);

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

const key = (d) => d.data.label;

const color = d3.scaleOrdinal()
    .domain(['a','b','c'])
    .range(["#FF0000", "#FFF000", "#008000"]);

const generate = (data) => {
    const dataSum = d3.sum(data, (d) => d.value);

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

    slice.enter()
        .insert("path")
        .style("fill", (d) => color(d.data.label))
        .attr("class", "slice");

    slice       
        .transition().duration(1000)
        .attrTween("d", function(d) {
            this._current = this._current || d;
            const interpolate = d3.interpolate(this._current, d);
            this._current = interpolate(0);
            return function(t) {
                return arc(interpolate(t));
            };
        })

    slice.exit()
        .remove();
};

const donutData = [
    {label: 'a', value: 80},
    {label: 'b', value: 10},
    {label: 'c', value: 10},
];

generate(donutData);

CSS 非常简单,不应该成为问题:

.donut { 
  width: 960px;
  height: 500px;
}

svg {
  width: 100%;
  height: 100%;
}
    
path.slice{
  stroke-width:2px;
}

我的印象是,

slice.enter()
部分有问题(缺少
.merge()
?),或更可能是出口前的整个
interpolate()
部分有问题。不幸的是,文档中没有任何内容,或者至少是我对它的解释,没有任何帮助。您可以在 CodePen 上查看当前(旧版,版本 3)正在运行的代码。

此外,如果有更好的方法从不使用 D3 的数据生成三部分圆环图,我也愿意接受这些建议。谢谢!

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

我重写了你的部分 slice.enter() (添加合并):

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

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

      const svg = d3.select(".donut")
          .append("svg")
          .attr("width", width)
          .attr("height", height)
          .append("g")
          .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

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

      const pie = d3.pie()
          .sort(null)
          .value((d) => d.value);

      const arc = d3.arc()
          .outerRadius(radius * 0.9)
          .innerRadius(radius * 0.6);

      const key = (d) => d.data.label;

      const color = d3.scaleOrdinal()
          .domain(['a', 'b', 'c'])
          .range(["#FF0000", "#FFF000", "#008000"]);

      const generate = (data) => {
          const dataSum = d3.sum(data, (d) => d.value);

          const slice = svg.select(".slices").selectAll("path.slice")
              .data(pie(data), key);

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

          slice.exit()
              .remove();
      };

      const donutData = [
          { label: 'a', value: 80 },
          { label: 'b', value: 10 },
          { label: 'c', value: 10 },
      ];

      generate(donutData);
      .donut {
          width: 960px;
          height: 500px;
      }

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

      path.slice {
          stroke-width: 2px;
      }
    <div class="donut"></div>

  
  <!-- === Vendor JS Files ================================= -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>

© www.soinside.com 2019 - 2024. All rights reserved.