有没有办法用预加载的数据填充这个多边形抽屉?

问题描述 投票:0回答:1

我目前正在修改react-map-gl 文档中的多边形抽屉的实现示例。具体是这个(源码).

在这个例子中,我真的不明白如何(以及是否)可以用数据预加载 MapBoxDraw。又名,如果我可以将一堆 GeoJSON 数据放入其中并打开一些多边形,准备进行编辑。

我目前正在尝试这样做(相关行以 HERE 关键字开头):

PolygonControl.tsx

import { useCallback, useEffect } from 'react'

import { useGeoMap } from '../../provider/GeoMapProvider'
import DrawControl from './components/DrawControl'
import { ChangeEvent } from './utils/Polygon.props'

export const PolygonControl = () => {
  const { mode, features, setFeatures } = useGeoMap()

  const onUpdate = useCallback((e: ChangeEvent) => {
    console.log('onUpdate', e.features)
    setFeatures((currFeatures) => {
      const newFeatures = { ...currFeatures }
      for (const f of e.features) {
        newFeatures[f.id] = f
      }
      return newFeatures
    })
  }, [])

  const onDelete = useCallback((e: ChangeEvent) => {
    setFeatures((currFeatures) => {
      const newFeatures = { ...currFeatures }
      for (const f of e.features) {
        delete newFeatures[f.id]
      }
      return newFeatures
    })
  }, [])

  return (
    <>
      {mode.type === 'polygon' && (
        <DrawControl
          position="top-right"
          displayControlsDefault={false}
          defaultMode="draw_polygon"
          controls={{
            polygon: true,
            trash: true,
          }}
          // HERE is where we pass in the pre-loaded polygons
          initialPolygons={features}
          onCreate={onUpdate}
          onUpdate={onUpdate}
          onDelete={onDelete}
        />
      )}
    </>
  )
}

DrawControl.tsx

import MapboxDraw from '@mapbox/mapbox-gl-draw'
import { useControl } from 'react-map-gl'

import { DrawPolygonControlProps } from '../utils/Polygon.props'

export default function DrawControl(props: DrawPolygonControlProps) {
  useControl<MapboxDraw>(
    () => {
      const draw = new MapboxDraw(props)

      // HERE: Check if there are pre-existing polygons to add
      if (props.initialPolygons) {
        Object.values(props.initialPolygons).forEach((feature) => {
          draw.add(feature)
        })
      }

      return draw
    },
    ({ map }) => {
      map.on('draw.create', props.onCreate)
      map.on('draw.update', props.onUpdate)
      map.on('draw.delete', props.onDelete)
    },
    ({ map }) => {
      map.off('draw.create', props.onCreate)
      map.off('draw.update', props.onUpdate)
      map.off('draw.delete', props.onDelete)
    },
    {
      position: props.position,
    },
  )

  return null
}

但是,这给了我以下错误:

TypeError: Cannot read properties of undefined (reading 'get')
调用draw.add函数时。

我不确定这是否可能,但如果是的话,如果一个善良的灵魂可以在这里阐明一个可能的解决方案,我将非常高兴。我可能错过但需要的任何额外信息将根据要求立即提供。

预先感谢您的帮助!

javascript reactjs mapbox react-map-gl
1个回答
0
投票

我们需要稍微调整一下 DrawControl.tsx 文件。

主要思想是保留对 MapboxDraw 实例的引用以便能够操作它,特别是通过 'add' 方法。

...

export default function DrawControl(props: DrawControlProps) {
  const mapDraw = useRef(null); // <- initialize a ref

  useControl<MapboxDraw>(
    () => {
      const draw = new MapboxDraw(props); // <- Store instance in a variable
      mapDraw.current = draw; // <- Assign it to ref
      return draw; // <- return instance
    },
    ({map}: {map: MapRef}) => {
      map.on('draw.create', props.onCreate);
      map.on('draw.update', props.onUpdate);
      map.on('draw.delete', props.onDelete);
    },
    ({map}: {map: MapRef}) => {
      map.off('draw.create', props.onCreate);
      map.off('draw.update', props.onUpdate);
      map.off('draw.delete', props.onDelete);
    },
    {
      position: props.position
    }
  );

  // We can now use the MapboxDraw instance (via ref) and use "add". 
  useEffect(() => {
    if (mapDraw.current && props.initialFeatures) {
      props.initialFeatures.forEach(feature => {
        mapDraw.current.add(feature);
      });
    }
  }, []);

  return null;
}
...

以下是它在地图端的使用方式:

<DrawControl
  position="top-left"
  displayControlsDefault={false}
  controls={{
    polygon: true,
    trash: true,
  }}
  defaultMode="simple_select"
  onCreate={onUpdate}
  onUpdate={onUpdate}
  onDelete={onDelete}
  initialFeatures={[
    {
      id: 'af82dd7ccff1acdb02d5576098bcca01',
      type: 'Feature',
      properties: {},
      geometry: {
        coordinates: [
          [
            [-4.1459062318538145, 48.69254630799924],
            [-4.145435776488171, 48.69134292282183],
            [-4.1428482719773, 48.69131704325446],
            [-4.142867874283979, 48.69258512639723],
            [-4.1459062318538145, 48.69254630799924],
          ],
        ],
        type: 'Polygon',
      },
    },
  ]}
/>
© www.soinside.com 2019 - 2024. All rights reserved.