|
function bubbleScale(setPath, setData, elem, opts){ |
|
|
|
var settings = { |
|
axisCategory: opts.axisCategory, |
|
axisValue: opts.axisValue, |
|
orientationVal: opts.orientationVal, |
|
rangeMax: opts.rangeMax, |
|
sortDescending: opts.sortDescending, |
|
chartHeight: opts.chartHeight, |
|
transSpeed: 700, |
|
dataPath: setPath + setData, |
|
chartContainerID: "#" + elem |
|
}; |
|
|
|
var margin = { |
|
top:0, |
|
left:20, |
|
right:20, |
|
bottom:20 |
|
}; |
|
|
|
var chartContainer = d3.select(settings.chartContainerID); |
|
var plotContainer = chartContainer.select(".plot-wrap.w-svg").html(''); |
|
|
|
var w = plotContainer.node().clientWidth - margin.left - margin.right, |
|
h = settings.chartHeight - margin.top - margin.bottom; |
|
// h = .7 * width; |
|
|
|
// cancel on mobile |
|
if(w < 576) { |
|
return; |
|
}; |
|
|
|
var premiseDiv = chartContainer.select("div.chart-premise"); |
|
|
|
// create inner div |
|
var div = plotContainer |
|
.append("div.svg-container") |
|
.style("width", (w + margin.left + margin.right) + "px") |
|
.style("height", (h + margin.top + margin.bottom) + "px"); |
|
|
|
// insert canvas inner div |
|
div.insert("canvas"); |
|
|
|
// append svg in inner div |
|
var svg = div |
|
.append("svg") |
|
.style("width", (w + margin.left + margin.right) + "px") |
|
.style("height", (h + margin.top + margin.bottom) + "px") |
|
.append("g.wrap") |
|
.translate([margin.left,margin.top]); |
|
|
|
d3.queue() |
|
.defer(d3.csv, settings.dataPath) |
|
.await(ready); |
|
|
|
var formatMoney = d3.format(".3n"); |
|
|
|
function ready(error, data){ |
|
if (error) throw "error: not loading data, bro"; |
|
|
|
// remove Ivan and Irene |
|
data = data.filter(function(d){ |
|
if (d["Event name"] !== "Louisiana Severe Storms" && d["Event name"] !== "Tropical Storm Allison") { |
|
return d; |
|
} |
|
}); |
|
|
|
// ui interaction |
|
var optionsArray = d3.keys(data[0]); |
|
|
|
// Remove Catastrophe, Events and Fatalities keys from UI options |
|
optionsArray = optionsArray.filter(function(d){ |
|
if (d !== "Year" && d !== "Event name" && d !== "Avg. claim") { |
|
return d; |
|
} |
|
}); |
|
|
|
data.forEach(function(d){ |
|
d.value = +d[settings.axisValue]; |
|
}); |
|
|
|
// sort data, highest to lowest |
|
data.sort(function(a,b){ |
|
return d3.descending(+a.value, +b.value) |
|
}); |
|
|
|
var maxx = d3.max(data, function(d){ return d.value; }); |
|
|
|
var scale = d3.scaleLinear() |
|
.domain([0, maxx]) |
|
.range([0,h/2]); |
|
|
|
// bubbles |
|
var bubble = svg.selectAll("circle.scale-fixed") |
|
.data(data) |
|
.enter() |
|
.append("g") |
|
.append("circle.scale-fixed") |
|
.attr("fill-opacity",".2") |
|
.attr("fill","#3fa0c6") |
|
.attr("stroke","#ffffff") |
|
.attr("stroke-width",".65px") |
|
.attr("r", function(d) { |
|
return scale(d.value); |
|
}) |
|
.attr("cx",w/2) |
|
.attr("cy",function(d){ |
|
return h - scale(d.value); |
|
}); |
|
|
|
// line indicator |
|
var rectLine = svg.selectAll("rect.anno-line") |
|
.data(data) |
|
.enter() |
|
.append("g") |
|
.append("rect.anno-line") |
|
.attr("width",function(d,i){ |
|
return w/2; |
|
}) |
|
.attr("height",".5") |
|
.attr("x",function(d,i){ |
|
if (i % 2) { |
|
return 0; |
|
} else { |
|
return w/2; |
|
} |
|
}); |
|
|
|
// line indicator |
|
rectLine |
|
.attr("y",function(d,i){ |
|
if (i >= 0 && i < (data.length - 1)) { |
|
var nextData = i>=0?rectLine.data()[i+1]:rectLine.data()[rectLine.data().length+1]; |
|
var thisHeight = scale(d.value) * 2; |
|
var nextHeight = scale(nextData.value) * 2; |
|
var newcoord = nextHeight + ((thisHeight - nextHeight) / 2); |
|
return h - (newcoord); |
|
} else { |
|
return h - scale(d.value); |
|
} |
|
}); |
|
|
|
// placement indicator |
|
var dot = svg.selectAll("circle.anno-dot") |
|
.data(data) |
|
.enter() |
|
.append("g") |
|
.append("circle.anno-dot") |
|
.attr("r", 4) |
|
.attr("cx",w/2); |
|
|
|
|
|
dot.attr("cy",function(d,i){ |
|
if (i >= 0 && i < (data.length - 1)) { |
|
var nextData = i>=0?dot.data()[i+1]:dot.data()[dot.data().length+1]; |
|
var thisHeight = scale(d.value) * 2; |
|
var nextHeight = scale(nextData.value) * 2; |
|
var newcoord = nextHeight + ((thisHeight - nextHeight) / 2); |
|
return h - (newcoord); |
|
} else { |
|
return h - scale(d.value); |
|
} |
|
}); |
|
|
|
// event LABEL EVENT |
|
var eventText = svg.selectAll("text.event-text") |
|
.data(data) |
|
.enter() |
|
.append("text.event-text") |
|
// stagger the placement of the rect, every other |
|
.attr("x",function(d,i){ |
|
if (i % 2) { |
|
return 0; |
|
} else { |
|
return w; |
|
} |
|
}) |
|
.attr("text-anchor",function(d,i){ |
|
if (i % 2) { |
|
return "start"; |
|
} else { |
|
return "end"; |
|
} |
|
}) |
|
.attr("dy","-6px") |
|
.text(function(d){ |
|
return d["Event name"]; |
|
}); |
|
|
|
eventText.attr("y",function(d,i){ |
|
// grab data of next key and math the distance between for placement |
|
if (i >= 0 && i < (data.length - 1)) { |
|
var nextData = i>=0?eventText.data()[i+1]:eventText.data()[eventText.data().length+1]; |
|
var thisHeight = scale(d.value) * 2; |
|
var nextHeight = scale(nextData.value) * 2; |
|
var newcoord = nextHeight + ((thisHeight - nextHeight) / 2); |
|
return h - (newcoord); |
|
} else { |
|
return h - scale(d.value); |
|
} |
|
}); |
|
|
|
// event VALUE |
|
var eventText = svg.selectAll("text.value-text") |
|
.data(data) |
|
.enter() |
|
.append("text.value-text") |
|
// stagger the placement of the rect, every other |
|
.attr("x",function(d,i){ |
|
if (i % 2) { |
|
return 0; |
|
} else { |
|
return w; |
|
} |
|
}) |
|
.attr("text-anchor",function(d,i){ |
|
if (i % 2) { |
|
return "start"; |
|
} else { |
|
return "end"; |
|
} |
|
}) |
|
.attr("dy","20px") |
|
.text(function(d){ |
|
var money = formatMoney(d["Total payout"]); |
|
return "$" + money + " Billion"; |
|
}); |
|
|
|
eventText.attr("y",function(d,i){ |
|
// grab data of next key and math the distance between for placement |
|
if (i >= 0 && i < (data.length - 1)) { |
|
var nextData = i>=0?dot.data()[i+1]:dot.data()[dot.data().length+1]; |
|
var thisHeight = scale(d.value) * 2; |
|
var nextHeight = scale(nextData.value) * 2; |
|
var newcoord = nextHeight + ((thisHeight - nextHeight) / 2); |
|
return h - (newcoord); |
|
} else { |
|
return h - scale(d.value); |
|
} |
|
}); |
|
}; // end of ready |
|
} |