xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<title>Treasury</title>
<script type="text/javascript" src="https://d3js.org/d3.v3.js"></script>
<style>
text.txt {
font-family: tahoma;
}
rect.backlistener {
fill: none;
pointer-events: all;
}
rect.background {
fill: none;
pointer-events: all;
}
rect.current {
pointer-events: all;
stroke: #222222;
stroke-width: 2;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: tahoma;
font-size: 12px;
}
#tooltip {
text-align: center;
position: absolute;
width: 200px;
height: auto;
padding: 10px;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
font-family: tahoma;
font-size: 16px;
line-height: 20px;
}
#basettip {
text-align: center;
position: absolute;
width: 200px;
height: auto;
padding: 10px;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#basettip.hidden {
display: none;
}
#basettip p {
margin: 0;
font-family: tahoma;
font-size: 16px;
line-height: 20px;
}
#source {
text-align: center;
position: absolute;
width: 200px;
height: auto;
padding: 10px;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#source.hidden {
display: none;
}
#source p {
margin: 0;
font-family: tahoma;
font-size: 16px;
line-height: 20px;
}
</style>
</head>
<body>
<button id="byGender">View by Gender</button>
<button id="byEthni">View by Ethnicity</button>
<button id="byAge">View by Age group</button>
<div id="tooltip" class="hidden">
<p><span id="people"> . </span></p>
<p>That is <span id="percent"> 100.0 </span>% of this income tier.</p>
</div>
<div id="basettip" class="hidden">
<p><span id="people"> . </span></p>
<p>That is <span id="percent"> 100.0 </span>% of the NZ population.</p>
</div>
<div id="source" class="hidden">
<p>*source: 2006 census</p>
</div>
<script type="text/javascript" src="../d3/d3.v3.js"></script>
<script type="text/javascript">
var h=700, w=1200, margin=5, padding=20, wside = 300;
var maxw = 600, maxwcur;
var maxVal;
var data, dnest, nodes;
var NbLines;
var caseDisplay;
var xScale = d3.scale.linear(), spreadScale = d3.scale.ordinal(),
yScale = d3.scale.linear().domain([0,50000,130000]).range([0,2*h/3,h]),
yScaleAx = d3.scale.linear().domain([0,50000,130000]).range([h,h/3,0]),
wScale = d3.scale.linear(), oScale = d3.scale.linear().domain([0,1]).range([0.2,0.9])
areaScale = d3.scale.linear(), cScale = d3.scale.linear().range(["#0033FF","#CC0000"])
toUnit = d3.scale.ordinal().rangeBands([0,1])
//cScale = d3.scale.category10();
var commasFormatter = d3.format(",.0f");
var yAxis = d3.svg.axis()
.scale(yScaleAx) // scale to be used
.orient("right") // position of the text (values)
.tickValues([0,5000,10000,20000,50000,70000,100000])
.tickFormat(function(d) { return "$" + commasFormatter(d); });
var entier = d3.format(",.0f"),
perc = d3.format(".1f");
var base, current, curlist;
var listGender=["male","female"],
listEthni = ["European","Maori","Pacific","Asian","Other"],
listAge = ["15-19","20-29","30-39","40-49","50-59","60-69","70-79","80+"],
nodesw = [];
var hierarchy = d3.layout.partition().sort(null);
var svg = d3.select("body").append("svg")
.attr("width", w+200+wside+padding)
.attr("height", h+2*padding) ;
var gmain = svg.append("g")
.attr("transform", "translate(" +(100+padding)+ "," +padding+ ")" );
var gside = svg.append("g")
.attr("transform", "translate(" +(100+padding+w)+ "," +padding+ ")" );
gmain.append("rect") // background rectangle to listen to click events
.attr("class", "background")
.attr("width", w)
.attr("height", h)
.attr("transform", "translate(" +padding/2+ "," +padding/2+ ")" )
// .attr("stroke","#DDDDDD").attr("stroke-width",2).attr("stroke-opacity",0.5)
.attr("fill","green").attr("opacity",0.3)
.on("click", back); // "back" function will return to higher level
d3.csv("incDistr.csv", function(dd){
data = dd;
NbLines = data.length;
for (ii=0;ii<NbLines;ii++){
data[ii].value = parseFloat(data[ii].value);
data[ii].tierh = parseFloat(data[ii].tierh);
data[ii].tierPos = parseFloat(data[ii].tierPos);
}
dnest = d3.nest()
.key(function(d) { return d.tier; })
.entries(dd);
nodes = {name: "totpop", children:[],tierh:0, tierPos:0};
for (ii=0;ii<dnest.length;ii++){
var tmp = [], add;
tmp = {name: dnest[ii].key, children:[],
tierh:dnest[ii].values[0].tierh, tierPos:dnest[ii].values[0].tierPos}
for (jj=0;jj<dnest[ii].values.length;jj++){
tmp.children.push(dnest[ii].values[jj])
}
nodes.children.push(tmp)
}
nodes = hierarchy(nodes);
NbLines = nodes.length;
maxVal = 0; var htmp;
for (ii=1;ii<NbLines;ii++){if(nodes[ii].value>maxVal){maxVal=nodes[ii].value;}}
areaScale.domain([0,maxVal]).range([0,(maxw*yScale(5000))]);
for (ii=1;ii<NbLines;ii++){
if (nodes[ii].tierPos>50000) {
nodes[ii].h = (yScale(50000+nodes[ii].tierh)-yScale(50000)-margin)
nodes[ii].w = (areaScale(nodes[ii].value)/(yScale(50000+nodes[ii].tierh)-yScale(50000))); }
else {
nodes[ii].w = (areaScale(nodes[ii].value)/yScale(nodes[ii].tierh))
nodes[ii].h = (yScale(nodes[ii].tierh)-margin)}
}
nodesw[0] = 0;
// display scale
var aa = Math.sqrt(areaScale(10000));
scale = gside.append("rect")
.attr("rx",6).attr("ry",6)
.attr("y",100).attr("x",5)
.attr("height",aa)
.attr("width",aa)
.attr("fill","none")
.attr("stroke","#BBBBBB").style("stroke-dasharray",("3,2")).attr("stroke-width",2);
gside.append("text").attr("class","txt")
.attr("y", 100+aa/2).attr("x",aa+15)
.attr("font-size","14px").attr("fill","#BBBBBB")
.attr("text-anchor","left")
.text("10,000 people");
// first display: level 0
caseDisplay = 0;
base = gmain.selectAll(".base")
.data(nodes).enter()
.append("rect").attr("class","base")
.attr("rx",6).attr("ry",6)
.attr("y",function(d){return (h-yScale(d.tierPos));})
.attr("height",function(d,i){return (d.depth==1)?d.h:0})
.attr("width",function(d,i){return (d.depth==1)?d.w:0})
.attr("x",function(d,i){return (d.depth==1)?(w/2-d.w/2):0})
.attr("fill","#BBBBBB").attr("opacity",0.7);
base.on("mouseover", basemov)
.on("mouseout", basemout)
svg.append("g")
.attr("class","axis")
.attr("transform", "translate("+(2*padding)+","+(padding/2)+")")
.call(yAxis) ;
d3.select("#byGender").on("click", function () {
caseDisplay = 1;
maxwcur = 0;
// Re-organise nodes
dnest = d3.nest()
.key(function(d) { return d.tier; })
.key(function(d) { return d.gender; })
.entries(data);
nodes = {name: "totpop", children:[],tierh:0, tierPos:0};
for (ii=0;ii<dnest.length;ii++){
var tmp = [], add;
tmp = {name: dnest[ii].key, children:[],
tierh:dnest[ii].values[0].values[0].tierh, tierPos:dnest[ii].values[0].values[0].tierPos}
for (jj=0;jj<dnest[ii].values.length;jj++){
add = {name: dnest[ii].values[jj].key, children:[],
tierh:dnest[ii].values[jj].values[0].tierh, tierPos:dnest[ii].values[jj].values[0].tierPos}
for (kk=0;kk<dnest[ii].values[jj].values.length;kk++){
add.children.push(dnest[ii].values[jj].values[kk])
}
tmp.children.push(add)
}
nodes.children.push(tmp)
}
nodes = hierarchy(nodes);
toUnit.domain(listGender)
cScale.domain([0,(1-toUnit.rangeBand())])
spreadScale.domain(listGender)
curlist = listGender;
createLayer();
})
d3.select("#byAge").on("click", function () {
caseDisplay = 2;
maxwcur = 0;
// Re-organise nodes
dnest = d3.nest()
.key(function(d) { return d.tier; })
.key(function(d) { return d.agetier; })
.entries(data);
nodes = {name: "totpop", children:[],tierh:0, tierPos:0};
for (ii=0;ii<dnest.length;ii++){
var tmp = [], add;
tmp = {name: dnest[ii].key, children:[],
tierh:dnest[ii].values[0].values[0].tierh, tierPos:dnest[ii].values[0].values[0].tierPos}
for (jj=0;jj<dnest[ii].values.length;jj++){
add = {name: dnest[ii].values[jj].key, children:[],
tierh:dnest[ii].values[jj].values[0].tierh, tierPos:dnest[ii].values[jj].values[0].tierPos}
for (kk=0;kk<dnest[ii].values[jj].values.length;kk++){
add.children.push(dnest[ii].values[jj].values[kk])
}
tmp.children.push(add)
}
nodes.children.push(tmp)
}
nodes = hierarchy(nodes);
toUnit.domain(listAge)
cScale.domain([0,(1-toUnit.rangeBand())])
spreadScale.domain(listAge)
curlist = listAge;
createLayer();
})
d3.select("#byEthni").on("click", function () {
caseDisplay = 3;
maxwcur = 0;
// Re-organise nodes
dnest = d3.nest()
.key(function(d) { return d.tier; })
.key(function(d) { return d.ethnicity; })
.entries(data);
nodes = {name: "totpop", children:[],tierh:0, tierPos:0};
for (ii=0;ii<dnest.length;ii++){
var tmp = [], add;
tmp = {name: dnest[ii].key, children:[],
tierh:dnest[ii].values[0].values[0].tierh, tierPos:dnest[ii].values[0].values[0].tierPos}
for (jj=0;jj<dnest[ii].values.length;jj++){
add = {name: dnest[ii].values[jj].key, children:[],
tierh:dnest[ii].values[jj].values[0].tierh, tierPos:dnest[ii].values[jj].values[0].tierPos}
for (kk=0;kk<dnest[ii].values[jj].values.length;kk++){
add.children.push(dnest[ii].values[jj].values[kk])
}
tmp.children.push(add)
}
nodes.children.push(tmp)
}
nodes = hierarchy(nodes);
toUnit.domain(listEthni)
cScale.domain([0,(1-toUnit.rangeBand())])
spreadScale.domain(listEthni);
curlist = listEthni;
createLayer();
})
})
function back(){
caseDisplay = 0;
gmain.selectAll(".current").transition().duration(500)
.attr("x",function(d){ return (d.depth==2)?(w/2+d.xx):0;})
base.on("mouseover", basemov)
.on("mouseout", basemout)
// gmain.selectAll(".base").transition().duration(1000).delay(500).attr("opacity",1);
gmain.selectAll(".base").transition().duration(1000).delay(750).attr("opacity",1);
gmain.selectAll(".current").transition().duration(1000).delay(750).attr("opacity",1e-6);
gmain.selectAll(".current").transition().delay(1750).remove();
svg.selectAll(".backlistener").remove();
gmain.selectAll(".legend").remove();
}
function createLayer() {
maxwcur = 0;
NbLines = nodes.length;
for (ii=1;ii<NbLines;ii++){
if (nodes[ii].tierPos>50000) {
nodes[ii].h = (yScale(50000+nodes[ii].tierh)-yScale(50000)-margin)
nodes[ii].w = (areaScale(nodes[ii].value)/(yScale(50000+nodes[ii].tierh)-yScale(50000))); }
else {
nodes[ii].w = (areaScale(nodes[ii].value)/yScale(nodes[ii].tierh))
nodes[ii].h = (yScale(nodes[ii].tierh)-margin)}
if (nodes[ii].depth==2) {
wScale.domain([0,1]).range([0,nodes[ii].parent.w]);
nodes[ii].w = wScale(nodes[ii].dx/nodes[ii].parent.dx);
nodes[ii].xx = wScale((nodes[ii].x-nodes[ii].parent.x)/nodes[ii].parent.dx)-nodes[ii].parent.w/2;
if (nodes[ii].w > maxwcur){maxwcur = nodes[ii].w;}
}
}
nodesw[0] = 0;
current = gmain.selectAll(".current")
.data(nodes).enter()
.append("rect").attr("class","current")
.attr("rx",6).attr("ry",6)
.attr("y",function(d){return (h-yScale(d.tierPos));})
.attr("height",function(d,i){return (d.depth==0)?0:d.h})
.attr("width",function(d){return (d.depth==2)?d.w:0})
.attr("x",function(d,i){ var wpar, xtmp;
if (d.depth==2){
console.log(i+", "+d.xx)
xtmp = d.xx;
if (d.parent.maxdx>0){if (xtmp>d.parent.maxdx){d.parent.maxdx=xtmp; d.parent.wmaxdx=d.w}}
else {d.parent.maxdx=xtmp; d.parent.wmaxdx=d.w}
}
else{xtmp=0}
return w/2+xtmp;})
.attr("fill","#BBBBBB").attr("opacity",1e-6)
.attr("stroke-opacity",1e-6)
.on("click",Spread);
spreadScale.rangeBands([maxwcur/2,w+maxwcur/2]);
gmain.selectAll(".current").transition().duration(500)
.attr("opacity",function(d){ return (d.depth>0)?(oScale(d.dx/d.parent.dx)):(1e-6)})
.attr("fill",function(d) {return cScale(toUnit(d.name))});
gmain.selectAll(".base").on("mouseover",null).on("mouseout",null).on("click",back)
gmain.selectAll(".base").transition().duration(500).attr("opacity",1e-6);
}
function Spread() {
gmain.selectAll(".current").transition().duration(500)
.attr("x",function(d){var wtmp, xtmp;
if (d.depth==2){
wtmp = d3.select(this).attr("width")
xtmp = spreadScale(d.name)-wtmp/2;
}
else{xtmp=0}
return xtmp;})
current.on("mouseover", function(d){ var txtmp, txtinc;
var xPos = parseFloat(d3.select(this).attr("x"));
var yPos = parseFloat(d3.select(this).attr("y"));
d3.select(this).attr("stroke-opacity",1);
if (d.depth==2){
var aa = d3.select("#tooltip")
// .style("left", (xPos+200) + "px")
.style("left", (w+100) + "px")
// .style("top", (yPos+50) + "px");
.style("top", (h/2) + "px");
var nb = entier(d.value);
var percent = perc((d.value/d.parent.value)*100);
txtinc = extrTxtInc(d);
switch (caseDisplay) {
case 1:
var bb;
(d.name == "male")?(bb="* men "):(bb="* women ");
txtmp = nb + bb + txtinc; break;
case 3:
txtmp = nb + "* people of "+d.name+" ethnicity" + txtinc; break;
case 2:
txtmp = nb + "* people aged " +d.name+ txtinc; break;
}
aa.select("#people").text(txtmp)
aa.select("#percent").text(percent)
d3.select("#tooltip").classed("hidden",false);
d3.select("#source")
.style("left", (w+100) + "px")
.style("top", (h-100) + "px")
.classed("hidden",false);
}
})
.on("mouseout", function(d){
d3.select(this).attr("stroke-opacity",1e-6);
d3.select("#tooltip").classed("hidden",true);
d3.select("#source").classed("hidden",true);
})
// svg.append("svg:rect") // background rectangle to listen to click events
// .attr("class", "backlistener")
// .attr("width", w)
// .attr("height", h)
// .attr("transform", "translate(" +padding/2+ "," +padding/2+ ")" )
// .on("click", back);
gmain.selectAll(".legend")
.data(curlist).enter()
.append("g").attr("class","legend")
.attr("transform", function(d) {
return "translate(" +spreadScale(d)+ "," +(h-20)+ ")" })
.append("text").attr("class","txt")
.attr("y", 0)
.attr("x",0)
.attr("font-size","14px")
.attr("text-anchor","middle")
.attr("opacity",1e-6)
.text(function (d){return d});
gmain.selectAll(".txt").transition().duration(500).delay(500)
.attr("opacity",1)
}
function extrTxtInc(d) { var txtmp, t0 =" earn ", t1, t2=" yearly";
switch (d.parent.name) {
case "No Income":
t0 = " have "
t1 = "no income";
t2 = ""; break;
case "<5000":
t1 = "between $1 and $5,000"; break;
case "<10000":
t1 = "between $5,000 and $10,000"; break;
case "<15000":
t1 = "between $10,000 and $15,000"; break;;
case "<20000":
t1 = "between $15,000 and $20,000"; break;
case "<25000":
t1 = "between $20,000 and $25,000"; break;
case "<30000":
t1 = "between $25,000 and $30,000"; break;
case "<40000":
t1 = "between $30,000 and $40,000"; break;
case "<50000":
t1 = "between $40,000 and $50,000"; break;
case "<70000":
t1 = "between $50,000 and $70,000"; break;
case "<100000":
t1 = "between $70,000 and $100,000"; break;
case ">100000":
t1 = "over $100,000"; break;
}
txtmp = t0+t1+t2;
return txtmp;
}
function basemov(d) {
var txtmp, txtinc;
d3.select(this).attr("opacity",0.95);
if (d.depth==1){
var aa = d3.select("#basettip")
.style("left", (w+100) + "px")
.style("top", (h/2) + "px");
var nb = entier(d.value);
var percent = perc((d.value/d.parent.value)*100);
var t0 =" earn ", t1, t2=" yearly";
switch (d.name) {
case "No Income":
t0 = " have "
t1 = "no income";
t2 = ""; break;
case "<5000":
t1 = "between $1 and $5,000"; break;
case "<10000":
t1 = "between $5,000 and $10,000"; break;
case "<15000":
t1 = "between $10,000 and $15,000"; break;;
case "<20000":
t1 = "between $15,000 and $20,000"; break;
case "<25000":
t1 = "between $20,000 and $25,000"; break;
case "<30000":
t1 = "between $25,000 and $30,000"; break;
case "<40000":
t1 = "between $30,000 and $40,000"; break;
case "<50000":
t1 = "between $40,000 and $50,000"; break;
case "<70000":
t1 = "between $50,000 and $70,000"; break;
case "<100000":
t1 = "between $70,000 and $100,000"; break;
case ">100000":
t1 = "over $100,000"; break;
}
txtmp = nb +"* NZ residents"+t0+t1+" annually";
aa.select("#people").text(txtmp)
aa.select("#percent").text(percent)
d3.select("#basettip").classed("hidden",false);
d3.select("#source")
.style("left", (w+100) + "px")
.style("top", (h-100) + "px")
.classed("hidden",false);
}
}
function basemout(d){
d3.select(this).attr("opacity",0.7);
d3.select("#basettip").classed("hidden",true);
d3.select("#source").classed("hidden",true);
}
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.js to a secure url
https://d3js.org/d3.v3.js