3Dtiles + CartoLayer

by felixp

HTML

<!DOCTYPE html>
<html>

  <head>
    <title>3Dtiles + CartoLayer</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <script src="https://unpkg.com/[email protected]/dist.min.js"></script>
    <script src="https://unpkg.com/@deck.gl/[email protected]/dist.min.js"></script>

    <script src="https://unpkg.com/@deck.gl/[email protected]/dist.min.js"></script>
    <!-- jsFiddle will insert css and js -->
  </head>

  <body>
    <div id="map"></div>
    <div id="credits"></div>
  </body>
</html>

CSS

body {
  margin: 0;
  padding: 0;
}

#map {
  width: 100vw;
  height: 100vh;
}

#credits {
  position: absolute;
  font-family: 'Helvetica';
  left: 8px;
  bottom: 4px;
  color: white;
  font-size: 9px;
}

JavaScript

// Credentials
const GOOGLE_MAPS_API_KEY = 'AIzaSyCRI5l6GB1OR3SuVQzD8v5UXL8iyAo0z2o';
deck.carto.setDefaultCredentials({
  accessToken: 'eyJhbGciOiJIUzI1NiJ9.eyJhIjoiYWNfN3hoZnd5bWwiLCJqdGkiOiJhMjQyNDM4MSJ9.5bAXb8y7PyIOB__X7i-iQUWCZgLkedtGoqRI25HuQxc'
});

// Photorealistic 3D Tile layer
const tiles3d = new deck.Tile3DLayer({
  id: 'google-3d-tiles',
  data: 'https://tile.googleapis.com/v1/3dtiles/root.json',
  onTilesetLoad: tileset3d => {
    // tileset3d.options.maximumScreenSpaceError = 4;
    tileset3d.options.onTraversalComplete = selectedTiles => {
      const uniqueCredits = new Set();
      selectedTiles.forEach(tile => {
        const {copyright} = tile.content.gltf.asset;
        copyright.split(';').forEach(uniqueCredits.add, uniqueCredits);
      });
      setCredits([...uniqueCredits].join('; '));
      return selectedTiles;
    };
  },
  loadOptions: {
    fetch: {headers: {'X-GOOG-API-KEY': GOOGLE_MAPS_API_KEY}}
  },
  operation: 'terrain+draw' // Required to enable draping of other layers
});

// Buildings from CARTO
const buildings = new deck.carto.CartoLayer({
  id: 'buildings',
  connection: 'bigquery',
  type: deck.carto.MAP_TYPES.TABLE,
  data: 'cartodb-on-gcp-backend-team.alasarr.madrid_buildings',
  getFillColor: deck.carto.colorBins({
    attr: 'grossFloorAreaM2',
    domain: [0, 200, 400, 1000, 2000, 5000],
    colors: 'BluYl'
  }),
  stroked: false,
  extensions: [new deck._TerrainExtension()] // Required to drape over 3D tiles
});

const deckgl = new deck.DeckGL({
  container: 'map',
  controller: true,
  initialViewState: {
    latitude: 40.4205,
    longitude: -3.7083,
    zoom: 15,
    pitch: 40,
    maxPitch: 40,
    position: [0, 0, 700] // Raise camera anchor to 700m above sea level
  },
  layers: [tiles3d, buildings]
});

const creditsElement = document.getElementById('credits');
function setCredits(credits) {
  creditsElement.innerHTML = credits;
}