body {
  margin: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.deck-tooltip {
  font-family: Helvetica, Arial, sans-serif;
  font-size: 12px;
  max-width: 320px;
}

h4 {
  margin: 0 0 8px;
}
/*
* https://deck.gl/docs/api-reference/extensions/path-style-extension
*/

const {
  Deck,
  MapView,
  GeoJsonLayer,
  ScatterplotLayer,
  MaskExtension
} = deck;
const {CSVLoader} = loaders;

// source: Natural Earth http://www.naturalearthdata.com/ via geojson.xyz
const COUNTRIES = 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_admin_0_scale_rank.geojson';
const TIMEZONES =
  'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/time_zones.geojson';
const CITIES =
  'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/cities15000.csv';

const INITIAL_VIEW_STATE = {
  latitude: 0,
  longitude: 0,
  zoom: 0
};

const deckgl = new Deck({
  views: new MapView({repeat: true}),
  initialViewState: INITIAL_VIEW_STATE,
  controller: {dragRotate: false},
  getTooltip
});

let allTimezones;
redraw([]);

function select(timezoneCode) {
  for (const f of allTimezones) {
    f.selected = f.properties.utc_name === timezoneCode;
  }
  redraw(allTimezones.filter(f => f.selected));
}

function redraw(selectedTimeZones) {
  const layers = [
    new GeoJsonLayer({
      id: 'base-map',
      data: COUNTRIES,
      stroked: true,
      filled: false,
      lineWidthMinPixels: 1,
      getLineColor: [120, 120, 120]
    }),
    new GeoJsonLayer({
      id: 'selected-timezone',
      data: selectedTimeZones,
      operation: 'mask'
    }),
    new GeoJsonLayer({
      id: 'timezones',
      data: TIMEZONES,
      onDataLoad: geojson => {
        allTimezones = geojson.features;
        select('UTC±00:00');
      },
      // Styles
      stroked: true,
      filled: true,
      getLineColor: [30, 150, 180],
      getLineWidth: f => f.selected ? 2 : 1,
      getFillColor: f => f.selected ? [255, 255, 255, 0] : [225, 225, 225, 200],
      lineWidthUnits: 'pixels',
      updateTriggers: {
        getLineWidth: selectedTimeZones,
        getFillColor: selectedTimeZones
      },
      // Interaction
      pickable: true,
      onClick: ({object}) => {
        select(object.properties.utc_name);
      },
      autoHighlight: true,
      highlightColor: [0, 200, 255, 128]
    }),
    new ScatterplotLayer({
      id: 'selected-cities',
      data: CITIES,
      getPosition: d => [d.longitude, d.latitude],
      getRadius: d => Math.sqrt(d.population),
      getFillColor: [255, 0, 128],
      radiusMinPixels: 1,
      pickable: true,
      maskId: 'selected-timezone',
      loaders: [CSVLoader],
      extensions: [new MaskExtension()]
    })
  ];
  deckgl.setProps({layers});
}

function getTooltip({object}) {
  if (!object) return null;

  let title, description;
  if (object.properties) {
    title = `${object.properties.name || ''} (${object.properties.utc_name})`;
    description = object.properties.places;
  } else {
    title = object.name;
    description = `Population: ${object.population}`;
  }

  return {
    html: `<h4>${title}</h4> ${description}`
  };
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.com/deck.gl@^8.9.0/dist.min.js
  2. https://unpkg.com/@loaders.gl/csv@^3.0.0/dist/dist.min.js