Reputation: 5148
I am unable to figure out the way to get a smooth transition while plotting points in D3. I have a script which plots the world map. I am listening to a server which is giving me latitudes and longitudes of events. I want to draw the event on the screen such that the circle increase in radius from 0 to 10 in 1 second. Because I am listening to the server I can have more than one datapoint in 1 second. How should I plot another point while the previous one is still in transition?
This is the code that I came up with but I am not able to figure out a way that I can add d3 type transition to the "circle" as that is only possible when you use d3.data([coords]).enter(). Using d3 here seems to me overkill since I can directly change the attributes.
EDIT:
Simplifying my problem a bit I decided to collect 1 second worth of data and then display those points all at once. However, I think I am not able to understand the essence of exit() as my code below is not removing the previous points and making new points at the coords. Points.exit().remove is not working because it returns an array of size 0 although coords changes every time. Also, it shows the first set of data on map continuously and does not change anything afterwards.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.8.0.min.js"></script>
<script type="text/javascript">
$(document).ready(
function() {
sse = new EventSource('/my_event_source');
sse.onmessage = function(message) {
console.log('A message has arrived!');
var data = JSON.parse(message.data);
data.data.forEach(function(d){
d.lat = +d.lat;
d.lg = +d.lg;
});
console.log(data.data)
plot(data.data);
}
})
</script>
<style>
.point{
fill:rgb(247,148, 32);
stroke:black;
stroke-width:0.7;
opacity:0.7;
}
</style>
<script type ="text/javascript">
function draw(geo_data){
"use strict";
var margin = 75,
width = 1920 -margin,
height = 1080 -margin;
var svg = d3.select('body')
.append("svg")
.attr('class',"main")
.attr('width', width+margin)
.attr('height', height+margin)
var svg2 = svg.append('g')
.attr('class','map');
// convrt the long, lat to pixels ()x,y
var projection = d3.geo.mercator()
.scale(220)
.translate([width/2, height/1.5]);
//svg objects
var path = d3.geo.path().projection(projection);
var map = svg2.selectAll('path')
.data(geo_data.features)
.enter()
.append('path')
.attr('d', path)
.style('fill','rgb(9,157,217)')
.style('stroke','black')
.style('stroke-width', 0.5);
svg.append("g").attr("class","point");
}
function plot(data){
"use strict";
var margin = 75,
width = 1920 -margin,
height = 1080 -margin;
var spot = d3.select('svg.main').select("g.point");
// convrt the long, lat to pixels ()x,y
var projection = d3.geo.mercator()
.scale(220)
.translate([width/2, height/1.5]);
var coords = data.map(function(d) {
return projection([d.lg, d.lat]);
});
var points = spot.selectAll("circle")
.data(coords);
points.exit().remove();
points.enter()
.append("circle")
.classed("circle", true)
.attr('cx', function(d){return d[0];})
.attr('cy', function(d){return d[1];})
.attr('r', 10);
}
</script>
</head>
<body>
<script type = "text/javascript">
/*Use d3 to load the GeoJSON file*/
d3.json("/static/world_countries.json", draw);
</script>
</body>
</html>
Upvotes: 0
Views: 411
Reputation: 1583
You should check out Mike Bostock's Thinking with Joins article. The problem you're having is conceptualizing how to use D3 to to operate on an array of items, but only have D3 animate new items recently added to the array. This is done with the .data().enter() command.
I put together an example of what you're trying to achieve, leaving out the geography dimension. The example has three main sections, initialization of variables, a draw function that runs every time a new item is added to the array, and a simulation of your server which randomly adds an item then calls draw().
You'll see that all the magic happens in the draw() function. Even though we repeatedly pass the ever-growing data array to the function, the function only animates the newly added items of data.
https://jsbin.com/qoqalufihe/edit?html,output
Upvotes: 1