reactjs 使用React Map Gl弹出窗口的点、线、多边形

bkhjykvo  于 2023-01-12  发布在  React
关注(0)|答案(1)|浏览(120)

我需要添加3种类型的元素到Map的基础上现有的数组(点,线,多边形)。对于他们中的每一个,我想输出信息从工具提示字段时,单击。

type Props = {
  data: ReportWidget;
  id: string | number;
  readonly: boolean;
  onRemoveWidget: (widget: ReportWidget, layoutId: string | number) => void;
  onUpdateWidget: (widget: ReportWidget, layoutId: string | number) => void;
};

type Coordinates = number[];

type PointTooltip = {
  fft_graph: string;
  Address: string;
  Engineer: string;
};

type MapElement = {
  id: string;
  type: string;
  geometry: number | Coordinates | Coordinates[];
  tooltip: PointTooltip;
  colour_value: ColourValueType;
};

export type ColourValueType = 'small' | 'medium' | 'large' | 'CI' | '';

const ELEMENTS: MapElement[] = [
  {
    id: '1',
    type: 'point',
    geometry: [53.2158932855, -1.182028563872],
    colour_value: 'large',
    tooltip: {
      fft_graph: 'url/link',
      Address: 'Somewhere',
      Engineer: 'Grant Holt',
    },
  },
  {
    id: '2',
    type: 'point',
    geometry: [53.2142438558, -1.1620287472],
    colour_value: 'medium',
    tooltip: {
      fft_graph: 'url/link',
      Address: 'Somewhere',
      Engineer: 'Grant Holt',
    },
  },
  {
    id: '3',
    type: 'polygon',
    geometry: [
      [53.2192662434484, -1.16776535930174],
      [53.2187209479796, -1.16673989105553],
      [53.2192662434484, -1.16776535930174],
    ],
    colour_value: '',
    tooltip: {
      fft_graph: 'url/link',
      Address: 'Somewhere',
      Engineer: 'Grant Holt',
    },
  },
  {
    id: '4',
    type: 'line',
    geometry: [
      [53.2158932438558, -1.16202856387472],
      [53.2159096813233, -1.16198840796217],
    ],
    colour_value: 'CI',
    tooltip: {
      fft_graph: 'url/link',
      Address: 'Somewhere',
      Engineer: 'Grant Holt',
    },
  },
];

const MapView: FC<Props> = ({ data, id, readonly, onRemoveWidget }) => {
  const { ref } = useDragMove(data, id, Boolean(readonly));
  const items = useMemo(() => [], []);
  const [popupElementOpen, setPopupElementOpen] = useState<string | null>(null);

  const defineMapElement = (item: MapElement) => {
    switch (item.type) {
      case 'point':
        return (
          <Marker
            latitude={item.geometry[0]}
            longitude={item.geometry[1]}
            onClick={() => {
              setPopupElementOpen(item.id);
            }}
          >
            <Styled.Marker type={item.colour_value} />
          </Marker>
        );
      case 'polygon':
        return (
          <Source
            type="geojson"
            data={{
              type: 'Feature',
              properties: {},
              geometry: {
                type: 'Polygon',
                coordinates: [item.geometry],
              },
            }}
          >
            <Layer
              id="zoneLayer"
              type="fill"
              paint={{
                'fill-color': '#82D0F5',
                'fill-opacity': 0.5,
              }}
            />
            <Layer
              id="outlineLayer"
              type="line"
              paint={{
                'line-color': '#007DBB',
                'line-width': 3,
              }}
            />
          </Source>
        );
      case 'line':
        return (
          <Source
            type="geojson"
            data={{
              type: 'Feature',
              properties: {},
              geometry: {
                type: 'LineString',
                coordinates: [item.geometry],
              },
            }}
          >
            <Layer
              id="lineLayer"
              type="line"
              layout={{
                'line-join': 'round',
                'line-cap': 'round',
              }}
              paint={{
                'line-color': '#007DBB',
                'line-width': 5,
              }}
            />
          </Source>
        );
    }
  };

  return (
    <WidgetLayout
      dropRef={ref}
      name="Map View"
      readonly={readonly}
      items={items}
      onDelete={() => onRemoveWidget(data, id)}
    >
      <Styled.Container>
        <Map
          initialViewState={{
            longitude: -0.118092,
            latitude: 51.509865,
            zoom: 5,
          }}
          style={{ height: 500, width: '100%' }}
          mapStyle="mapbox://styles/mapbox/streets-v9"
          mapboxAccessToken="pk.eyJ1Ijoic290bmlrMzMzIiwiYSI6ImNsYXZldWFuOTA1NnQzeHNqNzAwMjlyc2IifQ.inAD5RIWgxg-E05RC3aggQ"
        >
          {readonly &&
            ELEMENTS.map((el: MapElement) => (
              <Styled.Wrapper key={el.id}>
                {defineMapElement(el)}
                {popupElementOpen === el.id && (
                  <Popup
                    latitude={el.geometry[0]}
                    longitude={el.geometry[1]}
                    closeOnClick={false}
                    offset={10}
                    maxWidth="320px"
                    onClose={() => setPopupElementOpen(null)}
                  >
                    <Styled.Image />
                    <p>Adress: {el.tooltip.Address}</p>
                    <p>Engineer: {el.tooltip.Engineer}</p>
                  </Popup>
                )}
              </Styled.Wrapper>
            ))}
        </Map>
      </Styled.Container>
    </WidgetLayout>
  );
};

这是我尝试的,但是我得到了一个类型错误。我的类型有什么问题?我如何正确地传递坐标到标记和弹出窗口(因为弹出窗口是建立在2个坐标上的,如果我理解正确的话)?也许我可以做得更优雅?

hxzsmxv2

hxzsmxv21#

我认为,你需要检查你的元素的类型:

latitude={el.geometry[0]}
longitude={el.geometry[1]}

Because Here the type can be :


几何体:编号|坐标|坐标[];

相关问题