visState — один из центральных разделов состояния
приложения Kepler.gl. Именно здесь хранится информация, отвечающая за
визуальное представление данных на карте: загруженные наборы данных,
слои, фильтры, взаимодействия, настройки отображения, а также
конфигурации анимации и разделения карты на несколько представлений.
Если mapState отвечает за положение карты,
масштабирование и перемещение, то visState управляет тем,
что именно отображается поверх карты и каким образом эти
данные визуализируются.
Структура объекта может выглядеть следующим образом:
{
visState: {
datasets: [],
layers: [],
filters: [],
interactionConfig: {},
layerBlending: 'normal',
splitMaps: [],
animationConfig: {},
editor: {},
layerToBeMerged: [],
layerOrder: []
}
}
Каждое поле отвечает за отдельную подсистему визуализации.
После загрузки данных Kepler.gl выполняет следующие действия:
visState.datasets.Схематически процесс выглядит так:
CSV / GeoJSON
↓
addDataToMap()
↓
Dataset
↓
visState.datasets
↓
Автоматическое создание слоев
↓
visState.layers
↓
Отрисовка на карте
Все изменения пользовательского интерфейса фактически приводят к
изменению содержимого visState.
Поле datasets хранит все загруженные наборы данных.
Пример:
visState.datasets
[
{
id: 'cities',
label: 'Cities',
data: {
fields: [...],
rows: [...]
}
}
]
Каждый набор данных содержит:
| Поле | Назначение |
|---|---|
| id | Уникальный идентификатор |
| label | Название набора |
| data.fields | Описание колонок |
| data.rows | Строки данных |
| color | Цвет набора |
| allData | Исходные данные |
Описание колонок выглядит следующим образом:
fields: [
{
name: 'city',
type: 'string'
},
{
name: 'population',
type: 'integer'
},
{
name: 'latitude',
type: 'real'
},
{
name: 'longitude',
type: 'real'
}
]
Kepler.gl использует эту информацию для автоматического определения типов данных.
rows: [
['London', 9000000, 51.5074, -0.1278],
['Paris', 2140000, 48.8566, 2.3522]
]
Массив строк хранится отдельно от описания колонок.
Такой подход обеспечивает:
Поле layers содержит все визуальные слои карты.
Пример:
visState.layers
[
{
id: 'point-layer',
type: 'point',
config: {},
visualChannels: {}
}
]
Каждый объект описывает один слой.
Наиболее распространённые типы:
| Тип | Назначение |
|---|---|
| point | Точки |
| arc | Дуги |
| line | Линии |
| geojson | GeoJSON |
| polygon | Полигоны |
| grid | Grid Aggregation |
| hexagon | Hexbin Aggregation |
| heatmap | Тепловая карта |
| cluster | Кластеры |
| icon | Иконки |
| trip | Анимированные маршруты |
Пример слоя:
{
id: 'cities-layer',
type: 'point'
}
Большая часть настроек располагается внутри объекта
config.
Пример:
{
config: {
label: 'Cities',
dataId: 'cities',
columns: {
lat: 'latitude',
lng: 'longitude'
},
isVisible: true
}
}
Указывает источник данных.
{
dataId: 'cities'
}
Слой будет использовать набор данных с таким идентификатором.
Определяет связь между полями данных и слоем.
{
columns: {
lat: 'latitude',
lng: 'longitude'
}
}
Для слоя точек обязательны координаты.
Название слоя:
{
label: 'Population'
}
Отображается в панели Layers.
Управляет видимостью.
{
isVisible: true
}
или
{
isVisible: false
}
Внутри visConfig находятся параметры визуализации.
Пример:
{
visConfig: {
radius: 20,
opacity: 0.8,
filled: true
}
}
Размер точек:
{
radius: 30
}
Прозрачность:
{
opacity: 0.5
}
Заполнение объекта цветом:
{
filled: true
}
Цвет границы:
{
strokeColor: [255, 0, 0]
}
Формат RGB.
Толщина линий:
{
thickness: 4
}
Система визуальных каналов связывает значения данных с визуальными свойствами.
Пример:
visualChannels: {
colorField: {
name: 'population'
},
sizeField: {
name: 'population'
}
}
colorField: {
name: 'population'
}
colorScale: 'quantile'
Чем выше население, тем интенсивнее цвет.
sizeField: {
name: 'population'
}
sizeScale: 'sqrt'
Размер точки будет зависеть от значения поля.
Для трёхмерных слоёв:
heightField: {
name: 'population'
}
Хранит все фильтры.
visState.filters
Пример:
[
{
id: 'population-filter'
}
]
{
dataId: 'cities',
name: ['population'],
type: 'range',
value: [1000000, 10000000]
}
Будут отображаться только города в указанном диапазоне.
{
dataId: 'cities',
name: ['country'],
type: 'multiSelect',
value: ['France', 'Germany']
}
{
dataId: 'events',
name: ['timestamp'],
type: 'timeRange',
value: [
1680000000000,
1690000000000
]
}
Определяет настройки взаимодействия пользователя с картой.
Пример:
interactionConfig: {
tooltip: {},
brush: {},
geocoder: {},
coordinate: {}
}
Настройки всплывающих подсказок.
tooltip: {
enabled: true
}
Пример выбора колонок:
tooltip: {
fieldsToShow: {
cities: [
{
name: 'city'
},
{
name: 'population'
}
]
}
}
tooltip: {
compareMode: false
}
tooltip: {
compareType: 'absolute'
}
Инструмент выделения области.
brush: {
enabled: true
}
Радиус выделения:
brush: {
size: 50
}
Поиск местоположений.
geocoder: {
enabled: true
}
После включения появляется строка поиска адресов.
Отображение координат курсора.
coordinate: {
enabled: true
}
Параметр смешивания слоёв.
layerBlending: 'normal'
Поддерживаемые режимы:
normal
additive
subtractive
Стандартный режим.
layerBlending: 'normal'
Наложение цветов суммированием.
layerBlending: 'additive'
Особенно полезно для тепловых карт.
Вычитание цветов.
layerBlending: 'subtractive'
Используется значительно реже.
Позволяет отображать несколько карт одновременно.
Пример:
splitMaps: []
После разделения интерфейса:
splitMaps: [
{
layers: {}
},
{
layers: {}
}
]
Каждая карта может содержать собственный набор слоёв.
{
layers: {
'cities-layer': true,
'heatmap-layer': false
}
}
Это позволяет сравнивать различные варианты визуализации.
Используется для управления анимацией.
Особенно важно для слоя Trip Layer.
Пример:
animationConfig: {
currentTime: 0,
speed: 1
}
Текущий момент времени.
{
currentTime: 120
}
{
speed: 2
}
Анимация будет проигрываться в два раза быстрее.
Хранит состояние встроенных редакторов.
Пример:
editor: {
features: []
}
Используется при рисовании объектов непосредственно на карте.
Последовательность отображения слоёв.
layerOrder: [
'base-layer',
'cities-layer',
'heatmap-layer'
]
Чем дальше слой расположен в массиве, тем выше он будет находиться в визуальной иерархии.
Изменение порядка:
dispatch({
type: 'LAYER_MOVE_UP',
payload: {
layerId: 'cities-layer'
}
});
Служебное поле для операций объединения.
layerToBeMerged: [
'layer-1',
'layer-2'
]
Используется внутренними механизмами Kepler.gl при создании составных визуализаций.
Одной из ключевых особенностей является возможность полного восстановления визуализации через конфигурационный объект.
Пример экспортируемого состояния:
{
visState: {
layers: [...],
filters: [...],
interactionConfig: {...},
layerBlending: 'normal'
}
}
Такой объект может:
При экспорте конфигурации через интерфейс Kepler.gl большая часть
информации извлекается именно из visState.
Типичный экспорт содержит:
{
version: 'v1',
config: {
visState: {...},
mapState: {...},
mapStyle: {...}
}
}
Во время импорта:
KeplerGlSchema.load(...)
конфигурация преобразуется обратно в структуру состояния Redux.
Благодаря этому visState выступает главным источником
данных для восстановления всей пользовательской визуализации: слоёв,
фильтров, интерактивности, анимации, цветовых схем и связей между
данными и объектами карты.