Home > OS >  How to create Stacked Line Chart in d3js Multiple Y Axis and common X Axis
How to create Stacked Line Chart in d3js Multiple Y Axis and common X Axis

Time:02-04

Example Linechart

How can i draw a linechart like this in d3js?

CodePudding user response:

You can draw individual line charts which are translated vertically. Translating them vertically can be achieved by placing each chart into a SVG group (g) and translating the group by setting the transform attribute.

They all share the same x axis with the same domain and range.

const x = d3.scaleLinear()
  .domain([d3.min(t), d3.max(t)])
  .range([0, width]);

Here is the entire code:

// dummy data with common domain for all charts
const t = d3.range(200).map(o => o * 0.1   1);
// three series of data => three charts
const data = [
  t.map(t => (1   Math.cos(t))/2),
  t.map(t => 1 - 1/Math.pow(0.2*t, 2)),
  t.map(t => (1   Math.sin(t))/2),
];

// three different colors for three graphs
const graphColor = ['#F2CD5C', '#a71df2', '#A61f69'];

// we need to add some margin to see the full axis
const margin = { top: 10, bottom: 75, left: 30, right: 10 };
// static width and height - change this to whatever suits you
const width = 300;
const height = 400;

// the height of each stacked
const singleChartHeight = height / data.length;

const svg = d3.select('#stacked-charts')
  .append('svg')
  // set the size of the chart
  .attr('width', width   margin.left   margin.right)
  .attr('height', height   margin.top   margin.bottom)
  .attr("viewBox", [0, 0, width, height]);

// create a common x-axis for all charts
const x = d3.scaleLinear()
  .domain([d3.min(t), d3.max(t)])
  .range([0, width]);

// a global group with padding
const coreGroup = svg.append('g')
  .attr('class', 'stacked-charts')
  // translate the padding
  .attr('transform', 'translate('   margin.left   ' 0)');

// create three different y-axes - one for each series
const y = data.map(dataSeries => {
  return d3.scaleLinear()
    .domain([d3.min(dataSeries), d3.max(dataSeries)])
    .range([singleChartHeight, 0]);
});

// the line generator
const lineGenerator = d3.line();

// create a chart for each series of data
data.forEach((dataSeries, chartIndex) => {
  // create an individual group
  const chartGroup = coreGroup.append('g')
    .attr('class', 'chart')
    // stack by translating vertically
    .attr('transform', 'translate(0 '   (chartIndex * singleChartHeight)   ')');

  // use x/y axes to create the points
  const points = t.map((timestamp, timeStampIndex) => {
    return [
      // the x value
      x(timestamp),
      // the y value from one of the three axes
      y[chartIndex](dataSeries[timeStampIndex])
    ]
  });
  // create the SVG path for the line
  const path = lineGenerator(points);

  // draw the graph
  chartGroup.append('path')
    .attr('class', 'graph')
    .attr('d', path)
    .attr('fill', 'none')
    .attr('stroke', graphColor[chartIndex]);

  // add x axis
  chartGroup.append('g')
    .attr('class', 'x-axis')
    .call(d3.axisBottom(x))
    .attr('transform', 'translate(0 '  singleChartHeight   ')');

  // add y axis
  chartGroup.append('g')
    .attr('class', 'y-axis')
    .call(d3.axisLeft(y[chartIndex]));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div style="text-align: center;">
  <h1>Stacked Linear Charts</h1>
  <div id="stacked-charts"></div>
</div>

If you want all charts to have the same y-scale, they could also share the same y-axis.

  • Related