Bar
Bar charts renders a dataset as series of bars and is used for comparing numeric values between different categories.
Basic
See the full API here. Typically composed with VictoryChart
to create full charts.
<VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} /> </VictoryChart>
Bar Charts - Domain
Bars in VictoryBar
are centered around their corresponding value by default. You can move your bars away from your axis by setting a new domain, adding domainPadding
, or changing how bars are aligned relative to their values with the alignment
prop on VictoryBar
.
Using domainPadding
to adjust the bar position is the most common way to adjust the position of bars in a chart.
<VictoryChart domainPadding={{ x: 50 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} /> </VictoryChart>
Setting the bar alignment using the alignment
prop.
<VictoryChart theme={VictoryTheme.clean} > <VictoryBar alignment="start" data={sampleData} /> </VictoryChart>
Setting the bar alignment using the domain
prop.
<VictoryChart domain={{ x: [0.5, 5.5] }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} /> </VictoryChart>
Bar Charts - Horizontal
Bar charts can be rendered horizontally by setting the horizontal
prop to true
. This prop can be applied to either VictoryChart
or VictoryBar
.
<VictoryChart domainPadding={{ x: 20 }} horizontal theme={VictoryTheme.clean} > <VictoryBar /> </VictoryChart>
Bar Charts - Labels
Add labels to charts by setting the labels
prop to the name of a property in the dataset, or a function that returns the label value. You can customize the display of the labels by using the labelComponent
prop.
<VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} labels={({ datum }) => datum.y} /> </VictoryChart>
Bar Charts - Tooltips
Tooltips can be added by using a VictoryTooltip
component as the labelComponent
.
<VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} labelComponent={<VictoryTooltip />} labels={({ datum }) => datum.y} /> </VictoryChart>
Bar Charts - Grouped
Bar charts can be grouped to show how different subcategories compare to each other.
function App() { return ( <VictoryChart theme={VictoryTheme.clean} domain={{ y: [0.5, 5.5] }} domainPadding={{ x: 40 }} > <VictoryGroup offset={20} style={{ data: { width: 15 } }} > <VictoryBar data={[ { x: "2023 Q1", y: 1 }, { x: "2023 Q2", y: 2 }, { x: "2023 Q3", y: 3 }, { x: "2023 Q4", y: 2 }, ]} /> <VictoryBar data={[ { x: "2023 Q1", y: 2 }, { x: "2023 Q2", y: 3 }, { x: "2023 Q3", y: 4 }, { x: "2023 Q4", y: 5 }, ]} /> <VictoryBar data={[ { x: "2023 Q1", y: 1 }, { x: "2023 Q2", y: 2 }, { x: "2023 Q3", y: 3 }, { x: "2023 Q4", y: 4 }, ]} /> </VictoryGroup> </VictoryChart> ); } render(<App />);
Bar Charts - Grouped Labels
Bar chart labels for grouped bars can be rendered by setting the labels
prop to the name of a property in the dataset, an array, or a function that returns the label value.
function App() { return ( <VictoryChart theme={VictoryTheme.clean} domain={{ y: [0.5, 5.5] }} domainPadding={{ x: 40 }} > <VictoryGroup offset={20} style={{ data: { width: 15 } }} > <VictoryBar data={[ { x: "2023 Q1", y: 1 }, { x: "2023 Q2", y: 2 }, { x: "2023 Q3", y: 3 }, { x: "2023 Q4", y: 2 }, ]} labels={({ datum }) => datum.y } /> <VictoryBar data={[ { x: "2023 Q1", y: 2 }, { x: "2023 Q2", y: 3 }, { x: "2023 Q3", y: 4 }, { x: "2023 Q4", y: 5 }, ]} labels={({ datum }) => datum.y } /> <VictoryBar data={[ { x: "2023 Q1", y: 1 }, { x: "2023 Q2", y: 2 }, { x: "2023 Q3", y: 3 }, { x: "2023 Q4", y: 4 }, ]} labels={({ datum }) => datum.y } /> </VictoryGroup> </VictoryChart> ); } render(<App />);
Bar Charts - Combination
Bar charts can be rendered with other chart types like Line
.
<VictoryChart domainPadding={{ x: 20 }} horizontal theme={VictoryTheme.clean} > <VictoryBar /> <VictoryLine /> </VictoryChart>
Bar Charts - Animation
Charts can be animated by setting the animate
prop. See the animations guide for more information.
function App() { const [data, setData] = React.useState(getData()); React.useState(() => { const setStateInterval = window.setInterval(() => { setData(getData()); }, 4000); return () => { window.clearInterval( setStateInterval, ); }; }, []); return ( <VictoryChart theme={VictoryTheme.clean} domainPadding={{ x: 20 }} > <VictoryBar animate={{ duration: 1000 }} data={data} /> </VictoryChart> ); } function getData() { return [ { x: 1, y: _.random(1, 5) }, { x: 2, y: _.random(1, 10) }, { x: 3, y: _.random(2, 10) }, { x: 4, y: _.random(2, 10) }, { x: 5, y: _.random(2, 15) }, { x: 6, y: _.random(2, 8) }, { x: 7, y: _.random(2, 11) }, ]; } render(<App />);
Bar Charts - Zoom & Pan
Bar charts support pan and zoom behavior by using the VictoryZoomContainer
component. See the Pan & Zoom guide for more information.
<VictoryChart domain={{ x: [0, 10] }} theme={VictoryTheme.clean} containerComponent={ <VictoryZoomContainer zoomDimension="x" zoomDomain={{ x: [0, 5] }} minimumZoom={{ x: 1 }} /> } > <VictoryBar data={[ { x: 1, y: 2 }, { x: 2, y: 3 }, { x: 3, y: 5 }, { x: 4, y: 4 }, { x: 5, y: 7 }, { x: 6, y: 6 }, { x: 7, y: 8 }, { x: 8, y: 9 }, { x: 9, y: 10 }, { x: 10, y: 12 }, ]} /> </VictoryChart>
Bar Charts - Styles
Chart styling can be customized by using the theme or overriding the style prop on the component.
<VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} labels={({ datum }) => datum.y} style={{ data: { fill: "#c43a31", fillOpacity: 0.4, stroke: "#c43a31", strokeWidth: 2, }, labels: { fontSize: 12, fill: "#c43a31", }, }} /> </VictoryChart>
Bar Charts - Events
Events can be handled by passing an array of event objects to the events
prop on the component. Each event object should specify a target
and an eventHandlers
object. See the events guide for more information.
function App() { const toggleFillColor = (fill) => { if (fill === "black") { return null; } else { return { style: { fill: "black", }, }; } }; return ( <VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} labels={({ datum }) => datum.y} events={[ { target: "data", eventHandlers: { onClick: () => { return [ { target: "data", mutation: (props) => toggleFillColor( props.style ?.fill, ), }, ]; }, }, }, ]} /> </VictoryChart> ); } render(<App />);
Stacked Bar Charts
Bar charts can be stacked to show how different categories contribute to the total.
<VictoryChart domainPadding={{ x: 40 }} theme={VictoryTheme.clean} > <VictoryStack> <VictoryBar data={[ { x: "Sales", y: 2 }, { x: "Marketing", y: 3 }, { x: "Finance", y: 5 }, ]} /> <VictoryBar data={[ { x: "Sales", y: 1 }, { x: "Marketing", y: 4 }, { x: "Finance", y: 5 }, ]} /> <VictoryBar data={[ { x: "Sales", y: 3 }, { x: "Marketing", y: 2 }, { x: "Finance", y: 6 }, ]} /> </VictoryStack> </VictoryChart>
Stacked Bar Charts - 100%
While Victory does not support 100% stacked bar charts natively, you can achieve this by transforming your data.
const myDataset = [ [ { x: "a", y: 1 }, { x: "b", y: 2 }, { x: "c", y: 3 }, { x: "d", y: 2 }, { x: "e", y: 3 }, ], [ { x: "a", y: 2 }, { x: "b", y: 3 }, { x: "c", y: 7 }, { x: "d", y: 5 }, { x: "e", y: 3 }, ], [ { x: "a", y: 5 }, { x: "b", y: 2 }, { x: "c", y: 3 }, { x: "d", y: 4 }, { x: "e", y: 4 }, ], ]; function App() { // This is an example of a function you might // use to transform your data to make 100% data function transformData(dataset) { const totals = dataset[0].map( (data, i) => { return dataset.reduce( (memo, curr) => { return memo + curr[i].y; }, 0, ); }, ); return dataset.map((data) => { return data.map((datum, i) => { return { x: datum.x, y: (datum.y / totals[i]) * 100, }; }); }); } const dataset = transformData(myDataset); return ( <div> <VictoryChart domainPadding={{ x: 30, y: 20 }} theme={VictoryTheme.clean} > <VictoryStack> {dataset.map((data, i) => { return ( <VictoryBar data={data} key={i} /> ); })} </VictoryStack> <VictoryAxis dependentAxis tickFormat={(tick) => `${tick}%` } /> <VictoryAxis tickFormat={[ "a", "b", "c", "d", "e", ]} /> </VictoryChart> </div> ); } render(<App />);
Stacked Bar Charts - Grouped
Bar charts can be stacked and grouped to show how different subcategories contribute to the total.
function App() { const getBarData = () => { return [1, 2, 3, 4, 5].map(() => { return [ { x: 1, y: Math.random() }, { x: 2, y: Math.random() }, { x: 3, y: Math.random() }, ]; }); }; return ( <div> <VictoryChart domainPadding={{ x: 50 }} > <VictoryGroup offset={20} style={{ data: { width: 15 }, }} > <VictoryStack colorScale={"red"} > {getBarData().map( (data, index) => { return ( <VictoryBar key={index} data={data} /> ); }, )} </VictoryStack> <VictoryStack colorScale={"green"} > {getBarData().map( (data, index) => { return ( <VictoryBar key={index} data={data} /> ); }, )} </VictoryStack> <VictoryStack colorScale={"blue"} > {getBarData().map( (data, index) => { return ( <VictoryBar key={index} data={data} /> ); }, )} </VictoryStack> </VictoryGroup> </VictoryChart> </div> ); } render(<App />);
Diverging Bar Charts
Diverging bar are useful for showing how different categories compare to a common baseline. By default, Victory will calculate the domain based on the data provided.
<VictoryChart domainPadding={{ x: 50 }} theme={VictoryTheme.clean} > <VictoryBar data={[ { x: "rabbits", y: 5 }, { x: "cats", y: -10 }, { x: "dogs", y: 15 }, { x: "turtles", y: -8 }, { x: "snakes", y: -2 }, { x: "fish", y: 5 }, ]} /> </VictoryChart>
Diverging Bar Charts - Horizontal
Diverging bar are useful for showing how different categories compare to a common baseline. By default, Victory will calculate the domain based on the data provided.
<VictoryChart horizontal domainPadding={{ x: 50 }} theme={VictoryTheme.clean} > <VictoryBar data={[ { x: "rabbits", y: 5 }, { x: "cats", y: -10 }, { x: "dogs", y: 15 }, { x: "turtles", y: -8 }, { x: "snakes", y: -2 }, { x: "fish", y: 5 }, ]} /> </VictoryChart>
Diverging Bar Charts - Grouped
Diverging bar are useful for showing how different categories compare to a common baseline. By default, Victory will calculate the baseline based on the data provided.
function App() { return ( <VictoryChart domainPadding={{ x: 50 }} theme={VictoryTheme.clean} > <VictoryGroup offset={18} colorScale={"qualitative"} > {getBarData().map( (data, index) => { return ( <VictoryBar key={index} data={data} labels={({ datum }) => datum.y } /> ); }, )} </VictoryGroup> </VictoryChart> ); } function getBarData() { return _.range(5).map(() => { return [ { x: "rabbits", y: _.random(-5, 5), }, { x: "cats", y: _.random(-10, 10), }, { x: "dogs", y: _.random(-15, 15), }, ]; }); } render(<App />);
Diverging Bar Charts - Floating
Diverging bar are useful for showing how different categories compare to a common baseline.
const dataA = [ { x: "Television", y: 38 }, { x: "Smartwatch", y: 37 }, { x: "Fitness Monitor", y: 25 }, { x: "Tablet", y: 19 }, { x: "Camera", y: 15 }, { x: "Laptop", y: 13 }, { x: "Phone", y: 12 }, ]; const dataB = dataA.map((point) => { const y = Math.round( point.y + 3 * (Math.random() - 0.75), ); return { ...point, y }; }); const width = 400; const height = 300; function App() { return ( <VictoryChart horizontal height={height} width={width} padding={{ top: 100, bottom: 30, left: 50, right: 50, }} theme={VictoryTheme.clean} > <VictoryLegend x={90} y={20} orientation="horizontal" gutter={20} data={[ { name: "Ages 18-20", }, { name: "Ages 21-24", }, ]} /> <VictoryStack style={{ data: { width: 12 }, labels: { fontSize: 12 }, }} > <VictoryBar data={dataA} y={(data) => -Math.abs(data.y) } labels={({ datum }) => `${Math.abs(datum.y)}%` } /> <VictoryBar data={dataB} labels={({ datum }) => `${Math.abs(datum.y)}%` } /> </VictoryStack> <VictoryAxis style={{ axis: { stroke: "transparent", }, ticks: { stroke: "transparent", }, tickLabels: { fontSize: 12, fill: "black", }, }} /* Use a custom tickLabelComponent with an absolutely positioned x value to position your tick labels in the center of the chart. The correct y values are still provided by VictoryAxis for each tick */ tickLabelComponent={ <VictoryLabel x={width / 2} textAnchor="middle" /> } tickValues={dataA .map((point) => point.x) .reverse()} /> </VictoryChart> ); } render(<App />);
Polar Bar Charts
Bar charts can be rendered in polar coordinates by setting the polar
prop to true
and using VictoryPolarAxis
components.
<VictoryChart polar theme={VictoryTheme.clean} > <VictoryPolarAxis dependentAxis style={{ axis: { stroke: "none" } }} tickFormat={() => null} /> <VictoryPolarAxis /> <VictoryBar data={sampleData} /> </VictoryChart>
Polar Bar Charts - Stacked
Bar charts can be rendered in polar coordinates by setting the polar
prop to true
and using VictoryPolarAxis
components.
const directions = { 0: "E", 45: "NE", 90: "N", 135: "NW", 180: "W", 225: "SW", 270: "S", 315: "SE", }; const orange = { base: "#2D7FF9", highlight: "#2750AE", }; const red = { base: "#8B46FF", highlight: "#6B1CB0", }; const innerRadius = 30; function CompassCenter(props) { const { origin } = props; const circleStyle = { stroke: red.base, strokeWidth: 2, fill: orange.base, }; return ( <g> <circle cx={origin.x} cy={origin.y} r={innerRadius} style={circleStyle} /> </g> ); } function CenterLabel(props) { const { datum, active, color } = props; const text = [ `${directions[datum._x]}`, `${Math.round(datum._y1)} mph`, ]; const baseStyle = { fill: color.highlight, textAnchor: "middle", }; const style = [ { ...baseStyle, fontSize: 18, fontWeight: "bold", }, { ...baseStyle, fontSize: 12 }, ]; return active ? ( <VictoryLabel text={text} style={style} x={75} y={75} renderInPortal /> ) : null; } function App() { const [state, setState] = React.useState({ wind: getWindData(), }); return ( <VictoryChart polar animate={{ duration: 500, onLoad: { duration: 500 }, }} theme={VictoryTheme.clean} innerRadius={innerRadius} domainPadding={{ y: 10 }} events={[ { childName: "all", target: "data", eventHandlers: { onMouseOver: () => { return [ { target: "labels", mutation: () => ({ active: true, }), }, { target: "data", mutation: () => ({ active: true, }), }, ]; }, onMouseOut: () => { return [ { target: "labels", mutation: () => ({ active: false, }), }, { target: "data", mutation: () => ({ active: false, }), }, ]; }, }, }, ]} > <VictoryPolarAxis dependentAxis labelPlacement="vertical" style={{ axis: { stroke: "none" }, }} tickFormat={() => ""} /> <VictoryPolarAxis labelPlacement="parallel" tickValues={_.keys( directions, ).map((k) => +k)} tickFormat={_.values( directions, )} /> <VictoryStack> <VictoryBar style={{ data: { fill: ({ active }) => active ? orange.highlight : orange.base, width: 40, }, }} data={state.wind} x="windBearing" y="windSpeed" labels={() => ""} labelComponent={ <CenterLabel color={orange} /> } /> <VictoryBar style={{ data: { fill: (d, a) => a ? red.highlight : red.base, width: 40, }, }} data={state.wind} x="windBearing" y={(d) => d.windGust - d.windSpeed } labels={() => ""} labelComponent={ <CenterLabel color={red} /> } /> </VictoryStack> <CompassCenter /> </VictoryChart> ); } function getWindData() { return _.keys(directions).map((d) => { const speed = Math.floor(_.random() * 17) + 4; return { windSpeed: speed, windGust: speed + _.random(2, 10), windBearing: +d, }; }); } render(<App />);
Standalone Rendering
Bar charts can be rendered outside a VictoryChart.
<VictoryBar theme={VictoryTheme.clean} />
They can also be embeded in other SVG components by using the standalone
prop.
<div style={{ padding: "20px" }}> <svg width={300} height={300} style={{ display: "block", margin: "0 auto", }} > <circle cx={150} cy={150} r={150} fill="#9ded91" /> <VictoryBar standalone={false} theme={VictoryTheme.clean} width={300} height={300} padding={{ left: 10, right: 10 }} data={sampleData} /> </svg> </div>