D3 Stack - marcoFijan/frontend-data GitHub Wiki

Voor mijn orginele concept had ik een stacked bar chart nodig. Uiteindelijk heb ik te weinig tijd gehad voor mijn concept. Maar toch wilde ik wel een stacked bar chart maken.

Stack

Om een stacked bar chart te maken in d3 heb je stack() nodig. Met stack() geef je aan welke kolommen je in je data wilt visualiseren. Vervolgens geef je de data mee die stack moet gebruiken om de kolommen te vinden:

const stackColumns = stack().keys(['totalDisabledCapacity', 'totalNotDisabledCapacity'])
stackColumn(data)

stackColumns maakt vervolgens een array die uit 2 array's bestaat. In die 2 array's zitten de waarden van de kolommen totalDisabledCapacity en totalNotDisabledCapacity afbeelding.png De tweede array heeft als beginwaarde (index[0]) de eindwaarde van de eerste array. Stack 'stapelt' als het ware de data al op elkaar.

In principe heb je op deze manier al gelijk de waarden voor de hoogte van de staven.

Om vervolgens de staven te creëren moeten er een paar extra stappen gezet worden. Normaal gebruik je een enter.append() en 1 data join om alle staven te maken.

svg.selectAll('rect').data(data)
      .enter().append('rect')
        .attr('x', d => scaleX(d.data.province))
        .attr('y', d => scaleY(d[1]))
        .attr('width', scaleX.bandwidth())
        .attr('height', d => scaleY(d[0]) - scaleY(d[1]))

Maar doordat er nu met een array die weer array's bevat wordt gewerkt, moet er een extra 'loop' gebruikt worden om de data te kunnen lezen. Dit was even puzzelen voor mij, maar uiteindelijk ben ik eruit gekomen. Wanneer je de 'layers' als het ware aanmaakt, geef ik een class mee. Vervolgens loop ik met een nieuwe data join door de eerder opgegeven data om de juiste waarden op te halen.

const drawBar = function(){
  g.selectAll('.layer').data(stackedBars)
    .enter().append('g')
    .attr('class', 'layer')
    .attr("fill", d => colorScale(d.key))
    .selectAll('rect').data(d => d)
      .enter().append('rect')
        .attr('x', d => scaleX(d.data.province))
        .attr('y', d => scaleY(d[1]))
        .attr('width', scaleX.bandwidth())
        .attr('height', d => scaleY(d[0]) - scaleY(d[1]))
}