'SVG getBoundingClientRect() + "transform: rotate()" is bugged in Chrome in a very specific way
getBoundingClientRect() works fine on all SVG elements except in the circumstance when an element is rotated in Chrome.
Below I have drawn 2 lines, the one on the left is diagonal and the right line starts vertical, as represented by the black lines. The green box is a visual representation of the getBoundingClientRect(). I then apply the same transform rotate to both lines at the same time and then update the bounding box visual.
As you can see from the following, the left bounding box does not represent the actual bounds, however, the right one does.
The problem is I need the true client bounds of the line in whatever orientation it is. This works fine in Firefox. Does anyone know of another way to get or calculate the bounds when a line, specifically, has a transform rotate?
I have posted a copy of this here: getBoundingClientRect() + "transform: rotate()" is bugged in Chrome?. To help people with a similar problem, but then decided I'd actually ask the community.
Chrome: v100.0.4896.75
This bug has now been reported to the cromium bugs board here: https://bugs.chromium.org/p/chromium/issues/detail?id=1314959
UPDATE: I've added the same 2 static lines with a direct transform attribute with a rotation of 40deg, and 2 div's representing the 'getBoundingClientRect'. The left box is clearly not showing the smallest rectangle which contains the entire element.
UPDATE 2 Included a BBox Visual in blue. getBBox() simply calculates the bounds of a child relative to the SVG element itself, prior to any rotation transforms. getBoundingClientRect does calculate the transform correctly, but is using the BBox, which has it's own issues here: https://bugs.chromium.org/p/chromium/issues/detail?id=377665
let l = [1,2,3,4,5,6].map(d => document.getElementById(`line${d}`)),
vis = [1,2,3,4,5,6].map(d => document.createElement(`div${d}`)),
bboxvis = [1,2,3,4,5,6].map(d => document.createElement(`div${d}`)),
r = 0;
vis.map((element) => {
document.body.appendChild(element)
element.style.position = "absolute"
element.style.border = "1px solid green"
element.style.background = `#0FF0002e`
})
bboxvis.map((element) => {
document.body.appendChild(element)
element.style.position = "absolute"
element.style.border = "1px solid blue"
element.style.background = `#0000FF2e`
})
let updateBounds = (element, displayElement, bboxvisEl) => {
let rect = element.getBoundingClientRect(),
svgBounds = element.parentElement.getBoundingClientRect(),
bbox = element.getBBox(),
d = document.documentElement;
displayElement.style.top = rect.y+d.scrollTop+"px"
displayElement.style.left = rect.x+d.scrollLeft+"px"
displayElement.style.width = rect.width+"px"
displayElement.style.height = rect.height+"px"
bboxvisEl.style.top = bbox.y+svgBounds.y+d.scrollTop + "px"
bboxvisEl.style.left = bbox.x+svgBounds.x+d.scrollLeft +"px"
bboxvisEl.style.width = bbox.width+"px"
bboxvisEl.style.height = bbox.height+"px"
}
[3,4,5].forEach(i => {
updateBounds(l[i], vis[i], bboxvis[i]);
bboxvis[i].style.transform = `rotate(40deg)`;
})
setInterval(() => {
[0,1,2].forEach(i => {
l[i].setAttribute("transform", `rotate(${r} 80 80)`);
bboxvis[i].style.transform = `rotate(${r}deg)`;
updateBounds(l[i], vis[i], bboxvis[i]);
})
r++;
if(r===360) r=0;
}, 20)
.container {
width:140px;
height:140px;
display:inline-block;
}
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="40" y1="40" x2="120" y2="120" stroke="black" stroke-width="2"></line>
<line x1="40" y1="40" x2="120" y2="120" id="line1" stroke="red" stroke-width="2"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="80" y1="30" x2="80" y2="130" stroke="black" stroke-width="2"></line>
<line x1="80" y1="30" x2="80" y2="130" id="line2" stroke="red" stroke-width="2"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="60" y1="30" x2="100" y2="130" stroke="black" stroke-width="2"></line>
<line x1="60" y1="30" x2="100" y2="130" id="line3" stroke="red" stroke-width="2"></line>
</svg>
<br/>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="40" y1="40" x2="120" y2="120" id="line4" stroke="red" stroke-width="2" transform="rotate(40 80 80)"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="80" y1="30" x2="80" y2="130" id="line5" stroke="red" stroke-width="2" transform="rotate(40 80 80)"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="60" y1="30" x2="100" y2="130" id="line6" stroke="red" stroke-width="2" transform="rotate(40 80 80)"></line>
</svg>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
