Installation

To install React with Yarn, run:

yarn add [email protected]

To install React with npm, run:

npm install [email protected]

Hello World

A basic example to get you up and running.

import React from 'react';
import ReactDOM from 'react-dom';
import { Svg, Circle } from 'number-picture';

ReactDOM.render(
  <Svg width={400} height={400}>
    <Circle cx={200} cy={200} r={40} fill='black' />
  </Svg>
, 'body');

Shapes/Elements

Number Picture provides several shape primitives for constructing visualizations. They all render SVG by default but this can be overridden. The prop names are designed to be as similar to the API of native SVG.

Arc

Renders an arc shape using the D3 Arc generator.

import { Arc } from 'number-picture';

Usage

<Arc innerRadius={50} outerRadius={100} startAngle={0} endAngle={Math.PI} fill='black' />

Props

PropTypeDefaultDescription
innerRadiusnumberinner radius of arc
outerRadiusnumberouter radius of arc
startAnglenumberstart angle of arc in radians
endAnglenumberend angle of arc in radians
componentelement/string'path'component type that gets rendered

Area

Renders an area shape using the D3 Area generator.

import { Area } from 'number-picture';

Usage

<Area
  x={d => d.x}
  y1={d => d.y1}
  y0={80}
  points={[
    { x: 10, y1: 20 },
    { x: 30, y1: 40 },
    { x: 40, y1: 30 },
    { x: 50, y1: 70 },
    { x: 70, y1: 40 },
    { x: 90, y1: 50 },
  ]}
  fill='black'
/>
// TODO: document

AreaRadial

Renders a radial area shape using the D3 Radial Area generator.

import { RadialArea } from 'number-picture';
// TODO: document

Circle

Renders a circle.

import { Circle } from 'number-picture';

Usage

<Circle cx={100} cy={100} r={30} fill='black' />

Props

PropTypeDefaultDescription
cxnumberx position of circle center
cynumbery position of circle center
rnumbercircle radius
componentelement/string'circle'component type that gets rendered

Group

Renders a symbol shape using the D3 Symbol generator.

import { Group } from 'number-picture';

Usage

<Group transform={{ translate: [100, 50], rotate: [45] }}>
  <Rect width={50} height={10} />
</Group>

Props

PropTypeDefaultDescription
componentelement/string'g'component type that gets rendered

Line

Renders a line.

import { Line } from 'number-picture';

Usage

<Line x1={50} y1={50} x2={150} y2={150} stroke='black' strokeWidth={2} />

Props

PropTypeDefaultDescription
x1numberstarting x coordinate of line
y1numberstarting y coordinate of line
x2numberending x coordinate of line
y2numberending y coordinate of line
componentelement/string'line'component type that gets rendered

LineRadial

Renders a radial line using the D3 radial line generator.

import { LineRadial } from 'number-picture';

Usage

<LineRadial
  radius={50}
  fill="none"
  stroke='black'
  points={[
    [{ angle: 0 }],
    [{ angle: Math.PI * 0.25 }],
    [{ angle: Math.PI * 0.5 }],
    [{ angle: Math.PI * 0.75 }],
    [{ angle: Math.PI }],
    [{ angle: Math.PI * 1.25 }],
    [{ angle: Math.PI * 1.5 }],
    [{ angle: Math.PI * 1.75 }],
    [{ angle: Math.PI * 2 }],
  ]}
  strokeWidth={4}
/>

Props

PropTypeDefaultDescription
pointsarrayarray of points
anglenumber/func(point) => point[0]either a number setting the angle for each point or an accessor function to get the angle from each point
radiusnumber/func(point) => point[1]either a number setting the radius for each point or an accessor function to get the radius from each point
componentelement/string'path'component type that gets rendered

Rect

Renders a rectangle.

import { Rect } from 'number-picture';

Usage

<Rect x={100} y={100} width={200} height={300} fill='black' />

Props

PropTypeDefaultDescription
xnumberx position of rectangle
cynumbery position of rectangle
widthnumberrectangle width
heightnumberrectangle height
componentelement/string'rect'component type that gets rendered

Ribbon

Renders a ribbon using the D3 Ribbon generator.

import { Ribbon } from 'number-picture';

Usage

<Ribbon fill='black' />

Props

PropTypeDefaultDescription
sourceTODO
targetTODO
radiusTODO
startAngleTODO
endAngleTODO
componentelement/string'path'component type that gets rendered

