Layer definitions

Here I will comment on the different kinds of layers that can be placed into the layers array. The array itself opens and closes with square brackets. Each layer definition goes between curly brackets. There are commas between each of them, but not at the end (that’s standard for an array) The general format looks like this:

"layers": [
  {
    LAYER DEFINITION HERE
  },
  {
    ANOTHER LAYER DEFINITION
  }
]

Now we are going to look at specific kinds of layers.

XYZ LAYERS

Let’s start with a tiled basemap layer, also known as an XYZ layer. They take the form of 256 x 256 px images, most often in png format. They are stored in nested folders on a server somewhere. You will find a number of these layers at the bottom of the demo app-conf. However, I am going to start with them, because they provide the basis for your webmap. Here is a typical one:

      {
        "type": "XYZ",
        "name": "satellite_image",
        "url": "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
        "group": "media",
        "minResolution": 0.25,
        "maxResolution": 64000,
        "attributions": "<a href='https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9' target='_blank'>Esri, Maxar, Earthstar Geographics, and the GIS User Community</a>",
        "opacity": 1,
        "zIndex": 10,
        "queryable": false,
        "displayInLegend": true,
        "legendIcon": "https://crystal-demo.s3.us-east-2.amazonaws.com/assets/icons/satellite.png",
        "legendDisplayName": {
          "en": "Satellite image",
          "es": "Imagen satélital",
          "pt": "Imagem de satélite"
        },
        "visible": true
      },

This is a free satellite layer provided by ArcGis. Notice the URL ending in /MapServer/tile/{z}/{y}/{x}. You will probably come across similar web services in the future.

To define an XYZ layer you have to include at minimum the type, a name (which you choose yourself), and a url. Lists of URLs for free basemap layers can be found at https://leaflet-extras.github.io/leaflet-providers/preview. They all work with OpenLayers; however, you have to adjust the URL a little.

XYZ options

"minResolution":, "maxResolution": – set these to define the zoom levels at which the layer will appear and disappear. I usually set the max at 64000 and the min at 0.25. In some cases you will may want the satellite layer to take over for pixelated data layers – for example, you might want to start it at maxResolution: 2 and maintain it all the way to maxResolution: 0.25. Your layer will then be visible only when the user zooms in very close.

attributions”: This allows you to indicate the copyright (or copyleft) holders for a basemap layer.

"opacity": – you can control the opacity of the layer with a setting like "opacity": 0.5, which would make the layer 50% transparent. In some cases you may add a custom layer and find that it’s all white – in that case try writing"opacity": 0.99, which will likely solve the problem.

“zIndex”: This is used to adjust the visibility of the layer relative to other layers. Normally you don’t have to worry about it, but if you are having some trouble with one layer wrongly covering the other, you may want to try this. Typically the values here are 0,1,10,100,1000 or 10000.

"displayInLegend": – if you want this layer to appear in the legend (so that you can turn it on or off, for example), then you can set "displayInLegend": true.

"legendIcon": this is used to add an icon in the legend. These icons are automatically added for simple vector layers, but not for XYZ layers or for data-driven vector layers. In those cases you should use this option. To add a legend icon you have to produce or find an appropriate icon, then reduce it in size to 22 x 22 pixels, and finally, upload it to your s3 bucket or somewhere else you can retrieve it from. Then just follow the model above, putting the URL of your icon in place of the one in the model.

"legendDisplayName": – this is the name that will appear in the legend. It should be translated by you, in order to get it right. It is placed in an array, using whatever languages you have defined (see Translation section).

"visible": – this determines whether the layer is visible by default. If you set it to "visible": false, then the layer name will appear in the legend, but the layer will be unchecked. If the user wants to see it, they click on the checkbox. This is a good way to offer supplementary information.

WMS LAYERS

These Web Map Service layers are formatted at source, so as with XYZ tiles, you don’t have to worry about the color, it is what it is. Usually you can find a raster or vector file for download if you want more control. But if the styling fits you needs, WMS layers are very convenient.

