javascript - 将标题文本添加到 d3 中的路径中心

标签 javascript d3.js choropleth

我正在创建一个 svg 路径,我需要将 Title 设置在路径的中心。我尝试了很多例子但都失败了。

请检查代码片段。如何在每个 Title 的中心位置添加一个?

注意:我只使用路径,而不是坐标!

document.addEventListener("DOMContentLoaded", function () {
  const h = 300;
  const w = 300;

  const svg = d3
    .select("body")
    .append("svg")
    .attr("height", h)
    .attr("width", w);

  svg
    .selectAll("path")
    .data(map)
    .enter()
    .append("path")
    .attr("d", (m) => m.path)
    .attr("stroke-width", "1")
    .attr("stroke", "#000")
    .attr('fill','#fff')

  svg
    .selectAll("text")
    .data(map)
    .enter()
    .append("text")
    .attr("fill", "#fff")
    .text((m) =>m.title)
    .attr("x", (m) => m.id)
    .attr("y", (m) => m.id)
    .attr("transform", (m) => "translate(" + m.id + "," + m.id + ")");
});

const map=[ {
    id: 0,
    title: "Title 1",
    path: "M 45.25 34.96 l -0.97 -3.35 l -0.97 -2.39 l 2.43 -3.35 l 1.94 -4.31 l 1.94 -5.74 l 3.89 -5.74 l 0.97 6.22 l 0.49 3.35 l 3.89 3.83 l 3.89 -0.96 l 0.97 3.35 l 3.89 0.96 l 0.49 2.87 l 3.89 1.44 l 0.49 1.91 L 76.36 34 l 2.43 -2.87 l 1.46 3.83 l 1.94 2.39 l 2.92 1.91 l 0.97 1.91 l 2.43 -0.96 l 1.46 1.44 l -1.46 3.35 l 1.46 1.44 l 1.94 1.44 v 0.96 l 3.89 -0.48 v 1.91 l 0.97 1.91 v 2.39 l 2.43 1.91 l -0.49 4.31 l 1.94 3.35 l 2.43 3.35 l -0.97 3.35 v 4.79 v 4.31 l -1.46 3.83 l 0.97 4.79 l -2.43 3.35 l -3.4 4.79 l -3.89 -0.96 l -5.35 -0.48 l -1.94 -3.83 l -2.43 -1.91 l 2.92 -5.26 l -1.94 -3.83 l -2.43 -2.87 l -3.89 -1.44 l -1.94 -1.91 l -1.46 -2.87 l -2.43 0.96 c 0 0 -0.61 -0.48 -1.94 -0.96 s -3.4 -0.96 -3.4 -0.96 l -2.43 -0.96 l -2.43 1.91 l -3.89 -0.96 l -3.4 -1.44 l -2.92 1.91 l -0.49 2.39 c 0 0 -1.58 -0.24 -3.4 -0.96 c -1.82 -0.72 -3.89 -1.91 -3.89 -1.91 l -0.97 -1.44 l 3.4 -1.91 l 1.94 -2.39 l -1.46 -2.87 v -6.7 l 5.35 -0.48 l 1.94 -1.91 l 1.94 -2.87 l 4.37 -1.44 l 0.97 -3.35 l 2.43 3.83 l 2.43 -1.44 l 1.94 -3.35 l -1.94 -2.39 l -1.94 -2.87 v -3.35 l -3.4 -2.87 l -4.37 0.96 l -2.43 -3.83 l -2.43 1.91 l -2.92 -0.48 L 45.25 34.96 Z",
  },{
id: 1,
title: "Ttitle 2",
path: "M 19.49 126.38 l -2.43 -4.31 l -2.92 -3.83 l 1.94 -4.31 l -4.86 -0.96 l 1.46 -7.66 l 3.4 -2.39 l -0.49 -2.87 l 1.94 -3.83 l 5.83 -3.83 l 1.94 -5.26 l -4.37 -2.39 l 2.43 -4.31 l 0.97 -4.31 l 5.35 -1.91 v -4.79 l 7.29 0.96 l 5.35 -1.44 l 7.29 4.79 l 1.46 -3.83 l 4.96 -1.03 l 4.27 1.51 l 3.89 -0.48 l 9.72 2.39 l 3.89 4.31 l 3.4 1.44 l 4.86 5.74 l -3.4 4.79 l 0.97 3.35 l -2.43 2.39 l -0.97 3.83 h -3.4 l -2.43 -3.83 l -1.46 2.87 h -2.92 l -1.46 5.27 l 1.94 1.91 l -2.43 0.48 l -2.92 4.79 l -0.97 2.87 l -1.46 2.87 l 1.94 2.39 l -2.92 0.48 h -1.94 v -2.39 l -6.32 0.48 v 3.83 h -2.43 l -0.49 4.79 l 2.92 1.44 l -1.94 1.91 v 4.31 l 2.43 1.44 l 2.92 2.39 l -0.49 3.35 l -3.4 0.48 l -2.92 -2.87 l -2.43 -1.44 v -1.92 l -3.4 -3.35 h -2.92 l -0.97 -3.35 l -5.35 -2.87 l 0.49 -2.39 l -0.49 -1.44 l -4.37 1.44 l -2.92 2.39 l -2.43 -2.87 L 19.49 126.38 Z",
  }]
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, shrink-to-fit=no"
    />
    <link rel="stylesheet" href="assets/scss/style.css" />
  </head>

  <body>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script src="./assets/js/main.js"></script>
  </body>
