Skip to content

Instantly share code, notes, and snippets.

@GauravSahu
Last active August 29, 2015 14:17
Show Gist options
  • Save GauravSahu/88cc47008bcb62079e92 to your computer and use it in GitHub Desktop.
Save GauravSahu/88cc47008bcb62079e92 to your computer and use it in GitHub Desktop.
// hide the form if the browser doesn't do SVG,
// (then just let everything else fail)
if (!document.createElementNS) {
document.getElementsByTagName("form")[0].style.display = "none";
}
var percent = (function() {
var fmt = d3.format(".2f");
return function(n) { return fmt(n) + "%"; };
})(),
fields = [
{name: "(no scale)", id: "none"},
{name: "Net Migration", id: "netmig", key: "NETMIG%d", format: "+,"},
{name: "Residual", id: "residual", key: "RESIDUAL%d", format: "+,"},
{name: "Population Estimate", id: "popest", key: "POPESTIMATE%d"},
{name: "Population Change", id: "popchange", key: "NPOPCHG_%d", format: "+,"},
{name: "Births", id: "births", key: "BIRTHS%d"},
{name: "Deaths", id: "deaths", key: "DEATHS%d"},
{name: "Natural Increase", id: "natinc", key: "NATURALINC%d", format: "+,"},
{name: "Birth Rate", id: "birthrate", key: "RBIRTH%d", years: [2011], format: percent},
{name: "Death Rate", id: "deathrate", key: "RDEATH%d", years: [2011], format: percent},
],
years = [2010, 2011],
fieldsById = d3.nest()
.key(function(d) { return d.id; })
.rollup(function(d) { return d[0]; })
.map(fields),
field = fields[0],
year = years[0],
colors = colorbrewer.RdYlBu[3]
.reverse()
.map(function(rgb) { return d3.hsl(rgb); });
var body = d3.select("body"),
stat = d3.select("#status");
var fieldSelect = d3.select("#field")
.on("change", function(e) {
field = fields[this.selectedIndex];
location.hash = "#" + [field.id, year].join("/");
});
fieldSelect.selectAll("option")
.data(fields)
.enter()
.append("option")
.attr("value", function(d) { return d.id; })
.text(function(d) { return d.name; });
var yearSelect = d3.select("#year")
.on("change", function(e) {
year = years[this.selectedIndex];
location.hash = "#" + [field.id, year].join("/");
});
yearSelect.selectAll("option")
.data(years)
.enter()
.append("option")
.attr("value", function(y) { return y; })
.text(function(y) { return y; })
var map = d3.select("#map"),
zoom = d3.behavior.zoom()
.translate([-14550,-3650])
.scale(21.5)
.scaleExtent([15,100])
.on("zoom", updateZoom),
layer = map.append("g")
.attr("id", "layer"),
states = layer.append("g")
.attr("id", "states")
.selectAll("path")
.on("click", clicked);
// map.call(zoom);
updateZoom();
function updateZoom() {
var scale = zoom.scale();
layer.attr("transform",
"translate(" + zoom.translate() + ") " +
"scale(" + [scale, scale] + ")");
}
var proj = d3.geo.equirectangular(),
topology,
geometries,
rawData,
dataById = {},
carto = d3.cartogram()
.projection(proj)
.properties(function(d) {
return dataById[d.id];
})
.value(function(d) {
return +d.properties[field] * 100;
});
window.onhashchange = function() {
parseHash();
};
var segmentized = location.search === "?segmentized",
url = ["data",
segmentized ? "" : "https://gist.githubusercontent.com/GauravSahu/091f0b9c81e9794d4e14/raw/cede5469a53b4fa3564e985f4e617c28a58c59ff/uptopo.topojson"
].join("/");
d3.json(url, function(topo) {
topology = topo;
geometries = topology.objects.states.geometries;
d3.csv("data/updata.csv", function(data) {
rawData = data;
dataById = d3.nest()
.key(function(d) { return d.NAME; })
.rollup(function(d) { return d[0]; })
.map(data);
init();
});
});
function init() {
var features = carto.features(topology, geometries),
path = d3.geo.path()
.projection(proj);
states = states.data(features)
.enter()
.append("path")
.attr("class", "district")
.attr("id", function(d) {
return d.properties.NAME;
})
.attr("fill", "#fafafa")
.attr("d", path)
.on("click", clicked);
states.append("title");
parseHash();
}
function reset() {
stat.text("");
body.classed("updating", false);
var features = carto.features(topology, geometries),
path = d3.geo.path()
.projection(proj);
states.data(features)
.transition()
.duration(750)
.ease("linear")
.attr("fill", "#fafafa")
.attr("d", path);
states.select("title")
.text(function(d) {
return d.properties.NAME;
});
}
function update() {
var start = Date.now();
body.classed("updating", true);
var key = field.key.replace("%d", year),
fmt = (typeof field.format === "function")
? field.format
: d3.format(field.format || ","),
value = function(d) {
return +d.properties[key];
},
values = states.data()
.map(value)
.filter(function(n) {
return !isNaN(n);
})
.sort(d3.ascending),
lo = values[0],
hi = values[values.length - 1];
var color = d3.scale.linear()
.range(colors)
.domain(lo < 0
? [lo, 0, hi]
: [lo, d3.mean(values), hi]);
// normalize the scale to positive numbers
var scale = d3.scale.linear()
.domain([lo, hi])
.range([1, 1000]);
// tell the cartogram to use the scaled values
carto.value(function(d) {
return scale(value(d));
});
// generate the new features, pre-projected
var features = carto(topology, geometries).features;
// update the data
states.data(features)
.select("title")
.text(function(d) {
return [d.properties.NAME, fmt(value(d))].join(": ");
});
states.transition()
.duration(750)
.ease("linear")
.attr("fill", function(d) {
return color(value(d));
})
.attr("d", carto.path);
var delta = (Date.now() - start) / 1000;
stat.text(["calculated in", delta.toFixed(1), "seconds"].join(" "));
body.classed("updating", false);
}
var deferredUpdate = (function() {
var timeout;
return function() {
var args = arguments;
clearTimeout(timeout);
stat.text("calculating...");
return timeout = setTimeout(function() {
update.apply(null, arguments);
}, 10);
};
})();
var hashish = d3.selectAll("a.hashish")
.datum(function() {
return this.href;
});
function parseHash() {
var parts = location.hash.substr(1).split("/"),
desiredFieldId = parts[0],
desiredYear = +parts[1];
field = fieldsById[desiredFieldId] || fields[0];
year = (years.indexOf(desiredYear) > -1) ? desiredYear : years[0];
fieldSelect.property("selectedIndex", fields.indexOf(field));
if (field.id === "none") {
yearSelect.attr("disabled", "disabled");
reset();
} else {
if (field.years) {
if (field.years.indexOf(year) === -1) {
year = field.years[0];
}
yearSelect.selectAll("option")
.attr("disabled", function(y) {
return (field.years.indexOf(y) === -1) ? "disabled" : null;
});
} else {
yearSelect.selectAll("option")
.attr("disabled", null);
}
yearSelect
.property("selectedIndex", years.indexOf(year))
.attr("disabled", null);
deferredUpdate();
location.replace("#" + [field.id, year].join("/"));
hashish.attr("href", function(href) {
return href + location.hash;
});
}
}
function clicked(d) {
var x, y, k;
if (d && centered !== d) {
var centroid = path.centroid(d);
x = centroid[0];
y = centroid[1];
k = 4;
centered = d;
} else {
x = width / 2;
y = height / 2;
k = 1;
centered = null;
}
g.selectAll("path")
.classed("active", centered && function(d) { return d === centered; });
g.transition()
.duration(750)
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
.style("stroke-width", 1.5 / k + "px");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment