Mapbox Popup Example

Demonstrate how to create Popups and listen to their events.

by Sarah Godoshian

HTML

<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.52.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.52.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>

<div id="demo">
  <div id="output-container">
  </div>

  <div id="map" class="map">
  </div>

</div>

SCSS

#demo {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  #output-container {
    flex: 1;
  }
  .map {
    height: 300px;
    flex: 2;
    background-color: black;
  }
}

JavaScript

// Data from http://geojson.xyz/
const geojsonSource = 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_populated_places.geojson';
const outputContainer = document.getElementById('output-container');

mapboxgl.accessToken = 'pk.eyJ1IjoiY2NoYW5nc2EiLCJhIjoiY2lqeXU3dGo1MjY1ZXZibHp5cHF2a3Q1ZyJ9.8q-mw77HsgkdqrUHdi-XUg';

const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/outdoors-v10',
  renderWorldCopies: false, // so we dont need logic to show multiple popups ;)
});

let hoveredFeature;
let popupDOMElement = document.createElement('div');
let mapboxPopup = new mapboxgl.Popup();

mapboxPopup.on('close', () => {
	outputContainer.innerHTML += 'popup closed<br>';
});

mapboxPopup.on('open', () => {
	outputContainer.innerHTML += 'popup opened<br>';
});

const addLayerToMap = (layer) => {
	map.addLayer(layer);
  let popup;
  map.on('mousemove', layer.id, (e) => {
  	if (!e.features || !e.features.length) return;
  	const point = turf.point(Object.values(e.lngLat));
    const features = turf.featureCollection(e.features);
    const nearest = turf.nearestPoint(point, features)
    console.log(nearest);
    if ( ! hoveredFeature || (nearest.properties.NAME !== hoveredFeature.properties.NAME)) {
    	mapboxPopup.remove();
    	hoveredFeature = nearest;
      const details = hoveredFeature.properties;
      popupDOMElement.innerHTML = 
      	`
        	<h3>${details.NAME}, ${details.ADM0NAME}</h3>
          <b>Population</b> ${details.POP_MIN} - ${details.POP_MAX}
        `;
      mapboxPopup
      	.setLngLat(hoveredFeature.geometry.coordinates)
        .setDOMContent(popupDOMElement)
        .addTo(map);
      
    }
  });
};

fetch(geojsonSource)
  .then(response => {
    if (response.ok) return response.json();
    throw Error(response);
  })
  .then(json => {
    let layer = {
      id: 'populated-places',
      source: {
        type: 'geojson',
        data: json,
      },
      type: 'circle',
      paint: {
     ...