使用D3和Javascript在SVG矩形和SVG文本之间进行垂直对齐

3

为了练习技能,我正在创建自己的D3图表中的传奇。我无法使svg彩色矩形与相应的文本垂直对齐。

这是我的代码和截图:

mk=[0,1,2,3,4]
var legend_dim=50
var legend_X=300
var colors=["#1f78b4","#33a02c","#e31a1c","#ff7f00","#6a3d9a","#b15928"]

d3.select("#chart").selectAll("rect")
                      .data(mk)
                      .enter()
                      .append("rect")
                      .style("fill", function(d,i) { return colors[i]})                         .attr("x", function(d,i) { return 10*i})
                      .attr("x", legend_X)  
                      .attr("y", function (d,i){return i*legend_dim})
                      .attr("width", legend_dim)
                      .attr("height", legend_dim)



d3.select("#chart").selectAll("text")
                      .data(mk)
                      .enter()
                      .append("text")
                      .text(function(d,i) { return i})
                      .attr("x", legend_X+20)  
                      .attr("y", function (d,i){return (i)*legend_dim})
                      .attr("font-size","12px")

既然2的y属性相同,为什么它们会错位?我该如何对齐它们?顺便问一下,有没有设置文本框高度和宽度的方法?

enter image description here

1个回答

3
您的问题的基本性质是:
  • 对于一个SVG矩形,y值标记矩形的顶部。高度描述了矩形向下延伸多远。

  • 对于文本,y值表示每个SVG字符底部的y值。字符上升超过此线,而矩形向下延伸。请参见以下图像,该线位于y=100处,SVG文本的y值位于100处。文本的基线将与y=100对齐。但是,具有下降符的文本会延伸到低于此线的位置:

enter image description here

到达一个干净而明确的解决方案的挑战在于字体大小并非从最低下沉线的底部到最高上升线的顶部(甚至不是从字体基线到最高上升线的顶部)来测量,而是相对于具有任意边距的边界框。这个话题可以进一步扩展,本段的要点是,在我提出的解决方案中,您需要抵消文本的数量将取决于字体和字号。如果您想深究此问题,this 是一个很好的起点。

建议的解决方案:

如果您有一个已知 y 值的矩形,则可以添加一个固定值以放置文本。偏移量必须与文本大小成比例,并且鉴于字体大小不对应字母高度,该值通常应小于字体大小(以像素为单位)。虽然这可以通过肉眼观察或任意猜测来完成,但有条理的方法可能如下:

var fontSize = 50;
svg.append("text")
  .attr("y",rectangleY + fontSize*0.8)
  .attr("x",50)
  .text("|text |")
  .attr("font-size",fontSize);

或者,您可以使用dy属性来设置偏移量。将文本和矩形都设置为相同的y值,但为文本指定一个dy属性。两种方法如下所示:

var svg = d3.select("body")
  .append("svg")
  .attr("width",500)
  .attr("height",200);
  
var yValue = 100;
  
svg.append("rect")
  .attr("y",yValue)
  .attr("x",0)
  .attr("height",50)
  .attr("width",50)
  .attr("fill","orange");

// font below:
var fontSize = 50;
svg.append("text")
  .attr("y",yValue + fontSize*0.8)
  .attr("x",50)
  .text("|text |")
  .attr("font-size",fontSize);
  
// font below:
var fontSize = 50;
svg.append("text")
  .attr("y",yValue)
  .attr("dy",fontSize*0.8)
  .attr("x",310)
  .text("|text |")
  .attr("font-size",fontSize);
  
// font above:
svg.append("text")
  .attr("y",yValue)
  .attr("x",180)
  .text("|text|")
  .attr("font-size",fontSize);

  
  
svg.append("line")
  .attr("x1",0)
  .attr("x2",400)
  .attr("y1",100)
  .attr("y2",100)
  .attr("stroke","black");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>


哇!我想不到我认为是一个简单问题的东西背后有这么多“科学”。我天真地以为我可以画一个高度与彩色矩形相同且文本水平垂直居中对齐的容器。在那时,文本和彩色框之间的对齐将变得容易。谢谢伙计。明天我会尝试你建议的解决方案。 - Mauro Gentile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接