首页 > 解决方案 > D3.js:放错位置的标签

问题描述

我是 d3.js 的新手,我正在尝试创建一个半圆环图并将标签放在每个弧的中间。

我用 CodeSandbox 做了一个开发人员,它工作得很好。标签放置正确,但是当我将该代码带到我的 Web 应用程序的代码时。代码完全相同。这些标签放错了位置,我不知道为什么:(

两个代码之间的唯一区别在于,第一个屏幕截图的代码位于 Bootstrap 的“Col”内,而第二个屏幕截图的代码与您在 CodeSandBox 中看到的不同。

在这里,您可以在我的 Web 应用程序中看到半圆环图的屏幕截图:

在此处输入图像描述

如您所见,当 CodeSandbox 中的相同代码正常工作时,每个拱门的标签和正确图例的标签都放错了位置,将所有标签放在正确的位置。正如您在此屏幕截图中看到的:

在此处输入图像描述

为什么会这样?我怎样才能使标签正确地放置在两个开发项目中?

你可以在这个 CodeSandoox 中看到我的半甜甜圈图的所有代码

编辑半甜甜圈图

编辑我:

我在我的代码中创建了一个跟踪,以了解取决于 Web 浏览器的值。

这是我将标签居中到弧线的代码:

//We center the text inside the arc
arcs
  .append("svg:text")
  .attr("transform", function(d) {
    var textWidth = getTextWidth(
      (d.value.toFixed(2) + "%").toString(),
      "Roboto"
    );
    console.log(
      "d.value: " +
        d.value +
        " textWidth: " +
        textWidth +
        " arc.centroid(d)[0]: " +
        arc.centroid(d)[0]
    );
    return (
      "translate(" +
      (arc.centroid(d)[0] - textWidth) +
      "," +
      arc.centroid(d)[1] +
      ")"
    );
  })
  .attr("class", "label-half-donut")
  .attr("dy", ".35em")
  .attr("text-anchor", function(d) {
    // are we past the center?
    return (d.endAngle + d.startAngle) / 2 > Math.PI ? "end" : "start";
  })
  .text(function(d) {
    return d.value.toFixed(2) + "%";
  });

您可以在 CodeSandBox 按钮中找到所有代码。

CodeSandBox 的代码我用 Chrome 运行它,我得到了这个图形

在此处输入图像描述

Chrome 中返回的值是:

d.value: 13.13 textWidth: 33.916015625 arc.centroid(d)[0]: -86.00117936328948

构建弧的标签是这样的:

<g class="slice">
    <path fill="#17A2B8" d="M-124.99275003141527,-1.3462687637091173A125,125,0,0,1,-116.9896333088247,-44.02755612416768L-47.07429579530035,-16.85261627690394A50,50,0,0,0,-49.98187231803007,-1.3462687637091153Z"></path>
    <text transform="translate(-119.91719498828948,-16.12597743156403)" class="label-half-donut" dy=".35em" text-anchor="start">13.13%</text>
</g>

当我使用 Firefox 在我的网站上运行相同的代码时,我得到了这个图形:

在此处输入图像描述

返回的值为:

d.value: 13.13 textWidth: 38.150001525878906 arc.centroid(d)[0]: -86.00117936328948

构建弧的标签是:

<g class="slice">
    <path fill="#17A2B8" d="M-124.99275003141527,-1.3462687637091173A125,125,0,0,1,-116.9896333088247,-44.02755612416768L-47.07429579530035,-16.85261627690394A50,50,0,0,0,-49.98187231803007,-1.3462687637091153Z"></path>
    <text transform="translate(-124.15118088916839,-16.12597743156403)" class="label-half-donut" dy=".35em" text-anchor="start">13.13%</text>
</g>

两者的区别在于相同值“13.13”返回的textWidth返回不同的值,并且translate函数的x不同,因为是使用该值计算的。

这怎么可能?难道我做错了什么?

编辑二:

在@Coola 提出的解决方案之后。这适用于 Firefox,但不适用于 Chrome :(

火狐

在此处输入图像描述

铬合金

在此处输入图像描述

textWidth 的值仍然不同,具体取决于我使用的是 Firefox 还是 Chrome。

火狐

d.value: 13.13 textWidth: 38.150001525878906 arc.centroid(d)[0]     -86.00117936328948
d.value: 59.7 textWidth: 38.150001525878906 arc.centroid(d)[0]: -33.49019847517988 
d.value: 23.88 textWidth: 38.150001525878906 arc.centroid(d)[0]: 59.22461768695275 
d.value: 17.91 textWidth: 38.150001525878906 arc.centroid(d)[0]: 84.79723004914864

铬合金

d.value: 13.13 textWidth: 33.916015625 arc.centroid(d)[0]: -86.00117936328948
d.value: 59.7 textWidth: 33.916015625 arc.centroid(d)[0]: -33.49019847517988
d.value: 23.88 textWidth: 33.916015625 arc.centroid(d)[0]: 59.22461768695275
d.value: 17.91 textWidth: 33.916015625 arc.centroid(d)[0]: 84.79723004914864

标签: javascriptd3.js

解决方案


您的文本翻译未正确计算。您x对转换的价值应该是arc.centroid(d)[0] - textWidth / 2.

所以你的变换应该是这样的:

      .attr("transform", function(d) {
        var textWidth = getTextWidth(
          (d.value.toFixed(2) + "%").toString(),
          "Roboto"
        );
        console.log(
          "d.value: " +
            d.value +
            " textWidth: " +
            textWidth +
            " arc.centroid(d)[0]: " +
            arc.centroid(d)[0]
        );
        let x = arc.centroid(d)[0] - textWidth / 2;
        let y = arc.centroid(d)[1];
        return "translate(" + x + "," + y + ")";
      })

工作代码框在这里

Firefox 开发者版 v75.0b:

Firefox Codesandbox 截图

铬 v80.0.3987.149: 在此处输入图像描述

更新

在与 OP 讨论后,他们的工作区仍然存在问题。我们进行了更多调查,发现问题是由 font-family 的继承样式引起的,而 font-family 的计算textWidth正在完成Roboto.style("font-family", "'Roboto', sans-serif")为了解决这个问题,我们添加了标签文本的样式。这解决了问题,工作代码框在这里


推荐阅读