import L from 'leaflet' import './leaflet.bezier' const arcStyles = { edu: { color: 'rgb(245, 246, 150)', fillColor: 'rgb(245, 246, 150)', opacity: 0.5, weight: '1', }, company: { color: 'rgb(50, 100, 246)', fillColor: 'rgb(50, 100, 246)', opacity: 1.0, weight: '2', }, gov: { color: 'rgb(245, 150, 100)', fillColor: 'rgb(245, 150, 150)', opacity: 1.0, weight: '2', }, mil: { color: 'rgb(245, 0, 0)', fillColor: 'rgb(245, 0, 0)', opacity: 1.0, weight: '2', }, } const sortOrder = ['edu', 'company', 'gov', 'mil'] const redDot = L.icon({ iconUrl: '/assets/img/reddot.png', iconSize: [17, 17], // size of the icon iconAnchor: [8, 8], // point of the icon which will correspond to marker's location popupAnchor: [0, -5] // point from which the popup should open relative to the iconAnchor }) function addMarker(map, latlng, citations) { const marker = L.marker(latlng, { icon: redDot }).addTo(map) let message = citations.map(citation => { const { title, addresses, year, pdf, doi } = citation let rec = [ "", title, "", ] if (pdf && pdf.length) { rec.unshift("") rec.push("") } else if (doi && doi.length) { rec.unshift("") rec.push("") } if (year) { rec.push(" (" + year + ")") } const addressString = addresses.map(addr => addr.name).join('
') rec.push("
") rec.push(addressString) return rec.join("") }) marker.bindPopup(message.join('

')) return marker } function addArc(map, src, dest, arcStyle) { L.bezier({ path: [ [ { lat: src[0], lng: src[1] }, { lat: dest[0], lng: dest[1] }, ], ] }, arcStyle).addTo(map) } export default function append(el, payload) { const { data } = payload if (!data) return let { paper, citations } = data let source = [0, 0] let map = L.map(el).setView([25, 0], 2) L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', { attribution: 'Map data © OpenStreetMap contributors, ' + 'CC-BY-SA, ' + 'Imagery © Mapbox', maxZoom: 18, id: 'mapbox.dark', style: 'mapbox://styles/mapbox/dark-v9', accessToken: 'pk.eyJ1IjoiZmFuc2FsY3kiLCJhIjoiY2pvN3I1czJwMHF5NDNrbWRoMWpteHlrdCJ9.kMpM5syQUhVjKkn1iVx9fg' }).addTo(map) if (paper.addresses && paper.addresses.length) { source = [paper.addresses[0].lat, paper.addresses[0].lng].map(n => (parseFloat(n) || 0)) } else { console.error("No address found for root paper") // console.log(data) } // group papers by address let citationsByAddress = {} citations.forEach(citation => { if (!citation.addresses) { // console.log(citation) return } // console.log(citation) citation.addresses.forEach(address => { if (!(address.name in citationsByAddress)) { citationsByAddress[address.name] = { address, citations: []} } citationsByAddress[address.name].citations.push(citation) }) }) Object.keys(citationsByAddress).map(name => { const { citations: citationList, address: citationAddress } = citationsByAddress[name] // console.log(name, citationsByAddress[name]) // console.log(citation) const latlng = [citationAddress.lat, citationAddress.lng].map(n => parseFloat(n)) if (Number.isNaN(latlng[0]) || Number.isNaN(latlng[1])) return addMarker(map, latlng, citationList) const style = { ...arcStyles[citationAddress.type] } let weight = Math.min(citationList.length, 5) let opacity = 0.5 + Math.min(citationList.length / 5, 0.5) if (citationAddress.type !== 'edu') { weight += 1 opacity = 1 } style.weight = String(weight) style.opacity = opacity addArc(map, source, latlng, style) }) // console.log(paper) const rootMarker = addMarker(map, source, [paper]) rootMarker.openPopup() // a transparent div to cover the map, so normal scroll events will not be eaten by leaflet const mapCover = document.createElement("div") mapCover.classList.add("map_cover") mapCover.innerHTML = "
Click here to explore the map
" mapCover.querySelector('div').addEventListener('click', () => { map.scrollWheelZoom.enable() if (mapCover.parentNode === el) { el.removeChild(mapCover) } }) function stopPropagation(e) { e.stopPropagation() } mapCover.addEventListener('mousewheel', stopPropagation, true) mapCover.addEventListener('DOMMouseScroll', stopPropagation, true) map.scrollWheelZoom.disable() map.on('focus', () => { map.scrollWheelZoom.enable() if (mapCover.parentNode === el) { el.removeChild(mapCover) } }) map.on('blur', () => { map.scrollWheelZoom.disable() // el.appendChild(mapCover) }) el.appendChild(mapCover) }