Getting started with vx.

Evan Conrad
vx code
Published in
7 min readMay 19, 2017

--

Line plot created with vx.

vx is a collection of low-level react components for d3. Do you like React? Do you like d3? Wana combine them in a way that’s easy to use and makes sense? You want vx .

As of this writing, vx is in a super-beta and probably should not be used in production.

This guide assumes you:

  • Have knowledge of React.
  • May or may not have knowledge of d3.

Packages

vx tries hard to be tiny and compact. You should only import the packages you need. So, instead of doing something like this:

import vx from 'vx'; // BAD! 

You should import each package individually:

import { Bar } from '@vx/shape'; // GOOD! 

You can see a list of all packages here.

At the moment, documentation for each package lives in the package folder’s README.md file. For example, if you want to see what the @vx/shape package does, you would go to the folder here. Eventually, the docs will exist on the vx website.

Below is a short description of the a few of the packages we’ll be using in alphabetic order.

Axis Package

import { AxisLeft, AxisBottom } from '@vx/axis';
Axis Example

A typical graph axis with ticks that can help you label your graphs. Docs Here.

Gradient Package

import { GradientOrangeRed } from '@vx/gradient';
Gradient Example

A gradient is a definition of a fill attribute that you can use in your shapes. We’ll talk more about this in a bit. Docs Here.

Group Package

import { Group } from '@vx/group';

A group is just a container for other objects. It’s really just a wrapper around the g svg element. Docs Here.

Mock Data Package

import { browserUsage, genDateValue } from '@vx/mock-data';

The Mock Data package is a collection of data sets that you can use to test out your graphs. Docs Here.

Scale Package

import { scaleLinear } from '@vx/scale';

The Scale package is a wrapper around the original d3 scaling functions that let you scale your data to the size of your graph. For example, if your y values are between 100,000 and 200,000 your graph doesn’t need to be 200,000 pixels high. Docs Here.

Shape Package

import { Bar } from '@vx/shape';
Shape Example

The Shape package contains the majority of the “shapes” you see in the graphs. Bars, Lines, and Areas are all in here.

Building Your First Graph

We’ll start by using some data from @vx/mock-data like so:

import { appleStock } from '@vx/mock-data';// ...const data = appleStock;

If we console.log that data, we’ll see that it’s an array of JSON objects with date timestamps and close dollar values for apple stock.

We’ll also give our graph a width and a height.

const width = 750;
const height = 400;

We should also define some bounds and margins for our graph.

const margin = {
top: 60,
bottom: 60,
left: 80,
right: 80,
};
const xMax = width - margin.left - margin.right;
const yMax = height - margin.top - margin.bottom;

Defining What “X,Y” Means

If you’ve made graphs before in matlab or pyplot, you may have noticed that you needed to pass in an array of xs and ys. You also may have passed in an array of (x,y) tuples.

D3 and vx take a functional approach. We create two functions, x and y to define what we mean when we say “x” and “y”. With Javascript’s arrow syntax, this can cleanly be done with our data like so:

const x = d => new Date(d.date); // d.date is unix timestamps
const y = d => d.close;

We convert the unix timestamp to date objects. See this SO question for more.

If we were to take one element of our data and put it through these functions we might get something like this:

console.log(x(data[0])); // Fri Aug 21 1970 12:23:21 GMT-0600 (MDT)
console.log(y(data[0])); // 72.2

Then, if we wanted all the y values, we could run a map function on the data like so:

data.map(y); // Gives an array of all the y values

D3 calls this pattern “accessors.”

Scaling Our Data

Since we have timestamps, we’ll use the @vx/scale package’s scaleTime function for our x values and a scaleLinear for the y values.

import { scaleTime, scaleLinear } from '@vx/scale';
import { extent } from 'd3-array';
// ...const xScale = scaleTime({
range: [0, xMax],
domain: extent(data, x)
});

