Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Delta 4 - Positioning

svgdx provides alternatives to the absolute positioning of elements provided by SVG

Overview

Most SVG elements are placed on a coordinate grid using absolute values within a defined coordinate system. An exception to this is the <tspan> element, which naturally “follows on” in terms of position from the previous <tspan> element. Being able to do this (and more) would be useful for other SVG elements, and is provided by svgdx.

Two important notes should be considered when planning positioning in svgdx:

  • User units should be used throughout; absolute units (e.g. those with some measurement suffix, such as px or mm) will prevent svgdx understanding the positions of elements.
  • svgdx diagrams are ‘expected’ to be between approximately 10 and 1000 units in each dimension. While there are no hard limits on size, various aspects make assumptions about appropriate absolute values - such as default text or arrow-head size - which won’t be valid with very small or very large drawings. SVG is by nature scalable, and scaling the largest dimension to fit in this range should generally be feasible.

Simple relative positioning

The simple cases of ‘after the previous element’ and ‘below the previous element’ which <tspan> handles automatically for text are dealt with generically in svgdx through special cases of the xy attribute.

xy attribute valuemeaning
“^|h”to the right of (‘horizontally after’) the previous element
“^|H”to the left of (‘horizontally before’) the previous element
“^|v”below (‘vertically after’) the previous element
“^|V”above (‘vertically before’) the previous element

For each of these, a further numeric value can be given which provides the ‘margin’ before the next element starts.

So we can have:

a b c d
<svg>
 <rect xy="0" wh="20" text="a"/>
 <rect xy="^|h" wh="20" text="b"/>
 <rect xy="^|v" wh="20" text="c"/>
 <rect xy="^|h" wh="20" text="d"/>
</svg>

or:

A B C D
<svg>
 <rect xy="0" wh="20" text="A"/>
 <rect xy="^|h 10" wh="20" text="B"/>
 <rect xy="^|V 5" wh="20" text="C"/>
 <rect xy="^|H 10" wh="20" text="D"/>
</svg>

Layout

The most important concept for positioning is the element bounding box. This is an axis-aligned rectangle which is the minimum size required to cover a shape. For (non-rotated) <rect> elements, the bounding box is identical with the element’s own layout; for other shapes it will there will usually be some area inside the bounding box that is not within the shape itself.

The diagram below shows the bounding box (blue dashed line) of several shapes (in red).

Each bounding box has nine ‘locations’ which can be used as relative positioning points, as shown here:

tl t tr r br b bl l c

A mnemonic to remember these positions is “TRBL”, so stay out of ‘trouble’ by remembering these! A further point to note is that for the corner positions, the Top/Bottom indicator is always before the Left/Right indicator, so it’s always br - not rb - for the bottom-right corner.

Scalarspec

The following diagram shows the set of scalar values which may obtained from any bounding box in svgdx.

This is closely related to ‘uniform positioning’ - the idea that regardless of the native attributes for a shape (e.g. x/y/width/height for a <rect>, x1/y1/x2/y2 for a <line> and so on), shapes in svgdx can be positioned with any meaningful and sufficient combination of these attributes.

For example, a horizontal line in svgdx can be defined with a start point (x1 & y1, or using compound attributes xy1) and a width. Similarly if xy2 is given together with a width, that is the right most point of the horizontal line, which stretches out for width units up to that point.

y1 cy y2 x1 cx x2 w h

For an <ellipse> shape, additional rx and ry values are available, as in the next diagram. <circle> elements have a single r value for radius.

y1 cy y2 x1 cx x2 w h rx ry

There are some basic aliases for these ‘scalarspec’ values:

  • x == x1
  • y == y1
  • w == width
  • h == height