Deck gl minimap with gl settings

778 Views Asked by At

I have a problem with deckgl and minimap display. First of all I follow the deckgl documentation to integrate mapbox and especially the last section of https://deck.gl/docs/api-reference/mapbox/overview because I had problem with street name and other layers. But with it, my minimap isn't display and I don't understand why. I reproduce my problem in a simple react app:

Here my app.js file

import React, {useState, useRef, useCallback} from 'react';
import DeckGL from '@deck.gl/react';
import { MapView } from '@deck.gl/core';
import {ScatterplotLayer} from '@deck.gl/layers';
import {StaticMap} from 'react-map-gl';

import {MapboxLayer} from '@deck.gl/mapbox';
import {load} from '@loaders.gl/core';
import {CSVLoader} from '@loaders.gl/csv';

import {render} from 'react-dom';

const INITIAL_VIEW_STATE = {
  longitude: -74.50,
  latitude: 40,
  zoom: 9
};

const DATA_URL_BASE = 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/radio';
const DATA_URL = {
  STATIONS: `${DATA_URL_BASE}/stations.tsv`,
  COVERAGE: `${DATA_URL_BASE}/coverage.csv`,
  CONTOURS: `${DATA_URL_BASE}/service-contour/{z}/{x}-{y}.mvt`
};

const data = [
  {position: [-74.5, 40], size: 100}
];

export default function App() {
  const mapboxApiAccessToken = 'api_token';
  // DeckGL and mapbox will both draw into this WebGL context
  const [glContext, setGLContext] = useState();
  const deckRef = useRef(null);
  const mapRef = useRef(null);

  const onMapLoad = useCallback(() => {
    const map = mapRef.current.getMap();
    const deck = deckRef.current.deck;

    // You must initialize an empty deck.gl layer to prevent flashing
    map.addLayer(
      // This id has to match the id of the deck.gl layer
      new MapboxLayer({ id: "my-scatterplot", deck })
    );
  }, []);

  const layers = [
    new ScatterplotLayer({
      id: 'my-scatterplot',
      data,
      getPosition: d => d.position,
      getRadius: d => d.size,
      getFillColor: [255, 0, 0]
    })
  ];

  const minimapView = () => {
    return new MapView({
      id: 'minimap',
      x: '0%',
      y: '65%',
      width: '17%',
      height: '35%',
      clear: true,
      zoom: 4,
      controller: null,
    });
  }
  const mainview = () => {
    return new MapView({
      id: 'main',
      repeat: false,
      controller: true
    });
  }

  return (
    <DeckGL
      ref={deckRef}
      views = { [mainview(), minimapView() ]}
      layers={layers}
      initialViewState={INITIAL_VIEW_STATE}
      controller={true}
      onWebGLInitialized={setGLContext}
      glOptions={{
        /* To render vector tile polygons correctly */
        stencil: true
      }}
    >
      {glContext && (
        /* This is important: Mapbox must be instantiated after the WebGLContext is available */
      <MapView id="mainview">
        <StaticMap
          ref={mapRef}
          mapStyle="mapbox://styles/mapbox/light-v9"
          gl={glContext}
          mapboxApiAccessToken={mapboxApiAccessToken}
          onLoad={onMapLoad}
        />
        </MapView>
      )}
      <MapView id="minimap">
        <StaticMap key={"minimapmapbox"}
          attributionControl={false}
          reuseMaps 
          mapStyle = "mapbox://styles/mapbox/satellite-v9"
          mapboxApiAccessToken={mapboxApiAccessToken}>
        </StaticMap>
      </MapView>
    </DeckGL>
  );
}

export function renderToDOM(container) {
    render(<App />, container);

    load(DATA_URL.STATIONS, CSVLoader, {csv: {delimiter: '\t', skipEmptyLines: true}}).then(data => {
      render(<App data={data} />, container);
    });
}

and my index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>deck.gl Example</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body {margin: 0; font-family: sans-serif; width: 100vw; height: 100vh; overflow: hidden;}
  </style>
</head>
<body>
<div id="app"></div>
</body>
   <script type="text/javascript" src="app.js"></script>
   <script type="text/javascript">
     App.renderToDOM(document.getElementById('app'));
   </script>
</html>

In my main view, the base map and my minimap are display if gl is not set. But if gl is set (gl={glContext}) then the base map is display but minimap not. Anyone have an idea ?

Thanks in advance

1

There are 1 best solutions below

0
On

Here is a condenced example that will work for you

import React from 'react';
import {useState, useMemo, useCallback} from 'react';

import {render} from 'react-dom';
import {StaticMap} from 'react-map-gl';
import {MapView, } from '@deck.gl/core';
import {MVTLayer} from '@deck.gl/geo-layers';
import DeckGL from '@deck.gl/react';

import {load} from '@loaders.gl/core';


const mainView = new MapView({id: 'main', controller: true});
const minimapView = new MapView({
  id: 'minimap',
  x: 50,
  y: 50,
  width: '25%',
  height: '25%',
  clear: true
});

const minimapView2 = new MapView({
  id: 'minimap2',
  x: 100,
  y: 100,
  width: '25%',
  height: '25%',
  clear: true
});

const INITIAL_VIEW_STATE = {
  main: {
    longitude: -100,
    latitude: 40,
    zoom: 3,
    minZoom: 3
  },
  minimap: {
    longitude: -100,
    latitude: 40,
    zoom: 1
  }
};


export default function App({
}) {
  const [viewState, setViewState] = useState(INITIAL_VIEW_STATE);
  const onViewStateChange = useCallback(({viewState: newViewState}) => {
    setViewState(() => ({
      main: newViewState,
      minimap: {
        ...INITIAL_VIEW_STATE.minimap,
        longitude: newViewState.longitude,
        latitude: newViewState.latitude
      }
    }));
  }, []);

  return (
    <DeckGL
      layers={[
        new MVTLayer({
          id: 'service-contours',
          data: `https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/radio/service-contour/{z}/{x}-{y}.mvt`,
          maxZoom: 8,
        }),
      ]}
      views={[mainView, minimapView]}
      viewState={viewState}
      onViewStateChange={onViewStateChange}
    >
      <MapView id="main">
        <StaticMap reuseMaps mapStyle={mapStyle} />
      </MapView>
      <MapView id="minimap">
        <StaticMap
          reuseMaps
          mapStyle='https://basemaps.cartocdn.com/gl/positron-gl-style/style.json'
        />
      </MapView>
      
    </DeckGL>
  );
}

export function renderToDOM(container) {
  render(<App />, container);

  load(DATA_URL.STATIONS).then(data => {
    render(<App data={data} />, container);
  });
}