Brush Extension в Deck.gl предназначен для
реализации интерактивного выделения географических или экранных областей
с помощью прямоугольной «кисти». Это расширение используется поверх
различных слоёв (обычно GeoJsonLayer,
ScatterplotLayer, GridLayer,
HexagonLayer) и добавляет возможность динамического выбора
подмножества данных на основе пересечения с областью выделения.
Ключевая идея заключается в том, что Brush Extension не является самостоятельным слоем — он модифицирует поведение существующего слоя, добавляя:
Brush Extension работает на двух уровнях: CPU и GPU.
CPU-часть:
GPU-часть:
Основная оптимизация заключается в том, что часть вычислений переносится в шейдер, что позволяет обрабатывать большие наборы данных без деградации производительности.
Brush Extension подключается как расширение слоя через свойство
extensions.
import {ScatterplotLayer} from '@deck.gl/layers';
import {BrushExtension} from '@deck.gl/extensions';
const layer = new ScatterplotLayer({
id: 'points',
data: points,
getPosition: d => d.coordinates,
getRadius: 50,
getFillColor: [255, 140, 0],
extensions: [new BrushExtension()]
});
После подключения слой получает дополнительные параметры управления brush-выделением.
Brush Extension принимает конфигурацию, которая управляет поведением выделения.
getBrushRadiusОпределяет радиус «переходной зоны» вокруг кисти. Используется для создания мягких границ выделения.
new BrushExtension({
getBrushRadius: 100
})
brushEnabledВключает или отключает функциональность brush-выделения.
true — активное выделениеfalse — слой работает без расширенияbrushTargetОпределяет, к чему применяется кисть:
source — используется источник данных слояtarget — применяется к результату трансформации
слояBrush Extension не имеет отдельного event API, но интегрируется через стандартные события Deck.gl и обновление props слоя.
Основные механизмы:
Типичный цикл взаимодействия:
Brush-область представляет собой прямоугольник в экранных координатах:
x_{min} x x_{max},y_{min} y y_{max}
Каждый объект слоя проверяется на принадлежность:
В случае использования географических координат добавляется проекция:
(x, y) = P_{mercator}(, )
где (P_{mercator}) — функция Web Mercator проекции.
Brush Extension модифицирует uniforms, передаваемые в GPU:
brushBoundingBox — координаты прямоугольникаbrushActive — флаг активностиbrushRadius — радиус мягкой зоныВ вершинном или фрагментном шейдере выполняется проверка:
if (position.x < brushMinX || position.x > brushMaxX ||
position.y < brushMinY || position.y > brushMaxY) {
discard;
}
Для плавного выделения используется интерполяция расстояния до границы brush-зоны.
ScatterplotLayer является наиболее частым кандидатом для применения Brush Extension, поскольку работает с точечными данными.
new ScatterplotLayer({
id: 'scatter',
data,
getPosition: d => d.position,
getRadius: 20,
getFillColor: d => d.color,
extensions: [new BrushExtension()],
brushEnabled: true
});
При этом каждая точка проходит проверку принадлежности brush-области.
В случае агрегированных слоёв Brush Extension применяется к уже агрегированным ячейкам.
Особенность:
new HexagonLayer({
id: 'hex',
data,
getPosition: d => d.position,
radius: 1000,
extensions: [new BrushExtension()]
});
Основные факторы влияния на производительность:
Оптимизационные стратегии:
Brush Extension может комбинироваться с другими расширениями Deck.gl:
При комбинировании важно учитывать порядок применения расширений, так как он влияет на финальный результат рендеринга.
Brush Extension работает в экранных координатах, поэтому при изменении:
координаты brush автоматически пересчитываются через матрицы преобразования Deck.gl.
Базовая формула трансформации:
p’ = M_{view} M_{proj} p
где:
Состояние brush обычно хранится в следующей структуре:
{
brushStart: [x0, y0],
brushEnd: [x1, y1],
isBrushing: true,
bounds: {
xMin: Math.min(x0, x1),
xMax: Math.max(x0, x1),
yMin: Math.min(y0, y1),
yMax: Math.max(y0, y1)
}
}
Это состояние используется как для визуализации рамки, так и для фильтрации данных.
Brush Extension часто используется в задачах пространственной аналитики:
Поведение остаётся стабильным даже при работе с десятками тысяч объектов благодаря GPU-ускорению.