Skip to content
Advertisement

Reloading DeckGL HexagonLayer when data array changes/Triggering reload for DeckGL HexagonLayer

I’m using DeckGL with React to display some data on an OpenStreetMap. I’m planning on implementing some filters to be able to display different views on the data I have. My main problem is, that I can’t figure out how to refresh the data representing layer after filtering the data array.

I saw a bunch of people creating a DeckGL-Object in JavaScript, and then using this, to call deck.setProps() but I couldn’t figure out how to render this DeckGL-Object by using react.

This is my app.js:

export default function App({showBorder = false, onTilesLoad = null}) {
  layers = [
    /**
     * TileLayer ist ein Layer aus Open-Streetmap-Tiles (Anzeigen der Karte)
     */
    new TileLayer({
      data: [/*OSM TileServer*/],
      maxRequests: 20,
      pickable: true,
      onViewportLoad: onTilesLoad,
      autoHighlight: showBorder,
      highlightColor: [60, 60, 60, 40],
      minZoom: 0,
      maxZoom: 19,
      tileSize: 512 / devicePixelRatio,
      renderSubLayers: (props) => {
        const {
          bbox: {west, south, east, north}
        } = props.tile;
        return [
          new BitmapLayer(props, {
            data: null,
            image: props.data,
            bounds: [west, south, east, north]
          }),
          showBorder &&
            new PathLayer({
              id: `${props.id}-border`,
              visible: props.visible,
              data: [
                [
                  [west, north],
                  [west, south],
                  [east, south],
                  [east, north],
                  [west, north]
                ]
              ],
              getPath: (d) => d,
              getColor: [255, 0, 0],
              widthMinPixels: 4
            })
        ];
      }
    }),
    new HexagonLayer({
      id: 'hexagon-layer',
      data: /*JsonDataArray*/,
      pickable: true,
      extruded: true,
      radius: 2000,
      elevationRange: [25, 500],
      elevationScale: 200,
      autoHighlight: true,
      opacity: 0.2,
      colorRange: [
        [255, 255, 204],
        [199, 233, 180],
        [127, 205, 187],
        [65, 182, 196],
        [44, 127, 184],
        [37, 52, 148]
      ],
      getElevationHeight: () => 500,
      getPosition: (d) => d.coordinates,
    })
  ];

  return (
    <DeckGL
      layers={layers}
      views={new MapView({repeat: true})}
      initialViewState={INITIAL_VIEW_STATE}
      controller={true}
    />
  );
}

Obviously is there a little bit more to my app.js but I don’t think the missing parts are important since I just wanna know how I can refresh a layer.

I also have a index.html but I don’t think it’s content is really relevant either since it’s only use is to call the App function to render the layers.

I just can’t find out what to do, to cause a reload of the HexagonLayer.

Thanks for your help in advance.

Advertisement

Answer

  1. A good approach is using DataFilterExtension. GPU-based data filtering, go this way if you care about performance. For the moment there is a limitation of the extension for HexagonLayer, but maybe using GPUGridLayer can help you in your visualization also.

    I.e: let’s say you want to filter your qualitative data. filterRange needs numeric bounds (which defines whether an object should be rendered), so you can set your bounds as [1, 1] and check if some object matches with you current filter condition, if matches, getFilterValue gets 1, so that object will be rendered, otherwise, not rendered:

     const [filterCondition, setFilter] = useState('');
    
     useEffect(() => {
         // dispatch some action to set the filter
         setFilter('cities');
     }, []);
    
     new ScatterplotLayer({
         ...otherProps,
         getFilterValue: object => object.properties.target === filterCondition ? 1 : 0,
         filterRange: [1, 1],
         extensions: [new DataFilterExtension({ filterSize: 1 })],
         updateTriggers: {
             // It's important to tell deck.gl when to update
             getFilterValue: filterCondition
         }
     });
    
  2. Otherwise updating you data array should be enough. That means a CPU-based data filtering, if your data is not huge, it’s okey. Thanks to reactivity should be enough with something like this:

    const [yourData, setData] = useState([]);
    
    useEffect(() => {
        // dispatch some action to set data
        setData([newData]);
    }, []);
    
    const layers = [
        new HexagonLayer({
            ...otherProps,
            data: yourData
        });
    ];
    
    return (
        <DeckGL
            ...otherProps,
            layers={layers}
        />
    );
    

P.D: deck.setProps() is recommended to use in a non-reactive environment

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement