Cesium development tools | 01 component rewriting

Time:2022-1-14

In the initial introduction, we talked about the display and hiding of cesium small components. Interested partners can view the article I wrote earlier about cesium initialization interface and the display and hiding of related team components. The question is whether these components can be extended and rewritten without modifying the source code, in addition to controlling the explicit and implicit? The answer is of course! However, not all components can be rewritten. This section mainly explains how to modify the following three common controls without modifying the source code, so as to quickly realize the function of business requirements in practice. Of course, if you study the cesium source code deeply, you can also modify the source code.

Homebutton component

Homebutton function is very common and practical in practical application scenarios. The main function of this component is to return to the position when the system is initialized. The default is the position of the whole ball, as shown in the following figure:

Cesium development tools | 01 component rewriting

However, in the actual business scenario, the initialization range is generally the location of a city or park. If you use the homebutton component of cesium, you need to modify it so that when we click homebutton, the camera will not locate the default location of cesium, but the location we want. How should we modify it?

1) Modify the camera’s default rectangular range

    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
      110.15,
      34.54,
      110.25,
      34.56
    ); //Rectangle(west, south, east, north)

2) Add listening events in ViewModel of homebutton

if (viewer.homeButton) {
      viewer.homeButton.viewModel.command.beforeExecute.addEventListener(
        function (e) {
          e.cancel = true;
          //Where do you want to fly
          viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(117.16, 32.71, 15000.0),
          });
        }
      );
    }

Geocoder component

Geocoder means geocoding. Our common POI search is the credit of geocoder. By looking at the cesium source code (source / widgets / geocoder / geocoderviewmodel. JS, line 73), we find that cesium uses Bing map service to realize geocoding by default, and it is implemented through geocode method. Then we can override the geocode method to implement the custom geocode service. Next, we rewrite the geocode method to change the default Bing map service of cesium to OSM map service.

  function OpenStreetMapNominatimGeocoder() {}
   OpenStreetMapNominatimGeocoder.prototype.geocode = function (input) {
      var url = "https://nominatim.openstreetmap.org/search";
      var resource = new Cesium.Resource({
        url: url,
        queryParameters: {
          format: "json",
          q: input,
        },
      });

      return resource.fetchJson().then(function (results) {
        var bboxDegrees;
        return results.map(function (resultObject) {
          bboxDegrees = resultObject.boundingbox;
          return {
            displayName: resultObject.display_name,
            destination: Cesium.Rectangle.fromDegrees(
              bboxDegrees[2],
              bboxDegrees[0],
              bboxDegrees[3],
              bboxDegrees[1]
            ),
          };
        });
      });
    };

    var viewer = new Cesium.Viewer("cesiumContainer", {
      geocoder: new OpenStreetMapNominatimGeocoder(),
    });

Baselayerpicker component

Cesium provides us with the default selection panel of basemap and topographic map, controls the display and hiding by modifying the attribute of baselayerpicker, and realizes the switching and display of corresponding layers by selecting the basemap or topographic map in the panel. The default selection panel provided by cesum is shown in the following figure:

Cesium development tools | 01 component rewriting

These layers are online resources. If it is an offline environment or only displays several layer data provided by customers, how can we achieve it. To realize this function, first, let’s take a look at the main logic diagram of baselayerpicker, as shown below.

Cesium development tools | 01 component rewriting

As can be seen from the above figure, for developers to implement different imageryproviders, they only need to provide different providerviewmodels, such as bingmap, OSM, ArcGIS and Google maps. In this way, in the UI of baselayerpicker, there will be multiple providers for users to choose, and the interaction is handled by the baselayerpickerviewmodel class. Users do not need to care about the internal implementation, The baselayerpickerviewmodel class has been implemented for us all. Next, we use the logical relationship of baselayerpicker to implement custom imageryprovider (gaude vector map) and terrain provider (ArcGIS terrain) and display them in the selector panel. The following is a screenshot of the core code and results.

//Custom image layer
    var imageProviderVMs = [];
    let gaodeImageProvider = new Cesium.UrlTemplateImageryProvider({
      url:
        "http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
      subdomains: ["1", "2", "3", "4"],
    });
    var gaodeVM = new Cesium.ProviderViewModel({
      Name: "Gaode vector",
      iconUrl: Cesium.buildModuleUrl(
        "Widgets/Images/ImageryProviders/openStreetMap.png"
      ),
      Tooltip: "Gaode vector map service",
      creationFunction: function () {
        return gaodeImageProvider;
      },
    });
    imageProviderVMs.push(gaodeVM);
    viewer.baseLayerPicker.viewModel.imageryProviderViewModels = imageProviderVMs;
//Custom terrain layer
    var terrainProviderVMs = [];
    var terrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
      url:
        "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
      token:
        "KED1aF_I4UzXOHy3BnhwyBHU4l5oY6rO6walkmHoYqGp4XyIWUd5YZUC1ZrLAzvV40pR6gBXQayh0eFA8m6vPg..",
    });
    var arcgisVM = new Cesium.ProviderViewModel({
      Name: "ArcGIS terrain",
      iconUrl: Cesium.buildModuleUrl(
        "Widgets/Images/TerrainProviders/Ellipsoid.png"
      ),
      Tooltip: "ArcGIS terrain service",
      creationFunction: function () {
        return terrainProvider;
      },
    });
    terrainProviderVMs.push(arcgisVM);
    viewer.baseLayerPicker.viewModel.terrainProviderViewModels = terrainProviderVMs;
Cesium development tools | 01 component rewriting

Get the complete code, you can view my GitHub addresshttps://github.com/ls870061011/cesium_training/tree/main/examples3 in_ Part 1.