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

line is drawn in middle of chart when Y axis domain is [0, 0] #1656

Open
ajperez81 opened this issue Feb 18, 2020 · 1 comment
Open

line is drawn in middle of chart when Y axis domain is [0, 0] #1656

ajperez81 opened this issue Feb 18, 2020 · 1 comment

Comments

@ajperez81
Copy link

In a line chart, when all the data points have a zero value, I would expect them to show at the bottom, like this:
d3-5 7 0

That's the way dc.js works with d3 5.7.0 or lower. In d3 5.8.0 they "fixed" the way that scales map the value when the domain is collapsed (d3/d3-scale#117). Now it shows like this instead:
d3-5 8 0

I guess it could make sense if all the points had a value of 42, for instance. But when all of them are 0, it just looks weird.

Is there any way to workaround this issue, using dc.js, without having to redefine the Y axis domain myself?

This is the code I used for the examples, it's available also at codepen:

const data = [
  {day: 1, total: 0},
  {day: 2, total: 0}
];
const ndx = crossfilter(data);
const dim = ndx.dimension(d => d.day);
const grp = dim.group().reduceSum(d => d.total);
dc.lineChart('#chart')
  .dimension(dim)
  .group(grp)
  .width(500)
  .height(150)
  .x(d3.scalePoint().domain([1, 2]).range([0, 500]))
  .render();
@gordonwoodhull gordonwoodhull changed the title Issue when Y axis domain is [0, 0] line is drawn in middle of chart when Y axis domain is [0, 0] Feb 18, 2020
@gordonwoodhull
Copy link
Contributor

gordonwoodhull commented Feb 18, 2020

Huh, I'd noticed charts doing this but I hadn't narrowed it down to a change in D3.

I agree, it's annoying, but since you have to tell D3 a domain when it would otherwise, be empty, I can't think of anything simpler than preRender/preRedraw hooks:

chart
  .on('preRender', keep_ydomain_nonempty)
  .on('preRedraw', keep_ydomain_nonempty)

function keep_ydomain_nonempty(chart) {
  const min = chart.yAxisMin();
  if(min === chart.yAxisMax())
    chart.elasticX(false).y(d3.scaleLinear().domain([min, min+1]));
  else
    chart.elasticX(true);
}

Unfortunately this causes the Y axis to have a lot of useless ticks, which you'd probably have to weed out with more special cases:

image

fork of your codepen

I hope there is a better way.

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