Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions simplified drill-down v4
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v4.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<style>
#map {
background-color: #fff;
border: 1px solid #ccc;
}
.background {
fill: none;
pointer-events: all;
}
#countries, #states {
fill: #cde;
stroke: #fff;
stroke-linejoin: round;
stroke-linecap: round;
}
#countries .active, #states .active {
fill: #89a;
}
#cities {
stroke-width: 0;
}
.city {
fill: #345;
stroke: #fff;
}
pre.prettyprint {
border: 1px solid #ccc;
margin-bottom: 0;
padding: 9.5px;
}
</style>
</head>
<body>
<div id="map"></div>

<script src="//d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
var m_width = $("#map").width(),
width = 938,
height = 500,
country,
state;

var projection = d3.geoMercator()
.scale(150)
.translate([width / 2, height / 1.5]);

var path = d3.geoPath()
.projection(projection);

var svg = d3.select("#map").append("svg")
.attr("preserveAspectRatio", "xMidYMid")
.attr("viewBox", "0 0 " + width + " " + height)
.attr("width", m_width)
.attr("height", m_width * height / width);

// we create a rect area with an event listener associated to it
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", country_clicked);


var g = svg.append("g");

// the first map to show is the countries.topo.json
// the click event is also associated to each country
d3.json("json/countries.topo.json", function(error, us) {
g.append("g")
.attr("id", "countries")
.selectAll("path")
.data(topojson.feature(us, us.objects.countries).features)
.enter()
.append("path")
.attr("id", function(d) { return d.id; })
.attr("d", path)
.on("click", country_clicked);
});

function zoom(xyz) {
g.transition()
.duration(750)
//translate(x,y), scale(z)
.attr("transform", "translate(" + projection.translate() + ")scale(" + xyz[2] + ")translate(-" + xyz[0] + ",-" + xyz[1] + ")")
.selectAll(["#countries", "#states", "#cities"])
//scale the path width
.style("stroke-width", 1.0 / xyz[2] + "px")
.selectAll(".city")
//scale the point radius
.attr("d", path.pointRadius(20.0 / xyz[2]));
}

//get width, height and scale based on the path of the selected country
function get_xyz(d) {
var bounds = path.bounds(d);
var w_scale = (bounds[1][0] - bounds[0][0]) / width;
var h_scale = (bounds[1][1] - bounds[0][1]) / height;
var z = .96 / Math.max(w_scale, h_scale);
var x = (bounds[1][0] + bounds[0][0]) / 2;
var y = (bounds[1][1] + bounds[0][1]) / 2 + (height / z / 6);
return [x, y, z];
}

// the function associated to the click on the countries map
function country_clicked(d) {
//we clean the graph,
g.selectAll(["#states"]).remove();
g.selectAll("#USA").style('display', null);
state = null;


//the call picks the data associated to the path
if (d && country !== d) {
var xyz = get_xyz(d);
country = d;

if (d.id == 'USA') {
//in this case we do semantic-drill-down zooming
d3.json("json/states_" + d.id.toLowerCase() + ".topo.json", function(error, us) { //we load the specific json
//we create the new map
g.append("g")
.attr("id", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter()
.append("path")
.attr("id", function(d) { return d.id; })
.attr("class", "active")
.attr("d", path)
.on("click",function(){
//remove the states map
g.selectAll("#states").remove();
//recover the path of USA
g.selectAll("#USA").style('display', null);
//revert the zooming
var xyz = [width / 2, height / 1.5, 1];
country = null;
zoom(xyz);
});

//apply the new zoom
zoom(xyz);
// hide the original country path
g.selectAll("#" + d.id).style('display', 'none');
});
} else {
//we only do semantic zoomoing
zoom(xyz);
}
} else {
//we revert the zooming
var xyz = [width / 2, height / 1.5, 1];
country = null;
zoom(xyz);
}
}


$(window).resize(function() {
var w = $("#map").width();
svg.attr("width", w);
svg.attr("height", w * height / width);
});
</script>
</body>
</html>