console.clear() // load data d3.loadData('world-50m.json', 'wannacry-trimmed.tsv', function(err, res){ world = res[0] points = res[1] var sel = d3.select(".g-cyber-map").html('').st({position: 'relative'}) var width = sel.node().offsetWidth, height = width/960*500; var land = topojson.feature(world, world.objects.land), countries = topojson.mesh(world, world.objects.countries, (a, b) => a !== b ) var proj = d3.geoNaturalEarth().fitSize([width, height], land) var path = d3.geoPath().projection(proj); proj.scale(proj.scale()*1.25) var svg = sel.append("svg").at({width, height}) svg.append("path.land").at({d: path(land)}) svg.append('clipPath#clip') .append('path') .at({d: path(land)}) var color = d3.scaleLog() .domain([0.00390625, .125/2, 1.5]) .range(['rgb(228, 228, 177)', 'yellow', 'red']) points.forEach(d => d.pos = proj([d.lng, d.lat])) contour = d3.contourDensity() .x(d => d.pos[0]) .y(d => d.pos[1]) .bandwidth(7) .thresholds([.25, .5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512]) .cellSize(7) var layerSel = svg.append('g') .attr('clip-path', 'url(#clip)') .appendMany(contour(points), 'path.contour') .at({d: d3.geoPath(), fill: d => color(d.value)}) if (window.drawtimer) drawtimer.stop() drawtimer = d3.timer(contourLoop) function contourLoop(t){ var index = (t*2) % points.length activePoints = points.slice(index, index + Math.min(index/2, 5000)) layerSel.data(contour(activePoints)).at({d: d3.geoPath()}) } })