Based on material by Carlos Scheidegger and Kevin Sun
An SVG drawing starts with an
<svg> element, which requires width and height attributes, specified in pixels:
This is results in a blank canvas, which is kind of boring, but you should be able to verify, using the Developer Tools, that there is in fact an SVG element there. In the following, you’ll learn how to add basic graphical shapes to the SVG element.
Circles have an x (
cx) and a y (
cy) position specifying the center point, in addition to a radius (
I’m going to omit the HTML boilerplate going forward, unless there’s reason to include it. Note though, that valid HTML always needs to include that.See output in new page.
The SVG Coordinate system originates from the top-left.See output in new page.
Also, SVG dimensions are given in “user units”, which by default match to pixels. How the user units match to pixels can be changed, as the name “scalable” implies.
As you might have noticed, some appearance aspects in SVG are controlled by attributes (position, size); others (color, weight) are controlled by CSS properties. This is a perennial source of confusion, and unfortunately there’s no good way around it.
To add to the confusion, a subset of SVG attributes can also be specified via CSS: these are the “presentation attributes”. The following code has the same effect as the one above, where we used the style tag:See output in new page.
It’s worth remembering this because CSS declarations for these attributes will override inline attribute definitions in the DOM. This is in turn inconsistent with the rule for the style attribute itself, which overrides CSS definitions (on behalf of whoever designed this standard: I am sorry).
Finally, SVG style attributes are not the same as HTML style attributes. For example, to color a
<div>, we would use the
background-color css attribute, but to color an SVG circle, we use the
This inconsistency is propagated to things like the HTML
title attribute, which doesn’t work in SVG, but instead you have to use a
An Ellipse is specified by position, a radius in x and a radius in y:See output in new page.
Rectangles are specified with x, y, width, and height.See output in new page.
Lines are specified using two points, (x1, y1), (x2, y2).See output in new page.
You can also specify text in SVG:See output in new page.
The SVG path element is how you “escape” the basic SVG shapes. In case none of the predefined shapes are good enough for what you’re trying to achieve, you can draw any arbitrary shape you want using the path element. We will usually not use it manually, but it’s important that you know it exists, because it helps you understand how much of D3 works under the hood.
The path element is made up of a micro language. Here are some commands:
M 10 10Moves to the position without drawing a line.
L 50 10Draws a Line from the previous position to the position specified.
Zcloses a path using a straight line to the first point.
Callows us to draw curves, specifically cubic bezier curves (there are various other curves).
The curve starts from the previous position and uses two support points (parameters) through which, in the case of the cubic bezier curve, it doesn’t go trough, and then terminates at the final point.
Beyond this one simple example that does not do the path element justice, take a look at the MDN path tutorial.
The order in which elements are drawn is the order in which they appear:See output in new page.
Grouping and Transforming
Grouping elements is a very powerful idea, and we will use it extensively when we get to use SVG for actual visualizations. It is powerful because it gives us abstraction, in the same way that a function groups a sequence of operations under a single name. In dynamic visualizations, this makes it possible for us to move a large number of elements by simply taking one branch of the DOM and placing it in a different subtree; without groups, we would have to remember over and over again which elements we cared about.
Here’s an example where we use a group to inherit presentation attributes:See output in new page.
In addition, SVG groups enable geometric transformations. Geometric transformations are amazingly useful when we want to change the positions of a large number of elements in the same way, or when we want to express the positions of the elements in a more convenient manner. For example, recall that SVG’s basic coordinate system increases the y coordinate in the downward direction. If we want to draw a scatterplot based on the example above, then we’d have to remember every time to subtract the y coordinate we want from the height of the SVG element.
This is annoying and error-prone. Instead, we could encode that transformation directly, using SVG’s transform attribute:See output in new page.
The transform attribute is read right-to-left, and it’s saying:
to get the outer y coordinate, multiply the inner y coordinate by -1 (as specified by the
scale(1, -1)), and then add 200 (as specified by
translate(0, 200)). In other words, outer_y = 200 - inner_y, which is precisely the flipping we need.
Now the y coordinates behave as we would expect them in a scatterplot: increasing y means going up.
There are also more complex transformations for rotations or distortions.
The main problem with these transformations, is that they apply to everything:See output in new page.
Clearly, we don’t want that to happen in every situation.
Complete the exercise described in this JSBin.