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

如何通过Google Maps JavaScript API高亮边界争议国家?

解决Google Maps Platform中争议国家(如科索沃)的高亮与交互问题

我们是一家非营利组织,需要在Google Maps Platform(JavaScript API)上高亮所有接收过捐赠的国家,包括科索沃这类存在边界争议的地区。目前使用Country要素层可以正常修改非争议国家的样式,但争议国家无法修改样式,也无法监听鼠标悬停事件显示提示框,沿用非争议国家的实现方式无效,附上Vue.js与JavaScript混合的简化代码,寻求可行实现方案。

async showData(value) {
  this.graphData = [];

  let title = "Total donations in IUs/MGs";

  this.graphData.push(["Country", title]);
  datasource = this.datas.countriesReceivingDonations.year;

  this.graphMinValue = 1;

  this.graphMaxValue =
    datasource.length == 0
      ? null
      : datasource.reduce(function (prev, curr) {
          return prev.value > curr.value ? prev : curr;
        })?.value;
  this.graphTitle = title;

  await Promise.all(
    datasource.map(async (x) => {
      let placeId = await this.findPlaceId(x.code);
      let color = '#FF0000';

      this.graphData.push([
        { v: x.code, f: x.name, placeId: placeId, color: color },
        x.value,
      ]);
    })
  );

  this.setFeatureLayer();
},

async findPlaceId(countryCode) {
  //https://developers.google.com/maps/documentation/javascript/reference/geocoder#GeocoderRequest
  const request = {
    componentRestrictions: {
      country: countryCode,
    },
  };

  const { Geocoder } = await this.loader.importLibrary("geocoding");

  var geocoder = new Geocoder();
  var result = await geocoder.geocode(request);

  console.log(result.results[0].formatted_address);
  console.log(result);

  return result.results[0].place_id;
},

setFeatureLayer() {
  try {
    // Add a feature layer for countries.
    this.featureLayer = this.map.getFeatureLayer(
      google.maps.FeatureType.COUNTRY
    );

    // Add the event listeners for the feature layer.
    this.featureLayer.addListener("click", this.handleClick);
    this.featureLayer.addListener("mousemove", this.handleMouseMove);

    // Map event listener.
    this.map.addListener("mousemove", () => {
      // If the map gets a mousemove, that means there are no feature layers
      // with listeners registered under the mouse, so we clear the last
      // interacted feature ids.
      if (this.lastInteractedFeatureIds?.length) {
        this.lastInteractedFeatureIds = [];
        this.featureLayer.style = this.featureLayer.style;
      }
      this.infoWindow.close();
    });

    this.featureLayer.style = (featureStyleFunctionOptions) => {
      const placeFeature = featureStyleFunctionOptions.feature;

      let fillColor;
      let strokeColor;
      let strokeOpacity;
      let strokeWeight;
      let data = this.graphData.find(
        (x) => x[0].placeId == placeFeature.placeId
      );

      if (data != undefined) {
        fillColor = data[0].color; //"#ed174d";
        strokeColor = "gray"; //"#ed174d";
        strokeOpacity = 1.0;
        strokeWeight = 1.0;
      }

      return {
        fillColor,
        fillOpacity: 1,
        strokeColor,
        strokeOpacity,
        strokeWeight,
      };
    };
  } catch (e) {
    console.log(e);
  }
},

问题根源

Google Maps的Country要素层仅包含被广泛承认的主权国家,科索沃这类争议地区不在默认的FeatureType.COUNTRY范围内,因此无法通过常规要素层方法实现样式修改和事件监听。

实现方案

1. 自定义GeoJSON图层加载争议地区边界

  • 获取争议地区的权威GeoJSON边界数据(如科索沃的坐标集合)
  • 使用google.maps.Data类加载自定义GeoJSON图层并添加到地图
  • 为自定义图层设置统一样式,绑定鼠标交互事件

2. 整合现有要素层与自定义图层

  • 保留原Country要素层处理非争议国家
  • 对争议地区单独创建Data图层,样式逻辑和事件监听与原图层对齐,保证视觉统一

代码修改示例

新增加载争议地区的方法

async loadDisputedRegions() {
  // 示例:科索沃的GeoJSON数据(需替换为权威数据源的坐标)
  const kosovoGeoJson = {
    "type": "FeatureCollection",
    "features": [
      {
        "type": "Feature",
        "properties": { "name": "Kosovo", "code": "XK" },
        "geometry": {
          "type": "Polygon",
          "coordinates": [[/* 科索沃边界坐标数组 */]]
        }
      }
    ]
  };

  this.disputedDataLayer = new google.maps.Data();
  this.disputedDataLayer.addGeoJson(kosovoGeoJson);
  
  // 同步样式逻辑
  this.disputedDataLayer.setStyle((feature) => {
    const code = feature.getProperty('code');
    const data = this.graphData.find(x => x[0].v === code);
    if (data) {
      return {
        fillColor: data[0].color,
        fillOpacity: 1,
        strokeColor: 'gray',
        strokeOpacity: 1.0,
        strokeWeight: 1.0
      };
    }
    return {};
  });

  // 绑定交互事件,复用原有处理逻辑
  this.disputedDataLayer.addListener('click', (event) => {
    this.handleClick({ feature: event.feature });
  });

  this.disputedDataLayer.addListener('mousemove', (event) => {
    this.handleMouseMove({ feature: event.feature });
  });

  this.disputedDataLayer.setMap(this.map);
}

修改showData方法兼容争议地区

async showData(value) {
  // 原有代码保持不变...

  await Promise.all(
    datasource.map(async (x) => {
      let placeId;
      // 争议地区跳过地理编码,直接保留code用于后续匹配
      if (x.code === 'XK') {
        placeId = null;
      } else {
        placeId = await this.findPlaceId(x.code);
      }
      let color = '#FF0000';

      this.graphData.push([
        { v: x.code, f: x.name, placeId: placeId, color: color },
        x.value,
      ]);
    })
  );

  this.setFeatureLayer();
  // 加载争议地区图层
  this.loadDisputedRegions();
}

调整事件处理方法兼容自定义要素

handleClick(event) {
  const feature = event.feature;
  let matchData;
  // 区分默认要素层(含placeId)和自定义图层(用code匹配)
  if (feature.placeId) {
    matchData = this.graphData.find(x => x[0].placeId === feature.placeId);
  } else {
    const code = feature.getProperty('code');
    matchData = this.graphData.find(x => x[0].v === code);
  }
  // 原有提示框逻辑保持不变...
}

注意事项

  • 争议地区的边界数据需确保来源权威,避免引发争议
  • 自定义图层样式需与原Country要素层完全一致,保证视觉统一
  • 测试时需验证争议地区的样式渲染和交互事件是否正常触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 19:13:27