</html>

最佳答案

如果您只有路径数据,您可以考虑获取 bounding box 路径并使用此框的中心点。

对于不规则形状的地理区域,这将不同于 质心 的位置,但标签通常会显示为“足够”居中。

查看下面的修改:

  • 路径被分类(作为region)所以我们可以在下一步中选择
  • 使用 d3 each在区域的选择上并使用 getBBox
  • 找到 bbox 的中心并用它来定位标签
  • 使用 text-anchor 中间

工作示例:

document.addEventListener("DOMContentLoaded", function () {
  const h = 300;
  const w = 300;

  const svg = d3
    .select("body")
    .append("svg")
    .attr("height", h)
    .attr("width", w);

  svg
    .selectAll(".region") // <-- select the class
    .data(map)
    .enter()
    .append("path")
    .attr("class", "region") // <-- add the class
    .attr("d", (m) => m.path)
    .attr("stroke-width", "1")
    .attr("stroke", "#000")
    .attr('fill','#fff')

  svg
    .selectAll(".region") // <-- now we can select the paths and get the bbox
    .each((d, i, nodes) => {
      const bbox = d3.select(nodes[i]).node().getBBox();
      const centreX = bbox.x + (bbox.width / 2); // <-- get x centre 
      const centreY = bbox.y + (bbox.height / 2); // <-- get y centre
      svg 
        .append("text") // <-- now add the text element
        .text(d.title)
        .attr("x", centreX)
        .attr("y", centreY)
        .attr("fill", "#0804ee")
        .attr("text-anchor", "middle")
    });
    
    
    
});

