(function () { let mapData; // the map needs geojson input so turn the lnglat data into geojson let convertLngLatToGeojson = function (latlngs) { let geojson = { "type": "FeatureCollection", "features": [] }; latlngs.forEach(d => geojson.features.push({ "type": "Feature", "geometry": { "type": "Point", "coordinates": [+d.lng, +d.lat] }, "properties": { source: d.source } })); return geojson; }; let animateMarker = function (tick, data) { mapDisplay.getSource('locationData').setData(data[tick % data.length].geojson); tick +=1; if(tick < data.length) { // Request the next frame of the animation. requestAnimationFrame((timestep) => {animateMarker(tick, data)}); } else { let combinedgeojson = convertLngLatToGeojson(mapData) mapDisplay.getSource('locationData').setData(combinedgeojson) } // d3.interval((timestep) => {animateMarker(tick, data)},1000); }; mapboxgl.accessToken = 'pk.eyJ1Ijoid3d5bWFrIiwiYSI6IkxEbENMZzgifQ.pxk3bdzd7n8h4pKzc9zozw'; let mapDisplay = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/dark-v9', zoom: 3, center: [-98.5, 39.8] }); mapDisplay.addControl(new mapboxgl.NavigationControl()); mapDisplay.on('load', () => { d3.csv('latlngs.csv', d => { return { lat : +d.lat, lng : +d.long, timeParsed: moment(d.created_at).startOf('minute'), time : new Date(d.created_at), source : d.source } },(err, data) => { data.sort((a,b) => a.time.getTime() - b.time.getTime()); let mintime = d3.min(data, d=> d.time.getTime()); let maxtime = d3.max(data, d=> d.time.getTime()); let distinctSources = Array.from(new Set(data.map(d => d.source))); data.forEach(d => { d.timeElapsed = (d.timeParsed.unix() - moment(mintime).startOf('minute').unix())/60; }); mapData = data; let timeLapseArr= d3.nest().key(d => d.timeElapsed).entries(data); timeLapseArr.forEach(d => { d.key = +d.key; d.geojson = convertLngLatToGeojson(d.values) }); if(mapDisplay.getSource('locationData')){ mapDisplay.getSource('locationData').setData(timeLapseArr); return; } mapDisplay.addSource("locationData", { type: "geojson", data: timeLapseArr[0].geojson, }); mapDisplay.addLayer({ id: 'tweets', type: 'circle', source: 'locationData', paint: { 'circle-radius': { 'base': 2, 'stops': [[2, 4], [12, 8], [15, 20], [20, 80]] }, // color circles 'circle-color': '#3bb2d0' // 'circle-color': { // property: 'network_name', // type: 'categorical', // stops: [ // ['EE', '#fbb03b'], // ['3', '#223b53'], // ['O2', '#e55e5e'], // ['Vodafone', '#3bb2d0'], // ['Other', '#ccc']] // } } }); animateMarker(0, timeLapseArr) }); }); })();