Svg

Renders an Svg element.

import { Svg } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <circle r='100' cx='200' cy='200' />
</Svg>

Props

PropTypeDefaultDescription
patternsTODO
componentelement/string'svg'component type that gets rendered

SymbolShape

Renders a symbol shape using the D3 symbol generator.

import { SymbolShape } from 'number-picture';

Usage

<SymbolShape size={500} type='symbolCross' fill='black' />

Props

PropTypeDefaultDescription
sizenumberarea of SymbolShape shape
typestringname of D3 SymbolShape generator function. Possible values: 'symbolShapeCircle', 'symbolShapeCross', 'symbolShapeDiamond', 'symbolShapeSquare', 'symbolShapeStar', 'symbolShapeTriangle', 'symbolShapeWye'
componentelement/string'path'component type that gets rendered

Text

Renders text.

import { Text } from 'number-picture';

Usage

<Text dx={100} stroke='black'>Lorem ipsum</Text>

Props

PropTypeDefaultDescription
componentelement/string'text'component type that gets rendered

Layouts

The purpose of Layouts is to combine the Shapes/Elements above with datasets and enable declarative animations.

Most Layouts add useful metadata to the input data in useful ways and pass it on to the children.

For example the Pie Layout will calculate metadata from the input dataset like start- and end angles for each arc and pass it on to the children (along with the original data) in order to draw a pie chart.

Chord

Renders a D3 Chord layout.

import { Chord } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Chord
    data={[
      [11975, 5871, 8916, 2868],
      [1951, 10048, 2060, 6171],
      [8010, 16145, 8090, 8045],
      [1013, 990, 940, 6907],
    ]}
    animate
    nodeEnter={d => ({
      ...d,
      sourceStartAngle: d.sourceEndAngle,
      targetStartAngle: d.targetEndAngle,
    })}
  >{nodes => nodes.map((node, i) => (
    <Ribbon
      {...node}
      fill="black"
      stroke="black"
      fillOpacity={0.9}
      radius={height * 0.4}
      transform={{ translate: [200, 200] }}
    />
  ))}</Chord>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node has `source`, `target`, `key` and `data` properties. The `data` property value resembles the original input datum. Must return a valid React node.
padAngleTODO
sortGroupsTODO
sortSubgroupsTODO
sortChordsTODO
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Cluster

Renders a D3 Cluster layout.

