getBBox()vs getBoundingClientRect()vs getClientRects()

时间:2015-11-13 08:30:34

标签: javascript dom svg

我无法找到使用这些功能的明确参考: getBBox() vs getBoundingClientRect() vs getClientRects()

你能解释一下他们做了什么以及他们返回的坐标(及其参考)是什么?

3 个答案:

答案 0 :(得分:22)

getBBox SVG specification中定义,它在应用变换后返回 local 坐标系中的坐标。

getBoundingClientRect getClientRects CSSOM specification中定义。它们的主要区别在于它们返回外部 SVG坐标系中的坐标。

答案 1 :(得分:21)

某些元素(如span标记)在包含多行时会有多个 ClientRects MDN Element.getClientRects()
BoundingRect 是元素的 ClientRects 联合 MDN Element.getBoundingClientRect()

答案 2 :(得分:4)

这是我从MDN Element.getClientRects()复制的示例,我添加了addBoundingClientRectOverlay函数来比较addClientRectsOverlay。 您可以看到红色矩形来自getClientRects,黑色虚线矩形来自getBoundingClientRect,因此您可以分辨出不同之处。 enter image description here

function addClientRectsOverlay(elt) {
  // Absolutely position a div over each client rect so that its border width
  // is the same as the rectangle's width.
  // Note: the overlays will be out of place if the user resizes or zooms.
  var rects = elt.getClientRects();

  for (var i = 0; i != rects.length; i++) {
    var rect = rects[i];
    var tableRectDiv = document.createElement("div");
    tableRectDiv.style.position = "absolute";
    tableRectDiv.style.border = "1px solid red";
    var scrollTop =
      document.documentElement.scrollTop || document.body.scrollTop;
    var scrollLeft =
      document.documentElement.scrollLeft || document.body.scrollLeft;
    tableRectDiv.style.margin = tableRectDiv.style.padding = "0";
    tableRectDiv.style.top = rect.top + scrollTop + "px";
    tableRectDiv.style.left = rect.left + scrollLeft + "px"; // we want rect.width to be the border width, so content width is 2px less.
    tableRectDiv.style.width = rect.width - 2 + "px";
    tableRectDiv.style.height = rect.height - 2 + "px";
    document.body.appendChild(tableRectDiv);
  }
}
function addBoundingClientRectOverlay(elt) {
  // Absolutely position a div over each client rect so that its border width
  // is the same as the rectangle's width.
  // Note: the overlays will be out of place if the user resizes or zooms.
  var rect = elt.getBoundingClientRect();

  var tableRectDiv = document.createElement("div");
  tableRectDiv.style.position = "absolute";
  tableRectDiv.style.border = "1px dashed #321";
  var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  var scrollLeft =
    document.documentElement.scrollLeft || document.body.scrollLeft;
  tableRectDiv.style.margin = tableRectDiv.style.padding = "0";
  tableRectDiv.style.top = rect.top + scrollTop+1 + "px";
  tableRectDiv.style.left = rect.left + scrollLeft+1 + "px"; // we want rect.width to be the border width, so content width is 2px less.
  tableRectDiv.style.width = rect.width - 4 + "px";
  tableRectDiv.style.height = rect.height - 4 + "px";
  document.body.appendChild(tableRectDiv);
}
(function() {
  /* call function addClientRectsOverlay(elt) for all elements with assigned css class "withClientRectsOverlay"  */
  var elt = document.getElementsByClassName("withClientRectsOverlay");
  for (var i = 0; i < elt.length; i++) {
    addClientRectsOverlay(elt[i]);
    addBoundingClientRectOverlay(elt[i]);
  }
})();
strong {
  text-align: center;
}
div {
  display: inline-block;
  width: 150px;
}
div p,
ol,
table {
  border: 1px solid blue;
}
span,
li,
th,
td {
  border: 1px solid green;
}
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects -->

<h3>A paragraph with a span inside</h3>
<p>Both the span and the paragraph have a border set. The client rects are in red. Note that the p has only one border box, while the span has multiple border boxes.</p>

<div>
 <strong>Original</strong>
 <p>
  <span>Paragraph that spans multiple lines</span>
 </p>
</div>
 
<div>
 <strong>p's rect</strong>
 <p class="withClientRectsOverlay">
  <span>Paragraph that spans multiple lines</span>
 </p>
</div>

<div>
 <strong>span's rect</strong>
 <p>
  <span class="withClientRectsOverlay">Paragraph that spans multiple lines</span>
 </p>
</div><h3>A list</h3>
<p>Note that the border box doesn't include the number, so neither do the client rects.</p>

<div>
 <strong>Original</strong>
 <ol>
  <li>Item 1</li>
  <li>Item 2</li>
 </ol>
</div>

<div>
 <strong>ol's rect</strong>
 <ol class="withClientRectsOverlay">
  <li>Item 1</li>
  <li>Item 2</li>
 </ol>
</div>

<div>
 <strong>each li's rect</strong>
 <ol>
  <li class="withClientRectsOverlay">Item 1</li>
  <li class="withClientRectsOverlay">Item 2</li>
 </ol>
</div><h3>A table with a caption</h3>
<p>Although the table's border box doesn't include the caption, the client rects do include the caption.</p>

<div>
 <strong>Original</strong>
 <table>
  <caption>caption</caption>
  <thead>
    <tr><th>thead</th></tr>
  </thead>
  <tbody>
    <tr><td>tbody</td></tr>
  </tbody>
 </table>
</div>
 
<div>
 <strong>table's rect</strong>
 <table class="withClientRectsOverlay">
  <caption>caption</caption>
  <thead>
    <tr><th>thead</th></tr>
  </thead>
  <tbody>
    <tr><td>tbody</td></tr>
  </tbody>
 </table>
</div>