Javascript的getBBox()提供了一个比其内容文本更高的框。为什么?

时间:2016-03-22 04:52:27

标签: javascript d3.js svg

我正在使用D3.js在SVG容器上绘制一些文本(" 100%")。

现在我试图弄清楚该文本周围的边界框的尺寸。

我就是这样做的:

      var label = svgContainer.append("text")
        .attr("x", 200)
        .attr("y", 200)
        .text("100%")
        .attr("font-family", "Courier New")
        .attr("font-weight", "bold")
        .attr("font-size", "10px")
        .attr("fill", "black");
        .attr("transform", function(d){
            var bb = this.getBBox();
            console.log("bb.width = ", bb.width);
            console.log("bb.height = ", bb.height);
            return "translate(0, 0)";
          }
        );

这不仅会画出字符串" 100%"在我的屏幕上,但在console.log中,它还输出边界框的宽度和高度(分别为24和11.5!);

现在我想在屏幕上可视化上述边界框。所以在上面的代码之前,我先添加以下代码:

        var rect = svgContainer.append("rect")
          .attr("x", 200)
          .attr("y", 200-11.5)
          .attr("width", 24)
          .attr("height", 11.5)
          .attr("fill", "pink");

当我运行这个改变的代码时,我希望在" 100%"周围看到一个粉红色的边框。串。但我看到了以下内容!

enter image description here

为什么粉红色的边框高于文字?我需要获得文本的实际边界框的尺寸 - 而不是高于它的东西。我该怎么做?

以下是Plunker:https://plnkr.co/edit/XoVSZwTBNXhdKKJKkYWn

2 个答案:

答案 0 :(得分:4)

这里有两件事:

  1. 您只使用边界框的高度和宽度字段。您还应该考虑边界框的x和y属性 - 正如@Gilsha正确指出的那样。当你调整x和y时,你会看到盒子稍微低一点:
  2. 
    
    var svg = document.getElementById("my_svg_widget");
    
        
    var bbox = svg.getElementById("test").getBBox();
    
    var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
    rect.setAttribute("x", bbox.x);
    rect.setAttribute("y", bbox.y);
    rect.setAttribute("width", bbox.width);
    rect.setAttribute("height", bbox.height);
    rect.setAttribute("fill", "rgba(255, 0, 0, 0.5)");
    svg.appendChild(rect);
    
    <svg id="my_svg_widget" width="300" height="300" style="border-style:solid;border-color:purple;border-width: 2px;">
      <text id="test" x="100" y="100" font-family="Courier New" font-weight="bold" font-size="50px">100%</text>
    </svg>
    &#13;
    &#13;
    &#13;

    1. 这给我们带来了第二个原因。 getBBox()返回的边界框不是字形周围的紧密边界框。它包括文本的完整em-box高度 - 包括上限(字体中最高的字符)和下降(最低于基线)的容差。
    2. 如果我们在文本元素中包含其中一些字符,您可以看到我的意思。

      &#13;
      &#13;
      var svg = document.getElementById("my_svg_widget");
      
          
      var bbox = svg.getElementById("test").getBBox();
      
      var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
      rect.setAttribute("x", bbox.x);
      rect.setAttribute("y", bbox.y);
      rect.setAttribute("width", bbox.width);
      rect.setAttribute("height", bbox.height);
      rect.setAttribute("fill", "rgba(255, 0, 0, 0.5)");
      svg.appendChild(rect);
      &#13;
      <svg id="my_svg_widget" width="300" height="300" style="border-style:solid;border-color:purple;border-width: 2px;">
        <text id="test" x="100" y="100" font-family="Courier New" font-weight="bold" font-size="50px">&#193;100%&#x2563;</text>
      </svg>
      &#13;
      &#13;
      &#13;

答案 1 :(得分:2)

您可以直接使用边界框using System.Collections.Generic; using System.Globalization; using System.Text; using System.Threading.Tasks; using System.IO; namespace Test { class Program { static void Main() { { //I NEED TO COMPARE THIS TIME WITH THE LAST LOGGED TIME DateTime x = DateTime.Now; DateTime time = x; //File.GetLastWriteTimeUtc(watcher.Path + "\\vimrc"); DateTime newTimeFormat = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second); time.ToString("O"); string log = x.ToString(); { Console.WriteLine(Convert.ToDateTime(log).ToString("s")); var result = Convert.ToDateTime(Convert.ToDateTime(log).ToString("s")); //THIS ERRORS EVERY SINGLE TIME, EVEN WHEN LOG IS CONVERTED TO A 100% VERIFIABLE LEGITIMATE FORMAT if (result < time) { Console.WriteLine("bleh why don't my conversions work!?!??!!?"); } } } } } } x属性。使用以下代码。

y

&#13;
&#13;
var label = self.svgContainer.append("text")
  .attr("x", 200)
  .attr("y", 200)
  .text("100%")
  .attr("font-family", "Courier New")
  .attr("font-weight", "bold")
  .attr("font-size", "10px")
  .attr("fill", "black")
  .attr("transform", function(d){
      var bb = this.getBBox();
      self.svgContainer.insert("rect","text")
        .attr("x", bb.x)
        .attr("y", bb.y)
        .attr("width", bb.width)
        .attr("height", bb.height)
        .attr("fill", "pink");
      return "translate(0, 0)";
  });
&#13;
var myApp = angular.module('myApp', []);

myApp.controller('MyController', function() {
    var self = this;
    self.svgContainer = d3.select("#my_svg_widget");

    console.log("Hello!");
    

    var label = self.svgContainer.append("text")
      .attr("x", 200)
      .attr("y", 200)
      .text("100%")
      .attr("font-family", "Courier New")
      .attr("font-weight", "bold")
      .attr("font-size", "10px")
      .attr("fill", "black")
      .attr("transform", function(d){
          var bb = this.getBBox();
          self.svgContainer.insert("rect","text")
            .attr("x", bb.x)
            .attr("y", bb.y)
            .attr("width", bb.width)
            .attr("height", bb.height)
            .attr("fill", "pink");
          return "translate(0, 0)";
      });
  }
);
&#13;
&#13;
&#13;