|
<!DOCTYPE html> |
|
<html lang="en"> |
|
|
|
<head> |
|
<meta charset="utf-8"> |
|
<title>Egypt</title> |
|
|
|
<script src="https://d3js.org/d3.v4.min.js" type="text/javascript"></script> |
|
<script src="https://unpkg.com/topojson@3" type="text/javascript"></script> |
|
<script src="https://code.jquery.com/jquery-2.2.4.min.js" type="text/javascript"></script> |
|
|
|
<style type="text/css"> |
|
body { |
|
font: 10px Tahoma, sans-serif; |
|
} |
|
|
|
svg { |
|
font: 10px sans-serif; |
|
} |
|
|
|
#map { |
|
float: left; |
|
} |
|
|
|
path.land { |
|
fill: GhostWhite; |
|
} |
|
|
|
path.ocean { |
|
fill: DeepSkyBlue; |
|
} |
|
|
|
path.river { |
|
fill: none; |
|
stroke: DeepSkyBlue; |
|
} |
|
|
|
path.governate { |
|
fill-opacity: .5; |
|
fill: #ccc; |
|
stroke: white; |
|
cursor: pointer; |
|
} |
|
|
|
path.governate.selected { |
|
fill-opacity: .9; |
|
} |
|
|
|
path.governate.pinned { |
|
fill: YellowGreen; |
|
fill-opacity: .75; |
|
} |
|
|
|
li { |
|
cursor: pointer; |
|
background-color: steelBlue; |
|
padding: 3px 5px; |
|
margin: 1px; |
|
color: white; |
|
font-size: 12px; |
|
display: inline-block; |
|
} |
|
|
|
li.selected { |
|
background-color: #ccc; |
|
} |
|
|
|
li.pinned { |
|
background-color: YellowGreen; |
|
color: black; |
|
} |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<div class="container"> |
|
<div id="map"></div> |
|
<div id="list"></div> |
|
<button id="reset">Reset</button> |
|
</div> |
|
|
|
<script type="text/javascript"> |
|
var width = 620, |
|
height = 600; |
|
|
|
var zoom = d3.zoom() |
|
.translateExtent([[0, 0], [width, height]]) |
|
.scaleExtent([1, 10]); |
|
|
|
var svg = d3.select("#map").append("svg") |
|
.attr("width", width) |
|
.attr("height", height) |
|
.append("g") |
|
.call(zoom.on("zoom", zoomed)); |
|
|
|
var controls = d3.select('svg').append("g") |
|
.attr("width", 200) |
|
.attr("height", height) |
|
.attr("transform", "translate(50,50)"); |
|
|
|
var z = d3.scaleLinear() |
|
.domain([1, 10]) |
|
.range([0, 150]); |
|
|
|
var zoomAxis = d3.axisRight().scale(z); |
|
|
|
var zoomCursor = controls.append("g") |
|
.attr("transform", "translate(0," + z(1) + ")");; |
|
|
|
var list = d3.select("#list").append("ul"); |
|
|
|
d3.json("egypt.json", function (error, egypt) { |
|
var governate = topojson.feature(egypt, egypt.objects.governate); |
|
|
|
var projection = d3.geoMercator() |
|
.fitSize([width, height], governate); |
|
|
|
var path = d3.geoPath() |
|
.projection(projection); |
|
|
|
svg.selectAll(".governate") |
|
.data(governate.features) |
|
.enter().append("path") |
|
.attr("class", function (d) { return "governate " + d.id; }) |
|
.attr("d", path) |
|
.on("mouseover", select) |
|
.on("mouseout", unselect) |
|
.on("click", click) |
|
.append("title") |
|
.text(function (d) { return d.properties.name; }); |
|
|
|
svg.selectAll(".river") |
|
.data(topojson.feature(egypt, egypt.objects.rivers).features) |
|
.enter().append("path") |
|
.attr("class", "river") |
|
.attr("d", path) |
|
.attr("stroke-width", function (d) { |
|
return 1 / d.properties.scalerank; |
|
}) |
|
.append("title") |
|
.text(function (d) { return d.properties.name; }); |
|
|
|
svg.append("path") |
|
.datum(topojson.feature(egypt, egypt.objects.ocean)) |
|
.attr("class", "ocean") |
|
.attr("d", path); |
|
|
|
svg.append("path") |
|
.datum(topojson.feature(egypt, egypt.objects.lakes)) |
|
.attr("class", "ocean") |
|
.attr("d", path); |
|
|
|
list.selectAll("li") |
|
.data(topojson.feature(egypt, egypt.objects.governate).features) |
|
.enter().append("li") |
|
.text(function (d) { return d.properties.name; }) |
|
.on("mouseover", select) |
|
.on("mouseout", unselect) |
|
.on("click", click); |
|
|
|
zoomCursor.append("path") |
|
.attr("d", "M0,0H5L6,2L5,4H0z") |
|
.attr("transform", "translate(-3,-2)"); |
|
|
|
controls.append("g") |
|
.attr("transform", "translate(10,0)") |
|
.call(zoomAxis); |
|
}); |
|
|
|
$("#reset").click(reset); |
|
|
|
function select(d) { |
|
list.selectAll("li").classed("selected", function (e) { return e.id == d.id }); |
|
svg.selectAll(".governate").classed("selected", function (e) { return e.id == d.id }); |
|
} |
|
|
|
function unselect(d) { |
|
list.selectAll("li").classed("selected", false); |
|
svg.selectAll(".governate").classed("selected", false); |
|
} |
|
|
|
function click(d) { |
|
list.selectAll("li").classed("pinned", function (e) { return e.id == d.id }); |
|
svg.selectAll(".governate").classed("pinned", function (e) { return e.id == d.id }); |
|
} |
|
|
|
function reset() { |
|
svg.transition() |
|
.duration(750) |
|
.call(zoom.transform, d3.zoomIdentity); |
|
|
|
list.selectAll("li").classed("pinned", false); |
|
svg.selectAll(".governate").classed("pinned", false); |
|
} |
|
|
|
function zoomed() { |
|
svg.attr("transform", d3.event.transform); |
|
zoomCursor.attr("transform", "translate(0," + z(d3.event.transform.k) + ")"); |
|
} |
|
</script> |
|
</body> |