const MAXNUMCOORD = 100; const PINGWAITTIME = 1000*1; //1s const MAXIMGROTATION = parseInt(max_img_rotation); const OSMURL='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; const OSMATTRIB='Map data © OpenStreetMap contributors'; var ROTATIONWAITTIME = 1000*rotation_wait_time; //seconds var ZOOMLEVEL = zoomlevel; var regionhits = {}; var regionhitsMax = 10; var myOpenStreetMap = L.map('feedDivMap1').setView([0, 0], 1); var osm = new L.TileLayer(OSMURL, {minZoom: 0, maxZoom: 18}).addTo(myOpenStreetMap); class MapEvent { constructor(json, marker) { this.coord = json.coord; this.regionCode = json.regionCode; this.marker = marker; this.categ = json.categ; this.value = json.value; this.country = json.country; this.specifName = json.specifName; this.cityName = json.cityName; this.text = this.categ + ": " + this.value; let underText = ""; if (this.specifName !== null && this.cityName !== null) { underText = this.specifName+", "+this.cityName; } else if (this.specifName !== null) { underText = this.specifName; } else if (this.cityName !== null) { underText = this.cityName; } else { underText = ""; } this.textMarker = "{1}
{2}".replace("{1}", this.country).replace("{2}", underText); } } class MapEventManager { constructor() { this._mapEventArray = []; this._currentMapEvent; this._nextEventToShow = 0; this._first_map = true; this._coordSet = new Set(); //current lat and lon shown in worldMap this._latToPing; this._lonToPing; //Markers on the worldMap this._allMarkers = []; this._curMarkerNum = 0; //use for cancelTimeout this._timeoutRotate; } addMapEvent(mapevent) { if(this.getNumberOfEvent() > MAXIMGROTATION) { var toDel = this._mapEventArray[0]; toDel.marker.remove(); // remove marker this._coordSet.delete(toDel.text); this._mapEventArray = this._mapEventArray.slice(1); } if(!this._coordSet.has(mapevent.text)) { // avoid duplicate map this._mapEventArray.push(mapevent); this._coordSet.add(mapevent.text); this.popupCoord(mapevent.coord, mapevent.regionCode); } else { //console.log('Duplicate coordinates'); } if(this._first_map) { // remove no_map pic this.rotateMap(); this.ping(); this._first_map = false; } else { this.rotateMap(mapevent); } } getNumberOfEvent() { return this._mapEventArray.length } getNextEventToShow() { var toShow = this._mapEventArray[this._nextEventToShow]; this._nextEventToShow = this._nextEventToShow == this._mapEventArray.length-1 ? 0 : this._nextEventToShow+1; this._currentMapEvent = toShow; return toShow; } getCurrentMapEvent() { return this._currentMapEvent; } // Perform the roration of the map in the openStreetMap pannel rotateMap(mapEvent) { clearTimeout(this._timeoutRotate); //cancel current map rotation if (mapEvent == undefined) { var mapEvent = this.getNextEventToShow(); } this._latToPing = mapEvent.coord.lat; this._lonToPing = mapEvent.coord.lon; var marker = mapEvent.marker; myOpenStreetMap.flyTo([mapEvent.coord.lat, mapEvent.coord.lon], ZOOMLEVEL); mapEvent.marker.bindPopup(mapEvent.textMarker).openPopup(); $("#textMap1").text(mapEvent.text); if(ROTATIONWAITTIME != 0) { this._timeoutRotate = setTimeout(function(){ mapEventManager.rotateMap(); }, ROTATIONWAITTIME); } } directZoom() { var mapEvent = this.getCurrentMapEvent(); if (mapEvent != undefined) myOpenStreetMap.flyTo([mapEvent.coord.lat, mapEvent.coord.lon], ZOOMLEVEL); } ping() { var pnts = openStreetMapObj.latLngToPoint(this._latToPing, this._lonToPing); if (pnts != false) { //sometimes latLngToPoint return false $("#feedDiv2").append( $('
') .css({'left': pnts.x-15 + 'px'}) /* HACK to center the effect */ .css({'top': pnts.y-15 + 'px'}) .css({ 'background-color': 'orange' }) .animate({ opacity: 0, scale: 1, height: '80px', width:'80px', margin: '-25px' }, 400, 'linear', function(){$(this).remove(); }) ); } setTimeout(function(){ mapEventManager.ping(); }, PINGWAITTIME); } // Add and Manage markers on the map + make Animation popupCoord(coord, regionCode) { var coord = [coord.lat, coord.lon]; var color = 0.5*180; var pnts = openStreetMapObj.latLngToPoint(coord[0], coord[1]) if (pnts != false) { //sometimes latLngToPoint return false var addedMarker = openStreetMapObj.addMarker(this._curMarkerNum, coord, [color]); this._allMarkers.push(this._curMarkerNum) marker_animation(pnts.x, pnts.y, this._curMarkerNum); update_region(regionCode); this._curMarkerNum = this._curMarkerNum >= MAXNUMCOORD ? 0 : this._curMarkerNum+1; if (this._allMarkers.length >= MAXNUMCOORD) { var to_remove = this._allMarkers[0]; openStreetMapObj.removeMarkers([to_remove]); this._allMarkers = this._allMarkers.slice(1); } } } } function marker_animation(x, y, markerNum) { var markerColor = openStreetMapObj.markers[markerNum].element.config.style.current.fill; $("#feedDiv2").append( $('
') .css({'left': x-15 + 'px'}) /* HACK to center the effect */ .css({'top': y-15 + 'px'}) .css({ 'background-color': markerColor }) .animate({ opacity: 0, scale: 1, height: '80px', width:'80px', margin: '-25px' }, 700, 'linear', function(){$(this).remove(); }) ); } function update_region(regionCode) { if (regionCode in regionhits) { regionhits[regionCode] += 1; } else { regionhits[regionCode] = 1; } // Force recomputation of min and max for correct color scaling regionhitsMax = regionhitsMax >= regionhits[regionCode] ? regionhitsMax : regionhits[regionCode]; openStreetMapObj.series.regions[0].params.max = regionhitsMax; // Update data openStreetMapObj.series.regions[0].setValues(regionhits); } var mapEventManager = new MapEventManager(); var openStreetMapObj; $(function(){ $('#feedDiv2').vectorMap({ map: 'world_mill', markers: [], series: { markers: [{ attribute: 'fill', //scale: ['#1A0DAB', '#e50000', '#62ff41'], scale: ['#ffff66'], values: [], min: 0, max: 180 }], regions: [{ values: [], min: 0, max: 10, scale: ['#003FBF','#0063BF','#0087BF','#00ACBF','#00BFAD','#00BF89','#00BF64','#00BF40','#00BF1C','#08BF00','#2CBF00','#51BF00','#75BF00','#99BF00','#BEBF00','#BF9B00','#BF7700','#BF5200','#BF2E00','#BF0900'], normalizeFunction: 'linear', legend: { horizontal: true } }] }, }); openStreetMapObj = $("#feedDiv2").vectorMap('get','mapObject'); }); // Subscribe to the flask eventStream var source_map; function connect_source_map() { source_map = new EventSource(urlForMaps); source_map.onmessage = function(event) { var json = jQuery.parseJSON( event.data ); var marker = L.marker([json.coord.lat, json.coord.lon]).addTo(myOpenStreetMap); var mapEvent = new MapEvent(json, marker); mapEventManager.addMapEvent(mapEvent); }; source_map.onopen = function(){ console.log('connection is opened. '+source_map.readyState); }; source_map.onerror = function(){ console.log('error: '+source_map.readyState); source_map.close() setTimeout(function() { connect_source_map(); }, 5000); }; } $(document).ready(function () { $( "#rotation_wait_time_selector" ).change(function() { var sel = parseInt($( this ).val()); if(isNaN(sel)) { rotation_wait_time = 0; } else { rotation_wait_time = sel; } var old = ROTATIONWAITTIME; ROTATIONWAITTIME = 1000*rotation_wait_time; //seconds if(old == 0) { mapEventManager._timeoutRotate = setTimeout(function(){ mapEventManager.rotateMap(); }, ROTATIONWAITTIME); } }); $( "#zoom_selector" ).change(function() { var sel = parseInt($( this ).val()); ZOOMLEVEL = sel; mapEventManager.directZoom(); }); if (!!window.EventSource) { $.getJSON( urlForMaps, function( data ) { data.forEach(function(item) { var marker = L.marker([item.coord.lat, item.coord.lon]).addTo(myOpenStreetMap); var mapEvent = new MapEvent(item, marker); mapEventManager.addMapEvent(mapEvent); }); connect_source_map() }); } });