Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG Group Translation Issue - Wrong Units?

First off I'm a bit new to SVG. I just started working on a gantt-ish style timeline/roadmap for products supported in my area. Each item has a category, and subcategory, and then a number of versions. Each product ends up as its own separate mini-chart. The SVG is produced by d3.js, however the issue doesn't seem to be related to the JavaScript.

The example SVG is here: http://plnkr.co/edit/ipqZIZODDN4lYKVeLt73

Fundamentally there are two g groups that should be stacked on top of each other. In the example there is red and blue outline respectively. The blue group should be directly below the red group. To position the blue group I measured the height of the red group using getBBox. I then use that height and the transform attribute on blue group.

Here are the relevant groups:

<g class="product" transform="translate(0,0)" style="outline: thin solid red">...</g>
<g class="product" transform="translate(0,122)" style="outline: thin solid blue">...</g>

Note: these groups are contained within numerous other groups, however no transformations (with the exception of translate(0,0)) are applied to these groups.

In the example if you use the chrome inspector to measure the height of the red group, it is 121 pixels:

measured height

So the 122 used for the translate for the blue group should be fine. However when rendered the red and blue groups overlap significantly:

overlap

In fact if you adjust the numbers in the chrome inspector you need an offset of 143 pixels: transform="translate(0,143)", before the two groups align in the way I want them:

expected alignment

Are the units for the translation not in pixels? I don't see any obvious reason why the 122 unit translation wouldn't move the group 122 pixels unless that was so. It does render the same way in IE11 so it must be something about SVGs or this markup that I'm not aware of.

Does anyone have any ideas?

Update This morning I took some screenshots and measured the pixel values of the boxes. The blue box is indeed 121 pixels tall just as getBBox and the various browser inspectors I've used suggest. I then measured the offset and found that what is supposed to be a 122 pixel translation down is, in fact only 100 pixels. Further if using the manually corrected translation (which is 143 pixels down), the correct 121 pixel offset is measured:

enter image description here

Issue appears in IE11, IE11-Edge (Spartan), Chrome 40, and Firefox 36. With every modern browser rendering nearly the same, this has to be an issue with the markup, right? So where's the missing 22 pixels going?

like image 963
klyd Avatar asked Oct 19 '22 16:10

klyd


1 Answers

The concept that you're missing is that SVG group elements (<g>) don't have dimensions. (They're not like HTML <div> elements.) So the transforms defined on a group element simply cascade through to any elements that do have size. Ignoring the axes and labels for simplicity, the "top-most" element in your "bottom" graph is the bar:

<rect x="237.36726634488812" y="4" height="15" width="6.529179464677469"></rect>

That <rect> is, indeed, transformed with a translation of 122 pixels in the vertical direction, which you can measure in a screen capture. (It's then positioned with a y value of 4 pixels.)

like image 52
Stephen Thomas Avatar answered Oct 22 '22 08:10

Stephen Thomas