zeus.ugent.be/content/assets/scripts/datavis/bubbleMap.js
2018-05-16 22:42:07 +02:00

116 lines
3.2 KiB
JavaScript

(function () {
function bubbleMap() {
// Empty map variable, will init once
var map;
function init(mapId) {
if (map == null) {
map = new L.Map(mapId, { center: [51.023115, 3.710299], zoom: 12 })
.addLayer(new L.TileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png'));
map._initPathRoot();
d3.select(`#${mapId}`)
.select('svg')
.append('g')
.attr("class", "leaflet-zoom-hide")
}
}
function my(sel) {
init(sel.attr('id'));
const g = sel.select('g');
const dt = g.datum();
var div = d3.select(".tooltip").style('opacity', 0);
function vrUpdate() {
let g = d3.select('g');
const selection = g.selectAll('.location');
const data = selection.data();
const lines = g.selectAll('line');
const latlngs = data.map(e => map.latLngToLayerPoint(new L.LatLng(e.lat, e.lon)));
selection
.attr('cx', (e, i) => latlngs[i].x)
.attr('cy', (e, i) => latlngs[i].y)
;
}
const t = d3.transition()
.ease(d3.easeLinear)
.duration(100);
const sizes = _.countBy(dt, 'location_id');
const data = _.uniqBy(dt, 'location_id')
let radius = d3.scaleSqrt()
.range([0, 50])
.domain([0, 177])
;
// JOIN DATA
const selection = g.selectAll('.location').data(data, d => d.location_id);
const lines = g.selectAll('line').data(data, d => d.location_id);
// EXIT
selection.exit()
.transition(t)
.attr('r', 0)
.remove();
// ENTER
selection.enter()
.append('circle')
.style("stroke", "white")
.style("opacity", .4)
.style("fill", "blue")
.attr("r", 0)
.attr('class', 'location')
.each(d => {
const coord = map.latLngToLayerPoint(new L.LatLng(d.lat, d.lon));
g.append('circle')
.attr('r', radius(sizes[d.location_id]))
.attr('fill-opacity', 0)
.style('stroke', 'black')
.attr('transform', e => `translate(${coord.x}, ${coord.y})`)
.attr('opacity', 1)
.transition()
.duration(1000)
.ease(d3.easeLinear)
.attr('r', 75)
.attr('opacity', 0)
.remove();
})
.on("mouseout", _ => {
div.style("opacity", 0);
})
.merge(selection)
// We do the mouseover after the merge so the values update when changing time
.on("mouseover", function (d) {
div.text(`${d.name} (${sizes[d.location_id]})`);
let rect = d3.select(this).node().getBoundingClientRect();
let t_rect = div.node().getBoundingClientRect();
div
.style("opacity", .9)
.style("left", (rect.left + rect.width/2 - t_rect.width/2) + "px")
.style("top", (rect.top - t_rect.height - 5) + "px")
;
})
.transition(t)
.attr("r", d => radius(sizes[d.location_id]))
;
vrUpdate();
map.on("viewreset", vrUpdate);
}
return my;
}
window['bubbleMap'] = bubbleMap;
})();