开发者问题收集

使用填充 deck.gl mapbox 来适配边界

2022-12-19
845

我尝试将 fiBounds 与 WebMercatorViewport 对象一起使用,但收到有关 padding 属性的错误。

我的代码:

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>

初始渲染运行良好,但当状态发生变化(关闭地图、更新状态)时,我收到错误:

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)

我正在使用: deck.gl:“8.8.20” react-map-gl:“7.0.20”

2个回答

Mapbox 将边界作为初始状态的一部分。

请参阅 Mapbox API options.bounds

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

我没有使用 deck.gl ,但这是使用 react-map-gl 所做的。

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

为了生成边界框,我们可以使用 代码 提供的相同代码 。 href="https://stackoverflow.com/users/9596473/ar26">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
2023-06-23

git 讨论 获得解决方案 useMemo 应返回一个简单的视口,而不是 WebMercatorViewport 对象:

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
2022-12-25