Фильтры в Kepler.gl являются частью состояния визуализации и
управляются через слой visState, который хранит всю логику
взаимодействия с данными: от набора датасетов до конфигурации слоёв и
фильтрации. Динамическое управление фильтрами предполагает изменение
параметров фильтрации в реальном времени через действия (actions),
внешние события интерфейса или программную логику приложения без
пересборки карты.
Система фильтров интегрирована в Redux-подобное состояние Kepler.gl.
Основной контейнер — visState, внутри которого хранится
массив filters. Каждый элемент этого массива представляет
собой объект фильтра с набором параметров:
dataId, name)Фильтр всегда связан с конкретным датасетом через
dataId. Это позволяет одновременно применять разные фильтры
к разным источникам данных.
Динамическое управление фильтрами в Kepler.gl опирается на поток обновлений состояния. Любое изменение фильтра реализуется через dispatch action:
Ключевой момент заключается в том, что фильтр не изменяется напрямую
как объект JavaScript. Вместо этого создаётся новое состояние, которое
проходит через reducer visState.
Добавление фильтра происходит через действие, формирующее объект фильтра и передающее его в состояние:
dispatch(addFilter({
dataId: 'dataset_1',
name: 'timestamp',
type: 'timeRange',
value: [startTimestamp, endTimestamp]
}));
После обработки reducer автоматически интегрирует новый фильтр в
массив filters. Этот подход обеспечивает предсказуемость
состояния и совместимость с архитектурой Redux.
Основной механизм динамического управления связан с действием обновления фильтра. Оно используется при изменении значений слайдеров, внешних API или событий пользовательского интерфейса.
dispatch(updateFilter({
id: 'filter_1',
value: [newMin, newMax]
}));
При каждом вызове происходит перерасчёт данных слоёв, зависящих от фильтра. Kepler.gl оптимизирует вычисления, применяя фильтрацию на уровне GPU или WebGL-слоя, если это возможно.
В сложных приложениях фильтры часто синхронизируются с внешним состоянием: URL-параметрами, состоянием React или серверными событиями. Это позволяет создавать реактивные карты, изменяющиеся без перезагрузки.
Типичный подход заключается в подписке на изменения состояния:
store.subscribe(() => {
const state = store.getState();
const filters = state.keplerGl.map.visState.filters;
});
На основе этих данных можно формировать внешние контроллеры или сохранять конфигурацию.
Фильтры типа timeRange являются наиболее чувствительными
к динамическим изменениям. Они оперируют временными метками и часто
связаны с анимацией данных.
Структура такого фильтра включает:
timeIntervaldomainvaluespeedanimationWindowИзменение временного диапазона в реальном времени приводит к перерасчёту отображаемых объектов:
dispatch(updateFilter({
id: 'time_filter',
value: [t0, t1],
speed: 1
}));
При включённой анимации фильтр автоматически «прокручивает» диапазон, создавая эффект движения данных во времени.
Каждый слой (layer) в Kepler.gl может ссылаться на один
или несколько фильтров. Связь осуществляется через filterId
или косвенно через dataId. Это означает, что изменение
одного фильтра может влиять на несколько визуальных слоёв
одновременно.
Пример поведения:
Таким образом, динамическое управление фильтрами фактически управляет всей сценой визуализации.
В реальных приложениях часто требуется каскадное обновление фильтров. Например, изменение одного фильтра может автоматически пересчитывать другой.
Это реализуется через промежуточный слой логики:
function syncFilters(newValue) {
dispatch(updateFilter({
id: 'filter_a',
value: newValue
}));
dispatch(updateFilter({
id: 'filter_b',
value: computeDependentRange(newValue)
}));
}
Такой подход позволяет строить зависимые фильтры, где один параметр управляет несколькими измерениями данных.
Kepler.gl часто используется внутри React-приложений, где фильтры управляются через props и callbacks. Компоненты могут выступать как контроллеры состояния:
Каждое изменение UI-компонента вызывает dispatch действия, обновляющего visState.
const onCha nge = (value) => {
dispatch(updateFilter({ id: 'filter_1', value }));
};
Это обеспечивает односторонний поток данных и предотвращает рассинхронизацию интерфейса и карты.
При частых обновлениях фильтров возникает нагрузка на перерасчёт слоёв. Kepler.gl решает эту проблему через:
Особенно критично это при анимации времени, где фильтр обновляется десятки раз в секунду.
Система поддерживает несколько фильтров одновременно. Их взаимодействие строится по принципу логического пересечения:
Пример конфигурации:
filters: [
{ id: 'f1', type: 'range', value: [0, 100] },
{ id: 'f2', type: 'select', value: ['A', 'B'] },
{ id: 'f3', type: 'timeRange', value: [t0, t1] }
]
В некоторых архитектурах Kepler.gl используется как «визуальный движок», управляемый извне. В этом случае фильтры полностью контролируются приложением через глобальный store.
Изменения могут приходить:
Каждое событие преобразуется в updateFilter action и синхронизирует карту с внешним источником данных.
Состояние фильтров может быть сохранено и восстановлено. Это важно для сценариев, где требуется воспроизводимость визуализации.
Сериализуемые поля включают:
При восстановлении состояния Kepler.gl полностью реконструирует фильтры и их влияние на слои без дополнительной логики со стороны приложения.