Create an Interactive Scatter Plot with Vanilla JavaScript in Deck.gl

The code below builds on the JavaScript from [Create a Vanilla JavaScript Application with Mapbox and Deck.gl], but uses a more realistic approach to loading data and adds two basic features.

Rather than setting the ScatterplotLayer.data property to a static URL we make a fetch call to load some API data and parse it to JSON ourselves, then provide that when creating our map.

In addition to more closely matching what you're likely to see and do in a real application, this also lets us inspect the data to do things like calculate a center point. We can then pass that center to initialViewState, ensuring the data we render is in the viewport. Note that the zoom is still hard coded for simplicity, but in a real application you'd want to calculate that from the data as well.

The other feature this code adds is a basic tooltip and interactivity. To make the Scatterplot react to mouse events we specify pickable: true. We then attach a getTooltip function to the DeckGL instance that will be called any time the mouse passes into or out of a point. When getTooltip is called, it's passed a parameter describing the interaction. When a point is moused over, the parameter has an object property that is the corresponding data item. When the mouse leaves a point, object is undefined, hence the check at the beginning of the function. You can return a simple string from getTooltip or an object to specify HTML and CSS, as we've done here.

const {DeckGL, ScatterplotLayer} = deck;
const xhr = await fetch('/api/movebank/wildebeest/')
const arr = await xhr.json()

let minLng, minLat, maxLng, maxLat

for (let i = 0; i < arr.length; i++) {
  const row = arr[i];
  minLng = minLng ? Math.min(minLng, row.location_long) : row.location_long
  maxLng = maxLng ? Math.max(maxLng, row.location_long) : row.location_long
  minLat = minLat ? Math.min(minLat, row.location_lat) : row.location_lat
  maxLat = maxLat ? Math.max(maxLat, row.location_lat) : row.location_lat
}

const longitude = (minLng + maxLng) / 2
const latitude = (minLat + maxLat) / 2

new DeckGL({
  mapStyle: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
  initialViewState: {
    longitude,
    latitude,
    zoom: 8,
    maxZoom: 16
  },
  controller: true,
  layers: [
    new ScatterplotLayer({
      id: 'scatter-plot',
      data: arr,
      pickable: true,
      radiusScale: 10,
      radiusMinPixels: 2,
      getPosition: d => [d.location_long, d.location_lat, 0],
      getFillColor: [255, 0, 255]
    })
  ],
  getTooltip: ({object}) => object && {
    html: `<b>${object.individual_local_identifier}</b><br/>${object.timestamp}`,
    style: {
      fontFamily: 'Arial, Helvetica, sans-serif'
    }
  },
});