You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

地图Marker优化:实现同一地址多医生信息聚合显示及统计

解决方案

要解决同地址Marker重叠、无法完整展示所有医生信息的问题,核心是先对同一经纬度的医生进行分组,再为每个地址生成单个Marker并在Popup中展示所有医生信息。具体实现步骤如下:

1. 分组同一地址的医生

用useMemo处理医生列表,以纬度+经度作为唯一标识,将共享该地址的所有医生归为一组,同时自动统计每组的医生数量。

2. 生成单个Marker并展示所有医生链接

遍历分组后的地址数据,每个地址仅生成一个Marker,在Popup中循环渲染该地址下所有医生的专属跳转链接。

修改后的完整代码

import { useMemo } from 'react';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import { divIcon } from 'leaflet';
import { renderToStaticMarkup } from 'react-dom/server';
import { Link } from 'react-router-dom';

function DoctorsMap({ doctors_list, alternative_list, center, i18n }) {
  const iconMarkup = renderToStaticMarkup(
    <img src={config.domainUrl + "/src/client/assets/images/marker-icon.png"} />
  );
  const customMarkerIcon = divIcon({
    html: iconMarkup,
    iconSize: [25, 41],
    iconAnchor: [12, 41],
  });

  // 按地址分组医生:以经纬度拼接字符串为键,存储对应地址的医生数组和坐标
  const groupedDoctorsByAddress = useMemo(() => {
    if (!doctors_list || doctors_list.length === 0) return {};

    const addressGroups = {};
    doctors_list.forEach(doctor => {
      if (!doctor.office_address || doctor.office_address.length === 0) return;

      doctor.office_address.forEach(address => {
        if (!address.latitude || !address.longitude) return;
        // 保留6位精度避免浮点误差导致的同地址误判
        const addressKey = `${address.latitude.toFixed(6)},${address.longitude.toFixed(6)}`;
        
        if (!addressGroups[addressKey]) {
          addressGroups[addressKey] = {
            position: [address.latitude, address.longitude],
            doctors: []
          };
        }
        addressGroups[addressKey].doctors.push(doctor);
      });
    });

    return addressGroups;
  }, [doctors_list]);

  return (
    <MapContainer
      id="map"
      center={center}
      zoom={8}
      style={{
        marginBottom: "20px",
        width: "100%",
        height: "100vh",
        zIndex: 0,
      }}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <UpdateMapCentre mapCentre={center} />

      {/* 遍历分组后的地址,生成单个Marker */}
      {Object.values(groupedDoctorsByAddress).map((group, index) => (
        <Marker
          key={`marker-${index}`}
          icon={customMarkerIcon}
          position={group.position}
        >
          <Popup>
            {/* 显示该地址的医生数量 */}
            <p style={{ margin: "0 0 10px 0", fontWeight: "bold" }}>
              {group.doctors.length}名医生
            </p>
            {/* 循环渲染所有医生的跳转链接 */}
            <div>
              {group.doctors.map((doctor, docIndex) => {
                const doctorUrl = i18n.language === 'FR' 
                  ? doctor.url 
                  : doctor[`url_${i18n.language.toLowerCase()}`];
                return (
                  <Link
                    key={`doctor-${docIndex}`}
                    to={`/profile/${doctorUrl}`}
                    style={{ display: "block", marginBottom: "5px" }}
                  >
                    {doctor.name}
                  </Link>
                );
              })}
            </div>
          </Popup>
        </Marker>
      ))}
    </MapContainer>
  );
}

关键优化点说明

  • 地址分组逻辑:用toFixed(6)处理经纬度,避免因浮点精度问题导致相同地址被误判为不同地址。
  • 性能优化:通过useMemo缓存分组结果,仅在doctors_list变化时重新计算,减少不必要的渲染开销。
  • Popup展示:先明确显示医生数量,再逐个渲染医生链接,排版清晰直观。

内容的提问来源于stack exchange,提问作者amine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 15:10:26