|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<script src="http://mbostock.github.com/d3/d3.v2.js"></script> |
|
<script src="//cdnjs.cloudflare.com/ajax/libs/d3-legend/1.1.0/d3-legend.js"></script> |
|
<title></title> |
|
<style> |
|
.axis text { |
|
font: 10px sans-serif; |
|
} |
|
.axis path { |
|
fill: none; |
|
stroke: #FFF; |
|
stroke-width:4; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.axis line { |
|
display: none; |
|
} |
|
.color-legend text { |
|
font-family: 'Open Sans', sans-serif; |
|
font-size: 19pt; |
|
} |
|
|
|
</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 |
|
|
|
var legend = d.append("g") |
|
.attr("font-family", "sans-serif") |
|
.attr("font-size", 10) |
|
.attr("text-anchor", "end") |
|
.selectAll("g") |
|
.data(keys.slice().reverse()) |
|
.enter().append("g") |
|
.attr("transform", function(d) { return "translate(0," + d.z + ")"; }); |
|
legend.append("rect") |
|
.attr("x", width - 19) |
|
.attr("width", 19) |
|
.attr("height", 19) |
|
.attr("fill", z); |
|
|
|
legend.append("text") |
|
.attr("x", width - 24) |
|
.attr("y", 9.5) |
|
.attr("dy", "0.505856em") |
|
.text(function(d) { return d; }); |
|
} |
|
|
|
/* Here is an example */ |
|
|
|
var data = [[{x:"Africa",y:-0.756097561,z:"Abortion"}, |
|
{x:"Asia",y:1.473684211,z:"Abortion"}, |
|
{x:"Europe",y:6.135135135,z:"Abortion"}, |
|
{x:"North America",y:-0.846153846,z:"Abortion"}, |
|
{x:"Oceania",y:3,z:"Abortion"}, |
|
{x:"South America",y:-2.4,z:"Abortion"}], |
|
[{x:"Africa",y:0.073170732,z:"Domestic violence"}, |
|
{x:"Asia",y:0.868421053,z:"Domestic violence"}, |
|
{x:"Europe",y:1.594594595,z:"Domestic violence"}, |
|
{x:"North America",y:3.307692308,z:"Domestic violence"}, |
|
{x:"Oceania",y:3.5000,z:"Domestic violence"}, |
|
{x:"South America",y:5.8,z:"Domestic violence"}], |
|
[{x:"Africa",y:-0.731707317,z:"Harassment"}, |
|
{x:"Asia",y:-1.368421053,z:"Harassment"}, |
|
{x:"Europe",y:0.864864865,z:"Harassment"}, |
|
{x:"North America",y:-0.769230769,z:"Harassment"}, |
|
{x:"Oceania",y:1.5,z:"Harassment"}, |
|
{x:"South America",y:1.2,z:"Harassment"}], |
|
[{x:"Africa",y:1.634146341,z:"Constitution"}, |
|
{x:"Asia",y:1.157894737,z:"Constitution"}, |
|
{x:"Europe",y:0.405405405,z:"Constitution"}, |
|
{x:"North America",y:1.461538462,z:"Constitution"}, |
|
{x:"Oceania",y:0,z:"Constitution"}, |
|
{x:"South America",y:1.6,z:"Constitution"}], |
|
[{x:"Africa",y:2.41463414634146,z:"Other"}, |
|
{x:"Asia",y:1.3157894736842,z:"Other"}, |
|
{x:"Europe",y:3,z:"Other"}, |
|
{x:"North America",y:3,z:"Other"}, |
|
{x:"Oceania",y:3,z:"Other"}, |
|
{x:"South America",y:3,z:"Other"}], |
|
[{x:"Africa",y:1.48780487804878,z:"Property"}, |
|
{x:"Asia",y:1.36842105263158,z:"Property"}, |
|
{x:"Europe",y:3,z:"Property"}, |
|
{x:"North America",y:2.84615384615385,z:"Property"}, |
|
{x:"Oceania",y:3,z:"Property"}, |
|
{x:"South America",y:2.6,z:"Property"}], |
|
[{x:"Africa",y:1.09756097560976,z:"Work"}, |
|
{x:"Asia",y:-0.157894736842105,z:"Work"}, |
|
{x:"Europe",y:2.56756756756757,z:"Work"}, |
|
{x:"North America",y:1.15384615384615,z:"Work"}, |
|
{x:"Oceania",y:0.5,z:"Work"}, |
|
{x:"South America",y:3.2,z:"Work"}] |
|
|
|
] |
|
|
|
//var data = d3.csv("data.csv"); |
|
|
|
var h=500 |
|
,w=500 |
|
,margin=10 |
|
,color = d3.scale.category10() |
|
|
|
,x = d3.scale.ordinal() |
|
.domain(d3.range(1)) |
|
.rangeRoundBands([margin,w-margin], .1) |
|
|
|
,y = d3.scale.linear() |
|
.range([h-margin,0+margin]) |
|
|
|
,xAxis = d3.svg.axis().scale(x).orient("bottom") |
|
,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") |
|
.attr("x",function(d,i) { return x(d.x)}) |
|
.attr("y",function(d) { return y(d.y0)}) |
|
|
|
|
|
svg.append("g").attr("class","axis x") |
|
svg.append("g").attr("class","axis y") |
|
|
|
/*Legend*/ |
|
var foregroundBarLayer = svg.append("g"); |
|
|
|
var colorLegendG = svg.append("g") |
|
.attr("class", "color-legend") |
|
.attr("transform", "translate(596, 0)"); |
|
var nested = d3.nest() |
|
.key(function (d){ return d.z; }) |
|
.entries(data) |
|
var stack = d3.layout.stack() |
|
.y(function (d){ return d.y; }) |
|
.values(function (d){ return d.values; }); |
|
var colorScale = d3.scale.category10(); |
|
var layers = stack(nested.reverse()).reverse(); |
|
colorScale.domain(layers.map(function (layer){ |
|
return layer.key; |
|
})); |
|
|
|
var colorLegend = d3.legend.color() |
|
.scale(colorScale) |
|
.shapePadding(6.24) |
|
.shapeWidth(20) |
|
.shapeHeight(20) |
|
.labelOffset(5); |
|
|
|
colorLegendG.call(colorLegend); |
|
|
|
colorLegendG.selectAll("text").attr("z", 4); |
|
|
|
function listenForHover(selection, data){ |
|
selection |
|
.on("mouseover", function (d){ |
|
hoveredColorValue = d; |
|
render(data); |
|
}) |
|
.on("mouseout", function (d){ |
|
hoveredColorValue = null; |
|
render(data); |
|
}) |
|
.style("cursor", "pointer"); |
|
} |
|
|
|
listenForHover(colorLegendG.selectAll("rect"), data); |
|
listenForHover(colorLegendG.selectAll("text"), data); |
|
|
|
/*Legend.2*/ |
|
function render(data){ |
|
|
|
var nested = d3.nest() |
|
.key(function (d){ return d.z; }) |
|
.entries(data); |
|
|
|
var stack = d3.layout.stack() |
|
.y(function (d){ return d.y; }) |
|
.values(function (d){ return d.values; }); |
|
|
|
var layers = stack(nested.reverse()).reverse(); |
|
|
|
|
|
colorScale.domain(layers.map(function (layer){ |
|
return layer.key; |
|
})); |
|
|
|
colorLegendG.call(colorLegend); |
|
|
|
// Move the text down a bit. |
|
colorLegendG.selectAll("text").attr("y", 4); |
|
|
|
listenForHover(colorLegendG.selectAll("rect"), data); |
|
listenForHover(colorLegendG.selectAll("text"), data); |
|
} |
|
d3.csv("data.csv", render); |
|
/*Legend.2.E*/ |
|
|
|
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> |