import { Cluster } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Group transform={{ translate: [40, 80] }}>
    <Cluster
      data={{
        children: [
          {
            value: 10,
            key: '1',
            children: [
              { value: 1, key: '1a1' },
              { value: 2, key: '1a2' },
              {
                value: 3,
                key: '1a3',
                children: [
                  { value: 0.1, key: '1b1' },
                  { value: 0.2, key: '1b2' },
                ],
              },
            ],
          },
          {
            value: 20,
            key: '2',
            children: [
              { value: 1, key: '2a1' },
              { value: 2, key: '2a2' },
              {
                value: 3,
                key: '2a3',
                children: [
                  { value: 0.1, key: '2b1' },
                  { value: 0.2, key: '2b2' },
                ],
              },
            ],
          },
        ],
      }}
      size={[240, 320]}
      nodeEnter={d => ({ ...d, x: 200, y: 200 })}
      animate
    >{nodes => nodes.map(({ key, x, y }) => (
      <Circle
        key={key}
        cx={y}
        cy={x}
        r={10}
        fill="black"
      />
    ))}</Cluster>
  </Group>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node has `x`, `y`, key` and `data` properties. The `data` property value resembles the original input datum. Must return a valid React node.
separationTODO
sizeTODO
nodeSizeTODO
includeRootTODO
sumTODO
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Collection

Generic Layout component for animating datasets.

import { Collection } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Collection
    data={[
      { x: 10, key: '1' },
      { x: 50, key: '2' },
      { x: 100, key: '3' },
      { x: 250, key: '4' },
    ]}
  >{nodes => nodes.map(({ key, x }) => (
    <Circle key={key} r={10} cx={x} cy={200} />
  ))}</Collection>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node has the same properties as the corresponding datum from the input `data` prop. Must return a valid React node.
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Grid

Renders a grid layout using the d3-v4-grid library.

import { Grid } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Grid
    data={[
      { value: 1, key: '1' },
      { value: 2, key: '2' },
      { value: 3, key: '3' },
      { value: 4, key: '4' },
      { value: 5, key: '5' },
      { value: 6, key: '6' },
      { value: 7, key: '7' },
      { value: 8, key: '8' },
      { value: 9, key: '9' },
      { value: 10, key: '10' },
    ]}
    bands
    size={[400, 400]}
    nodeEnter={d => ({ ...d, x: 200, y: 200 })}
    animate
  >{nodes => nodes.map(({ nodeWidth, nodeHeight, x, y, key, value }) => (
    <Circle
      key={key}
      cx={x + nodeWidth / 2}
      cy={y + node200}
      r={value}
      fill="black"
    />
  ))
  }</Grid>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node has `nodeWidth`, `nodeHeight`, `x`, `y`, `value`, `key` and `data` properties. The `data` property value resembles the original input datum. Must return a valid React node.
bandsbooleanfalseconfigure the grid to treat nodes as bands instead of points
sizearray[1, 1]set overall dimensions of layout
nodeSizearraysets the size of all individual nodes
rowsnumberfixes the layout to a certain number of rows
colsnumberfixes the layout to a certain number of columns
paddingarray [x, y]sets the padding between the node bands. `x` and `y` are relative to the band width/height, similar to the padding parameter of `d3.scale.ordinal().rangeBands()`. If nodeSize prop is set, padding is absolute
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Pack

Renders a D3 Pack layout.

import { Pack } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Pack
    data={{
      children: [
        { value: 1, key: '1' },
        { value: 2, key: '2' },
        { value: 3, key: '3' },
      ],
    }}
    sum={datum => datum.value}
    size={[400, 400]}
    includeRoot={false}
    nodeEnter={d => ({ ...d, r: 0 })}
    animate
  >{nodes => nodes.map(({ x, y, r, key }) => (
    <Circle
      key={key}
      cx={x}
      cy={y}
      r={r}
      fill="black"
    />
  ))}</Pack>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node has `x`, `y`, `r`, key` and `data` properties. The `data` property value resembles the original input datum. Must return a valid React node.
radiusTODO
sizeTODO
paddingTODO
includeRootTODO
sumTODO
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Partition

Renders a D3 Partition layout.

import { Partition } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Partition
    data={{
      children: [
        { value: 1, key: '1' },
        { value: 2, key: '2' },
        {
          value: 0,
          key: '3',
          children: [
            { value: 1, key: 'a1' },
            { value: 2, key: 'a2' },
            {
              value: 0,
              key: 'a3',
              children: [
                { value: 1, key: 'b1' },
                { value: 2, key: 'b2' },
                {
                  value: 3,
                  key: 'b3',
                },
              ],
            },
          ],
        },
      ],
    }}
    sum={datum => datum.value}
    size={[400, 400]}
    nodeEnter={d => ({ ...d, r: 0 })}
    animate
  >{nodes => nodes.map(({ key, x0, y0, x1, y1 }) => (
    <Rect
      key={key}
      x={x0}
      y={y0}
      width={x1 - x0}
      height={y1 - y0}
      fill="black"
      stroke="white"
    />
  ))}</Partition>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node has `x0`, `y0`, `x1`, `y1`, `key` and `data` properties. The `data` property value resembles the original input datum. Must return a valid React node.
separationTODO
sizeTODO
roundTODO
includeRootTODO
sumTODO
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Pie

Renders a D3 Pie layout.

import { Pie } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Pie
    data={[
      { id: 1, key: '1', value: 1 },
      { id: 2, key: '2', value: 2 },
      { id: 3, key: '3', value: 3 },
    ]}
    value={datum => datum.value}
    id={datum => datum.id}
    sort={(a, b) => a.id - b.id}
    nodeEnter={d => ({ ...d, startAngle: d.endAngle })}
    animate
  >{nodes => nodes.map(({ startAngle, endAngle, key }) => (
    <Arc
      key={key}
      innerRadius={0}
      outerRadius={100}
      startAngle={startAngle}
      endAngle={endAngle}
      fill="black"
      stroke="white"
      strokeWidth={1}
    />
  ))}</Pie>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node has `startAngle`, `endAngle`, `key` and `data` properties. The `data` property value resembles the original input datum. Must return a valid React node.
