Visx is a library that lets us add graphics to our React app easily.
In this article, we’ll look at how to use it to add a line with markers into our React app.
Install Required Packages
We have to install a few modules.
To get started, we run:
npm i @visx/curve @visx/glyph @visx/group @visx/mock-data @visx/responsive @visx/scale @visx/shape
to install the packages.
Create Lines with Markers
We can create lines with markers with the @visx/glyph
module to add the markers.
To do this, we write:
import React from "react";
import { Group } from "@visx/group";
import {
Glyph as CustomGlyph,
GlyphCircle,
GlyphCross,
GlyphDiamond,
GlyphSquare,
GlyphStar,
GlyphTriangle,
GlyphWye
} from "@visx/glyph";
import { LinePath } from "@visx/shape";
import genDateValue from "@visx/mock-data/lib/generators/genDateValue";
import { scaleTime, scaleLinear } from "@visx/scale";
import { curveMonotoneX, curveBasis } from "@visx/curve";
const defaultMargin = { top: 10, right: 10, bottom: 10, left: 10 };
export const primaryColor = "#8921e0";
export const secondaryColor = "#00f2ff";
const contrastColor = "#ffffff";
const Glyphs = [
GlyphCircle,
GlyphCross,
GlyphDiamond,
GlyphStar,
GlyphTriangle,
GlyphSquare,
GlyphWye,
({ left, top }) => (
<CustomGlyph left={left} top={top}>
<circle r={12} fill={secondaryColor} />
<text fontSize={16} textAnchor="middle" dy="0.5em">
{"?"}
</text>
</CustomGlyph>
)
];
const data = genDateValue(Glyphs.length * 2);
const date = (d) => d.date.valueOf();
const value = (d) => d.value;
const xScale = scaleTime({
domain: [Math.min(...data.map(date)), Math.max(...data.map(date))]
});
const yScale = scaleLinear({
domain: [0, Math.max(...data.map(value))]
});
const getX = (d) => xScale(date(d)) ?? 0;
const getY = (d) => yScale(value(d)) ?? 0;
function Example({ width, height, margin = defaultMargin }) {
if (width < 10) return null;
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
xScale.range([0, innerWidth]);
yScale.range([innerHeight, 0]);
return (
<svg width={width} height={height}>
<rect
x={0}
y={0}
width={width}
height={height}
fill={secondaryColor}
rx={14}
/>
<Group left={margin.left} top={margin.top}>
<LinePath
data={data}
x={getX}
y={getY}
stroke={primaryColor}
strokeWidth={2}
strokeDasharray="2,2"
curve={curveBasis}
/>
<LinePath
data={data}
x={getX}
y={getY}
stroke={primaryColor}
strokeWidth={2}
curve={curveMonotoneX}
/>
{data.map((d, i) => {
const CurrGlyph = Glyphs[i % Glyphs.length];
const left = getX(d);
const top = getY(d);
return (
<g key={`line-glyph-${i}`}>
<CurrGlyph
left={left}
top={top}
size={110}
stroke={secondaryColor}
strokeWidth={10}
/>
<CurrGlyph
left={left}
top={top}
size={110}
fill={i % 2 === 0 ? primaryColor : contrastColor}
stroke={i % 2 === 0 ? contrastColor : primaryColor}
strokeWidth={2}
/>
</g>
);
})}
</Group>
</svg>
);
}
export default function App() {
return (
<div className="App">
<Example width={500} height={300} />
</div>
);
}
We add the margins for the graph with the defaultMargin
variable.
primaryColor
, secondaryColor
have the colors for the lines.
contrastColor
have the background color for the markers.
The Glyphs
array have the icons and a function that returns a custom component with the icon.
CustomGlyph
takes the left
and top
properties to set its position.
data
has the data for the line.
date
and value
are functions that return the value given the entry.
xScale
has the scale for the x-axis.
And yScale
has the scale for the y-axis.
The Example
component is where we put the chart together.
We set the width and height of the chart with the innerWidth
and innerHeight
variables.
The Group
component wraps around the parts of the chart.
LinePath
has the lines for the graph.
We pass in the getX
and getY
functions to render the data as lines.
The first LinePath
renders a dotted line.
And the 2nd one renders a solid line.
The markers are rendered with the data.map
callback.
It returns the CurrGlyph
components to render our marker.
We set the left
and top
props to set the position.
CurrGlyph
is created from the Glyphs
array by getting the icon to render by its index.
Now we should see 2 lines with markers for each.
Conclusion
We can create lines with markers easily in our React app with the Visx library.