This demo shows the D3 interaction with the time line slider. The x axis of the slider shows the date of data. User is able to drag the slider to change the date across the axis and the map will display the data in scatters before this date.
Interaction element is refered from Mike Bostock’s Blocks
This data is from The USGS Earthquake Hazards Program.
This dataset is about U.S earthquake incidents from year 1900 which the magnitude of the earthquake are larger than 5.5
forked from loveice622's block: USA earthquake data from year 1900
forked from Mike Bostock's block: earth-USA earthquake data from year 1900
forked from loveice622's block: Time Slider-USA earthquake data from year 1900
xxxxxxxxxx
<meta charset="utf-8">
<style>
.graticule {
fill: none;
stroke: #777;
stroke-width: .5px;
stroke-opacity: .5;
}
.land {
fill: #222;
}
.county-boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
.state-boundary {
fill: none;
stroke: #fff;
}
.head {
font-size: 20pt;
font-family: 'Gill Sans MT';
alignment-baseline: middle;
fill: #000000;
}
.ticks {
font: 10px sans-serif;
}
.track,
.track-inset,
.track-overlay {
stroke-linecap: round;
}
.track {
stroke: #000;
stroke-opacity: 0.3;
stroke-width: 10px;
}
.track-inset {
stroke: #ddd;
stroke-width: 8px;
}
.track-overlay {
pointer-events: stroke;
stroke-width: 50px;
stroke: transparent;
cursor: crosshair;
}
.handle {
fill: #fff;
stroke: #000;
stroke-opacity: 0.5;
stroke-width: 1.25px;
}
div.tooltip {
background: rgb(219, 219, 219); padding: 6px; border-radius: 4px; border: 1px solid rgb(114, 114, 114); border-image: none; width: auto; height: auto; text-align: left; color: black; font-size: 12px; visibility: hidden; position: absolute; z-index: 1200; max-width: 350px; opacity: 0.9; -webkit-border-radius: 4px; -mozilla-border-radius: 4px;
}
</style>
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
var width = 960,
height = 550;
margin = {right: 50, left: 50}
var projection = d3.geoAlbers()
.rotate([96, 0])
.center([-.6, 35.7])
.parallels([37.5, 45.5])
.scale(800)
.translate([width / 2, height / 2])
.precision(.1);
var path = d3.geoPath()
.projection(projection);
var graticule = d3.geoGraticule()
.extent([[-98 - 45, 38 - 45], [-98 + 45, 38 + 45]])
.step([5, 5]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var tooltipdiv = d3.select("body")
.append("div")
.attr("class", "tooltip");
svg.append('text')
.attr('class', 'head')
.attr('x', 230)
.attr('y', 20)
.text('USA earthquake data from year 1900');
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
d3.json("https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/us.json", function(error, us) {
if (error) throw error;
svg.insert("path", ".graticule")
.datum(topojson.feature(us, us.objects.land))
.attr("class", "land")
.attr("d", path);
svg.insert("path", ".graticule")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "state-boundary")
.attr("d", path);
});
var parseTime = d3.timeParse("%Y-%m-%d")
var formatTime = d3.timeFormat("%Y");
var parseYear = d3.timeParse("%Y")
d3.csv("us-earthquake-from1900.csv", function(d){
h=200
w=960
var allData=[];
d.forEach(function(d){ allData.push(d)});
var grouped=getGroupedData(allData)
//grouped.forEach(function(d){console.log(d.year,d.value7) })
var yMax = d3.max(grouped, function(d){return d.value;});
// X range to operate on
var extent = d3.extent(grouped, function(d){
return parseYear(d.year);
});
//console.log(extent)
// scale function
var x = d3.scaleTime()
.domain(extent)
.range([0, w-100])
.clamp(true);
var y = d3.scaleLinear()
.domain([0, yMax])
.range([h, 0]);
var xAxis = d3.axisBottom()
.scale(x)
.ticks(d3.timeYear, 5)
.tickSize(5)
.tickFormat(function() { return null; })
var chartBrush = d3.brushX()
.extent([[0, 0], [width, h]])
.on("end", brushended);
var svgChart = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 300);
svgChart.append("g")
.attr("class", "brush")
.call(chartBrush)
.selectAll("rect")
.attr("height", h)
.attr("transform", "translate( 0,-1)");
var bar = svgChart.selectAll("#bar")
.data(grouped)
.enter().append("g")
.each(function(d){
d.year = parseYear(d.year);
d.value = d.value;
d.value7=d.value7;
//console.log(d.year)
})
.attr("id", "bar")
.attr("transform", function(d) { return "translate(" + x(d.year) + ",0)"; })
.attr("class","year")
.on("mouseover", function(d){
var textTooltip = "<strong>"+formatTime(d.year)+'</strong><br /> mag>5.5: '+d.value+'<br /> mag>7.0: ' +d.value7;
tooltipdiv.html(textTooltip)
.style("top", d3.event.pageY - 20 + "px")
.style("left", d3.event.pageX + 20 + "px")
.style("visibility", "visible");
//console.log(d3.event.pageY,d3.event.pageX)
})
.on("mouseout", function(){tooltipdiv.style("visibility", "hidden"); });
bar.append("rect") //found
.attr("width", 3)
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return y(0) - y(d.value); })
.style("fill", "#E88D0C")
bar.append("rect") //fell
.attr("width", 3)
.attr("y", function(d) {return y(d.value7); })
.attr("height", function(d) { return y(0) -y(d.value7); })
.style("fill", "red")
svgChart.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + h + ")")
.call(d3.axisBottom(x)
.ticks(20)
.tickPadding(0))
.attr("text-anchor", null)
function brushended() {
if (!d3.event.sourceEvent) return; // Only transition after input.
if (!d3.event.selection) return; // Ignore empty selections.
var d0 = d3.event.selection.map(x.invert),
d1 = d0.map(d3.timeYear.round);
// If empty when rounded, use floor & ceil instead.
if (d1[0] >= d1[1]) {
d1[0] = d3.timeYear.floor(d0[0]);
d1[1] = d3.timeYear.offset(d1[0]);
}
console.log(d1[0],d1[1])
d3.select(this).transition().call(d3.event.target.move, d1.map(x));
updateData(d1[1],d,d1[0])
}
// console.log(extent)
formatDate = d3.timeFormat("%Y");
// initial value
var startValue = x(new Date('2012-03-20'));
startingValue = new Date('2012-03-20');
// var x = d3.scaleLinear()
// .domain([0, 180])
// .range([0, width])
//.clamp(true);
var slider = svg.append("g")
.attr("class", "slider")
.attr("transform", "translate(" + margin.left + "," + (height-100) + ")");
slider.append("text")
.attr("x",0)
.attr("y",-20)
.text("Show earthquakes before selected year")
slider.append("line")
.attr("class", "track")
.attr("x1", x.range()[0])
.attr("x2", x.range()[1])
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-inset")
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-overlay")
.call(d3.drag()
.on("start.interrupt", function() { slider.interrupt(); })
.on("start drag", function() { updateData(x.invert(d3.event.x),d); }));
slider.insert("g", ".track-overlay")
.attr("class", "ticks")
.attr("transform", "translate(0," + 18 + ")")
.selectAll("text")
.data(x.ticks(10))
.enter().append("text")
.attr("x", x)
.attr("text-anchor", "middle")
.text(function(d) { return formatDate(d); });
var handle = slider.insert("circle", ".track-overlay")
.attr("class", "handle")
.attr("r", 10);
function updateData(h,d,s)
{
console.log(formatDate(h))
handle.attr("cx", x(h));
svg.selectAll('circle[class=scatter]').remove()
for(i = 0; i < d.length; i ++){
var mystring =d[i].time
filterYear=parseTime(mystring.split('T')[0])
//console.log(formatTime(d.time))
//if(formatTime(filterYear)==formatTime(h))
if(parseInt(formatTime(filterYear))<=parseInt(formatTime(h)) &&
parseInt(formatTime(filterYear))>=parseInt(formatTime(s)))
{
svg.append("circle")
.attr("cx", projection([d[i].longitude,d[i].latitude])[0])
.attr("cy", projection([d[i].longitude,d[i].latitude])[1])
.attr("r", (d[i].mag-5)*4)
.style("fill", "red")
.attr("class", "scatter")
}
}
}
})
function getGroupedData(data)
{
var grouped=[]
var tempYear='NIL'
var counts=0
var counts7=0
for(i = 0; i < data.length; i ++)
{
var strYear =data[i].time.split('-')[0]
var mag = parseFloat(data[i].mag)
if(strYear==tempYear)
{
counts++
if(mag>7.0)
{
counts7++
}
}
else
{
if(tempYear!='NIL')
{
var singleObj = {}
singleObj['year'] =strYear; //+'-01-01'; //data[i].time.split('T')[0];
singleObj['value'] = counts;
singleObj['value7'] = counts7;
grouped.push(singleObj)
}
tempYear = strYear
counts=1
counts7 =0
}
}
return grouped;
}
</script>
https://d3js.org/d3.v4.min.js
https://d3js.org/topojson.v1.min.js