GeoArrow Layers
See Peer Dependencies for the complete list of required packages for each component.
Why GeoArrow
GeoArrow is a memory layout for geospatial data built on top of Apache Arrow. Compared to GeoJSON:
- No JSON parse pass. Coordinates live in flat typed arrays — the bytes you fetch are the bytes the GPU consumes.
- Streamable. Arrow IPC and GeoParquet are columnar and chunked; you can render a single
RecordBatchwhile more arrive over the network. - Smaller wire size. Float64 coordinates packed at full precision typically beat GeoJSON by 3–10×.
- Typed. Each layer wrapper reads the GeoArrow extension column (
geoarrow.point,geoarrow.linestring,geoarrow.polygon, etc.) directly off the ArrowTable— you rarely need an explicitgetPositionaccessor.
The six wrappers below extract GeoArrow geometry columns inside the Vue wrapper and feed flat-buffer attributes straight to stock @deck.gl/layers (and @deck.gl/geo-layers for the trips wrapper). No runtime dependency on @geoarrow/deck.gl-geoarrow — the wrappers ship as code-split chunks loaded only when you instantiate them.
Installation
pnpm add @deck.gl/core @deck.gl/mapbox @deck.gl/layers apache-arrow
For VLayerDeckglGeoArrowTrips (animated trips) also add @deck.gl/geo-layers:
pnpm add @deck.gl/geo-layers
VLayerDeckglGeoArrowScatterplot
Renders points from a GeoArrow point or multipoint column. Wraps the stock deck.gl ScatterplotLayer.
<script setup lang="ts">
import { VMap } from '@geoql/v-maplibre';
import { VLayerDeckglGeoArrowScatterplot } from '@geoql/v-maplibre/deck.gl';
import { tableFromIPC } from 'apache-arrow';
import type { Table } from 'apache-arrow';
const table = shallowRef<Table | null>(null);
onMounted(async () => {
const buffer = await (await fetch('/points.arrows')).arrayBuffer();
table.value = tableFromIPC(new Uint8Array(buffer));
});
</script>
<template>
<VMap :options="{ style, center: [-122, 37], zoom: 10 }">
<VLayerDeckglGeoArrowScatterplot
v-if="table"
id="points"
:data="table"
:get-fill-color="[100, 150, 220, 200]"
:get-radius="50"
radius-units="meters"
pickable
/>
</VMap>
</template>
VLayerDeckglGeoArrowPath
Renders polylines from a GeoArrow linestring or multilinestring column. Useful for GPS traces, route geometries, road networks. Wraps the stock deck.gl PathLayer.
<VLayerDeckglGeoArrowPath
id="routes"
:data="table"
:get-color="[255, 140, 0, 255]"
:get-width="3"
width-units="pixels"
pickable
/>
VLayerDeckglGeoArrowPolygon
Filled polygons with optional stroke. Wraps the stock deck.gl PolygonLayer (composite of SolidPolygonLayer for fill + PathLayer for outline). Consumes a GeoArrow polygon or multipolygon column.
<VLayerDeckglGeoArrowPolygon
id="countries"
:data="table"
:get-fill-color="[100, 150, 220, 180]"
:get-line-color="[180, 220, 255, 255]"
:line-width-min-pixels="1"
stroked
filled
pickable
/>
VLayerDeckglGeoArrowSolidPolygon
3D extruded polygons — best for building footprints, height-mapped choropleths, voxel-style visualizations. Wraps the stock deck.gl SolidPolygonLayer.
<VLayerDeckglGeoArrowSolidPolygon
id="buildings"
:data="table"
:get-fill-color="[200, 100, 50, 200]"
:get-elevation="(d) => d.height_m"
extruded
filled
pickable
/>
VLayerDeckglGeoArrowText
Renders text labels at point positions. The wrapper extracts XY positions from the GeoArrow point column and reads the label string from a sibling column (default name name, overridable via the text-column prop). Wraps the stock deck.gl TextLayer.
<VLayerDeckglGeoArrowText
id="city-labels"
:data="table"
text-column="name"
:get-color="[230, 230, 230, 255]"
:get-size="14"
size-units="pixels"
billboard
/>
VLayerDeckglGeoArrowTrips
Animated trips along GeoArrow linestrings, with per-vertex timestamps. The wrapper extracts vertices from the GeoArrow linestring column and reads per-vertex timestamps from a parallel List<float64> column (default name timestamps, overridable via the timestamps-column prop). Drive the animation by binding :current-time to a requestAnimationFrame clock. Wraps the stock deck.gl TripsLayer from @deck.gl/geo-layers.
<VLayerDeckglGeoArrowTrips
id="city-trips"
:data="table"
timestamps-column="timestamps"
:get-color="[255, 140, 0, 200]"
:get-width="4"
width-units="pixels"
:current-time="time"
:trail-length="180"
fade-trail
/>
Loading data
Every wrapper accepts an apache-arrow.Table or RecordBatch directly via the data prop — pick whichever is more convenient.
From Arrow IPC (.arrows, .arrow, .feather)
import { tableFromIPC } from 'apache-arrow';
const buffer = await (await fetch(url)).arrayBuffer();
const table = tableFromIPC(new Uint8Array(buffer));
// pass `table` directly, or `table.batches[0]` for a single RecordBatch
From GeoParquet
GeoParquet decoding is not part of apache-arrow itself. Use parquet-wasm or @loaders.gl/parquet to convert a .parquet file into an Arrow Table:
import { readParquet } from 'parquet-wasm';
import { tableFromIPC } from 'apache-arrow';
const wasmTable = readParquet(new Uint8Array(buffer));
const table = tableFromIPC(wasmTable.intoIPCStream());
const batch = table.batches[0];
Sample data
The official geoarrow/geoarrow-data repository hosts CORS-enabled sample files you can use to prototype:
| File | Size | Geometry |
|---|---|---|
natural-earth_countries-geography.arrows | 178 KB | Polygon (countries) |
natural-earth_cities.arrows | ~70 KB | Point (cities) |
microsoft-buildings_* | varies | Polygon (buildings) |
Stream them via jsDelivr's CDN for snappy reloads:
const url =
'https://cdn.jsdelivr.net/gh/geoarrow/geoarrow-data@main/natural-earth/files/natural-earth_countries-geography.arrows';
Picking & events
All six wrappers emit @click and @hover with a deck.gl PickingInfo payload. Because the underlying layers consume binary (flat-buffer) attributes, info.object is typically null — read row data on demand via the Arrow Table.get(info.index) API:
<VLayerDeckglGeoArrowPolygon
id="countries"
:data="table"
pickable
@click="(info) => console.log('row', info.index, table?.get(info.index))"
/>