首页 > 解决方案 > 如何使用mapbox在同一图层中绘制多个不同颜色的点?

问题描述

我想使用 mapbox 在同一图层中绘制多个点,所有这些点都将具有自己的属性,例如颜色和标签。并且在单击单个点时,它应该显示一个带有该点 ID 的弹出窗口。

这是否可以实现,到目前为止,我一直在循环点数组,并且为每个点创建一个单独的源和层。

for(let i = 0; i < buildings.length; i++){
      let mapSource = map.getSource(buildings[i].building_id);
      if(!mapSource){
        map.addSource(buildings[i].building_id, {
          'type': 'geojson',
          'data': {
            'type': 'Feature',
            'geometry': {
              'type': 'Point',
              'coordinates': buildings[i].centroid.coordinates
            }
          }
        });
      }
      let mapLayer = map.getLayer(buildings[i].building_id);
      if(!mapLayer){
          map.addLayer({
            'id': buildings[i].building_id,
            'type': 'circle',
            "paint": {
              "circle-radius": 6,
              "circle-color": SectionColors[buildings[i].section[0]]
            },
            "source": buildings[i].building_id
          });
      }
      let mapLabel = map.getLayer(`${buildings[i].building_id}-label`);
      if(!mapLabel){
        map.addLayer({
          'id': `${buildings[i].building_id}-label`,
          'type': 'symbol',
          'source': buildings[i].building_id,
          'layout': {
            'text-field': `${buildings[i].building_id}`,
            'text-size': 14,
            'text-variable-anchor': ["left"],
            'text-radial-offset': 0.3,
            'text-justify': 'auto',
          },
          'paint': {
            'text-color': '#fff308'
          }
        });
      }
      map.on('click', buildings[i].building_id, function(e){
        setPopUpTop(e.point.y+10);
        setPopUpLeft(e.point.x+10);
        setBuildingPopup(true);
        setBuilding(buildings[i].building_id);
        setInfoPanel(false);
      });
      map.on('mousemove', buildings[i].building_id, function(e){
        map.getCanvas().style.cursor = 'pointer';
        if(buildings[i].section){
          let sectionBuildings = buildings.filter(item => item.section && item.section.includes(buildings[i].section[0]))
          for(let j = 0; j < sectionBuildings.length; j++){
            let mapLayer = map.getLayer(`${sectionBuildings[j].building_id}-borders-onHover`);
            if(typeof mapLayer === 'undefined'){
              map.addLayer({
                'id': `${sectionBuildings[j].building_id}-borders-onHover`,
                'type': 'circle',
                'source': sectionBuildings[j].building_id,
                "paint": {
                  "circle-radius": 8,
                  "circle-color": '#fff308'
                },
              });
            }
          }
        }
      });
      map.on('mouseleave', buildings[i].building_id, function(e){
        map.getCanvas().style.cursor = '';
        if(buildings[i].section){
          let sectionBuildings = buildings.filter(item => item.section && item.section.includes(buildings[i].section[0]))
          for(let j = 0; j < sectionBuildings.length; j++){
            let mapLayer = map.getLayer(`${sectionBuildings[j].building_id}-borders-onHover`);
            if(typeof mapLayer !== 'undefined'){
              map.removeLayer(`${sectionBuildings[j].building_id}-borders-onHover`);
            }
          }
        }
      });
    }

当点数很少时,性能差异不大,但是当我绘制大量点(如 300-400)时,性能非常慢。

标签: reactjsmapbox-gl-js

解决方案


您需要做的第一件事是使用特征集合在一个源中包含多个点:

map.addSource('multiple-points-source', {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "color": "#FFFFFF"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [-46.757, 71.413]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "color": "#000000"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [-32.345, 72.816]
      }
    }
  ]
}

之后,您可以使用数据驱动的样式来用点特征属性中的颜色填充圆圈:

map.addLayer({
  'id': 'multiple-points-layer',
  'type': 'circle',
  'source': 'multiple-points-source',
  'layout': {
  },
  'paint': {
    // use data-driven styling
    'circle-color': ['get', 'color'],
  },
});

这是一个使用这种技术的工作示例:https ://jsfiddle.net/132ygokd/2/


推荐阅读