Cesium自定义天地图底图颜色

发布时间 2023-09-08 14:46:23作者: cheng0607

自定义天地图底图颜色

在使用Cesium创建3D地球应用程序时,默认的天地图颜色并不能满足全部需求,就需要自定义天地图底图颜色。

开搞。

天地图的支持

天地图不支持在cesium中对矢量底图的颜色进行自定义,需要从Cesium入手——即扩展Cesium的地图加载类,以便能够使用自定义的代码来处理地图瓦片。该方法是以前在网上看到的,可惜分享该方法的原文地址没找到。

扩展Cesium的地图加载类

  1. 创建一个新类,继承自Cesium.UrlTemplateImageryProvider。该类将处理地图瓦片。

  2. 在新类的构造函数中,调用父类的构造函数,并设置一些必要的参数。

    class GrayscaleImageryProvider extends Cesium.UrlTemplateImageryProvider {
              constructor(options) {
                super(options);
                this._tilingScheme = new Cesium.WebMercatorTilingScheme();
              }
    
              get tilingScheme() {
                return this._tilingScheme;
              }
    
            }
    
  3. 在新类中实现一个名为“requestImage”的方法。该方法将在获取瓦片图像时被调用,我们可以在该方法中使用自定义的着色器代码来处理瓦片图像。具体实现方式可以参考Cesium官方文档

    requestImage(x, y, level, request) {
      return Cesium.when(
        super.requestImage(x, y, level, request),
        async (image) => await this.convertToGrayscale(image)
      );
    }
    async convertToGrayscale(image) {
      const canvas = document.createElement("canvas");
      canvas.width = image.width;
      canvas.height = image.height;
      const context = canvas.getContext("2d");
      context.drawImage(image, 0, 0);
    
      const imageData = context.getImageData(
        0,
        0,
        canvas.width,
        canvas.height
      );
      const data = imageData.data;
      for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];
        const grey = r * 0.3 + g * 0.59 + b * 0.11;
        data[i] = grey;
        data[i + 1] = grey;
        data[i + 2] = grey;
        data[i] = 55 - data[i];
        data[i + 1] = 255 - data[i + 1];
        data[i + 2] = 305 - data[i + 2];
      }
      context.putImageData(imageData, 0, 0);
      const bitmap = await createImageBitmap(canvas);
      return bitmap;
    }
    

在地图上加实例

当我们扩展了Cesium的地图加载类后,我们需要在地图上使用它。以下是具体实现的步骤:

	const grayscaleImageryProvider = new GrayscaleImageryProvider({
		url: "http://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=天地图token",
		subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
	});
	
viewer.imageryLayers.addImageryProvider(grayscaleImageryProvider);

现在,我们已经成功地扩展了Cesium的地图加载类,并将自定义地图加载程序添加到了Cesium的场景中。在自定义地图加载程序中,我们可以使用自己的代码来处理地图瓦片,从而实现自定义的地图底图颜色。

附代码

if (false) {
        class GrayscaleImageryProvider extends Cesium.UrlTemplateImageryProvider {
          constructor(options) {
            super(options);
            //天地图是墨卡托投影,所以使用WebMercatorTilingScheme
            this._tilingScheme = new Cesium.WebMercatorTilingScheme();
          }

          get tilingScheme() {
            return this._tilingScheme;
          }

          requestImage(x, y, level, request) {
            return Cesium.when(
              super.requestImage(x, y, level, request),
              async (image) => await this.convertToGrayscale(image)
            );
          }
          async convertToGrayscale(image) {
            const canvas = document.createElement("canvas");
            canvas.width = image.width;
            canvas.height = image.height;
            const context = canvas.getContext("2d");
            context.drawImage(image, 0, 0);

            const imageData = context.getImageData(
              0,
              0,
              canvas.width,
              canvas.height
            );
            const data = imageData.data;
            for (let i = 0; i < data.length; i += 4) {
              const r = data[i];
              const g = data[i + 1];
              const b = data[i + 2];
              const grey = r * 0.3 + g * 0.59 + b * 0.11;
              data[i] = grey;
              data[i + 1] = grey;
              data[i + 2] = grey;
              data[i] = 55 - data[i];
              data[i + 1] = 255 - data[i + 1];
              data[i + 2] = 305 - data[i + 2];
            }
            context.putImageData(imageData, 0, 0);
            const bitmap = await createImageBitmap(canvas);
            return bitmap;
          }
        }
        const grayscaleImageryProvider = new GrayscaleImageryProvider({
          url: "http://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=c84ac120f6fd53354ce8d46ec7feee22",
          subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"], //subdomains用于负载均衡,一般用数字表示
        });

        viewer.imageryLayers.addImageryProvider(grayscaleImageryProvider);
        viewer.scene.requestRender();
      }