1

I'm trying to use fiBounds with the WebMercatorViewport object but getting an error about the padding property.

my code:

const initialViewState: IViewport | WebMercatorViewport = useMemo(() => {
if (locationsFitBounds) {
  const minLat: number = Math.min(...locationsFitBounds.map((l: MapLocation) => l.latitude))
  const maxLat: number = Math.max(...locationsFitBounds.map((l: MapLocation) => l.latitude))
  const minLng: number = Math.min(...locationsFitBounds.map((l: MapLocation) => l.longitude))
  const maxLng: number = Math.max(...locationsFitBounds.map((l: MapLocation) => l.longitude))
  const southWest: [number, number] = [minLng, minLat]
  const northEast: [number, number] = [maxLng, maxLat]
    return new WebMercatorViewport({ width: 1920, height: 400 }).fitBounds([southWest, northEast], {padding: 200})
} else {
  return viewport
}
}, [locationsFitBounds, viewport])

 <React.Fragment>
  <DeckGL
    width="100%"
    height="100%"
    controller={true}
    initialViewState={initialViewState}
  >
    <Map
      attributionControl={false}
      style={{ width: "100%", height: "100%" }}
    />
  </DeckGL>
</React.Fragment>

The inital render is working well but when the state is changing (closing the map, updating states) I'm getting the error:

   Uncaught TypeError: Cannot assign to read only property 'padding' of object '#<WebMercatorViewport>'
    at positionChildrenUnderViews (position-children-under-views.ts:60:1)
    at deckgl.ts:254:1
    at renderWithHooks (react-dom.development.js:16175:1)
    at updateForwardRef (react-dom.development.js:20023:1)
    at beginWork (react-dom.development.js:22465:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4161:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4210:1)
    at invokeGuardedCallback (react-dom.development.js:4274:1)
    at beginWork$1 (react-dom.development.js:27405:1)
    at performUnitOfWork (react-dom.development.js:26513:1)

I'm using: deck.gl: "8.8.20" react-map-gl": "7.0.20"

Ar26
  • 949
  • 1
  • 12
  • 29

2 Answers2

0

Got a solution from git discussion The useMemo should return a simple viewport and not a WebMercatorViewport object:

  const initialViewState: IViewport = useMemo(() => {
    if (fitLocations) {
      const minLat: number = Math.min(...fitLocations.map((l: MapLocation) => l.latitude))
      const maxLat: number = Math.max(...fitLocations.map((l: MapLocation) => l.latitude))
      const minLng: number = Math.min(...fitLocations.map((l: MapLocation) => l.longitude))
      const maxLng: number = Math.max(...fitLocations.map((l: MapLocation) => l.longitude))
      const southWest: [number, number] = [minLng, minLat]
      const northEast: [number, number] = [maxLng, maxLat]
      const { latitude, longitude, zoom } = new WebMercatorViewport({ width: 800, height: 600 }).fitBounds(
        [southWest, northEast],
        { padding: 100 }
      )
      return { ...viewport, latitude, longitude, zoom }
    } else {
      return viewport
    }
  }, [fitLocations, viewport])
Ar26
  • 949
  • 1
  • 12
  • 29
0

Mapbox offers the bounds as part of the initial state.

See options.bounds on the Mapbox API

The initial bounds of the map. If bounds is specified, it overrides center and zoom constructor options.

I am not using deck.gl, but here is what did with react-map-gl.

<Map
  initialViewState={{
    bounds: getBoundingBox(fitLocations),
    fitBoundsOptions: { padding: 60 },
  }}
  >
  ...
  </Map>

For generating the bounding box we can use the same code provided by on Ar26.

const getBoundingBox = (fitLocations) => {
      const minLat: number = Math.min(...fitLocations.map((l: MapLocation) => l.latitude))
      const maxLat: number = Math.max(...fitLocations.map((l: MapLocation) => l.latitude))
      const minLng: number = Math.min(...fitLocations.map((l: MapLocation) => l.longitude))
      const maxLng: number = Math.max(...fitLocations.map((l: MapLocation) => l.longitude))
      const southWest: [number, number] = [minLng, minLat]
      const northEast: [number, number] = [maxLng, maxLat]
      return [southWest, northEast]

}
Mark Nunes
  • 827
  • 10
  • 23