Highlight feature with effects and blending

Explore in the sandboxView live

This sample uses layer blending and effect on multiple layers to create a more artistic way of highlighting features selected by the user.

How it works

When the application loads, the basemap is displayed over all other layers in the map. When a user clicks on a country, the country will be highlighted as shown below:

multiply-layers-blendmode

The light gray canvas vector tiles layer and a countries feature layer are added to a group layer and the destination-over blendMode is set on the group layer. With the destination-over blendMode, the background layer covers, or is placed over, the top layer. The content of the top layer is visible where both layers do not overlap. When the app loads, you see the modern antique vector tiles basemap on top of the groupLayer.

          
// This group layer groups the gray canvas vector tiles and
// countries feature layer.
// With destination-over blendMode, the background layer covers
// the top layer. The top layer is put underneath the destination layer.
// So when the app starts, the basemap layer will be shown over this layer
const groupLayer = new GroupLayer({
  layers: [vtLayer, countries],
  blendMode: "destination-over"
});
map.add(groupLayer);

The countryGraphicsLayer is created with the destination-in blendMode and is added to the basemap as shown below. The destination-in blendMode displays the background layer where it overlaps with the top layer. Everything else is made transparent. When the app loads, a white polygon graphic that covers the world is added to the graphics layer. Because this polygon covers the entire world, you see the entire modern antique basemap over the graphics layer.

                  
// countryGraphicsLayer is added to the view's basemap.
// It will contain black polygon covering the extent of the world
// the country graphic will also be added to this layer when user clicks a country.
// With destination-in blend mode, the contents of background layer is
// kept where it overlaps with top layer. Everything else is made transparent.
// In this case, the countryGraphicsLayer will be displayed underneath
// modern antique vector tiles basemap.
// The bloom effect will add a glow around the selected country.
const countryGraphicsLayer = new GraphicsLayer({
  blendMode: "destination-in",
  countryGraphicsLayer
});

map.loadAll().then(async () => {
  addWorld(); // adds a black polygon graphic that covers the world
  // add the country graphicslayer to the basemap
  map.basemap.baseLayers.add(countryGraphicsLayer);
});

Then when user clicks a country, the country feature is added to the countryGraphicsLayerThen we zoom to the clicked country while decreasing the opacity of the white graphic all way to full transparency. Once this graphic is fully transparent, you will see the content of the group layer where the group layer and the basemap do not overlap. Remember we have destination-over blendMode set on the groupLayer. We still see the basemap for the clicked country, because the graphics layer is displaying the clicked country feature.

                                
// listen to the view's click event
view.on("click", async (event) => {
  // query the countries featurelayer for a country that intersects the point
  // user clicked on
  const {
    features: [feature]
  } = await layerView.queryFeatures({
    geometry: view.toMap(event),
    returnGeometry: true,
    maxAllowableOffset: 10000,
    outFields: ["*"]
  }
  countryGraphicsLayer.graphics.removeAll();
  animation && animation.remove(
  let world = addWorld(
  // add the clicked country feature to the graphicslayer
  if (feature) {
    feature.symbol = symbol;
    countryGraphicsLayer.graphics.add(feature
    // add a fade animation to show the highlight effect
    // for the selected country
    animation = fadeWorld(world
    // zoom to the highlighted country
    view.goTo(
      {
        target: view.toMap(event),
        extent: feature.geometry.extent.clone().expand(1.8)
      },
      { duration: 1000 }
    );
  }
});

The map would look and behave like the following where the group layer is displayed over the basemap when:

  • The blendMode property is not set on any of the layers
  • Only country's GraphicsLayer has the destination-in blendMode set and is part of the basemap.

multiply-layers-no-blendmode

If country's GraphicsLayer does not have the bloom effect set then the app would look and behave like the following when the user clicks on a country.

multiply-layers-no-blendmode

If the groupLayer is the only layer that has a blend mode set (destination-over in this case), then the app would look and behave like the following when the user clicks on a country.

multiply-layers-no-blendmode