21st June, 2015

SVG with React

I’ve been using ReactJS for about 6 months now and have been very happy with my experience as a developer. I never considered it for generative art because it just seemed like a needlessly complex approach. Then I came across projects such as Flipboard’s react-canvas and React Art which made me reconsider this opinion. I love the idea of being able to build small isolated reusable components. Then use them to compose complex systems.

More recently I came across Brent Jackson’s fantastic tutorial on Building SVG Icons with React. Not sure about everyone else but, I prefer the Canvas API to that of SVG. The SVG syntax for constructing shapes just seems extremely complicated and then having to manipulate them in JS is even more painful. The upside of SVG however is that it’s part of the DOM. You can mix it with other parts of the DOM in more ehm real world scenarios.

With React you can compose a complex SVG images inside out — without having to worry about DOM manipulation. Every time state changes the document is re-rendered. Therefore, the SVG element updates to reflect this new state too.

I was really inspired by Brent’s tutorial and just had to try this out myself. The first thing I built was a Tetrahedron Generator. Fairly straightforward, not the most complex geometry in the world. You can find the source code here: github.com/winkerVSbecks/react-tetrahedrons.

It was really fast to build and this weird SVG syntax didn’t seem that weird any more. The next step was to build something a bit more complex… a Fermat point calculator. This required a bit more thinking but that was mostly because of geometry and math rather than SVG or React.

Let’s look at an example of a component. I needed to build an SVG circle and then allow the user to click and drag it around. I started by creating a new component called Handle. Here’s the template for it:

<circle
  className="handle"
  id={ this.props.id }
  cx={ this.props.x }
  cy={ this.props.y }
  fill={ clrs.yellow }
  onMouseDown={ this.selectElement }
  onMouseMove={ this.drag }
  onMouseUp={ this.deSelectElement }
  onMouseLeave={ this.deSelectElement } />

The logic for clicking and dragging and all the event handlers are isolated within this component itself. However, you can still pass in callbacks. This allows you to capture the drag and respond to it. Here’s an example of how you would use the Handle component:

<Handle
  x={ pt[0] }
  y={ pt[1] }
  id={ idx }
  onUpdate={ dragUpdate } />

In the long term I hope to extend this ideology to Canvas. The idea is to build a library of such components with React. Each component would then be rendered to Canvas using PaperJS.