valueTODO
sortTODO
sortValuesTODO
startAngleTODO
endAngleTODO
padAngleTODO
idTODO
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Stack

Renders a D3 Stack layout.

import { Stack } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Stack
    data={[
      { a: 0.1, b: 0.1, c: 0.2, key: '1' },
      { a: 0.2, b: 0.1, c: 0.2, key: '2' },
      { a: 0.3, b: 0.1, c: 0.2, key: '3' },
    ]}
    keys={['a', 'b', 'c']}
    animate
  >{nodes => nodes.map((node, i) => (
    <Group transform={{ rotate: [180, 200, 200] }} key={node.key}>
      <Rect
        x={40}
        y={node[0][0] * 400}
        width={80}
        height={(node[0][1] - node[0][0]) * 400}
        fill="black"
        stroke="white"
      />
      <Rect
        x={160}
        y={node[1][0] * 400}
        width={80}
        height={(node[1][1] - node[1][0]) * 400}
        fill="black"
        stroke="white"
      />
      <Rect
        x={280}
        y={node[2][0] * 400}
        width={80}
        height={(node[2][1] - node[2][0]) * 400}
        fill="black"
        stroke="white"
      />
    </Group>
  ))}</Stack>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node is a series returned for the D3 Stack generator with additional `key` and `data` properties. The `data` property value resembles the original input datum. Must return a valid React node.
valueTODO
keysTODO
orderTODO
offsetTODO
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Treemap

Renders a D3 Treemap layout.

import { Treemap } from 'number-picture';

Usage

<Svg width={400} height={400}>
  <Treemap
    data={{
      children: [
        { value: 10, key: '1' },
        { value: 20, key: '2' },
        {
          value: 30,
          key: '3',
          children: [
            { value: 1, key: 'a1' },
            { value: 2, key: 'a2' },
            {
              value: 3,
              key: 'a3',
              children: [
                { value: 0.1, key: 'b1' },
                { value: 0.2, key: 'b2' },
                {
                  value: 0.3,
                  key: 'b3',
                },
              ],
            },
          ],
        },
      ],
    }}
    sum={datum => datum.value}
    size={[400, 400]}
    nodeEnter={d => ({ ...d, r: 0 })}
    animate
  >{nodes => nodes.map(({ key, x0, y0, x1, y1 }) => (
    <Rect
      key={key}
      x={x0}
      y={y0}
      width={x1 - x0}
      height={y1 - y0}
      fill="black"
      stroke="white"
    />
  ))}</Treemap>
</Svg>

Props

PropTypeDefaultDescription
data (required)array of objectsdata that gets optionally animated and passed on to children. Each datum must have a unique `key` property.
children (required)funcFunction as Child that recieves one param: `nodes`. Each node has `x0`, `y0`, `x1`, `y1`, `key` and `data` properties. The `data` property value resembles the original input datum. Must return a valid React node.
tileTODO
sizeTODO
roundTODO
paddingTODO
paddingInnerTODO
paddingOuterTODO
paddingTopTODO
paddingRightTODO
paddingBottomTODO
paddingLeftTODO
includeRootTODO
sumTODO
animatebooleananimate children values on enter, update and exit
nodeEnterfunc(datum) => datumaccessor function for getting a datum before it enters - used for animations. TODO: document `datum` signature
nodeExitfunc(datum) => datumaccessor function for getting a datum before it exits - used for animations. TODO: document `datum` signature
componentelement/string'g'component type that wraps children

Guides

These guides cover specific goals or features you might want to implement when working with NumberPicture.

Transforms

All elements can have transforms applied to them like translations, rotations, and so forth.

Every element/shape component accepts a transform prop which can either be an object or an array.

Object example:

<Group transform={{
  translate: [10, 20],
  rotate: [180, 50, 50],
  skewX: [20],
  skewY: [40],
  matrix: [1, 2, 3, 4, 5, 6],
  scale: [10, 20],
}} />

Array example:

<Group transform={[
  { type: 'translate': value: [10, 20] },
  { type: 'rotate': value: [90, 50, 50] },
  { type: 'skewX': value: [20] },
  { type: 'skewY': value: [40] },
  { type: 'matrix': value: [1, 2, 3, 4, 5, 6] },
  { type: 'scale': value: [10, 20] },
]} />

If you use the array syntax multiple transforms of the same type can be applied. Transforms are applied in the order from last to first.