,
      {
        "type": "WMS",
        "name": "states",
        "url": "https://ahocevar.com/geoserver/wms",
        "layers": "topp:states",
        "group": "underground",
        "queryable": true,
        "displayInLegend": true,
        "renderMode": "image",
        "legendDisplayName": "US states",
        "visible": true,
        "zIndex": 1000,
        "minResolution": 0.5,
        "maxResolution": 64000,
        "label": true,
        "hoverable": true,
        }

To define a WMS layer you need the type, name, url and also the “layers” field, which takes the name of the layer that you want. Typically, but not always, a WMS will have more than one layer; and in any case, it will always have a layer name.

VECTOR LAYERS

These are point, line and polygon layers that link sidebar content to geographic features. VECTOR layers allow interactivity, including zoom-to-feature and entity-networks. VECTOR layers also offer extensive styling options, including data-driven properties. And they can be edited on the fly by the user.

 {
        "type": "VECTOR",
        "name": "points",
        "url": "./geoserver/wfs?service=WFS&version=1.1.0&request=GetFeature&typename=workspace1:points&outputFormat=application/json&srsname=EPSG:3857",
        "group": "media",
        "queryable": true,
        "format": "GeoJSON",
        "legendDisplayName": {
          "en": "Points",
          "es": "Puntos",
          "pt": "Pontos"
        },
        "visible": true,
        "displayInLegend": true,
        "displaySidebarInfo": true,
        "zIndex": 100,
        "minResolution": 0,
        "maxResolution": 64000,
        "label": false,
        "hoverable": true,
        "legendIcon": "https://crystalball-mapkit.s3.us-east-2.amazonaws.com/assets/icons/legend_point.png",
        "style": {
          "type": "circle",
          "radius": 8,
          "strokeWidth": 2,
          "stylePropFnRef": {
            "strokeColor": "variable1",
            "fillColor": "variable2"
          },
          "hoverTextColor": "white",
          "hoverBackgroundColor": "#000000"
        }
      },

This is obviously complicated, but you just need to copy the model and adjust it. I am going to comment all the options, dividing it into Layer options and Style options. Anything I don’t discuss can be left as is.

Layer options

"name": – first give the layer a name. This is the name you will use in the Layer groups, as explained below. It’s best practice to name the layer exactly the same as the file name. The file name is the one used by the DB and Geoserver).

"url": – now put the file name in this line, directly after workspace1:. You do not have to change anything else on this line, just the file name.

"queryable":true means it will deliver data on click, and false means no click event is possible.

"legendDisplayName": – same as XYZ layers.

"displaySidebarInfo": – if you indicate true, that means a sidebar text will appear when the user clicks the layer on. At first the window will be blank, but a user with an administrative role can add content as though it were a blog. Notice that this option can be added to an XYZ layer as well, or any other kind of layer.

"hoverable": – if you set this to true, then any file with a “title” field in the properties will display that title on hover. The text color and background color caan be selected, see the end of the "Styling" section.

"legendIcon": – same as XYZ layers.

–Style options

"type": – use line or circle. If it is a polygon, that’s the default, so you can just take this line out.

"radius": – this determines the radius of the circle, in pixels.

"strokeWidth": – add a value (it’s in pixels)

"strokeColor": – add a named color (eg “blue”), a hex color (eg “#000000”), or if you want transparency, use an rgba code (eg “rgba(0, 0, 0, 0.5)”).

"fillColor": – add a named color (eg “blue”), a hex color (eg “#000000”), or if you want transparency, use an rgba code (eg “rgba(0, 0, 0, 0.5)”).

"stylePropFnRef": – notice that the strokeColor and fillColor fields have been wrapped in this function:

          "stylePropFnRef": {
            "strokeColor": "variable1",
            "fillColor": "variable2"
          },

Adding the field "stylePropFnRef" allows us to use properties from the data – in this case, variable1 and variable2, which are field names in the DB – to change the styling. In addition to changing the colors, as here, you can also make the radius of a circle increase or decrease according to some quantity – like the output of the feature, or its age, or whatever. However, doing this requires leaving the app-conf and changing part of the program, updating git hub, and rebuilding the docker containers. It’s not difficult but it will be covered in a future section called “data-driven styling”.