I'm new to D3 and just wrote a small code to display point transitions on a map:
Static Image
I started with a small sample of ~100 points, which works fine.
But eventually, I want to display about 1000 points as in this animation here: https://www.zeit.de/feature/pendeln-stau-arbeit-verkehr-wohnort-arbeitsweg-ballungsraeume
But even 500 points seem to be too much to handle for D3 and the browser - the animations don't repeat anymore.
I read that I should use canvas for better performance, but after reading some tutorials I still cannot properly rewrite my SVG code to canvas code. Any help on how to correctly use canvas here appreciated.
The code using SVG:
Promise.all([
d3.json('http://opendata.ffe.de:3000/rpc/map_region_type?idregiontype=2&generalized=1'),
d3.csv('../Daten/d3_input_sample_klein.csv')
]).then(([bl, centroids]) => {
var aProjection = d3.geoMercator()
.fitSize([800, 600], bl);
var geoPath = d3.geoPath()
.projection(aProjection);
var svg = d3.select('body')
.append('svg')
.attr('width', 1000)
.attr('height', 1000);
// draw basemap
svg.selectAll('path')
.data(bl.features)
.enter()
.append('path')
.attr('d', geoPath)
.attr('class', 'bl');
// get max value for scaleLinear
var max = d3.max(centroids, function (d) {
return parseInt(d.value);
});
var radiusScale = d3.scaleLinear()
.domain([0,max])
.range([1, 10]);
// create circles with radius based on "value"
function circleTransition() {
var circles = svg.selectAll('circle')
.data(centroids)
.enter()
.append('circle')
.style('fill', 'white')
.attr('r', function (d) {
return radiusScale(d.value);
});
repeat();
// transition circles from "start" to "target" and repeat
function repeat() {
circles
.attr('cx', (d) => aProjection([d.x_start, d.y_start])[0])
.attr('cy', (d) => aProjection([d.x_start, d.y_start])[1])
.transition()
.duration(4000)
.attr('cx', (d) => aProjection([d.x_target, d.y_target])[0])
.attr('cy', (d) => aProjection([d.x_target, d.y_target])[1])
.on('end', repeat);
};
};
circleTransition();
The loaded CSV file contains lat/lon coordinates like this:
x_start | y_start | x_target | y_target | value |
---|---|---|---|---|
9.11712 | 54.28097 | 8.77778 | 54.71323 | 122 |
9.79227 | 53.64759 | 9.60330 | 53.86844 | 87617 |
9.70219 | 53.58864 | 8.80382 | 54.80330 | 2740 |
Is there an easy way to transform this code to using canvas or improve performance in another way?
Thanks! Michael