Create a earthquake time range by clicking and dragging on the timeseries.
This map & chart shows earthquakes (magnitude 3.0 or greater) that occurred in the Canterbury region of New Zealand during the month of September, 2010.
The shade of the map circles show the depth of the earthquake. Lighter shades are shallower and darker shades are deeper.
The map is created using Leaflet. The earthquake layer is a custom Leaflet layer which uses d3js to generate a svg overlay.
Earthquake data sourced from GeoNet.
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.leafletjs.com/leaflet-0.5/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="https://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" />
<![endif]-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.5/leaflet.min.js"></script>
<script src="https://d3js.org/d3.v3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.0-rc.3/lodash.underscore.min.js"></script>
<script type="text/javascript" src="colorbrewer.js"></script>
<script type="text/javascript" src="leaflet.points-layer.js"></script>
<style type="text/css">
html, body {
margin: 0;
padding: 0;
height: 100%;
}
#map {
height: 365px;
width: 960px;
margin-bottom: 1em;
}
.leaflet-popup-content ul { padding-left: 1.5em; }
.circle { visibility: hidden; }
.circle.selected { visibility: visible; }
svg {
font: 10px sans-serif;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id='map' data-source="quakes_christchurch_20100901-20101001_mag-gt3.json"></div>
<script type="text/javascript">
(function () {
var extent, scale,
classes = 9, scheme_id = "BuPu",
reverse = false;
scheme = colorbrewer[scheme_id][classes],
container = L.DomUtil.get('map'),
map = L.map(container).setView([-43.6, 172.3], 10);
L.tileLayer('https://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png', {
attribution: '<a href="https://content.stamen.com/dotspotting_toner_cartography_available_for_download">Stamen Toner</a>, <a href="https://www.openstreetmap.org/">OpenStreetMap</a>, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
maxZoom: 17
}).addTo(map);
d3.json(container.dataset.source, function(collection) {
L.pointsLayer(collection, {
radius: get_radius,
applyStyle: circle_style
}).addTo(map);
var chart = timeseries_chart(scheme)
.x(get_time).xLabel("Earthquake origin time")
.y(get_magnitude).yLabel("Magnitude")
.brushmove(on_brush);
d3.select("body").datum(collection.features).call(chart);
});
function get_time(d) {
return d3.time.format.iso.parse(d.properties.origintime);
}
function get_magnitude(d) {
return +d.properties.magnitude;
}
function on_brush(brush) {
var s = brush.extent();
d3.selectAll(".circle").classed("selected", function (d) {
var time = get_time(d);
return s[0] <= time && time <= s[1];
});
}
function get_radius(d) {
return d.properties.magnitude * d.properties.magnitude;
}
function circle_style(circles) {
if (!(extent && scale)) {
extent = d3.extent(circles.data(), function (d) { return d.properties.depth; });
scale = d3.scale.log()
.domain(reverse ? extent.reverse() : extent)
.range(d3.range(classes));
}
circles.attr('opacity', 0.4)
.attr('stroke', scheme[classes - 1])
.attr('stroke-width', 1)
.attr('fill', function (d) {
return scheme[(scale(d.properties.depth) * 10).toFixed()];
});
circles.on('click', function (d, i) {
L.DomEvent.stopPropagation(d3.event);
var t = '<h3><%- id %></h3>' +
'<ul>' +
'<li>Magnitude: <%- mag %></li>' +
'<li>Depth: <%- depth %>km</li>' +
'</ul>';
var data = {
id: d.id,
mag: d.properties.magnitude,
depth: d.properties.depth
};
L.popup()
.setLatLng([d.geometry.coordinates[1], d.geometry.coordinates[0]])
.setContent(_.template(t, data))
.openOn(map);
});
}
function timeseries_chart(color) {
var margin = { top: 5, right: 5, bottom: 40, left: 45 },
width = 960 - margin.left - margin.right,
height = 80;
var x = d3.time.scale(),
y = d3.scale.linear(),
x_label = "X", y_label = "Y",
brush = d3.svg.brush().x(x).on("brush", _brushmove);
var get_x = no_op,
get_y = no_op;
function timeseries(selection) {
selection.each(function (d) {
x.range([0, width]);
y.range([height, 0]);
var series = d3.select(this).append("svg").attr("id", "quake-timeseries")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g").attr("id", "date-brush")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x_axis = series.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
var y_axis = series.append("g")
.attr("class", "y axis");
x_axis.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", 30)
.style("text-anchor", "end")
.text(x_label);
y_axis.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text(y_label);
series.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width - 1)
.attr("height", height - .25)
.attr("transform", "translate(1,0)");
series.append("g")
.attr("class", "brush")
.call(brush)
.selectAll("rect")
.attr("height", height)
.style("stroke-width", 1)
.style("stroke", color[color.length - 1])
.style("fill", color[2])
.attr("opacity", 0.4);
x.domain(d3.extent(d, get_x));
x_axis.call(d3.svg.axis().scale(x).orient("bottom"));
y.domain(d3.extent(d, get_y));
y_axis.call(d3.svg.axis().scale(y).orient("left"));
series.append("g").attr("class", "timeseries")
.attr("clip-path", "url(#clip)")
.selectAll("circle")
.data(d).enter()
.append("circle")
.style("stroke", color[color.length - 2])
.style("stroke-width", .5)
.style("fill", color[color.length - 1])
.attr("opacity", .4)
.attr("r", 2)
.attr("transform", function (d) {
return "translate(" + x(get_x(d)) + "," + y(get_y(d)) + ")";
});
});
}
timeseries.x = function (accessor) {
if (!arguments.length) return get_x;
get_x = accessor;
return timeseries;
};
timeseries.y = function (accessor) {
if (!arguments.length) return get_y;
get_y = accessor;
return timeseries;
};
timeseries.xLabel = function (label) {
if (!arguments.length) return x_label;
x_label = label;
return timeseries;
}
timeseries.yLabel = function (label) {
if (!arguments.length) return y_label;
y_label = label;
return timeseries;
}
timeseries.brushmove = function (cb) {
if (!arguments.length) return brushmove;
brushmove = cb;
return timeseries;
};
function _brushmove() {
brushmove.call(null, brush);
}
function no_op() {}
return timeseries;
}
}());
</script>
</body>
</html>
Modified http://cdn.leafletjs.com/leaflet-0.5/leaflet-src.js to a secure url
Modified http://d3js.org/d3.v3.js to a secure url
Modified http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.0-rc.3/lodash.underscore.min.js to a secure url
https://cdn.leafletjs.com/leaflet-0.5/leaflet-src.js
https://d3js.org/d3.v3.js
https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.0-rc.3/lodash.underscore.min.js