Popups 弹窗

独立弹窗组件,可以放置在地图上的任意位置,无需附加到标记。

MapPopup 是一个独立弹窗组件, 可以放在地图上的任何位置而不需要标记。必须在 Map 内部使用。

基本用法

MapWithPopup.tsx
12345678910111213141516171819202122
import { Map, MapPopup } from class="tk-string">"@/components/ui/map";

export function MapWithPopup() {
  return (
    <div className=class="tk-string">"h-[320px] overflow-hidden rounded-lg">
      <Map center={[-74.006, 40.7128]} zoom={11}>
        <MapPopup
          longitude={-74.006}
          latitude={40.7128}
          closeButton
        >
          <div className=class="tk-string">"p-2">
            <h3 className=class="tk-string">"font-semibold">纽约市</h3>
            <p className=class="tk-string">"text-sm text-muted-foreground">
              美国人口最多的城市
            </p>
          </div>
        </MapPopup>
      </Map>
    </div>
  );
}

受控弹窗

通过状态控制弹窗的显示和隐藏:

ControlledPopup.tsx
12345678910111213141516171819202122232425
import { Map, MapPopup } from class="tk-string">"@/components/ui/map";
import { useState } from class="tk-string">"react";

export function ControlledPopup() {
  const [show, setShow] = useState(true);

  return (
    <div className=class="tk-string">"h-[320px] overflow-hidden rounded-lg">
      <Map center={[-74.006, 40.7128]} zoom={11}>
        {show && (
          <MapPopup
            longitude={-74.006}
            latitude={40.7128}
            closeButton
            onClose={() => setShow(false)}
          >
            <div className=class="tk-string">"p-2">
              <p>点击关闭按钮隐藏弹窗</p>
            </div>
          </MapPopup>
        )}
      </Map>
    </div>
  );
}

点击地图显示弹窗

结合 useMap hook 实现点击地图显示弹窗:

ClickPopupMap.tsx
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
class="tk-string">"use client";

import { Map, MapPopup, useMap } from class="tk-string">"@/components/ui/map";
import { useEffect, useState } from class="tk-string">"react";

function ClickHandler() {
  const { map, isLoaded } = useMap();
  const [popup, setPopup] = useState<{
    lng: number;
    lat: number;
  } | null>(null);

  useEffect(() => {
    if (!map || !isLoaded) return;

    const handleClick = (e) => {
      setPopup({ lng: e.lngLat.lng, lat: e.lngLat.lat });
    };

    map.on(class="tk-string">"click", handleClick);
    return () => map.off(class="tk-string">"click", handleClick);
  }, [map, isLoaded]);

  if (!popup) return null;

  return (
    <MapPopup
      longitude={popup.lng}
      latitude={popup.lat}
      closeButton
      onClose={() => setPopup(null)}
      closeOnClick
    >
      <div className=class="tk-string">"text-sm">
        <p>坐标:</p>
        <p className=class="tk-string">"font-mono">{popup.lat.toFixed(4)}, {popup.lng.toFixed(4)}</p>
      </div>
    </MapPopup>
  );
}

export function ClickPopupMap() {
  return (
    <div className=class="tk-string">"h-[320px] overflow-hidden rounded-lg">
      <Map center={[-74.006, 40.7128]} zoom={11}>
        <ClickHandler />
      </Map>
    </div>
  );
}

属性

MapPopup 继承了 MapLibre GL 的PopupOptions(排除 classNamecloseButton)。

属性类型默认值描述
longitudenumber弹窗位置经度
latitudenumber弹窗位置纬度
onClose() => void弹窗关闭时的回调
childrenReactNode弹窗内容
classNamestring弹窗容器的额外 CSS 类名
closeButtonbooleanfalse显示关闭按钮

下一步

路线

MapRoute 组件