Dynamic filters on Geo Map GL Viewport Changes


#1

Hey guys,
I’m currently leveraging the Geo Map GL widget for a project and I’m interested in enhancing the interactivity of my dashboard. Specifically, I’m looking to apply dynamic filters to my charts based on the visible section of the map. The goal is to automatically adjust the data displayed in all related charts to only show information pertinent to the area currently in view on the map, especially when zooming into or panning across different regions.

Could anyone provide guidance or share insights on how to achieve this functionality? Any examples or pointers to relevant documentation would be greatly appreciated.


#2

Hi @johnb for achieve your goal, you could use a Bounds filter

In order to create that filter you need four geographic coordinates (in this case the visible area of your map), to implement it you could follow the next steps:

  1. Get your aktive instance of your map visualization.
  2. Get the map from your aktive instance.
  3. Get the bounds.
  4. Create the filter.
  5. Apply to all your visualizations.

Here is an example:

    // Get aktive instance of the map
    let aktiveInstance = cf.getVisualization("id-of-your-map")
    // Get map object
    let map = aktiveInstance.get("map")
    // Get bounds
    let bounds = map.getBounds()
    let nw = bounds.getNorthWest();
    let se = bounds.getSouthEast();
    let ne = {"lng":se.lng, "lat":nw.lat};
    let sw = {"lng":nw.lng, "lat":se.lat};
    let center = bounds.getCenter();
    // Create the filter:
    // The order is important because you are drawing a rectangular shape, 
    // so you start with one corner and ends with the same corner (total 5 pairs of coordinates in the array), 
    // in this example we start with `nw` and ends with `nw` closing the shape.
    let filterBoundaries = [[nw.lng, nw.lat], [ne.lng, ne.lat], [se.lng, se.lat], [sw.lng, sw.lat], [nw.lng, nw.lat]];

    let boundaryFilter = cf.Filter("location").label("zoomFilter").type("POLYGON").operation("IN").value(filterBoundaries);

    // Apply filter to all visualizations
    cf.getAllVisualizations().filter(c => {
        return !c._isAktiveLayer && !["interaction-manager-id", "id-of-your-map"].includes(c._elementId); // Not apply filter to the interaction manager or your map
    }).forEach(c => {
        c.staticFilters(boundaryFilter).execute();
    });

You could wrap all this code in a function and call the function on the events you need, like zoomend moovend and dragend.
Example:

 // ... previous setup of your map
        .on("execute:stop", e => {
            let aktiveMap = cf.getVisualization("id-of-your-map");
            let geoMap = aktiveMap.get("map");
            geoMap.on("zoomend", () => {
              // execute your filters update function
            });
            geoMap.on("moveend", () => {
              // execute your filters update function
            });
            geoMap.on("dragend", () => {
              // execute your filters update function
            });
          })

Hope this helps you.