Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dual-axis capability on a basic chart #28

Closed
yanofsky opened this issue Mar 3, 2015 · 10 comments
Closed

Dual-axis capability on a basic chart #28

yanofsky opened this issue Mar 3, 2015 · 10 comments

Comments

@yanofsky
Copy link
Contributor

yanofsky commented Mar 3, 2015

I've been working on trying to figure out the best way to allow for a left axis and a right axis on different scales. (and thus series on different scales) Like this:

apples-oranges_chartbuilder 76

At the moment d4 provides no way to override the chart-wide scale on a feature by feature basis.

So far I've tried the following,

  • add alt_scale to the yAxis feature's accessors with a default of null
  • change the first line of yAxis.render from scope.scale(this.y) to scope.scale(scope.alt_scale() ? scope.alt_scale() : this.y);
    • in other words: "if there is a custom scale, use that, otherwise use the default"

but there is no way to access a custom scale (that I can see) from inside of a feature (such as lineSeries) since the accessor is called in the context of the chart not the context of the feature. (e.g. d4.functor(scope.accessors.y).bind(this))

If you want to keep this functionality, perhaps it's better adding alt_y on the chart object instead—a clone of chart.y. Then there can be alt_y accessors on each feature and logic on when to use it in the render based on a use_alt_y accessor boolean on the feature. A similar thing could also be added to the x methods.

Of course once there are two axes...why not three, four, etc? That type of functionality would require the chart.x and chart.y methods to return arrays of scales and features to have something like y_scale_index (defaulting to 0). It could also really mess up the API.

What are your thoughts on how to achieve this @heavysixer?

@heavysixer
Copy link
Owner

Hey @yanofsky this sounds like a great addition to d4, let me see if I can figure it out. Do you have a fiddle or codepen you can share for what you've done so far? It is always helpful for me if I can fiddle with actual code.

I understand the issue with the declarative nature of the API, maybe we can do something like this

chart.y(function(){},1) where 1 is the index (defaulting to 0 if omitted)?

I think I might need to wrap my head around it a bit before I am totally sure, however this is something which is very common in data visualization and therefore a worthwhile addition.

Thanks!

@yanofsky
Copy link
Contributor Author

yanofsky commented Mar 4, 2015

Sure thing, here's a fiddle http://jsfiddle.net/26n3znsh/
The idea is that the line and right axis should be on an independent scale from the bars and the left axis

If we were to do it how you have above i can imagine the commented out methods on lines 70, 88, and 125 being the way forward (though maybe 125 isn't necessary?)

@heavysixer
Copy link
Owner

@yanofsky thinking this through a bit last night I have a couple questions / comments i'd like to get your thoughts on.

  1. I think this is absolutely an essential feature so we'll add it.
  2. Like you pointed out keeping the API expressive and consistent is an important consideration.
  3. We need to ensure we solve this problem with a pattern or metaphor we can use elsewhere so that once a developer has learned it they can apply that concept everywhere.

With that in mind I am wondering what you think of this approach.

  1. Add xScale and yScale proxies to the features that use scales so that they can be injected from the using method e.g.
var chart = d4.charts.column();
  chart
    .x(function(axis){
      axis
      .scale('linear')
    })
    .using('bars', function(bars) {
      bars
        .xScale(function(axis){ axis.scale('ordinal')})
    })

@yanofsky
Copy link
Contributor Author

yanofsky commented Mar 7, 2015

Sorry for the slow reply!

That looks workable. The things that have been tying me up thinking about it is how to make it easiest to maintain the background auto scaling

Would there be a way to select an scale/axis by index? Or get a list of the current list of scales/axes? I think that would be useful.

@heavysixer
Copy link
Owner

Hey @yanofsky i am working on this feature as we speak so this is perfect timing. Can you explain what you mean by auto-scaling? My thinking was that d4 would assume a single scale at the chart level, and then features could be locally overridden with a new scale. In this way you'd declare a single scale object outside the main chart object and then assign it to all the features you'd need like the axis, and line series. This would keep the inner workings of d4 basically the same, while still allowing for feature specific overrides. Thoughts?

@heavysixer
Copy link
Owner

@yanofsky
Copy link
Contributor Author

yanofsky commented Mar 7, 2015

Awesome, thanks, for doing this so quickly. It really helps us out a lot

What I was getting at before is that by default the domain of the nth scale could be calculated automatically...but the person who gets this deep into charting with d4 would probably be okay setting the scale too

@heavysixer
Copy link
Owner

Thank you for the feedback, if after playing with my implementation you have suggestions for improvements I am very happy to hear about it. Thanks again for your continued support of d4.

@heavysixer
Copy link
Owner

@yanofsky sounds like you are using d4 on a regular basis, do you have any other pain points that you've noticed in using the lib?

@yanofsky
Copy link
Contributor Author

yanofsky commented Mar 9, 2015

I do!

I'll put them in as separate issues to keep them organized on here...as such some of them are unique to our use case so I won't be offended by any wontfix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants