Most of this focuses on the ‘hard part’ of d3, which is the concept of the selection and data join. This is about what you might call an easier part, or an even-lower-level one: SVG.
SVG, short for Scalable Vector Graphics, is a standard for vector drawing that integrates with HTML and is implemented by most browsers. Unlike Canvas, it’s not raster-based but rather preserves the structure of your drawing and is much like HTML in terms of events, updates, and being-a-tree. Unlike Canvas, it’s old, big, and complex.
Just like math, we tend to use a subset of SVG for most drawings: here’s that.
There are a few basic shapes available in SVG:
<circle> is a circle: you’ll always want to set its attribute
r for radius.
Circles are positioned with
cy, or with transforms.
<rect> is a rectangle: it requires a
height attribute to show up,
and is positioned with
y attributes, or transforms.
<path> is the most versatile kind of shape: filled, it can look like a polygon, unfilled
it can look like a line. You can shape it into a circle or a rectangle, or use
it as the path for text to shape around. Even though SVG also has a
<polyline> element, most of the maps
and drawings you see in d3 are made of paths, since paths can express all
of the same shapes.
The path data attribute is a source of much confusion for new users of
d3, since it’s confusing. That is, for the purposes of efficiency, it’s very
concise and has optional syntax: sometimes coordinates are separated with
but they don’t have to be, and saying
L10 10 L10 10 is equivalent to saying
L10 10 10 10.
The basic parts of path data are commands, like
L, which say ‘draw
a line from here to there’ or ‘start a new line’ or ‘draw a squiggly line’
or ‘close this line by adding a segment back to the first point’.
Then there are coordinates, like
10 10, which are X and Y positions
of places to go. Path data is just coordinates and commands, strung together
to tell lines where to start, go, and end.
This railroad diagram may or may not bring you some sense of higher enlightenment about path data.
SVG has its own transforms, with a very similar syntax, which you can use to position any element. And unlike HTML, there are no ‘float’ or ‘inline’ ideas in SVG - the position of each element doesn’t affect the position of elements outside of its subtree.
On the downside, SVG transforms are sometimes not 3D accelerated when HTML transforms are - so they aren’t necessarily fast.
There are also has positioning attributes -
you can set the position of a
y attributes, and of a circle
cy. Sometimes these are useful - especially with text,
when you can set position relative to the baseline with positioning attributes
and then positioning in the page with a
A bit odd from the perspective of HTML is the
<g> element, but it’s incredibly
useful, for a variety of reasons.
g element is a group: meaning, you can put elements into
g and those
elements are transformed when
g is transformed, they’re removed when it’s
removed, and so on.
SVG currently doesn’t support z-indexes order of elements on a page is their
order in rendering. Thus, it makes sense to have logical groups of elements
in the page - for instance, the iD editor uses
<g> elements to stack roads, buildings, and rivers on top of
each other in the right order.
SVG also doesn’t use nesting as much as HTML, so
<g> is used
to group items that are really just stacked on top of each other, like
if you need a multi-circle stack for a bullseye.
<g> element is often used in a very similar fashion to Canvas’s idea of transformations -
by using a
<g>, you can shift the contents of a graph so that there’s a margin
around its boundary, or scale groups of shapes all at once.
<g> is really useful for d3 because it provides a DOM way of
expressing subselections - you can use a
<g> element for each series of a
multiple series chart or for each chapter of a book, and easily bind the group
of data to the
<g> and the subsets to its contents.
SVG can be styled with CSS, but uses different properties to do roughly equivalent
styling. It’s basically more unified - to set the fill of a circle, you set
fill, and the same thing to set the fill of text or a path.
d3 protects us from the oddity of interacting with SVG elements through some built-in magic. If you used d3 in the olden days, you would see code like
Herein lies a little detail: HTML and SVG use XML Namespaces
so that both SVG and HTML can have tags named
text without a conflict.
SVG uses the namespace
http://www.w3.org/2000/svg, so instead of simply
document.createElement, you’ll need to use its cousin
To create an SVG element with a circle of radius 5, you would write:
A little dirty, right? Anyway, d3 simplifies this since 2.6
by automatically using the namespace
http://www.w3.org/2000/svg to create
<svg> element, and then selections
automatically use that namespace for each new insertion.