Lattice Grid Buy a licence

developer guide

deck.gl as a Viewer of a JavaScript Data Grid

Your grid's rows, drawn by your own deck.gl layers, over your own map. The grid never imports deck.gl and deck.gl never imports the grid; bindDeck is the one connection between them.

bindDeck: one function, two-way

Import the deck.gl module and hand bindDeck a live grid and the deck.gl Deck instance a page has already built. Your own layers function is called with the rows the grid currently shows, so a filter, a sort or a live update reaches the map the same frame it reaches the table.

import { bindDeck } from '@toclocoinc/lattice-grid/modules/deckgl';

const binding = bindDeck(grid, {
  deck,                                  // your own deck.gl Deck (or a React DeckGL's .deck)
  position: { lon: 'lon', lat: 'lat' },  // or geometry: '<col>'
  viewportFilter: true,
  layers: (rows, ctx) => [
    new ScatterplotLayer({
      id: 'rows',
      data: rows,          // exactly the rows the grid currently shows
      getPosition: (r) => [r.lon, r.lat],
      getRadius: 4000,
    }),
  ],
});
// layers is your own function, written against your own deck.gl classes; the
// module never imports deck.gl itself. It is called with the rows the grid
// shows and its result goes straight to deck.setProps({ layers }).

The map's own pan and zoom, as a filter

With viewportFilter on, every pan and zoom writes one withinBbox condition back onto the grid, the same condition the built-in maps write, replacing only its own previous one; a box set from elsewhere pans the map to match it in turn.

Rows inside the view, from a paged source

Bound to a paged pushdown source, bindDeck asks the engine for the rows inside deck's current view rather than only the loaded page, and falls back to density cells past a row cap.

// A paged pushdown grid hands over the rows inside deck's current view from
// the engine, the same question the built-in maps ask, not only the loaded
// page:
bindDeck(grid, { deck, position: { lon: 'lon', lat: 'lat' }, viewportCap: 20000, layers });
// Past viewportCap, ctx.binned is true and the engine hands over density
// cells instead of individual rows. ctx.features carries the rows as GeoJSON
// features and ctx.provenance says what was handed over.
binding.destroy();  // removes the viewport-filter binding and stops updating layers

See it running: a deck.gl scatterplot over a MapLibre basemap, drawing straight from the grid. The geospatial guide covers the built-in maps and the geometry column type that also feeds this binding.