svgdotjs/svgdom

Rotating a curve gives unexpected bounding rect

Closed this issue · 3 comments

Given a curved path with a rotation applied

<path d="M 100,100 c 100,-100 300,100 200,200 z" transform="rotate(45)"></path>
Preview

test-bug2

I expect the bounding rectangle returned by element.getBoundingClientRect() to give me the outer bounds of the shape (or at the very least fully contain the shape). Currently, svgdom cuts off part of the curve.

Expected

test-bug2

Actual

test-bug2

Test code
const { createSVGWindow } = require('svgdom')
const document = createSVGWindow().document;

const root = document.documentElement;
root.setAttribute("xmlns", "http://www.w3.org/2000/svg");
root.setAttribute("viewBox", "0 0 500 500");
root.setAttribute("width", "500");
root.setAttribute("height", "500");
root.setAttribute("stroke-width", "5");

// Add a curved shape
const shape = document.createElementNS("http://www.w3.org/2000/svg", 'path');
shape.setAttribute("fill", "none");
shape.setAttribute("stroke", "blue");
shape.setAttribute("d", "M 100,100 c 100,-100 300,100 200,200 z");
shape.setAttribute("transform", "translate(200) rotate(45)");
root.appendChild(shape);

// Get the shape bounds
const bounds = shape.getBoundingClientRect();

// Add the bounding box
const shapeBox = document.createElementNS("http://www.w3.org/2000/svg", 'rect');
shapeBox.setAttribute("x", bounds.x);
shapeBox.setAttribute("y", bounds.y);
shapeBox.setAttribute("width", bounds.width);
shapeBox.setAttribute("height", bounds.height);
shapeBox.setAttribute("fill", "none");
shapeBox.setAttribute("stroke", "green");
root.appendChild(shapeBox);

console.log(root.outerHTML);
SVG result
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" width="500" height="500" stroke-width="5">
    <path fill="none" stroke="blue" d="M 100,100 c 100,-100 300,100 200,200 z" transform="translate(200) rotate(45)"></path>
    <rect x="200" y="141.4213562373095" width="65.55161555970358" height="282.842712474619" fill="none" stroke="green"></rect>
</svg>

Extra note

It looks like Chrome and Firefox don't agree on what the bounding box should be either, but both of them fully contain the shape. I'm not sure what the specs say about this situation.

Chrome

ss1627660402-ae29

Firefox

ss1627660439-ec7c

haha, FF and Chrome are wildly different :D. The situation is actually quite clear. Transformation does not matter for bounding box calculation. Therefore the bounding box should be the one of the unrotated arc.

Will investigate whats going wrong with our implementation

Scratch that. You used getBoundingClientRect. In that case transform matters.

Release as 0.1.10. Good catch. I needed to change a key concept of how boxes are calculated