Skip to content

Instantly share code, notes, and snippets.

@wilson428
Last active September 27, 2015 14:13
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 wilson428/da8c414874780bef3e89 to your computer and use it in GitHub Desktop.
Save wilson428/da8c414874780bef3e89 to your computer and use it in GitHub Desktop.
Internal topoJSON borders used .mesh vs .merge
(function() {
var root = this;
// create a new SVG element
var elasticSVG = function(selector, opts) {
opts = opts || {};
// containing DOM element, which defaults to body
var parent = document.querySelectorAll(selector || "body");
if (!parent || !parent.length) {
console.log("Couldn't find a parent for elasticSVG making the selector '" + selector + "'");
return;
}
parent = parent[0];
// you can specify a width if you like, or we'll snap to size of container
var base = {
width: typeof opts.width !== "undefined" ? opts.width : parent.clientWidth,
scale: 1
};
// we need to remember the original width for scaling purposes
base.original_width = base.width;
// you can either specify the height or the aspect ratio. If neither is specified, refaults to roughly the golden ratio
if (typeof opts.height !== "undefined") {
base.height = opts.height;
opts.aspect = base.height / base.width;
} else {
opts.aspect = typeof opts.aspect !== "undefined" ? opts.aspect : 0.618;
base.height = base.width * opts.aspect;
}
var xmlns = "http://www.w3.org/2000/svg";
var svg = document.createElementNS(xmlns, "svg");
svg.setAttributeNS(null, "width", base.width);
svg.setAttributeNS(null, "height", base.height);
parent.appendChild(svg);
// setting resize to "auto" sets the viewport to the original width and height so that the SVG always scales
if (opts.resize && opts.resize == "auto") {
svg.setAttributeNS(null, "viewBox", "0 0 " + base.width + " " + base.height);
}
function resize() {
console.log(parent)
base.width = parent.clientWidth;
base.height = base.width * opts.aspect;
base.scale = base.width / base.original_width;
svg.setAttributeNS(null, "width", base.width);
svg.setAttributeNS(null, "height", base.height);
// optional callback
if (opts.onResize) {
opts.onResize(base.width, base.height, base.scale);
}
}
var resizeTimer;
// http://stackoverflow.com/questions/3339825/what-is-the-best-practise-to-not-to-override-other-bound-functions-to-window-onr
function addResizeEvent(func, dur) {
var oldResize = window.onresize,
resizeTimer,
dur = typeof dur === "undefined" ? 250 : parseInt(dur, 10);
window.onresize = function () {
clearTimeout(resizeTimer);
if (typeof oldResize === 'function') {
oldResize();
}
resizeTimer = setTimeout(function() {
func();
}, dur);
}
}
addResizeEvent(resize, 250);
if (opts.resize && opts.resize === "auto") {
resize(); // call this on load since sometimes the initial conditions are wider than container
}
base.setResize = function(f) {
opts.onResize = f;
}
base.svg = svg;
return base;
}
// support various modular environments
if (typeof define === "function" && define.amd) { // RequireJS
define(elasticSVG);
} else if (typeof module === "object" && module.exports) { // browserify
module.exports = elasticSVG;
} else {
root.elasticSVG = elasticSVG; // directly included
}
}());
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0">
<title>TopoJSON Counties With Organic Borders</title>
<style>
path.county {
fill: #eee;
stroke: #fff;
stroke-width: .5px;
}
path.state {
fill: none;
stroke: #404040;
stroke-width: 1px;
}
.Example {
max-width: 900px;
width: 100%;
height: 1500px;
}
.title {
font-size: 24px;
font-family: Arial;
text-align: center;
}
</style>
</head>
<body>
<div class="Example">
<div class="title">Merged</div>
<div id="map_merged"></div>
<div class="title">Meshed</div>
<div id="map_meshed"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="elasticSVG.js"></script>
<script>
var projection = d3.geo.albersUsa()
.scale(1200)
.translate([450, 275]);
var path = d3.geo.path().projection(projection);
d3.json("us.json", function(error, topology) {
if (error) throw error;
// MESHED
// make the SVG responsive
var el_meshed = elasticSVG("#map_meshed", {
width: 900,
aspect: 0.65,
resize: "auto"
});
var svg_meshed = d3.select(el_meshed.svg).append("g");
//meshed
var counties = topojson.feature(topology, topology.objects.counties).features;
svg_meshed.selectAll("path")
.data(counties)
.enter().append("path")
.attr("class", "county")
.attr("d", path)
.on("click", function(d) {
console.log(d);
});
svg_meshed.append("path")
.datum(topojson.mesh(topology, topology.objects.counties, function(a, b) { return a.id - a.id % 1000 !== b.id - b.id % 1000; }))
.attr("class", "state")
.attr("d", path);
// MERGED
// make the SVG responsive
var el_meshed = elasticSVG("#map_merged", {
width: 900,
aspect: 0.65,
resize: "auto"
});
var svg_merged = d3.select(el_meshed.svg).append("g");
//meshed
svg_merged.selectAll("path")
.data(counties)
.enter().append("path")
.attr("class", "county")
.attr("d", path);
// let's get an organic list of fips
var fips = {};
counties.forEach(function(county) { fips[county.id - county.id % 1000] = 1; });
var states = [];
// and merge by fips
Object.keys(fips).forEach(function(fip) {
var state = topojson.merge(topology, topology.objects.counties.geometries.filter(function(d) { return d.id - d.id % 1000 == fip; }));
states.push(state);
});
svg_merged.append("g").attr("id", "states").selectAll(".state").append("path")
.data(states)
.enter()
.append("path")
.attr("class", "state")
.attr("d", function(d) {
return path(d);
});
});
</script>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment