Skip to content

Instantly share code, notes, and snippets.

@ZJONSSON
Created November 2, 2011 16:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZJONSSON/1334054 to your computer and use it in GitHub Desktop.
Save ZJONSSON/1334054 to your computer and use it in GitHub Desktop.
Icesave capital structure - nest/layout example
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.29.1"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?1.29.1"></script>
<STYLE>
body { font-size:14px;margin-left:20px}
.axis {
shape-rendering: crispEdges;
}
.tick {
stroke: #D0D0D0 ;
stroke-dasharray: 4;
stroke-width:1px;
}
.y.axis path, .x.axis path, .y2.axis path {
fill: none;
stroke: #000;
}
.title { font-size:16px;}
.box { float:left;margin:10px;padding:10px;border-style: dotted;border-width:1px}
</STYLE>
</head>
<body>
<div id="chart"></div>
<div class="box">
<input type="radio" name="group1" id="priority" checked>No agreement - automatic subrogation<br>
<input type="radio" name="group1" id="prorata">Icesave agreement - pari-passu distribution<br>
</div>
<div class="box">
<input type="radio" name="group2" id="relative" checked>View Relative<br>
<input type="radio" name="group2" id="absolute">View Absolute<br>
</div><div style="clear:both"></div>
<br>
Red areas contain balances up to the minimum-guarantee. Green areas represent balances that are in excess of the minimum-guarantee.<br>
Deposit accounts are split into the following categories:
<ul>
<li>Category A: accounts with less than 20k EUR</li>
<li>Category B: accounts with more than 20k EUR and less than 40K EUR</li>
<li>Category C: accounts with more than 40k EUR</li>
</ul>
<br>(C) 2011 <a href="mailto:ziggy.jonsson.nyc@gmail.com">ziggy.jonsson.nyc@gmail.com</a>
<script type="text/javascript">
data = [{group:'A',party:'TIF',amount:1543,accts:133377,balance:11.57,total:1543},
{group: 'A',party:'FSCS',amount:0,accts:133377,balance:0,total:1543},
{group: 'B',party:'TIF',amount:1544,accts:63214,balance:21,total:1544+683},
{group: 'B',party:'FSCS',amount:683,accts:63214,balance:14.21,total:1544+683},
{group: 'C',party:'TIF',amount:896,accts:32579,balance:21,total:896+2121},
{group: 'C',party:'FSCS',amount:2121,accts:32579,balance:71.61,total:896+2121}]
by_party=d3.nest().key(function(d) { return d.party}).sortKeys(d3.descending).entries(data)
by_group=d3.nest().key(function(d) { return d.group}).sortKeys(d3.ascending).entries(data)
text=[]
h=200
w=400
x=[]
x=y=xAxis=yAxis=[]
x=d3.scale.linear().domain([0,4739+2047]).range([0,w]);
y=d3.scale.linear().domain([0,100]).range([h,0]);
xAxis = d3.svg.axis().scale(x).ticks(10).tickSize(-h)
yAxis = d3.svg.axis().scale(y).ticks(10).tickSize(-w).orient("left")
function recalc(duration) {
duration = duration ? duration : 0;
percent = d3.select("#relative").property("checked")
paripassu = d3.select("#prorata").property("checked")
if (!paripassu) {
d3.layout.stack()
.values(function(d) { return d.values})
.x(function(d,i) { return d.group})
.y(function(d) { return (percent) ? d.amount / d.total *100 : d.balance})(by_party)
d3.layout.stack()
.values(function(d) { return d.values})
.x(function(d,i) { return d.party})
.y(function(d) { return (percent) ? d.total : d.accts})
.out(function(d,y0,y) {
d.x0=y0;
d.x=y;
})(by_group)
} else {
d3.layout.stack()
.values(function(d) { return [d]})
.y(function(d) { return (percent) ? d.amount: (d.amount==0 ? 0 : (d.accts*d.amount/d.total))})
.out(function(d,y0,y) {
d.x0=y0;
d.x=y;
d.y0=0;
d.y= (percent) ? 100 : d.total/d.accts*1000;
})(data)
}
y.domain([0,d3.max(data,function(d) { return d.y0+d.y})])
x.domain([0,d3.max(data,function(d) { return d.x0+d.x})])
setTimeout(function(){d3.select(".x.title").text(percent ? "Amounts in EUR million" : "Deposit account no.")},duration*2/3)
setTimeout(function(){d3.select(".y.title").text(percent ? "Recovery percentage" : "Account size - EUR '000")},duration*2/3)
redraw(duration)
}
//
function redraw(duration) {
boxes=boxes.data(data,function(d) { return d.group+" "+d.party})
boxes.enter()
.append("svg:rect")
.attr("class","boxes")
.style("fill","green")
.style("stroke","black")
.style("fill",function(d) { return d.party=='TIF' ? 'darkred' : "green"})
.style("opacity",function(d) { return (d.amount == 0) ? 0 : 0.9})
.append("svg:title")
.text(function(d) { return d.group+" "+d.party+" "+d.amount+"m EUR"})
labels=labels.data(data,function(d) { return d.group+" "+d.party})
text=labels.enter()
.append("svg:text")
.attr("class","labels")
.style("stroke","white")
.style("opacity",function(d) { return (d.amount == 0) ? 0 : 0.9})
.style("stoke","none")
.style("fill","white")
text.append("svg:tspan").text(function(d) { return d.group+" "+d.party}).style("text-anchor","middle")
text.append("svg:tspan").attr("dy","1.3em").attr("dx","-2.5em").text(function(d) { return d.amount+"m"}).style("text-anchor","middle")
boxes.transition().duration(duration)//function(d,i) { return duration*(1+i/6)})
.attr("x",function(d) {return x(d.x0);})
.attr("width",function(d) {return x(d.x);})
.attr("height",function(d) {return y(0)-y(d.y);})
.attr("y",function(d) {return y((d.y+d.y0))})
.attr("ID",function(d) { return "x0: "+d.x0+" x:"+d.x+" y0:"+d.y0+" y:"+d.y})
labels.transition().duration(duration)
.attr("x",function(d) { return x(d.x0)+x(d.x/2)})
.attr("y",function(d) { return y(d.y/2+d.y0)})
x_ax.transition().duration(duration).call(xAxis)
y_ax.transition().duration(duration).call(yAxis)
}
svg=d3.select("#chart")
.append("svg:svg")
.attr("height",h)
.attr("width",w)
x_ax=svg.append("svg:g")
.attr("class","x axis")
.attr("transform","translate(0,"+h+")")
y_ax=svg.append("svg:g")
.attr("class","y axis")
boxes=svg.append("svg:g").selectAll(".boxes")
labels=svg.append("svg:g").selectAll(".labels")
recalc(0)
setTimeout(function() { chartTitles(svg,{chartTitle:"Icesave claims capital structure",xTitle:"Amount in EUR million",yTitle:"Recovery percentage"})},100)
d3.selectAll("input").on("click",function() { recalc(1000) })
// Helper function
function chartTitles(svg,titles) {
svg.selectAll(".title").remove()
bbox = svg[0][0].getBBox()
xbbox = svg.select(".x.axis")[0][0] ? svg.select(".x.axis")[0][0].getBBox() : svg[0][0].getBBox();
ybbox = svg.select(".y.axis")[0][0] ? svg.select(".y.axis")[0][0].getBBox() : svg[0][0].getBBox();
console.log(titles)
console.log(titles.chartTitle)
if (titles.chartTitle) {
svg.append("svg:text")
.text(titles.chartTitle)
.attr("class","main title")
.attr("x",xbbox ? xbbox.x+xbbox.width/2 : bbox.x+bbox.width/2)
.attr("y",0)
.attr("dy","-1em")
.style("text-anchor","middle")
console.log("I'm In")
}
if (titles.xTitle){
svg.append("svg:text")
.text(titles.xTitle)
.attr("class","x title")
.attr("x",xbbox.width/2)
.attr("y",ybbox.height)
.attr("dy","1em")
.style("text-anchor","middle")
}
if (titles.yTitle) {
console.log("bbox: ")
console.log(bbox)
console.log(parseFloat(bbox.y)+parseFloat(bbox.height)/2)
svg.append("svg:g")
.attr("transform","translate("+
(parseFloat(bbox.x)-18)+" "
+String(+ybbox.y+parseFloat(ybbox.height)/2)+") rotate(-90)")
.append("svg:text")
.attr("class","y title")
.text(titles.yTitle)
.style("text-anchor","middle")
}
if (titles.y2Title) {
svg.append("svg:g")
.attr("transform","translate("+(parseFloat(bbox.x)+bbox.width+5)+" "+bbox.y+bbox.height/2+") rotate(90)")
.append("svg:text")
.attr("class","y2 title")
.text(titles.y2Title)
.style("text-anchor","middle")
}
bbox=svg[0][0].getBBox()
svg.attr("viewBox",(+bbox.x-1)+" "+(+bbox.y-5)+" "+(+bbox.width+2)+" "+(+bbox.height+10))
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment