heavysixer / d4

A friendly reusable charts DSL for D3
MIT License
433 stars 46 forks source link

Use nested axes for groups #29

Closed nsonnad closed 9 years ago

nsonnad commented 9 years ago

Hello. So the more flexible and canonical way to do grouped columns/rows in d3 is to have what I'm calling "nested axes", meaning an outer axis to place the groups and an inner one to place the series within each group. See this example.

I've refactored grouped-column-series to use this kind of implementation. This fixes https://github.com/heavysixer/d4/issues/25 and https://github.com/heavysixer/d4/issues/10, which as far as I can tell are the same issue. It also removes some hard-coding in the size and placement of the groups and such, because values are set according to the rangeBand of the outer axis. You can check against my grouped-axes branch on d4-www to see it in action. All of the grouped column/row examples work as far as I can tell.

My naming treats x or y as the outer axis, and groups as the inner.

I'm curious to see if you have any feedback on the stuff in scales.js and base.js, as some of the checks in there seem a bit dirty. Also, customizing the inner axis is not possible through the chart definition because it needs the rangeBand() of the outer axis to determine the range. So I've included roundBands as a customizable property of the groups scale.

I should note as well that this is a breaking change as the groups axis key is required. It may be possible to fall back to an index, but I'm not so sure how to do that at the moment. Thanks and sorry for the long winded explanation!

heavysixer commented 9 years ago

Hi @nsonnad thanks so much for your continued contributions. I have not reviewed the code yet, but I am also wondering if it might also effect to @yanofsky's question in #28 ?

nsonnad commented 9 years ago

It shouldn't have an effect as all this does is add an extra axis in the case of grouped columns and rows. Here's how it works:

1) Declare which dimension your groups lie along in the chart definition, eg in grouped-column.js:

axes: {
  groups: {
    scale: 'ordinal',
    dimension: 'x',
    roundBands: 0.1
  }
}

2) Create a g for each group of columns/rows, and translate them to the position along their specified dimension, according to that dimension's key.

3) Set the group axis range to the rangeBand() of this outer axis, and position the columns/rows relative to according to this "inner" group axis.

Continuous axes and the x/y scales are untouched in this change, they are just being used to place a g that contains its own axis versus placing the rects individually.

heavysixer commented 9 years ago

The code looks good, one question. Do you know if the sorting example you referenced earlier http://bl.ocks.org/EE2dev/af14387f43b5f332e360 would be possible with the refactoring?

heavysixer commented 9 years ago

Hi @nsonnad, I've looked at the d4-www branch and noticed that the arrow feature, and axis example charts are broken. I guess this is because they have not been updated to use the new implementation? Once those are fixed please send me a PR on those files as well and I'll merge everything down and do a new release.

Thanks!

heavysixer commented 9 years ago

I've fixed the remaining d4-www examples and will push a new version of the site.