For the parameters, we’re going to put in a range which is the values that we want to scale down our x’s to. In this case, we want the info to go from the left to right of our graph, so 0 to xMax.

In the domain, we’re going to make use of a d3-array function extent (docs here). extent will take an array and one of our x or y functions (d3 calls them accessors) and returns the min and max values.

We can then create a y value scale like so:

import {extent, max} from 'd3-array';// ...const yScale = scaleLinear({
range: [yMax, 0],
domain: [0, max(data, y)],
});

Here we’re adding another d3 function max that will get us the largest y value in the data.

Creating Our First Element

vx expects your elements to be rendered inside of an svg element, so we’ll start by creating one.

const chart = ( <svg width={width} height={height}> </svg> );

Then, we’ll create an <Shape.AreaClosed/> element (Docs Here) inside a <Group /> element.

import { AreaClosed } from '@vx/shape';const chart = (
<svg width={width} height={height}>
<Group top={margin.top} left={margin.left}>
<AreaClosed
data={data}
xScale={xScale}
yScale={yScale}
x={x}
y={y}
fill={"red"}
/>
</Group>
</svg>
)

If we render this chart, we’ll see something like this:

Example First Chart

Giving Context to the Data

Now we can add some axes to label our information. We’ll add an import statement at the top like:

import { AxisLeft, AxisBottom } from ‘@vx/axis’;

To add a bottom axis, we’ll add an Axis.AxisBottom (Docs Here) to our chart like so:

<AxisBottom
scale={xScale}
top={yMax}
label={'Years'}
stroke={'#1b1a1e'}
tickTextFill={'#1b1a1e'}
/>

Then, we can add an Axis.AxisLeft with:

<AxisLeft
scale={yScale}
top={0}
left={0}
label={'Close Price ($)'}
stroke={'#1b1a1e'}
tickTextFill={'#1b1a1e'}
/>

All together we have:

<svg width={width} height={height}>
<Group top={margin.top} left={margin.left}>
<AxisLeft
scale={yScale}
top={0}
left={0}
label={'Close Price ($)'}
stroke={'#1b1a1e'}
tickTextFill={'#1b1a1e'}
/>
<AxisBottom
scale={xScale}
top={yMax}
label={'Years'}
stroke={'#1b1a1e'}
tickTextFill={'#1b1a1e'}
/>
<AreaClosed
data={data}
xScale={xScale}
yScale={yScale}
x={x}
y={y}
fill={"red"}
/>
</Group>
</svg>

Which will create a graph that looks like this:

Graph with Axes

Making It Pretty

It’s functional, but it’s not super appealing. Let’s use some of vx’s gradient features to make this graph a little nicer.

To use a gradient, we first need to define it. We’ll do that by added a @vx/gradient component (Docs Here).

import { LinearGradient } from '@vx/gradient';

VX comes with a whole bunch of pre-made gradients that you can use, but let’s create our own for now.

I bookmarked webgradients awhile ago, so I’m gonna take one off there. We’ll take two color values and pop them into an element like this:

<LinearGradient
from='#fbc2eb'
to='#a6c1ee'
id='gradient'
/>

Then, we’ll change the fill of our AreaClosed to be url("#gradient") and remove that line on top like so:

<AreaClosed
data={data}
xScale={xScale}
yScale={yScale}
x={x}
y={y}
fill={"url(#gradient)"}
stroke={""}
/>

Now we’ll have a graph that looks like this:

Gradient Graph

Full Source

You can find the full source code for the graph we just made here.

Where to Go From Here

Want to do more with vx ? Check out some of the other packages!

  • Play with icons with the @vx/glyph package!
  • Explore Brush & Zoom features with the@vx/brush package!
  • Use Text and Labels with the@vx/text package!
  • Paint with Patterns in the @vx/pattern package!

Check out the new gallery to get a better sense of how to use vx .

Want to help vx get to a production stage? Checkout the V1 project on Github and submit a PR!

--

--