NUD3
Nud3 built in demo can be viewed at https://nuvi.github.io/nud3
Nud3 is a composable charting/graph library for React utilizing D3.
It is super opinionated and not very opinionated at the same time.
It utilizes React's cloneElement for prop injection, that way you don't need to pass the data to each component for your graph.
We do this, so composing charts is declarative and obvious. You say what you want and nothing more.
Nud3's base render is called "Chart" (super clever we know). It makes some assumptions about your data and scales then renders its children, by injecting the
denormalized data into each child, which should all have one purpose. An x-axis, y-axis, and line chart renderer should all be separate components making your
"BasicLineChart".
BasicLineChart.js
You'll notice in this example, attributes that belong to only the AxisBottom, are the only to receive those options.
import React from 'react';
import PropTypes from 'prop-types';
import {
Chart,
LineChart,
AxisBottom,
AxisLeft,
} from 'nud3';
export default function BasicLineChart (props) {
return (
<Chart
className="basic-line-chart"
data={ props.data }
xKey="date"
valueKeys={ props.valueKeys }
height={ 300 }
paddingLeft={ 30 }
paddingBottom={ 50 }
>
<AxisLeft />
<AxisBottom textTransform="rotate(-45)" textDy="-0.25em" textDx="-0.75em" />
<LineChart transitionDuration={ 400 } transitionDelay={ 100 } />
</Chart>
);
}
BasicLineChart.propTypes = {
data: PropTypes.array,
valueKeys: PropTypes.array,
};
What does Nud3 have?
We try to include plenty of the basic to setup your own charts without much work, while not doing it all for you. Here are some of the charts we have.
Charts
- AreaChart
- BarChart
- BubbleChart
- ChoroplethMap
- LineChart
- PieChart
- RangeSelector
- Scatterplot
- TreeMapChart
- WebChart
Axes
- AxisBottom
- AxisLeft
- AxisTop
- AxisRight
- HorizontalHoverBar
- Nested child becomes Tooltip
- VerticalHoverBar
- Nested child becomes Tooltip
Data Manipulators
- createHierarchyData
- data - (array) Array of data
- parentIdAttribute - (string) Attribute of the parent id. Example is parentIdAttribute = 'parent' for { name: 'WhatsApp', parent: 'Facebook' }.
- idAttribute - (string) Attribute of id, to match against. Example is idAttribute = 'id' for { name: 'Facebook, Inc', id: 'Facebook' }.
- PadDataBetweenDates
- startDate - (Date) Beginning Date to Start Padding
- endDate - (Date) End Date to pad to
- dateInterval - (String) hour, day, month, year - A moment.js compatible interval
- padWith - (Any) object to pad the data with, defaults to
{}
Animators
- HorizontalCurtain
- VerticalCurtain
Creating your own chart
Nud3's base Chart does a lot of heavy lifting to setup charts and create denormalized data from normalized data. If you nest your custom component into a <Chart />
it will clone it and inject a few props for you, but will keep your original props too:
- areaWidth - (number) The width of the area to render, it takes in account for the Chart's width minus the left and right padding.
- areaHeight - (number) The height of the area to render, it takes in account for the Chart's height minus the top and bottom padding.
- paddingTop - (number) The top padding of the graph. Typically you transform your graph down this much.
- paddingLeft - (number) The left padding of the graph. Typically you transform your graph over this much.
- paddingRight - (number) The right padding of the graph. Typically you can ignore since SVG is a top-left render.
- paddingBottom - (number) The bottom padding of the graph. Typically you can ignore since SVG is a top-left render.
- originalData - (array) The original data passed as the prop
data
to the <Chart>
- chartData - (array) The denormalized data, based on valueKeys. So if you have 2 value keys, this will be an array, with two arrays.
- valueKeys - (array) Array of strings, that are attributes of the originalData datum. This helps build out the yScale.
- xKey - (string) A single string that represents an attribute that is originalData datum. This helps build out the xScale.
- classNamePrefix - (string) the class name given to the
<Chart>
, use this for prefixing your custom chart if you want. - DEBUG - (bool) if the DEBUG prop was sent to the
<Chart>
this will be true.
These valueKeys are interesting, explain how they work
So lets say you have a valueKeys of ['total_users']
and the data you pass to the is:
[
{ name: 'Facebook', total_users: 1600 },
{ name: 'Twitter', total_users: 360 },
{ name: 'Pinterest', total_users: 153 }
]
It will generate the following denormalized structure:
[
[
{
yValue: 1600,
yKey: 'total_users',
original: { name: 'Facebook', total_users: 1600 }
},
{
yValue: 360,
yKey: 'total_users',
original: { name: 'Twitter', total_users: 360 }
},
{
yValue: 153,
yKey: 'total_users',
original: { name: 'Pinterest', total_users: 153 }
}
]
]
This is helpful for things like PieGraphs, TreeMaps, ChoroplethMaps.
But for LineCharts and BarCharts, we need to provide an xKey to build that xAxis out, so if you provided the valueKeys of ['total_users']
and the xKey of 'name' you would end up with:
[
[
{
yValue: 1600,
yKey: 'total_users',
xValue: 'Facebook',
xKey: 'name',
original: { name: 'Facebook', total_users: 1600 }
},
{
yValue: 360,
yKey: 'total_users',
xValue: 'Twitter',
xKey: 'name',
original: { name: 'Twitter', total_users: 360 }
},
{
yValue: 153,
yKey: 'total_users',
xValue: 'Pinterest',
xKey: 'name',
original: { name: 'Pinterest', total_users: 153 }
}
]
]
And one more example where you want a LineGraph with two lines, you would provide it with two valueKeys like ['total_users', 'market_cap']
[
{ name: 'Facebook', total_users: 1600, market_cap: 400.8 },
{ name: 'Twitter', total_users: 360, market_cap: 11.3 },
{ name: 'Pinterest', total_users: 153, market_cap: 11 }
]
Will create a chartData prop of:
[
[
{
yValue: 1600,
yKey: 'total_users',
xValue: 'Facebook',
xKey: 'name',
original: { name: 'Facebook', total_users: 1600, market_cap: 400.8 }
},
{
yValue: 360,
yKey: 'total_users',
xValue: 'Twitter',
xKey: 'name',
original: { name: 'Twitter', total_users: 360, market_cap: 11.3 }
},
{
yValue: 153,
yKey: 'total_users',
xValue: 'Pinterest',
xKey: 'name',
original: { name: 'Pinterest', total_users: 153, market_cap: 11 }
}
],
[
{
yValue: 400.8,
yKey: 'market_cap',
xValue: 'Facebook',
xKey: 'name',
original: { name: 'Facebook', total_users: 1600, market_cap: 400.8 }
},
{
yValue: 11.3,
yKey: 'market_cap',
xValue: 'Twitter',
xKey: 'name',
original: { name: 'Twitter', total_users: 360, market_cap: 11.3 }
},
{
yValue: 11,
yKey: 'market_cap',
xValue: 'Pinterest',
xKey: 'name',
original: { name: 'Pinterest', total_users: 153, market_cap: 11 }
}
]
]
Run the examples locally
$ npm install
$ npm link
# link self
$ npm link nud3
# circular link
$ npm run watch
$ npm start
open browser to http://localhost:8000