React

React Art and Paths.js

Intro

Paths.js is a cool library. It comes with 3 levels of generating paths.

  • Low level which helps you generate paths/lines.
  • Mid level which generates paths for shapes
  • High level which takes a set of data and generates graphs

All of these are great when working with react-art because it's just returning data. I'll say it once, and a million more but libraries that just generate data make it easy to traverse and render with react-art.

<!-- more -->

Paths

UPDATE:

Sebastian Markbage (the creator of ReactART and ART), informed me that ReactART itself has a Path implementation. I realized this but didn't think much of it. However per the discussion here https://discuss.reactjs.org/t/react-art-with-paths-js/492 the ART path is faster as it takes advantage of the current mode to create the most efficient path instead of taking a string and converting it back into native for instructions for canvas rendering.

The ReactART.Path has similar methods. Check out the discuss thread for a link to the implementation to find out the supported methods. I'm currently working on ReactART documentation so expect that soon.

Example:

var path = Path()
  .moveto(10, 20)
  .lineto(30, 50)
  .lineto(25, 28)
  .qcurveto(27, 30, 32, 27)
  .closepath();

This is can just be plugged right into react-art Shape element.

Like so

var React = require('react'),
	ReactArt = require('react-art'),
	Surface = ReactArt.Surface,
	Shape = ReactArt.Shape,
	Path = require('paths-js/path');

var Demo = React.createClass({
	getInitialState: function() {
		return {
			to: {
				x: 30,
				y: 50
			}
		}
	},
	getPath: function() {
		var path = Path()
					  .moveto(10, 20)
					  .lineto(this.state.to.x, this.state.to.y)
					  .lineto(25, 28)
					  .qcurveto(27, 30, 32, 27)
					  .closepath();

	 	return path.print();
	},
	startAnimating: function() {

		if (this.state.to.x === 100) {
			this.addToPosition = -1;
		} else if (this.state.to.x === 29) {
			this.addToPosition = 1;
		}

		this.state.to.x += this.addToPosition;
		this.state.to.y += this.addToPosition;

		this.setState(this.state);
	},
	componentDidMount: function() {
		this.addToPosition = 1;
		setInterval(this.startAnimating, 17)
	},
	render: function() {
		return (
			<div>
				<Surface
					width={500}
					height={500}
				>
					<Shape d={this.getPath()} stroke="#000" strokeWidth={1} />
				</Surface>
			</div>
		)
	}
});

module.exports = Demo;
<p data-height="624" data-theme-id="0" data-slug-hash="VLmOOE" data-default-tab="result" data-user="browniefed" class='codepen'>See the Pen <a href='http://codepen.io/browniefed/pen/VLmOOE/'>VLmOOE</a> by Jason Brown (<a href='http://codepen.io/browniefed'>@browniefed</a>) on <a href='http://codepen.io'>CodePen</a>.</p> <script async src="//assets.codepen.io/assets/embed/ei.js"></script>

Simple Shapes

Now react-art already comes with a few different shapes but paths.js have a few built in as well, like Rectangle and Bezier curve.

var rectangle = Rectangle({
  top: 10,
  bottom: 3,
  left: -2,
  right: 5
});

And how that looks is very similar to the previous example

var React = require('react'),
	ReactArt = require('react-art'),
	Surface = ReactArt.Surface,
	Group = ReactArt.Group,
	Shape = ReactArt.Shape,
	Rectangle = require('paths-js/rectangle'),
	Bezier = require('paths-js/bezier');

var Demo = React.createClass({
	getPath: function() {
		var rectangle = Rectangle({
					  top: 10,
					  bottom: 3,
					  left: -2,
					  right: 5
					});

	 	return rectangle.path.print();
	},
	getBez: function() {
		var points = [[1, 50], [50, 100], [100, 3], [4, 0]];
		var curve = Bezier({
		  points: points,
		  tension: 0.2
		});

		return curve.path.print();
	},
	render: function() {
		return (
			<div>
				<Surface
					width={500}
					height={500}
				>
					<Group x={100} y={100}>
						<Shape d={this.getPath()} stroke="#000" strokeWidth={1} />
					</Group>
					<Group x={200} y={200}>
						<Shape d={this.getBez()} stroke="#000" strokeWidth={1} />
					</Group>
				</Surface>
			</div>
		)
	}
});

