Skip to content

Instantly share code, notes, and snippets.

@mbertrand
Last active August 29, 2015 14:17
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 mbertrand/34abee79acba54251801 to your computer and use it in GitHub Desktop.
Save mbertrand/34abee79acba54251801 to your computer and use it in GitHub Desktop.
D3.js + Google Maps: USGS Earthquake data
body, html, #map {
font-family: Arial, Helvetica, sans-serif;
margin: 0;
width: 100%;
height: 100%;
}
.SvgOverlay {
position: relative;
width: 100%;
height: 100%;
}
.SvgOverlay svg {
position: absolute;
top: -4000px;
left: -4000px;
width: 8000px;
height: 8000px;
}
.SvgOverlay path {
fill: #000;
fill-opacity: .2;
stroke: #fff;
stroke-width: 1.5px;
}
.highlight{
fill: red;
fill-opacity: .6;
stroke: yellow;
stroke-width: 1.5px;
}
.SvgOverlay path:hover {
fill: red;
fill-opacity: .7;
}
div#quake-pop-up {
display: none;
position:absolute;
color: white;
font-size: 14px;
background: rgba(0,0,0,0.5);
padding: 5px 10px 5px 10px;
-moz-border-radius: 5px 5px;
border-radius: 5px 5px;
z-index: 99;
}
div#quake-pop-up-title {
font-size: 15px;
width:300px;
margin-bottom: 4px;
font-weight: bolder;
}
div#quake-pop-up-content {
font-size: 14px;
}
div#quake-pop-desc {
margin-left: 10px;
width: 300px;
color: white;
}
div#quake-pop-img {
font-size: 30px;
font-weight: bolder;
color: white;
}
.hist {
position: absolute;
right:0;
bottom:0;
z-index: 9000;
color: white;
font-size: 10px;
background: rgba(250,250,250,0.7);
padding: 5px 10px 5px 10px;
-moz-border-radius: 5px 5px;
border-radius: 5px 5px;
z-index: 95;
}
.bar rect {
fill: blue;
shape-rendering: crispEdges;
}
.bar rect:hover {
fill: red;
}
.bar text {
fill: #000;
font-size: 10px;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/d3/2.10.0/d3.v2.min.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/themes/blitzer/jquery-ui.css" type="text/css">
<link rel="stylesheet" href="gmap_d3.css" type="text/css">
<script>
$(function () {
var $map = $("#map");
var map = new google.maps.Map($map[0], {
zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: {lat:33.045579573575154, lng:-96.97189523828126}
});
var overlay = new google.maps.OverlayView();
d3.json("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson", function (collection) {
overlay.onAdd = function () {
var layer = d3.select(this.getPanes().overlayMouseTarget).append("div").attr("class", "SvgOverlay");
var svg = layer.append("svg");
var quakes = svg.append("g").attr("class", "Quakes");
overlay.draw = function () {
var markerOverlay = this;
var overlayProjection = markerOverlay.getProjection();
// Turn the overlay projection into a d3 projection
var googleMapProjection = function (coordinates) {
var googleCoordinates = new google.maps.LatLng(coordinates[1], coordinates[0]);
var pixelCoordinates = overlayProjection.fromLatLngToDivPixel(googleCoordinates);
return [pixelCoordinates.x + 4000, pixelCoordinates.y + 4000];
}
path = d3.geo.path().projection(googleMapProjection);
quakes.selectAll("path")
.data(collection.features)
.attr("d", path.pointRadius(function (d) {
return Math.sqrt((Math.exp(parseFloat(d.properties.mag))));
}))
.attr("class","myPathClass")
.enter().append("svg:path")
.attr("d", path.pointRadius(function (d) {
return Math.sqrt((Math.exp(parseFloat(d.properties.mag))));
}))
.on("mouseover", function (d) {
var mousePosition = d3.svg.mouse(this);
var format = d3.time.format("%Y-%m-%d %HH:%MM:%SS");
$("#quake-pop-up").fadeOut(100, function () {
// Popup content
$("#quake-pop-up-title").html(format(new Date(parseInt(d.properties.time))));
$("#quake-pop-img").html(d.properties.mag);
$("#quake-pop-desc").html(d.properties.place);
$("#quake-pop-up").css({
"right": 0,
"top": 50
});
$("#quake-pop-up").fadeIn(100);
});
}).
on("mouseout", function () {
//$("#quake-pop-up").fadeOut(50);
});
};
createHistogram(collection, quakes);
};
overlay.setMap(map);
});
});
function createHistogram(dataset, svgclass) {
var formatCount = d3.format(",.0f");
var values = dataset.features.map(function (d) {return d.properties.mag;});
var margin = {top: 10, right: 30, bottom: 40, left: 30},
width = 500 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([0, 10])
.range([0, width]);
// Generate a histogram using twenty uniformly-spaced bins.
var data = d3.layout.histogram()
.bins(x.ticks(10))
(values);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.y; })])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var svgbar = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("class", "hist")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svgbar.append("text")
.attr("font-size", "14px")
.attr("font-weight", "bold")
.attr("y", 5)
.attr("x", 300)
.attr("text-anchor", "middle")
.text("Earthquakes over the past 30 days");
var bar = svgbar.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bar")
.attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; })
.on("mouseover", function(d, i) {
d3.selectAll(".SvgOverlay path").filter(function(e) {
return d3.min(d) <= e.properties.mag && e.properties.mag < d3.max(d)
}).style({'fill': 'red', 'stroke': 'yellow'})
})
.on("mouseout", function(d, i) {
d3.selectAll(".SvgOverlay path").filter(function(e) {
return d3.min(d) <= e.properties.mag && e.properties.mag < d3.max(d)
}).style({'fill': '', 'stroke': ''});
});
bar.append("rect")
.attr("x", 1)
.attr("width", x(data[0].dx) - 1)
.attr("height", function(d) { return height - y(d.y); });
bar.append("text")
.attr("dy", ".75em")
.attr("y", -10)
.attr("x", x(data[0].dx) / 2)
.attr("text-anchor", "middle")
.text(function(d) { return formatCount(d.y); });
svgbar.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("font-size", "12px")
.attr("y", 30)
.attr("x", 200)
.attr("text-anchor", "middle")
.text("Magnitude");;
return svgbar;
}
</script>
</head>
<body >
<div id="map"></div>
<div id="quake-pop-up">
<div id="quake-pop-up-title"></div>
<div id="quake-pop-up-content">
<table> <tr>
<td><div id="quake-pop-img"></div></td>
<td><div id="quake-pop-desc"></div></td>
</tr> </table>
</div>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment