В основе визуализации Kepler.gl лежит слойная модель deck.gl, где каждый слой представляет независимую единицу рендеринга данных. Расширяемость достигается за счёт возможности подключения пользовательских классов слоёв, наследуемых от базовых реализаций deck.gl. Это позволяет внедрять специализированные визуализации без изменения ядра приложения.
Kepler.gl использует декларативное описание слоёв через состояние визуализации (visState), где каждый слой описывается набором параметров: типом, источником данных, стилями и фильтрами. Пользовательские слои интегрируются в эту систему через регистрацию и последующее использование в конфигурации карты.
Любой кастомный слой в deck.gl реализуется через наследование от
класса Layer. В зависимости от сложности задачи
используются:
Layer — базовый абстрактный слойCompositeLayer — композиция нескольких вложенных
слоёвКлючевые методы, определяющие поведение слоя:
initializeState — инициализация состоянияupdateState — реакция на изменение propsrenderLayers — композиция дочерних слоёв (для
CompositeLayer)getColor, getPosition и другие
accessor-функцииdraw — низкоуровневый рендер (WebGL)Наиболее распространённый подход — композиция стандартных слоёв deck.gl с дополнительной логикой обработки данных.
import {CompositeLayer, ScatterplotLayer} from '@deck.gl/layers';
class HeatScatterLayer extends CompositeLayer {
initializeState() {
this.state = {
maxRadius: 1000
};
}
renderLayers() {
const {data, getPosition, getWeight} = this.props;
return new ScatterplotLayer({
id: `${this.id}-scatter`,
data,
getPosition,
getRadius: d => getWeight(d),
radiusUnits: 'meters',
opacity: 0.8,
pickable: true
});
}
}
HeatScatterLayer.layerName = 'HeatScatterLayer';
Такой слой позволяет переопределять логику отображения без вмешательства в низкоуровневый WebGL-код.
Kepler.gl ожидает регистрацию кастомных слоёв через расширение конфигурации. Основной механизм — добавление слоя в список доступных типов и маппинг его в систему визуализации.
import KeplerGl from 'kepler.gl';
import {addDataToMap} from 'kepler.gl/actions';
const customLayers = {
heat_scatter: HeatScatterLayer
};
Далее слой подключается через состояние:
const mapConfig = {
version: 'v1',
config: {
visState: {
layers: [
{
id: 'custom-layer-1',
type: 'heat_scatter',
config: {
dataId: 'dataset_1',
label: 'Heat Scatter',
columns: {
lat: 'latitude',
lng: 'longitude'
}
}
}
]
}
}
};
Kepler.gl не использует прямую инстанциацию слоёв. Вместо этого применяется фабрика слоёв, где тип слоя сопоставляется с классом.
import KeplerGl from 'kepler.gl';
import {LayerManager} from 'kepler.gl';
const layerClasses = {
heat_scatter: HeatScatterLayer
};
function getLayer(type) {
return layerClasses[type];
}
В реальной интеграции используется расширение
KeplerGlSchema и middleware Redux, через которое слой
регистрируется в runtime.
В случаях, когда требуется максимальный контроль над
WebGL-пайплайном, используется наследование от Layer.
import {Layer} from '@deck.gl/core';
class PulsingPointLayer extends Layer {
initializeState() {
const {gl} = this.context;
this.setState({
time: 0
});
}
draw({uniforms}) {
const {gl} = this.context;
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
// кастомный WebGL рендеринг
}
updateState({props, oldProps}) {
if (props.time !== oldProps.time) {
this.setState({time: props.time});
}
}
}
PulsingPointLayer.layerName = 'PulsingPointLayer';
Такой подход требует ручного управления шейдерами и состоянием WebGL-контекста.
Для сложных визуализаций применяется программирование вершинных и
фрагментных шейдеров через shadertools.
import {Layer} from '@deck.gl/core';
class GlowLayer extends Layer {
getShaders() {
return {
vs: `
attribute vec3 positions;
void main(void) {
gl_Position = project_position_to_clipspace(positions);
}
`,
fs: `
precision highp float;
void main(void) {
gl_FragColor = vec4(1.0, 0.5, 0.0, 0.7);
}
`
};
}
}
Шейдеры позволяют реализовывать эффекты свечения, анимации плотности, тепловые карты и нестандартные визуальные метрики.
Кастомные слои используют accessor-паттерн для извлечения данных из объектов массива:
class CustomLayer extends CompositeLayer {
renderLayers() {
const {data, getValue} = this.props;
return new ScatterplotLayer({
data,
getPosition: d => d.coordinates,
getRadius: d => getValue(d),
getFillColor: [255, 100, 0]
});
}
}
Accessor-функции позволяют отделить структуру данных от логики рендеринга, обеспечивая совместимость с Kepler.gl datasets.
Kepler.gl хранит состояние слоёв в Redux-структуре
visState.layers. Каждый слой представляет сериализуемый
объект:
idtypeconfigvisualChannelsdataIdПри создании кастомного слоя важно обеспечить сериализуемость всех параметров, так как состояние может сохраняться и восстанавливаться.
const layerConfig = {
id: 'custom_1',
type: 'heat_scatter',
config: {
opacity: 0.6,
visConfig: {
radius: 10
}
}
};
Фильтрация данных в Kepler.gl происходит на уровне
visState.filters. Кастомный слой автоматически получает
отфильтрованный набор данных, если использует стандартный pipeline.
renderLayers() {
const {filteredData} = this.props;
return new ScatterplotLayer({
data: filteredData,
getPosition: d => d.position
});
}
При необходимости можно переопределять поведение фильтрации,
используя updateTriggers и кастомные селекторы Redux.
При работе с большими наборами данных ключевое значение имеют:
updateTriggersTypedArray для числовых данныхnew ScatterplotLayer({
data,
updateTriggers: {
getRadius: props.radiusScale
}
});
Дополнительно применяются стратегии spatial indexing и GPU instancing для снижения нагрузки на CPU.
CompositeLayer позволяет объединять несколько визуализаций в единый слой:
class MultiVizLayer extends CompositeLayer {
renderLayers() {
return [
new ScatterplotLayer({...}),
new PathLayer({...}),
new TextLayer({...})
];
}
}
Такой подход используется для создания сложных картографических представлений, где один слой отвечает за несколько визуальных каналов.
Kepler.gl использует Redux middleware для управления слоями. Кастомные слои должны быть совместимы с action-потоками:
addLayerupdateLayerremoveLayerСлой регистрируется как часть схемы приложения и становится доступен через UI-конфигурацию или программный API.
dispatch(addLayer({
...layerConfig,
type: 'heat_scatter'
}));
Kepler.gl использует визуальные каналы (visual channels), такие как:
Кастомный слой может подключаться к этим каналам через декларацию:
visualChannels: {
colorField: {name: 'intensity'},
sizeField: {name: 'weight'}
}
Это обеспечивает совместимость с UI-конфигурацией Kepler.gl без изменения интерфейса.
Интерактивность реализуется через pickable и
события:
new ScatterplotLayer({
pickable: true,
onClick: info => {
console.log(info.object);
}
});
Kepler.gl интегрирует picking через единый event manager, поэтому кастомные слои автоматически участвуют в системе интеракции при соблюдении интерфейса deck.gl.