D3 Building Blocks #3: SVG Shapes and Attributes
Tags: d3, javascript, svg, codenewbie
Published: 2020-12-01 15:04:44

Now that we've had an introduction to using D3 methods to represent HTML elements and CSS styling, it's time to explore Scalable Vector Graphics, or SVGs. In this post, we'll move beyond manipulating and styling text elements, and start to explore creating visual elements using lines and shapes.

# Scalable Vector Graphics (SVGs)

A common issue that arises when working with images is scaling. We've all had the experience of trying to enlarge a photo or other image, only to have the resolution become blurry as it gets larger. This happens because most image files are based on pixels, and the number of pixels does not increase when we try to make it bigger, so the enlarged version looks less detailed. Scalable Vector Graphics, or SVGs, are images that are based on drawn paths in the HTML, rather than a collection of pixels. As a result, the quality or resolution of the image remains high even when it is enlarged.

## The `<svg>` Element

In order to create an SVG, we can place an `<svg>` tag within our HTML code, or use our new D3 methods to create and append an `<svg>` element to the DOM. 

Example 1: `<svg>` in HTML
```html
<body>
  <svg>
    // contents of svg
  </svg>
</body>
```

Example 2: `<svg>` in D3
```javascript
d3.select("body")
  .append("svg")
```

## Attributes for the `<svg>`
The `<svg>` element is basically just a canvas, or drawing space within the DOM. We can set its viewport size by assigning values for the height and width properties, in pixels. 

The `<svg>` coordinate plane has a horizontal x-axis, which starts at 0 at on the left and increments upwards to the right. The y-axis is vertical and starts at 0 at the top and increments up as you move downwards (*this may feel counter-intuitive at first*).

```html
<body>
  <svg height="500" width="900">
    // contents of svg
  </svg>
</body>
// this svg element has a height of 500px and a width of 900px, and is located at the top left corner of the document
```

The height and width attributes can also be set using the D3 `attr()` method:
```javascript
d3.select("svg")
  .attr("height", 500)
  .attr("width", 900)
```

A common convention, however, is to set the height and width as constants, and then pass the variable to set the value of these attributes. This makes it easier to make adjustments, since only the values of the constants need to be modified.
```javascript
const height = 500
const width = 900

d3.select("svg")
  .attr("height", height)
  .attr("weight", weight)
```

# Drawing Shapes 

Once we have an `<svg>` element in the DOM, we can start drawing shapes within it. Below, we'll explore some of the most common shapes, and how to set their size and position through their attributes.

## Circle
To draw a circle, we use the `<circle>` tag. To set the position of our circle on the `<svg>`, we can set the `cx` and `cy` attributes. If we do not specify these attributes, the center of the circle will be placed at the x=0, y=0 position on the `<svg>` canvas. To set the radius, we can set the `r` attribute. 

```html
<body>
  <svg>
    <circle cx="50" cy="30" r="10"></circle>
  </svg>
</body>
```
OR using D3 code:

```javascript
d3.select("svg")
  .append("circle")
  .attr("cx", 50)
  .attr("cy", 30)
  .attr("r", 10)
```

## Rectangle
We can draw rectangles by using the `<rect>` tag, and set the rectangle size using the `width` and `height` attributes, and set the position using the `x` and `y` attributes.

```html
<body>
  <svg>
    <rect x="100" y="30" width="20" height="10"></rect>
  </svg>
</body>
```

OR using D3 code:

```javascript
d3.select("svg")
  .append("rect")
  .attr("x", 100)
  .attr("y", 30)
  .attr("width", 20)
  .attr("height", 10)
```
## Line 
We can draw lines by using the `<line>` tag, and specifying the x and y coordinates of the endpoints of the line, as well as the stroke color.

```html
<svg>
  <line x1="0" y1="0" x2="100" y2="100" stroke="red"></line>
</svg>
```

OR using D3 code:

```javascript
d3.select("svg")
  .append("line")
  .style("stroke", "red")
  .attr("x1", 0)
  .attr("y1", 0) 
  .attr("x2", 100) 
  .attr("y2", 100)
```

## Path
In SVG, a path is simply a collection of connected lines. To create a path, we can use the `<path>` tag and set the `d` attribute to specific the exact path of the line. The `d` attribute is a string that starts with an M (Move To), followed by the x and y coordinates of the starting point of the path. It is then followed by an L (Line To), and the x and y coordinates of the end point of the first line. We can then continue to add x and y coordinate pairs to create additional segments until the path is complete. 

```html
<svg>
  <path d="M100 50 L75 25 L100 0" stroke="green" fill="none"></path>
</svg>
```

OR using D3 code:

```javascript
d3.select("svg")
  .append("path")
  .style("stroke", "green")
  .attr("d", "M100 50 L75 25 L100 0")

// path starts at 100,50
// then draws a line segment from 100,50 to 75,25
// then draws a line segment from 75,25 to 100,0
```

Read the [SVG documentation](https://developer.mozilla.org/en-US/docs/Web/SVG) to learn more about Scalable Vector Graphics elements and attributes.

- [SVG Elements](https://developer.mozilla.org/en-US/docs/Web/SVG/Element)
- [SVG Attributes](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute)