Skip to content

Instantly share code, notes, and snippets.

@milroc
Forked from ZJONSSON/index.html
Last active October 6, 2015 12:08
Show Gist options
  • Save milroc/2991587 to your computer and use it in GitHub Desktop.
Save milroc/2991587 to your computer and use it in GitHub Desktop.
axes as whitespace

This is a fork of Ziggy Jonsson's Bar Stack (flex lao) to add to this conversation.

The purpose of this gist was to recommend using whitespace to represent the axes of visualizations, as they signify the zero point in the opposite dimensions encoding. Additionally, this enhances the users comprehension because positive and negative areas are able to be assessed independently.

When doing visual encoding, we tend to ignore whitespace and let 0's handle themselves. To learn about other techniques around this concept, refer to: The Design of Nothing: Null, Zero, Blank by Andy Kirk (@visualisingdata).

Proposed Improvements:

  • aesthetics (very little changes from original example were made).
  • transitions that serve a purpose and flow with the expectation of the reader.
<!DOCTYPE html>
<html>
<head>
<script src="http://mbostock.github.com/d3/d3.v2.js"></script>
<title>barStack</title>
<style>
.axis text {
font: 10px sans-serif;
}
.axis path {
fill: none;
stroke: #FFF;
stroke-width:4;
shape-rendering: crispEdges;
}
.axis line {
display: none;
}
</style>
</head>
<body>
<script type="text/javascript" >
function barStack(d) {
var l = d[0].length
while (l--) {
var posBase = 0, negBase = 0;
d.forEach(function(d) {
d=d[l]
d.size = Math.abs(d.y)
if (d.y<0) {
d.y0 = negBase
negBase-=d.size
} else
{
d.y0 = posBase = posBase + d.size
}
})
}
d.extent= d3.extent(d3.merge(d3.merge(d.map(function(e) { return e.map(function(f) { return [f.y0,f.y0-f.size]})}))))
return d
}
/* Here is an example */
var data = [[{x:1,y:3},{x:2,y:6},{x:3,y:-3}],
[{x:1,y:4},{x:2,y:-2},{x:3,y:-9}],
[{x:1,y:10},{x:2,y:-3},{x:3,y:4}]]
var h=500
,w=500
,margin=10
,color = d3.scale.category10()
,x = d3.scale.ordinal()
.domain(d3.range(data[0].length+1))
.rangeRoundBands([margin,w-margin], .1)
,y = d3.scale.linear()
.range([h-margin,0+margin])
,xAxis = d3.svg.axis().scale(x).orient("bottom").tickSize(6, 0)
,yAxis = d3.svg.axis().scale(y).orient("left")
barStack(data)
y.domain(data.extent)
svg = d3.select("body")
.append("svg")
.attr("height",h)
.attr("width",w)
svg.selectAll(".series").data(data)
.enter().append("g").classed("series",true).style("fill", function(d,i) { return color(i)})
.selectAll("rect").data(Object)
.enter().append("rect")
svg.append("g").attr("class","axis x")
svg.append("g").attr("class","axis y")
var layout = 0,dur=0
redraw()
dur = 1500
function redraw() {
if (layout=!layout) {
/* Readjust the range to witdh and height */
x.rangeRoundBands([margin,w-margin], .1)
y.range([h-margin,0+margin])
/* Reposition and redraw axis */
svg.select(".x.axis")
.transition().duration(dur)
.attr("transform","translate (0 "+y(0)+")")
.call(xAxis.orient("bottom"))
svg.select(".y.axis")
.transition().duration(dur)
.attr("transform","translate ("+x(0)+" 0)")
.call(yAxis.orient("left"))
/* Reposition the elements */
svg.selectAll(".series rect")
.transition().duration(dur)
.attr("x",function(d,i) { return x(d.x)})
.attr("y",function(d) { return y(d.y0)})
.attr("height",function(d) { return y(0)-y(d.size)})
.attr("width",x.rangeBand())
} else {
/* Readjust the range to witdh and height */
x.rangeRoundBands([h-margin,0+margin], .1)
y.range([margin,w-margin])
/* Reposition and redraw axis */
svg.select(".x.axis")
.transition().duration(dur)
.attr("transform","translate ("+y(0)+" 0)")
.call(xAxis.orient("left"))
svg.select(".y.axis")
.transition().duration(dur)
.attr("transform","translate (0 "+x(0)+")")
.call(yAxis.orient("bottom"))
/* Reposition the elements */
svg.selectAll(".series rect")
.transition().duration(dur)
.attr("y",function(d,i) { return x(d.x)})
.attr("x",function(d) { return y(d.y0-d.size)})
.attr("width",function(d) { return y(d.size)-y(0)})
.attr("height",x.rangeBand())
}
d3.select("body").append("button")
.attr("type","button")
.text("Change Layout")
.style("position","absolute")
.style("left","5px")
.style("top","5px")
.on("click",redraw)
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment