Built with blockbuilder.org
forked from maelafifi's block: fresh block
license: mit |
Built with blockbuilder.org
forked from maelafifi's block: fresh block
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<link href="style.css" rel="stylesheet" type="text/css"> | |
<title>SF Arrests</title> | |
</head> | |
<body> | |
<svg width="960" height="600"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="script.js"></script> | |
</body> |
// the geojson files are large, so loading them locally | |
var urls = { | |
basemap: "https://usf-cs360-2017.github.io/homework3-maelafifi/SVDistricts.geojson" | |
}; | |
var svg = d3.select("body").select("svg"); | |
var g = { | |
basemap: svg.append("g").attr("id", "basemap"), | |
tooltip: svg.append("g").attr("id", "tooltip") | |
}; | |
// https://github.com/d3/d3-geo#conic-projections | |
var projection = d3.geoConicEqualArea(); | |
var path = d3.geoPath().projection(projection); | |
// http://mynasadata.larc.nasa.gov/latitudelongitude-finder/ | |
// center on san francisco [longitude, latitude] | |
// choose parallels on either side of center | |
projection.parallels([37.692514, 37.840699]); | |
// rotate to view we usually see of sf | |
projection.rotate([122, 0]); | |
// we want both basemap and streets to load before arrests | |
// https://github.com/d3/d3-queue | |
var q = d3.queue() | |
.defer(d3.json, urls.basemap) | |
.await(drawMap); | |
function drawMap(error, basemap) { | |
if (error) throw error; | |
console.log("basemap", basemap); | |
// make sure basemap fits in projection | |
projection.fitSize([960, 600], basemap); | |
// draw basemap | |
var land = g.basemap.selectAll("path.land") | |
.data(basemap.features) | |
.enter() | |
.append("path") | |
.attr("d", path) | |
.attr("class", "land"); | |
g.basemap.selectAll("path.neighborhood") | |
.data(basemap.features) | |
.enter() | |
.append("path") | |
.attr("d", path) | |
.attr("class", "neighborhood") | |
.each(function(d) { | |
// save selection in data for interactivity | |
d.properties.outline = this; | |
}); | |
var tip = g.tooltip.append("text").attr("id", "tooltip"); | |
tip.attr("text-anchor", "end"); | |
tip.attr("dx", -5); | |
tip.attr("dy", -5); | |
tip.style("visibility", "hidden"); | |
// add interactivity | |
land.on("mouseover", function(d) { | |
tip.text("District " + d.properties.numbertext.toLowerCase()); | |
tip.style("visibility", "visible"); | |
d3.select(d.properties.outline).raise(); | |
d3.select(d.properties.outline).classed("active", true); | |
}) | |
.on("mousemove", function(d) { | |
var coords = d3.mouse(g.basemap.node()); | |
tip.attr("x", coords[0]); | |
tip.attr("y", coords[1]); | |
}) | |
.on("mouseout", function(d) { | |
tip.style("visibility", "hidden"); | |
d3.select(d.properties.outline).classed("active", false); | |
}); | |
} | |
function translate(x, y) { | |
return "translate(" + String(x) + "," + String(y) + ")"; | |
} |
body { | |
background-color: white; | |
text-align: center; | |
font-family: sans-serif; | |
font-size: 9pt; | |
} | |
#tooltip { | |
font-weight: 600; | |
text-shadow: 0px 0px 2px white; | |
fill: black; | |
stroke: none; | |
} | |
path.land { | |
fill: #dddddd; | |
stroke: none; | |
} | |
path.neighborhood { | |
fill: none; | |
stroke: white; | |
stroke-width: 3.5px; | |
pointer-events: none; | |
} | |
path.street { | |
fill: none; | |
stroke: white; | |
stroke-width: 1px; | |
pointer-events: none; | |
} | |
.active { | |
stroke: red !important; | |
stroke-width: 1.5px !important; | |
} | |
circle.symbol { | |
fill-opacity: 0.6; | |
stroke: white; | |
stroke-width: 1px; | |
} |