Geeking-out on SVG Graphics part-two
Tags: graphics, svg, javascript, css
Published: 2022-05-07 18:07:58

---
title: Geeking-out on SVG Graphics part-two
published: true
description: Hand-coding SVG graphics for pleasure
series: Geeking-out on SVG Graphics
tags: graphics, svg, javascript, css
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4llij0p4tw3zxmnmgafc.jpg
---

#Reprise
My project is to create an SVG-based backdrop in the style of a cutting mat for software engineers (well me, not really anyone else, apologies for being selfish).

As stated in the [previous post](https://dev.to/tracygjg/geeking-out-on-svg-graphics-part-one-512g), I going to start by plot a grid 4000px by 2500px with cells of 250px square and bounded with a slightly thicker rectangle. Also, as stated previously, I have chosen a background colour based on engineer's marking fluid (#191662) and a grey (#777) for the grid lines and the by-line.

I will release the cutting-mat SVG image at the end of each stage via my [GitHub](https://github.com/TracyGJG/cutting-mat) repo. 

##Plotting the grid
The top-most element of an SVG file is an `<svg>` element. SVG is based on XML and includes a reference to the default namespace (http://www.w3.org/2000/svg) and version number (1.1).

```html
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
 <!-- Content here. -->
</svg>
```

The SVG element can be nested to contain content in a  conveniently manner. As stated previously, SVG files can also reference CSS files and even JavaScript files as follows. It is also useful to stipulate the target width and height of the content as attributes of the `SVG` element.

```html
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
  width="1400" height="1000">

  <link xmlns="http://www.w3.org/1999/xhtml"
    rel="stylesheet" type="text/css"
    href="cutting-mat.css"/>

  <!-- Content here. -->

  <script href="cutting-mat.js"></script>
</svg>
```

> I have found viewing SVGs in a web browser such as Chrome or Edge to be particularly useful as the dev tools provide access to the SVG Document Object Model (DOM), along with the styles defined in the CSS file and code provided by the JS files. 

Viewing the above example will not show a great deal as the SVG element is by default transparent and the CSS and JS files we currently have provide/do nothing, so let's add a rectangular background by changing the SVG and CSS files as follows. We can even use custom properties in CSS.

```CSS
:root {
  --background-colour: #191662;
}

.backdrop {
  fill: var(--background-colour);
}
```

The backdrop will take the form of an SVG rectangle element `<rect ... />` located at the origin of the image and sized to fill the image.

```HTML
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
  width="1400" height="1000">

  <link xmlns="http://www.w3.org/1999/xhtml"
    rel="stylesheet" type="text/css"
    href="cutting-mat.css"/>

    <rect x="0" y="0" width="1400" height="1000"
      class="backdrop"></rect>
</svg>
```

##Adding the by-line
Next, I want to add a by-line in the bottom-right corner using a `<text .../>` element. By default text elements are located using the bottom-left corner of the block containing the text. This can be changed using the `text-anchor` attribute (or CSS property) to justify the text from the centre of the block, or the right as follows.

```CSS
.byline {
  fill: var(--byline-colour);
  font-size: 1.5rem;
  text-anchor: end;
}
```

We have also added another colour to the `:root` and applied it to the fill property/attribute of the text element. Also, notice we have stipulated as font-size of 1.5rem, which as the root element is using the default font-size of 16px, this will provide text of 24px in size. We can now add a text element to the SVG as follows.

```html
<text x="1380" y="980"
  class="byline">Created by T-G Gilmore, 2022, using hand-written SVG, CSS and JavaScript</text>
```

Next, I want to add an HTML link to a [creative-commons licence](https://creativecommons.org/licenses/by-nc-sa/4.0/) in the bottom-left corner, which can be achieved using the `foreignObject` element to embed the HTML in the SVG.

```html
<foreignObject x="20" y="948" width="106" height="38">
  <a xmlns="http://www.w3.org/1999/xhtml" rel="license" 
    href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
    <img alt="Creative Commons Licence" 
      src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
  </a>
</foreignObject>
```

##Time to create the grid
We will add the grid to the SVG element, contained within SVG element of the whole document, so we can size and position all related content at the same time.

```html
<svg x="60" y="60" width="1280" height="800" id="grid">
  <g>
    <!-- Horizontal and vertical lines inserted here -->
  </g>
  <g>
    <rect x="0" y="0" width="1280" height="800" class="border">
    </rect>
  </g>
</svg>
```

The containing SVG element has an `id` attribute used by the JavaScript to locate the element in the DOM. The other four attributes `x, y, width, height` control the position and size of the container. Notice the width is 1280px, which is narrower than the overall SVG, and it is positioned 60px from the left side. It is also positioned 60px from the top and 800px tall. Also notice the ratio of the width to height, 1280:800 when divided by 80px gives the 16:10 I was aiming for from the previous post.

Notice the SVG element contains two group elements `<g>`. The first group contains a comment initially but we will soon be adding JavaScript to inject the horizontal and vertical grid lines.

The second group element contains the rectangle element that bounds the lines. The rectangle (`rect` element) has a class attribute we will use to style the border and lines as follows.

```CSS
#grid rect {
  stroke: var(--grid-colour);
  stroke-width: 3;
  fill: transparent;
}

#grid line {
  stroke: var(--grid-colour);
}
```

Just link HTML, SVG has a stacking order the can be applied most easily through the order elements appear in the document. By placing the rectangle in the second group it will appear on top of the grid lines.

We will be adding the custom property `--grid-colour` to the `:root` with the value of `#777`, which is a medium grey. Now for the JavaScript, we include the following functions in the 'cutting-mat.js' file.

```JavaScript
(function () {
  drawGrid();

  // :

})();

function drawGrid() {
  const gridSize = 40;
  const grid = document.querySelector('#grid g');

  function repeatFn(occurrence, fn) {
    [...'*'.repeat(occurrence)].forEach(fn);
  }

  function drawLine(x1, y1, x2, y2, dash) {
    return `<line x1="${x1}" y1="${y1}" x2="${x2
      }" y2="${y2}" stroke-dasharray="4,${dash * 4}"></line>`;
  }

  repeatFn(16 * 2, (_, index) => {
    const vert = gridSize * index;
    grid.innerHTML += drawLine(vert, 0, vert, 800, index % 2);
  });

  repeatFn(10 * 2, (_, index) => {
    const horiz = gridSize * index;
    grid.innerHTML += drawLine(0, horiz, 1280, horiz, index % 2);
  });
}
```

I want the grid to be formed from alternating dashed and solid lines at 40px (gridSize) intervals, all injected into the first group of the #grid element (grid). To help repeat the drawing of lines I have created a helper function `repeatFn` that takes two parameters 'occurrence' and 'fn'.
* occurrence: indicates how many times the function should be performed.
* fn: is the function to be called.

Another helper function `drawLine` constructs the SVG instruction to populate the SVG `line`. Using the repeatFn function we call drawLine 32 times for the verticals and 20 times for the horizontals all using the drawLine function.

##Nearly finished with the grid
That is it for this post but there is a minor issue. The rectangle is supposed to have a line width of 3px according to the CSS. But if you have been following along you will notice the rectangle does not appear that thick. The reason is one third of the width is outside the boundary of the SVG container. We can resolve this issue by;
1. expanding the SVG by a few pixels (4px in both directions) and
2. offset the content of the SVG element by -2px in both directions.

To achieve this we first increase the width and height of the SVG element and position it -2px as follows.

```html
<svg x="58" y="58" width="1284" height="804" id="grid">
```

Next we have to remap the coordinate system within the SVG element to offset everything using the `viewBox` attribute that consists of four numeric values. The first two numbers of the 'x' and 'y' location that we will offset left and up by 1px. The last two values are the width and height that will remain unchanged from the size of the `svg` element.

```html
<svg x="58" y="58" width="1284" height="804"
   viewBox="-2 -2 1284 804" id="grid">
```

And this is how it looks so far:

![SVG Cutting mat mk1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ub7hmu6lr22rw23ycjs.png)

In the [next post](https://dev.to/tracygjg/geeking-out-on-svg-graphics-part-three-3adg) we will be rendering the screen resolutions as described in my [original post](https://dev.to/tracygjg/geeking-out-on-svg-graphics-part-one-512g).