Filter and Map Location Data in a JavaScript Grid
A table of sites, stores or claims usually keeps a postcode or a pair of numbers for where a row is. Finding “everything inside this box” or “the five closest to here” then means pulling every row into the browser and testing each one by hand, or writing that logic again for the next table. A grid column can hold the shape itself instead: a point, a line or a polygon, filtered, sorted and drawn like any other value.
A column can hold a shape
Declare a column type: 'geometry' and it reads a point, line or polygon
from WKT, WKB or GeoJSON, whichever a source hands it, and shows a plain
sentence in the cell: a coordinate, or a shape and its area. Four filters
come with it, on top of everything every other column already offers:
within a box, within a polygon, intersecting another shape, and within a
distance of a point. Sort the column and rows order by location.
grid.filters.set({ col: 'site', op: 'withinBbox', value: [-4, 50, 2, 56] });
GeoParquet, read in the browser, filtered by DuckDB
Point the DuckDB adapter at a GeoParquet file with spatial: true and
those same four filters run inside DuckDB itself rather than in the
browser, over a file that stays where it is. The
remote GeoParquet demo
puts this against a real 203 MB extract of places data, sorted so that
nearby places sit together in the file: filtering a neighbourhood-sized box
down fetches around 40 MB of it, not the whole file, and the first rows
arrive in about seven seconds while the engine loads. Every filter after
that is fast, because the browser never asked for more than the rows in
view. The
GeoParquet demo on this site shows the same
pushdown on a smaller file, with the query plan printed beside the grid so
the filter’s own SQL is there to read.
Maps that are viewers, not pictures
markermap, bubblemap and choropleth all read a geometry column
directly: a point places a marker, and on a choropleth a polygon draws
its own boundary, filled by a measure from the same row, with no separate
map file to load and join by code. The
choropleth demo fills each country from the
shape in its own row. The
power plants demo
carries close to 35,000 sites worldwide: zoomed in, every plant draws as
its own bubble; zoomed out past the cap of 20,000 points in one view, the
map switches to density cells instead of thinning the set at random, so
the picture stays honest at any scale. The
live earthquakes demo
draws the same map against a feed that keeps moving.
Pan the map, narrow the grid
Turn on viewportFilter and panning or zooming a map writes one condition
back onto the grid it reads from: whatever is on screen becomes the filter,
and every other chart, tile or table reading that same grid follows it.
Set a matching condition from somewhere else, a saved view or a sibling
panel, and the map pans to meet it instead of fighting it. The
viewport filter demo puts a map and a grid
side by side on one filter, either one able to drive it.
Tiles and charts that ask the engine
A KPI tile or a chart sitting beside a grid that only holds a page of a
much larger table used to describe that page, not the true total. Ask a
tile to total a filtered column and it reads the whole matching set through
the same adapter the grid uses, then says so: chart.provenance() reports
whether a figure came from the engine or from the browser, so a number on
screen never has to be trusted blind. The
engine tiles demo totals a column across a
paged DuckDB source this way, in step with the grid’s own filters.
Or draw it yourself, with deck.gl
The built-in maps cover markers, bubbles and choropleths; a page already
building its view in deck.gl can bind the grid to it directly instead.
bindDeck hands your own deck.gl layers exactly the rows the grid shows,
redraws them as the grid changes, and turns the map’s own pan and zoom into
the same viewport filter the built-in maps write. The
deck.gl demo draws a scatterplot layer over a real
basemap this way, straight from the grid’s rows. The
GIS demo goes
further: a world choropleth of generating capacity by country, a hexagon
density layer as you zoom into a region, and the plants themselves at city
scale, each layer fed by the same grid and the same filters, with the map’s
viewport narrowing the rows as you move.
See it running
The geospatial guide covers the column type, the four operators and every map option in full, and the full changelog lists everything else this release shipped.