arcgis js api 4.x 地图区域掩模

2,103 阅读2分钟

哟哟哟哟哟哟哟~ 私密马赛同志们! 看我今天敲的什么代码

最近在学习arcgis js api,对于英语不好的我来说真是难的一批.只能拿着翻译软件一行一行的去翻译文档,终究是我菜了

                                                

由于天地图的卫星图不知道为什么图层到一定程度就会有一条不规则的线影响到了页面的美观

产品想让我去掉这条线 真是笑死,我要是能我还在这吗? 为了这条线我几次抬头见到的都是那迷人的月亮!!! 只能想办法遮挡住了.

 arcgis 不像高德提供了专门的方法来做地图区域的掩膜,但是它在加载各种地图图层的方法中提供了blendMode 这个属性它的翻译是这样滴

这个方法是实现掩膜的重要因素

 blendMode: 'destination-in', //  目标/背景层在不与顶层重叠的地方绘制。 其他的一切都是透明的。

使用GeoJson加载出你想要的行政区划然后指定下 blendMode就ok了

<!DOCTYPE html>
<html>
 
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>地图掩模</title>
 
    <link rel="stylesheet" href="https://js.arcgis.com/4.20/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.20/"></script>
 
    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
  </style>

  <script>
    require([
    "esri/Map",
    "esri/views/MapView",
    "esri/layers/GeoJSONLayer",
    "esri/layers/GraphicsLayer",
    "esri/layers/GroupLayer"
    ], function (Map, MapView, GeoJSONLayer, GraphicsLayer, GroupLayer) {

    const map = new Map({
      basemap: "osm"
    });
    const view = new MapView({
      map: map,  // References a Map instance
      container: "viewDiv",  // References the ID of a DOM element
      center: [ 120.117,30.218], // 指定中心点
      zoom:11,
      background: { // autocasts new ColorBackground()
        color:[255, 255, 255,1]  // autocasts as new Color()
      },
    });
    // 加载杭州市区划
    const hzsLayer = new GeoJSONLayer({
        url: 'https://geo.datav.aliyun.com/areas_v3/bound/330100_full.json',
        id: "hzsLayer",
        blendMode :'destination-in',
        popupEnabled: false,
        renderer: {
          type: 'simple',
          symbol: {
            type: 'simple-fill',
            color: [227, 139, 79, 1],
            outline: {
              color:  [0, 122, 204, 0.8],
              width: 2
            }
          }
        }
    });
    map.add(hzsLayer)
  });
  </script>
</head>
 
<body>
    <div id="viewDiv"></div>
</body>
 
</html>

这个虽然能做到遮掩但是没法显示区划的边界,除非在加载一次这个geojson 图层同时拿掉blendMode 这种写法不推荐,个人认为不是最优雅的实现方式,所以哒咩~

我们可以使用GraphicsLayer初始化一个图形图层将GeoJSONLayer里的features添加到图形图层中使得与原始地图产生分离,这里建议使用GroupLayer将以上两个图层添加到这个群组图层中同时后续的操作也要添加到这个群组图层中否则地图上将不显示!!

下面是代码(也可以参考官方文档的案例)

<!DOCTYPE html>
<html>
 
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>地图掩膜</title>
 
    <link rel="stylesheet" href="https://js.arcgis.com/4.20/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.20/"></script>
 
    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
  </style>

   <script>   
    require([ "esri/Map", "esri/views/MapView",  "esri/layers/TileLayer",  "esri/layers/GeoJSONLayer",  "esri/layers/GraphicsLayer",  "esri/layers/GroupLayer"],
     function (Map, MapView,TileLayer, GeoJSONLayer, GraphicsLayer, GroupLayer) {
          /*** 
           * 这个图层要加载两次 第一次指定了 混合模式 文档里有很多方式都可以尝试下 加载到了地图的初始化图层中     * 第二次 加载到了群组图层中作为要显示的地图     * 为什么要这样做?? 底图启用混合模式后 使得与view 定义的背景色一致 所以需要再次在群组图层中加载下 这样才会显示出指定的行政区划  
           ***/  
      const baseMap = new TileLayer({ 
          blendMode: 'destination-over',  
          portalItem: {  
          id: "10df2279f9684e4a9f6a7f08febac2a9"
        }
      });
      const tileLayer = new TileLayer({
        portalItem: {
          id: "10df2279f9684e4a9f6a7f08febac2a9"
        } 
      }); 
      // 加载图形图层   
      const graphicsLayer = new GraphicsLayer({
        blendMode: 'destination-in', 
        id:'graphicsLayer' 
      })  
      // groupLayer.add(graphicsLayer) 
        // 加载群组图层 由于与原始的地图产生了分离 所以后续所有的地图展示都应该加在这个群组中否则会有不出现的情况  
      const groupLayer = new GroupLayer({ 
        layers:[tileLayer,graphicsLayer],   
        effect: 'brightness(1.5) drop-shadow(8px, 8px, 8px)' 
      })

      // 加载杭州市区划 
      const hzsLayer = new GeoJSONLayer({ 
        url: 'https://geo.datav.aliyun.com/areas_v3/bound/330100_full.json',      
        id: "hzsLayer",   
        // blendMode :'destination-in',
        popupEnabled: false,
        renderer: {
        type: 'simple',  
          symbol: {
            type: 'simple-fill',
            color: [227, 139, 79, 0],
            outline: {
              color:
                [0, 122, 204, 0.8], 
                width: 2 
            }
        }} 
      }); 
              
      groupLayer.add(hzsLayer) 
      showCity(hzsLayer)  
                    /**     * 获得图层中的 所有的features 然后添加到graphicsLayer    */   
      async function showCity (layer) {
          const { features } = await layer.queryFeatures()
          features.forEach(feature => { 
            if (feature) {
            const gra = feature.clone()    
            graphicsLayer.add(gra) 
          } 
        }) 
      } 
      const map = new Map({
        layers:[baseMap,groupLayer]
      }); 
      const view = new MapView({    
        map: map, 
        // References a Map instance
        container: "viewDiv",  // References the ID of a DOM element
        center: [ 120.117,30.218], // 指定中心点  
        zoom:11,  
        background: { // autocasts new ColorBackground()        
          color:[0, 205, 255,1]  // autocasts as new Color() 
        }
      });
    }); 
    </script>
<body>
    <div id="viewDiv"></div>
</body>
 
</html>