Advanced GPU-based data filtering system that allows layers to show/hide objects based on numeric values and categorical properties, with support for soft filtering transitions and real-time filtering counts.
Adds GPU-based data filtering functionalities to layers, enabling show/hide of objects based on user-defined numeric and categorical properties.
/**
* Adds GPU-based data filtering functionalities to layers
* Allows layers to show/hide objects based on user-defined properties
*/
class DataFilterExtension extends LayerExtension<Required<DataFilterExtensionOptions>> {
static extensionName: 'DataFilterExtension';
static defaultProps: DataFilterExtensionDefaultProps;
constructor(opts?: DataFilterExtensionOptions);
getShaders(extension: this): any;
initializeState(context: LayerContext, extension: this): void;
updateState(params: UpdateParameters, extension: this): void;
draw(params: any, extension: this): void;
finalizeState(): void;
}
interface DataFilterExtensionProps<DataT = any> {
/**
* Accessor to retrieve the value for each object that it will be filtered by.
* Returns either a number (if filterSize: 1) or an array of numbers.
* @default {type: 'accessor', value: 0}
*/
getFilterValue?: Accessor<DataT, number | number[]>;
/**
* Accessor to retrieve the category (number | string) for each object that it will be filtered by.
* Returns either a single category (if categorySize: 1) or an array of categories.
* @default {type: 'accessor', value: 0}
*/
getFilterCategory?: Accessor<DataT, FilterCategory | FilterCategory[]>;
/**
* Enable/disable the data filter. If disabled, all objects are rendered.
* @default true
*/
filterEnabled?: boolean;
/**
* The [min, max] bounds which defines whether an object should be rendered.
* If an object's filtered value is within the bounds, the object will be rendered.
* Can be a single range or array of ranges for multi-dimensional filtering.
* @default [-1, 1]
*/
filterRange?: [number, number] | [number, number][];
/**
* If specified, objects will be faded in/out instead of abruptly shown/hidden.
* When the filtered value is outside of filterSoftRange but within filterRange,
* the object will be rendered as "faded."
* @default null
*/
filterSoftRange?: [number, number] | [number, number][] | null;
/**
* When an object is "faded", manipulate its size so that it appears smaller or thinner.
* Only works if filterSoftRange is specified.
* @default true
*/
filterTransformSize?: boolean;
/**
* When an object is "faded", manipulate its opacity so that it appears more translucent.
* Only works if filterSoftRange is specified.
* @default true
*/
filterTransformColor?: boolean;
/**
* The categories which define whether an object should be rendered.
* Can be a single array or array of arrays for multi-dimensional category filtering.
* @default [0]
*/
filterCategories?: FilterCategory[] | FilterCategory[][];
/**
* Callback fired when the number of filtered objects changes.
* Only called if the countItems option is enabled.
*/
onFilteredItemsChange?: (evt: {
/** The id of the source layer */
id: string;
/** The number of data objects that pass the filter */
count: number;
}) => void;
}
interface DataFilterExtensionOptions {
/**
* The size of the category filter (number of columns to filter by).
* The category filter can show/hide data based on 1-4 properties of each object.
* Set to 0 to disable category filtering.
* @default 0
*/
categorySize?: 0 | 1 | 2 | 3 | 4;
/**
* The size of the filter (number of columns to filter by).
* The data filter can show/hide data based on 1-4 numeric properties of each object.
* Set to 0 to disable numeric filtering.
* @default 1
*/
filterSize?: 0 | 1 | 2 | 3 | 4;
/**
* Use 64-bit precision instead of 32-bit for numeric filtering.
* @default false
*/
fp64?: boolean;
/**
* If true, reports the number of filtered objects with the onFilteredItemsChange callback.
* @default false
*/
countItems?: boolean;
}
interface DataFilterExtensionDefaultProps {
getFilterValue: {type: 'accessor', value: number};
getFilterCategory: {type: 'accessor', value: number};
onFilteredItemsChange: {type: 'function', value: null, optional: boolean};
filterEnabled: boolean;
filterRange: [number, number];
filterSoftRange: null;
filterCategories: number[];
filterTransformSize: boolean;
filterTransformColor: boolean;
}
type FilterCategory = number | string;Usage Examples:
import { ScatterplotLayer } from "@deck.gl/layers";
import { DataFilterExtension } from "@deck.gl/extensions";
// Basic numeric filtering
const numericFilterLayer = new ScatterplotLayer({
id: "filtered-points",
data: dataPoints,
extensions: [new DataFilterExtension({ filterSize: 1 })],
getPosition: d => d.coordinates,
getFilterValue: d => d.temperature, // Filter by temperature
filterRange: [20, 30], // Show only temperatures between 20-30
filterEnabled: true
});
// Multi-dimensional numeric filtering
const multiFilterLayer = new ScatterplotLayer({
id: "multi-filtered",
data: dataPoints,
extensions: [new DataFilterExtension({ filterSize: 2 })],
getPosition: d => d.coordinates,
getFilterValue: d => [d.temperature, d.humidity], // Filter by both
filterRange: [[20, 30], [40, 80]], // Temperature 20-30, humidity 40-80
filterEnabled: true
});
// Soft filtering with fade transitions
const softFilterLayer = new ScatterplotLayer({
id: "soft-filtered",
data: dataPoints,
extensions: [new DataFilterExtension({ filterSize: 1 })],
getPosition: d => d.coordinates,
getFilterValue: d => d.score,
filterRange: [0, 100], // Hard bounds
filterSoftRange: [20, 80], // Objects outside this range are faded
filterTransformSize: true, // Fade by making smaller
filterTransformColor: true, // Fade by reducing opacity
filterEnabled: true
});
// Category filtering
const categoryFilterLayer = new ScatterplotLayer({
id: "category-filtered",
data: dataPoints,
extensions: [new DataFilterExtension({ categorySize: 1 })],
getPosition: d => d.coordinates,
getFilterCategory: d => d.type, // Filter by category
filterCategories: ["typeA", "typeC"], // Show only these categories
filterEnabled: true
});
// Combined numeric and category filtering with counting
const combinedFilterLayer = new ScatterplotLayer({
id: "combined-filtered",
data: dataPoints,
extensions: [new DataFilterExtension({
filterSize: 1,
categorySize: 1,
countItems: true
})],
getPosition: d => d.coordinates,
getFilterValue: d => d.value,
getFilterCategory: d => d.status,
filterRange: [0, 50],
filterCategories: ["active", "pending"],
onFilteredItemsChange: ({id, count}) => {
console.log(`Layer ${id} has ${count} visible items`);
},
filterEnabled: true
});// Filter by up to 4 numeric properties simultaneously
const advancedFilter = new DataFilterExtension({ filterSize: 4 });
const layer = new ScatterplotLayer({
extensions: [advancedFilter],
getFilterValue: d => [d.temp, d.humidity, d.pressure, d.windSpeed],
filterRange: [[20, 30], [40, 80], [1000, 1020], [0, 15]]
});// Use 64-bit precision for high-precision numeric filtering
const precisionFilter = new DataFilterExtension({
filterSize: 1,
fp64: true
});
const layer = new ScatterplotLayer({
extensions: [precisionFilter],
getFilterValue: d => d.preciseValue, // High-precision numeric value
filterRange: [1000000.1, 1000000.9] // Small range requiring precision
});// Track the number of visible objects in real-time
const countingFilter = new DataFilterExtension({
filterSize: 1,
countItems: true
});
const layer = new ScatterplotLayer({
extensions: [countingFilter],
getFilterValue: d => d.value,
filterRange: [0, 100],
onFilteredItemsChange: ({id, count}) => {
updateUI(`${count} items visible`);
}
});The extension provides two shader module variants:
dataFilter: Standard 32-bit precision filteringdataFilter64: High-precision 64-bit filteringBoth modules support: