inverted y axis

5,029 views
Skip to first unread message

Nils

unread,
Mar 19, 2012, 1:28:24 PM3/19/12
to d3-js
I absolutely love d3 but I'm getting stuck on drawing vertical bar
charts. Because the y-axis is inverted (ie. 0 is at the top and values
increase down the screen), I keep having to calculate y-position and
height by subtracting from the chart height. I feel this might be
introducing some inaccuracies and it's quite a bit more work.

Are there any helpers within d3 to make this job easier? Such as an
inverted scale or perhaps I can draw svg shapes by specifying their
bottom + height, rather than y-position + height?

Many thanks in advance,

Nils

Mike Bostock

unread,
Mar 19, 2012, 1:42:34 PM3/19/12
to d3...@googlegroups.com
I recommend using an inverted range for the y-scale, so that it always
encodes position:

var y = d3.scale.linear()
.domain([minValue, maxValue])
.range([height, 0]);

When you compute the "y" attribute of a rect, you can use the y-scale
directly. For the height attribute, you'll have to use height - y(d),
but that seems reasonable to me. When you use an inverted range this
way, you can also use the scale with a d3.svg.axis, and it will do the
right thing.

Mike

Phrogz

unread,
Mar 19, 2012, 1:44:47 PM3/19/12
to d3...@googlegroups.com
On Monday, March 19, 2012 11:28:24 AM UTC-6, Nils wrote:
Are there any helpers within d3 to make this job easier? Such as an
inverted scale or perhaps I can draw svg shapes by specifying their
bottom + height, rather than y-position + height?

Unless I misunderstand you, if you are using a d3.scale.linear all you have to do is invert either the domain or range values. For example:

var y = d3.scale.linear().domain([0,100]).range([0,300]);
console.log( y(0), y(50), y(100) );
//-> [0, 150, 300]

var y2 = d3.scale.linear().domain([0,100]).range([450,150]);
console.log( y2(0), y2(50), y2(100) );
//-> [450, 300, 150]

The first example maps increasing x to increasing y, which is not what you wanted. The second one maps increasing x to decreasing y. (It also offsets x=100 to y=150, in case you needed padding.)

Nils

unread,
Mar 27, 2012, 7:46:25 AM3/27/12
to d3-js
Thanks both.
I had also switched to this method after posting but it's good to have
it confirmed, in case I had missed something.
Reply all
Reply to author
Forward
0 new messages