自定义 BlendLayer

尝试一下在线预览

这个示例演示了如何通过对 GeoScene World Hillshade 国家地理世界地图 服务应用 多重 混合操作来创建一个 自定义切片图层multiply 混合模式将顶图层的每个像素的值与底图层的相应像素值相乘。在这个示例中,将山阴贴图与国家地理贴图相乘,可以创建比默认的国家地理底图更详细的地形表示。您可以使用示例中的 LayerList 微件打开和关闭混合图层。 BlendLayer 默认是打开的。

国家地理默认

定义混合图层(Geoscene Hillshade + National Geographic)
custom-layers-no-blend custom-layers-blend

要创建自定义切片图层,必须在 BaseTileLayer 上调用 createSubclass()  。 BaseTileLayer 是一个专门为创建自定义切片图层而设计的类,例如本例中创建的 BlendLayer 。 当创建 BlendLayer 时,定义了一个叫做 multiplyLayers 的属性,这是一组将混合在一起的切片图层。

         
1
2
3
4
5
6
7
8
9
const BlendLayer = BaseTileLayer.createSubclass({
  // multiplyLayers stores tile layers
  // used as the basis for creating
  // a blend layer. Layers stored in this property
  // will be blended using "multiply" operation.
  properties: {
    multiplyLayers: null
  }
});

添加到 multiplyLayers 数组中的切片图层是 可加载的资源  。如果自定义切片图层需要可加载资源,那么你必须使用 load() 方法在该图层中加载它们。这确保了在自定义图层解析并 loaded  之前,加载图层运行所需的所有可加载资源。

                  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const BlendLayer = BaseTileLayer.createSubclass({
  properties: {
    multiplyLayers: null
  },

  // Called when the layer is added to the map
  // prior to it being rendered in the view.
  load: function() {
    // iterate through each layer in multiplyLayers property
    this.multiplyLayers.forEach((layer) => {
      // call load method on each layer and add as
      // a resolving promise of the custom layer.
      // The tile layers must load() prior to the BlendLayer
      // resolving and moving to the "loaded" status.
      this.addResolvingPromise(layer.load());
    }, this);
  }
});

一旦图层加载了所需的资源,我们必须覆盖 BlendLayer 的 fetchTile() 方法。在这个方法中,在 multiplyLayers 属性中返回的每个切片图层上调用 fetchTile() 一旦每个切片图层返回视图中可见的切片,我们对切片应用 multiply 运算,以便 BlendLayer  将显示混合图像。

                                     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Fetches the tile(s) visible in the view
fetchTile: function (level, row, col, options) {
  const tilePromises = this.multiplyLayers.map((layer) => {
    // calls fetchTile() on the tile layers returned in multiplyLayers property
    // for the tiles visible in the view
    return layer.fetchTile(level, row, col, options);
  });

  return promiseUtils.eachAlways(tilePromises)
    .then((results) => {
      // Reject with abort error if the request was aborted.
      // It is expected that `fetchTile` will already have rejected with abort errors
      // in that case but those errors are caught by `eachAlways`, so we need to re-
      // throw it
      if (options && options.signal && options.signal.aborted) {
        throw promiseUtils.createAbortError();
      }
      // create a canvas
      const width = this.tileInfo.size[0];
      const height = this.tileInfo.size[0];
      const canvas = document.createElement("canvas");
      const context = canvas.getContext("2d");

      canvas.width = width;
      canvas.height = height;

      // multiply - multiplies the numbers for each pixel of the top layer (nat geo)
      // with the corresponding pixel for the bottom layer (hillshade).
      context.globalCompositeOperation = "multiply";
      results.forEach((result) => {
        const image = result.value;
        context.drawImage(image, 0, 0, width, height);
      });

      return canvas;
    });
  }

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.