const map=[ {
    id: 0,
    title: "Title 1",
    path: "M 45.25 34.96 l -0.97 -3.35 l -0.97 -2.39 l 2.43 -3.35 l 1.94 -4.31 l 1.94 -5.74 l 3.89 -5.74 l 0.97 6.22 l 0.49 3.35 l 3.89 3.83 l 3.89 -0.96 l 0.97 3.35 l 3.89 0.96 l 0.49 2.87 l 3.89 1.44 l 0.49 1.91 L 76.36 34 l 2.43 -2.87 l 1.46 3.83 l 1.94 2.39 l 2.92 1.91 l 0.97 1.91 l 2.43 -0.96 l 1.46 1.44 l -1.46 3.35 l 1.46 1.44 l 1.94 1.44 v 0.96 l 3.89 -0.48 v 1.91 l 0.97 1.91 v 2.39 l 2.43 1.91 l -0.49 4.31 l 1.94 3.35 l 2.43 3.35 l -0.97 3.35 v 4.79 v 4.31 l -1.46 3.83 l 0.97 4.79 l -2.43 3.35 l -3.4 4.79 l -3.89 -0.96 l -5.35 -0.48 l -1.94 -3.83 l -2.43 -1.91 l 2.92 -5.26 l -1.94 -3.83 l -2.43 -2.87 l -3.89 -1.44 l -1.94 -1.91 l -1.46 -2.87 l -2.43 0.96 c 0 0 -0.61 -0.48 -1.94 -0.96 s -3.4 -0.96 -3.4 -0.96 l -2.43 -0.96 l -2.43 1.91 l -3.89 -0.96 l -3.4 -1.44 l -2.92 1.91 l -0.49 2.39 c 0 0 -1.58 -0.24 -3.4 -0.96 c -1.82 -0.72 -3.89 -1.91 -3.89 -1.91 l -0.97 -1.44 l 3.4 -1.91 l 1.94 -2.39 l -1.46 -2.87 v -6.7 l 5.35 -0.48 l 1.94 -1.91 l 1.94 -2.87 l 4.37 -1.44 l 0.97 -3.35 l 2.43 3.83 l 2.43 -1.44 l 1.94 -3.35 l -1.94 -2.39 l -1.94 -2.87 v -3.35 l -3.4 -2.87 l -4.37 0.96 l -2.43 -3.83 l -2.43 1.91 l -2.92 -0.48 L 45.25 34.96 Z",
  },{
id: 1,
title: "Ttitle 2",
path: "M 19.49 126.38 l -2.43 -4.31 l -2.92 -3.83 l 1.94 -4.31 l -4.86 -0.96 l 1.46 -7.66 l 3.4 -2.39 l -0.49 -2.87 l 1.94 -3.83 l 5.83 -3.83 l 1.94 -5.26 l -4.37 -2.39 l 2.43 -4.31 l 0.97 -4.31 l 5.35 -1.91 v -4.79 l 7.29 0.96 l 5.35 -1.44 l 7.29 4.79 l 1.46 -3.83 l 4.96 -1.03 l 4.27 1.51 l 3.89 -0.48 l 9.72 2.39 l 3.89 4.31 l 3.4 1.44 l 4.86 5.74 l -3.4 4.79 l 0.97 3.35 l -2.43 2.39 l -0.97 3.83 h -3.4 l -2.43 -3.83 l -1.46 2.87 h -2.92 l -1.46 5.27 l 1.94 1.91 l -2.43 0.48 l -2.92 4.79 l -0.97 2.87 l -1.46 2.87 l 1.94 2.39 l -2.92 0.48 h -1.94 v -2.39 l -6.32 0.48 v 3.83 h -2.43 l -0.49 4.79 l 2.92 1.44 l -1.94 1.91 v 4.31 l 2.43 1.44 l 2.92 2.39 l -0.49 3.35 l -3.4 0.48 l -2.92 -2.87 l -2.43 -1.44 v -1.92 l -3.4 -3.35 h -2.92 l -0.97 -3.35 l -5.35 -2.87 l 0.49 -2.39 l -0.49 -1.44 l -4.37 1.44 l -2.92 2.39 l -2.43 -2.87 L 19.49 126.38 Z",
  }]
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, shrink-to-fit=no"
    />
    <link rel="stylesheet" href="assets/scss/style.css" />
  </head>

  <body>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script src="./assets/js/main.js"></script>
  </body>
</html>

关于javascript - 将标题文本添加到 d3 中的路径中心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74358276/

相关文章:

javascript - 如何构建自定义 extjs4 库来编写这样的代码?

javascript - 标记未与传单 d3 中的路径正确对齐

geopandas - 将 geopandas 数据帧传递给 `folium.Choropleth`( map 呈现灰色)

r - 等值线世界地图

python - 与绘图一起使用的位置模式列表

javascript - 通过 Javascript 方法从 Google 电子表格获取光标行/列

javascript - AngularJS 在使用 ng-show ng-hide 时我仍然看到两个对象 1 毫秒

javascript - 更改 html span 内部文本

html - 在 d3js 中使用动态输入(CSV)

javascript - D3.js force directed graph,通过使边缘相互排斥来减少边缘交叉