Based on material by Carlos Scheidegger and Kevin Sun

So far we have only seen textual content in HTML, but this is a data visualization course. SVG (“Scalable Vector Graphics”) is a subset of the HTML5 standard that will provide us with essentially all of our graphical needs. SVG is extremely powerful, broadly supported, and very easy to program for. It’s also the preferred target for D3, the javascript library we’ll use for our visualization design.

Alternative methods for bringing dynamic graphics to your browser are Canvas and WebGL, which we unfortunately won’t be tackling.

Minimal Example

An SVG drawing starts with an <svg> element, which requires width and height attributes, specified in pixels:

See output in new page.

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.

Circle

Circles have an x (cx) and a y (cy) position specifying the center point, in addition to a radius (r).

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.

Coordinate System

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.

Presentation Attributes

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 fill attribute.

This inconsistency is propagated to things like the HTML title attribute, which doesn’t work in SVG, but instead you have to use a title element:

See output in new page.

Ellipse

An Ellipse is specified by position, a radius in x and a radius in y:

See output in new page.

Rectangle

Rectangles are specified with x, y, width, and height.

See output in new page.

Lines

Lines are specified using two points, (x1, y1), (x2, y2).

See output in new page.

Text

You can also specify text in SVG:

See output in new page.

Path

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 10 Moves to the position without drawing a line.
  • L 50 10 Draws a Line from the previous position to the position specified.
  • Z closes a path using a straight line to the first point.
  • C allows us to draw curves, specifically cubic bezier curves (there are various other curves).
See output in new page.

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.

Ordering

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.

Exercise

Complete the exercise described in this JSBin.