|
<!doctype html> |
|
<html lang="en"> |
|
|
|
<head> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
body { |
|
background-color: white; |
|
} |
|
svg { |
|
border: 2px solid black; |
|
background-color: white; |
|
} |
|
|
|
.selected { |
|
fill: red; |
|
} |
|
|
|
.boundary { |
|
fill: #DEB887; |
|
stroke: black; |
|
stroke-width: 1px; |
|
} |
|
|
|
.hidden { |
|
display: none; |
|
} |
|
|
|
div.tooltip { |
|
color: #222; |
|
background: #fff; |
|
border-radius: 3px; |
|
box-shadow: 0px 0px 2px 0px #a6a6a6; |
|
padding: .2em; |
|
text-shadow: #f5f5f5 0 1px 0; |
|
opacity: 0.9; |
|
position: absolute; |
|
} |
|
</style> |
|
|
|
</head> |
|
|
|
<body> |
|
<div id="map"></div> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script src="http://d3js.org/topojson.v1.min.js"></script> |
|
<script> |
|
var width = 962, |
|
rotated = 90, |
|
height = 502; |
|
|
|
//countries which have states, needed to toggle visibility |
|
//for USA/ etc. either show countries or states, not both |
|
var usa, canada; |
|
var states; //track states |
|
//track where mouse was clicked |
|
var initX; |
|
//track scale only rotate when s === 1 |
|
var s = 1; |
|
var mouseClicked = false; |
|
|
|
|
|
var projection = d3.geo.mercator() |
|
.scale(153) |
|
.translate([width/2,height/1.5]) |
|
.rotate([rotated,0,0]); //center on USA because 'murica |
|
|
|
var zoom = d3.behavior.zoom() |
|
.scaleExtent([1, 20]) |
|
.on("zoom", zoomed); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height) |
|
//track where user clicked down |
|
.on("mousedown", function() { |
|
d3.event.preventDefault(); |
|
//only if scale === 1 |
|
if(s !== 1) return; |
|
initX = d3.mouse(this)[0]; |
|
mouseClicked = true; |
|
}) |
|
.on("mouseup", function() { |
|
if(s !== 1) return; |
|
rotated = rotated + ((d3.mouse(this)[0] - initX) * 360 / (s * width)); |
|
mouseClicked = false; |
|
}) |
|
.call(zoom); |
|
|
|
|
|
function rotateMap(endX) { |
|
projection.rotate([rotated + (endX - initX) * 360 / (s * width),0,0]) |
|
g.selectAll('path') // re-project path data |
|
.attr('d', path); |
|
} |
|
//for tooltip |
|
var offsetL = document.getElementById('map').offsetLeft+10; |
|
var offsetT = document.getElementById('map').offsetTop+10; |
|
|
|
var path = d3.geo.path() |
|
.projection(projection); |
|
|
|
var tooltip = d3.select("#map") |
|
.append("div") |
|
.attr("class", "tooltip hidden"); |
|
|
|
//need this for correct panning |
|
var g = svg.append("g"); |
|
|
|
//det json data and draw it |
|
d3.json("combined2.json", function(error, world) { |
|
if(error) return console.error(error); |
|
|
|
//countries |
|
g.append("g") |
|
.attr("class", "boundary") |
|
.selectAll("boundary") |
|
.data(topojson.feature(world, world.objects.countries).features) |
|
.enter().append("path") |
|
.attr("name", function(d) {return d.properties.name;}) |
|
.attr("id", function(d) { return d.id;}) |
|
.on('click', selected) |
|
.on("mousemove", showTooltip) |
|
.on("mouseout", function(d,i) { |
|
tooltip.classed("hidden", true); |
|
}) |
|
.attr("d", path); |
|
|
|
usa = d3.select('#USA'); |
|
canada = d3.select('#CAN'); |
|
|
|
//states |
|
g.append("g") |
|
.attr("class", "boundary state hidden") |
|
.selectAll("boundary") |
|
.data(topojson.feature(world, world.objects.states).features) |
|
.enter().append("path") |
|
.attr("name", function(d) { return d.properties.name;}) |
|
.attr("id", function(d) { return d.id;}) |
|
.on('click', selected) |
|
.on("mousemove", showTooltip) |
|
.on("mouseout", function(d,i) { |
|
tooltip.classed("hidden", true); |
|
}) |
|
.attr("d", path); |
|
|
|
states = d3.selectAll('.state'); |
|
}); |
|
|
|
function showTooltip(d) { |
|
label = d.properties.name; |
|
var mouse = d3.mouse(svg.node()) |
|
.map( function(d) { return parseInt(d); } ); |
|
tooltip.classed("hidden", false) |
|
.attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px") |
|
.html(label); |
|
} |
|
|
|
function selected() { |
|
d3.select('.selected').classed('selected', false); |
|
d3.select(this).classed('selected', true); |
|
} |
|
|
|
|
|
function zoomed() { |
|
var t = d3.event.translate; |
|
s = d3.event.scale; |
|
var h = 0; |
|
|
|
t[0] = Math.min( |
|
(width/height) * (s - 1), |
|
Math.max( width * (1 - s), t[0] ) |
|
); |
|
|
|
t[1] = Math.min( |
|
h * (s - 1) + h * s, |
|
Math.max(height * (1 - s) - h * s, t[1]) |
|
); |
|
|
|
zoom.translate(t); |
|
if(s === 1 && mouseClicked) { |
|
rotateMap(d3.mouse(this)[0]) |
|
return; |
|
} |
|
|
|
g.attr("transform", "translate(" + t + ")scale(" + s + ")"); |
|
|
|
//adjust the stroke width based on zoom level |
|
d3.selectAll(".boundary") |
|
.style("stroke-width", 1 / s); |
|
|
|
//toggle state/USA visability |
|
if(s > 1.5) { |
|
states |
|
.classed('hidden', false); |
|
usa |
|
.classed('hidden', true); |
|
canada |
|
.classed('hidden', true); |
|
} else { |
|
states |
|
.classed('hidden', true); |
|
usa |
|
.classed('hidden', false); |
|
canada |
|
.classed('hidden', false); |
|
} |
|
} |
|
</script> |
|
</body> |
|
</html> |
Hey, I have a doubt, How do I use this code of yours to make this world map only focus on counties of US on clicking or zoom instead of US and Canada both .?