module.exports = Demo;
<p data-height="624" data-theme-id="0" data-slug-hash="xGRNvW" data-default-tab="result" data-user="browniefed" class='codepen'>See the Pen <a href='http://codepen.io/browniefed/pen/xGRNvW/'>xGRNvW</a> by Jason Brown (<a href='http://codepen.io/browniefed'>@browniefed</a>) on <a href='http://codepen.io'>CodePen</a>.</p> <script async src="//assets.codepen.io/assets/embed/ei.js"></script>

Graphs

var pie = Pie({
  data: [
    { name: 'Italy', population: 59859996 },
    { name: 'Mexico', population: 118395054 },
    { name: 'France', population: 65806000 },
    { name: 'Argentina', population: 40117096 },
    { name: 'Japan', population: 127290000 }
  ],
  accessor: function(x) { return x.population; },
  compute: {
    color: function(i) { return somePalette[i]; }
  },
  center: [20, 15],
  r: 30,
  R: 50
});

Some code of it in action

var React = require('react'),
	ReactArt = require('react-art'),
	Surface = ReactArt.Surface,
	Group = ReactArt.Group,
	Shape = ReactArt.Shape,
	Pie = require('paths-js/Pie');


var pie = Pie({
  data: [
    { name: 'Italy', population: 59859996 },
    { name: 'Mexico', population: 118395054 },
    { name: 'France', population: 65806000 },
    { name: 'Argentina', population: 40117096 },
    { name: 'Japan', population: 127290000 }
  ],
  accessor: function(x) { return x.population; },
  compute: {
    color: function(i) { return '#000'; }
  },
  center: [20, 15],
  r: 30,
  R: 50
});

var Demo = React.createClass({

	getPie: function() {
		return pie.curves.map(function(shape) {
			return (
				<Group>
					<Text fill="#A6BD8A" font='bold 12px "Arial"' x={shape.sector.centroid[0] - 12} y={shape.sector.centroid[1]}>{shape.item.name}</Text>
					<Shape d={shape.sector.path.print()} stroke={shape.color} strokeWidth={1} />
				</Group>
			)
		})
	},
	render: function() {
		return (
			<div>
				<Surface
					width={500}
					height={500}
				>
					<Group x={50} y={45}>
						{this.getPie()}
					</Group>
				</Surface>
			</div>
		)
	}
});


module.exports = Demo;
<p data-height="624" data-theme-id="0" data-slug-hash="waoLvB" data-default-tab="result" data-user="browniefed" class='codepen'>See the Pen <a href='http://codepen.io/browniefed/pen/waoLvB/'>waoLvB</a> by Jason Brown (<a href='http://codepen.io/browniefed'>@browniefed</a>) on <a href='http://codepen.io'>CodePen</a>.</p> <script async src="//assets.codepen.io/assets/embed/ei.js"></script>

Conclusion

These examples may look boring but they just show off a bit of the control you can have with react-art and a simple path generator. Not only that but because we aren't depending on the DOM in any case these examples should also work on react-native. Combined with some tweening you could make some very effective graphs that animate. That is a topic for another time.

Liked this content?

Get notified more about React!

No Spam! We Promise!

Related Content

Custom Handling the Android Back Button with React Navigation

In this lesson we'll explore setting up a stack navigator in React Navigation. We'll create a custom component that uses withNavigation to allow us to listen to navigation transitions. Using the BackHandler from React Native we can ask the screen if custom needs are required when the hardware back button is pressed. Finally we'll prompt the user if they want to navigate.

Conditional JavaScript Callbacks with Reanimated in React Native

In this lesson we'll explore how to setup a draggable circle. Then we'll dive into using the call method to create JavaScript callbacks whenever certain conditions are met inside of Reanimated.

Test Successful Async Form Submissions with React Router

In this lesson we'll explore how to test that an async form submission successfully happened using Jest. We'll also take advantage of react-testing-library to render our react components to a fake dom. We'll use MemoryRouter to mock what a browser would normally do in the event of a transition, and create a fake component route to confirm that the submission successfully redirected us to the url we wanted.

Custom Handling the Android Back Button with React Navigation

In this lesson we'll explore setting up a stack navigator in React Navigation. We'll create a custom component that uses withNavigation to allow us to listen to navigation transitions. Using the BackHandler from React Native we can ask the screen if custom needs are required when the hardware back button is pressed. Finally we'll prompt the user if they want to navigate.