Bar Stack & Line chart combined
Tags: visx, d3, react
Published: 2022-11-29 15:19:10

The [visx](https://airbnb.io/visx/) library by airbnb is my to-go-to when building charts with React.

It’s well documented, based on d3, really flexible and customizable.

You can find a lot of articles explaining to you how to build a simple chart using visx, they even provide some sandbox.

> When struggling with a chart, always go to the d3 documentation and do some research on how to perform this or that.

### How can I align properly two charts of different types and scales?

I need to display some data over time, my x-axis is time-based in this example.

The stack bar chart needs by default a scale band.

I would like to add a line displaying other data *based on the same x-axis values* I’m using for the bar stack chart.

#### ❌ Create two different x-axis scales
My first approach was to create two different x-axis scales. But because the line chart and the bar stack are not using the same scale type, the alignment of my two charts was off.

#### ✅ Only use one scale type
So as a requirement, I could only use one scale type, since I don’t have much choice with the bar stack, it had to be a scale band.

```javascript
import { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale';

... 

// create the scale that will be passed to the <BarStack /> component
const xScale = scaleBand({
  domain: selectedBarPoints.map(getX),
});
```

In order to get the line chart aligned, I need to use my `xScale` somehow.

The key is to pass the `xScale` that we are using for the bar stack chart to the `x` props of the `LinePath`, but with a twist:

```javascript
 x={d => xScale.bandwidth() / 2 + xScale(d.x)}
```

**Explanations**

```javascript
// width of the bar divided by 2 to get the middle
xScale.bandwidth() / 2

// the x position of the bar in the chart
xScale(d.x)
```

![Bar stack chart combined with a line chart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r8e7qau919c1hwsezr3u.png)

Here is a more "in-context" example, also adding dots on top of the line:

```javascript
<svg ref={containerRef} width="100%" height={height}>
  <Group
    width={width}
    height={height}
    top={margin.top}
    left={margin.left}
  >
    <BarStack
      data={selectedBarPoints}
      x={getX}
      xScale={xScale}
      yScale={yScale}
    >
      {barStacks =>
        barStacks.map(barStack =>
          map(barStack.bars, (bar, index) => 
          (
              <rect
                x={bar.x}
                y={bar.y - 0.8}
                height={bar.height}
                width={bar.width}
              />
            )),
        )
      }
    </BarStack>
    {selectedLinePoints.map((datapoints, i) => (
        <Fragment key={`fragment-line-${datapoints.id}`}>
          <LinePath
            data={datapoints.data}
						// here is where the magic happens
            x={d => xScale.bandwidth() / 2 + xScale(d.x)}
            y={d => yScale(d.y)}
          />
          {datapoints.data.map((dot) => (
            <g key={`line-glyph-${dot.x}`}>
              <GlyphCircle
								// operate the same logic to position a dot on the line
                left={xScale.bandwidth() / 2 + xScale(dot.x)}
                top={yScale(dot.y)}
              />
            </g>
          ))}
        </Fragment>
      ))}
  </Group>
</svg>
```

Happy coding charts!