Escaping Flatland: Isometric Art with SVG
In this Post ...
I'll expore the power of perspective through the mastry of isometry with scalable vector graphics.
Introduction
If you've ever delved into the world of technical drawings, architecture and the like you've come across isometric perspective. And almost certainly you've seen its application. Isometric style is ubiquitous in art. The intricate illusions of M.C. Escher come to mind. Not to mention an entire genre of video game art. Here, I want to step behind the visuals and explore some of the math that lies at the heart of isometry; mapping from the isometric grid to 2D coordinate systems and back again.
What is Isometric Art
Isometric art is an artistic expression that applies a method for visually representing the world of 3D objects in 2 dimensions. It leverages axonometric projection where the three coordinate axes are equally foreshortened and depth scaling is deliberately held constant to produce fascinating, and at times mind bending, views.
The heart of the art form revolves around the isometric grid. You can render this grid by rotating a square 45 degrees and squashing its height to half its width. In the resulting plane, the axes tilt away from the standard Cartesian X-axis: one leans 30 degrees upward, while the other stretches across 120 degrees. This arrangement produces the familiar three-way symmetry of isometric perspective.

Grid Formulas
If you want to create interactive art as with games and simulations you'll want to move characters and objects around your isometric "world". For that you need two key utilities; (1) mapping from the isometric grid coordinates to the SVG coordinate system, and (2) the inverse function; mapping from SVG back to the isometric grid.
Mapping the Isometric Grid to SVG
Given isometric grid coordinates, $i$ and $j$ the following equations map to SVG:
$$ \text{svgX} = ( i - j ) \times w / 2 $$
$$ \text{svgY} = ( i + j ) \times h / 2 $$
Here, $w$ is the width and $h$ is the height of the diamond shaped isometric tile.
Isometric Inverse: Mapping SVG Back to the Grid
Given the grid mapping functions we can derive the inverse to project SVG coords onto the grid. I'll spare you the algebra to derive them and jump right to the formulas: $$ i = 0.5 \times \left( \frac{\text{localX}}{(w/2)} + \frac{\text{localY}}{(h/2)} \right) $$ $$ j = 0.5 \times \left( \frac{\text{localY}}{(h/2)} - \frac{\text{localX}}{(w/2)} \right) $$
To generalize these formulas for use where isometric grids can be offset from the SVG origin we can compute $localX$ and $localY$ as follows:
- $\text{localX} = \text{svgX} - \text{offsetX}$
- $\text{localY} = \text{svgY} - \text{offsetY}$
Implementation
And here's a module that I created implementing the formulas for the SVG Artists Collective™. The module defines a world model encapsulating the mapping utilities which can be injected into sprites needing to navigate an isometric world.
/** * WorldModel module for isometric game. `WorldModel` holds * information related to world state such as tile width/height * (generally 2:1 as a rule and utility functions mapping SVG * coordinates to and from isometric *grids* comprising the * "terra firma". */ export const WorldModel = { tileWidth: 60, tileHeight: 30, /** * Get SVG coords given grid coords. isometric map assumes a * 45 degree rightward rotation of cartesian axes and 2:1 * tile width to height ... * * @param {number} i th column * @param {number} j th row */ isometricMap: function( i, j ) { const svgX = ( i - j ) * this.tileWidth / 2; const svgY = ( i + j ) * this.tileHeight / 2; return { x: svgX, y: svgY }; }, /** * Get grid coords given SVG coords. * * For more on SVG coordinate systems Please see: * * https://dr-nick-nagel.github.io/blog/trans-matrix.html * * @param {number} svgX SVG viewport coord X * @param {number} svgY SVG viewport coord Y */ svgMap: function( svgX, svgY, offesets={ x: 0, y: 0 } ) { // These formulas are derived by solving the isometricMap equations. const halfW = this.tileWidth / 2; const halfH = this.tileHeight / 2; // apply offsets to grids offset from the SVG origin... let localX = svgX - offesets.x; let localY = svgY - offesets.y; let i = 0.5 * ( localX/halfW + localY/halfH ); let j = 0.5 * ( localY/halfH - localX/halfW ); i = Math.round(i); j = Math.round(j); return { i: i, j: j }; } }
Note the use of Math.round()
in the svgMap
function which I've used to snap the SVG coordinate to the nearest grid tile.
Summary and Discussion
In this post I wanted to focus on the heart of supporting isometric views in interactive and procedural SVG artworks.
Isometric projection is used ubiquitously across many application domains including the production of technical and engineering drawings, instruction manuals and architectural design. And of course, Isometry is ubiquitous across game development frameworks.
As an artist, I find playing with isometric perspective fun and engaging. And as a cognitive scientist I've long been intrigued by the effects of isometric perspective on perception and the mind. So it was a no-brainer for me to include support for isometric applications in the SvgCC™ artists framework. Below is an example of the approach at work.
This demo was fun to create and helped guide several architectural decisions for the framework. Maybe it's the start of a new chess game. In any case, I hope you, the reader have enjoyed this study of isometric perspective and will look for more developments from the SVG Artists Collaborative in the near future!