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.

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;

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;

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;

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.

Discord Logo

Code Daily Discord

Join our community and get help with React, React Native, and all web technologies. Even recommend tutorials, and content you want to see.