Экспорт результата

Экспорт данных и визуализаций в Kepler.gl является одной из ключевых функций, позволяющих использовать результаты анализа вне браузерного интерфейса и интегрировать их в внешние системы, отчёты и пайплайны обработки данных. Архитектура библиотеки предполагает разделение исходных данных, конфигурации слоёв и состояния карты, что делает процесс экспорта многоуровневым: можно извлекать как сырые данные, так и полностью готовые визуальные настройки.

Конфигурация карты в Kepler.gl представляет собой JSON-структуру, содержащую описание слоёв, фильтров, взаимодействий и стилей отображения. Экспорт конфигурации используется для сохранения состояния визуализации и её последующего восстановления.

Основной метод получения конфигурации связан с состоянием Redux-стора, в котором хранится состояние kepler.gl:

const mapConfig = store.getState().keplerGl.map.config;

Чаще используется более полная структура:

const keplerState = store.getState().keplerGl;

Внутри этого объекта находятся:

  • visState — слои, фильтры, взаимодействия
  • mapState — положение камеры, масштаб, центр карты
  • uiState — состояние интерфейса
  • mapStyle — стили подложки карты

Экспорт полной конфигурации обычно осуществляется через сериализацию:

const exportPayload = JSON.stringify(keplerState, null, 2);

Такой формат позволяет восстановить карту в идентичном виде при повторной инициализации.

Экспорт данных слоёв

Kepler.gl не изменяет исходные данные, а лишь создаёт над ними визуальные слои. Это позволяет извлекать данные в исходном или частично трансформированном виде.

Доступ к данным слоя осуществляется через visState:

const datasets = store.getState().keplerGl.visState.datasets;

Каждый dataset содержит:

  • data — исходный массив или таблица данных
  • fields — описание колонок
  • meta — метаданные загрузки

Экспорт данных слоя может быть выполнен через обход структуры:

const extractData = (datasets) => {
  return Object.keys(datasets).map(key => ({
    id: key,
    data: datasets[key].data,
    fields: datasets[key].fields
  }));
};

В ряде случаев данные уже преобразованы в формат, оптимизированный для визуализации, поэтому при экспорте необходимо учитывать возможные вычисленные поля, агрегаты и фильтры.

Экспорт отфильтрованных данных

Фильтрация в Kepler.gl применяется на уровне visState.filters. Это означает, что экспорт может учитывать активные фильтры, если требуется выгрузка только видимых данных.

Структура фильтров:

const filters = store.getState().keplerGl.visState.filters;

Каждый фильтр содержит параметры:

  • dataId
  • value
  • domain
  • type
  • enlarged

Применение фильтров к данным для экспорта требует повторной обработки:

const applyFilters = (data, filters) => {
  return data.filter(row => {
    return filters.every(filter => {
      const value = row[filter.name];

      if (filter.type === 'range') {
        return value >= filter.value[0] && value <= filter.value[1];
      }

      if (filter.type === 'timeRange') {
        const timestamp = new Date(value).getTime();
        return timestamp >= filter.value[0] && timestamp <= filter.value[1];
      }

      return true;
    });
  });
};

Такой подход позволяет формировать экспортируемые наборы данных, полностью соответствующие текущему состоянию визуализации.

Экспорт через встроенные утилиты Kepler.gl

Kepler.gl предоставляет вспомогательные функции для сериализации состояния и подготовки данных к сохранению. Одним из ключевых механизмов является экспорт состояния в формате snapshot.

Snapshot включает:

  • конфигурацию карты
  • данные слоёв
  • состояние интерфейса

Типичная структура snapshot:

{
  "version": "v1",
  "config": {
    "visState": {},
    "mapState": {},
    "mapStyle": {}
  },
  "data": []
}

Создание snapshot часто реализуется через пользовательскую функцию:

const createSnapshot = (state) => ({
  version: 'v1',
  config: {
    visState: state.visState,
    mapState: state.mapState,
    mapStyle: state.mapStyle
  },
  data: Object.values(state.visState.datasets)
});

Экспорт в GeoJSON

При работе с геопространственными данными часто требуется экспорт в GeoJSON — стандарт, совместимый с большинством GIS-систем.

Если слой содержит координаты, их можно преобразовать:

const toGeoJSON = (dataset) => {
  return {
    type: "FeatureCollection",
    features: dataset.data.map(row => ({
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [row.lng, row.lat]
      },
      properties: row
    }))
  };
};

Для полигональных и линий требуется учитывать структуру геометрии, заданную в слое (например, arc, path или polygon).

Экспорт визуальных слоёв

Слои Kepler.gl (point, arc, line, heatmap и другие) не экспортируются напрямую как изображения, но могут быть сериализованы в конфигурацию, которая затем воспроизводится в другом окружении.

Описание слоя находится в:

const layers = store.getState().keplerGl.visState.layers;

Каждый слой содержит:

  • type
  • config
  • visualChannels

Экспорт слоя:

const exportLayers = layers.map(layer => ({
  id: layer.id,
  type: layer.type,
  config: layer.config,
  visualChannels: layer.visualChannels
}));

Такой формат используется для переноса визуализаций между проектами без потери логики отображения.

Экспорт карты как изображения

Хотя Kepler.gl работает в DOM, экспорт визуального результата возможен через рендеринг canvas или использование сторонних библиотек.

Один из распространённых подходов — захват canvas:

const canvas = document.querySelector('canvas');
const image = canvas.toDataURL('image/png');

Результат представляет собой base64-кодированное изображение, которое может быть сохранено или отправлено на сервер.

При наличии WebGL-рендеринга необходимо учитывать, что некоторые слои могут рендериться в несколько canvas-слоёв, поэтому используется объединение через html2canvas или аналогичные инструменты.

Экспорт данных с учётом производных полей

Kepler.gl поддерживает вычисляемые поля (derived columns), создаваемые через выражения. Эти поля не всегда присутствуют в исходном датасете, но входят в визуализацию.

При экспорте необходимо учитывать:

  • вычисленные агрегаты
  • нормализованные значения
  • результат фильтрации и биннинга

Пример извлечения вычисленных полей:

const extractAllFields = (dataset) => {
  return dataset.fields.map(field => field.name);
};

И объединение с данными:

const exportWithDerived = (dataset) => {
  return dataset.data.map(row => {
    const result = {};
    dataset.fields.forEach(field => {
      result[field.name] = row[field.name];
    });
    return result;
  });
};

Экспорт состояния через Redux middleware

При интеграции Kepler.gl в приложение часто используется middleware, позволяющий перехватывать действия и сохранять состояние при изменениях.

Пример логирования состояния:

const exportMiddleware = store => next => action => {
  const result = next(action);

  if (action.type.startsWith('LAYER_')) {
    const state = store.getState().keplerGl;
    saveState(state);
  }

  return result;
};

Функция saveState может отправлять данные на сервер или сохранять в localStorage:

const saveState = (state) => {
  localStorage.setItem('keplerState', JSON.stringify(state));
};

Экспорт в внешние форматы данных

В зависимости от целевой системы данные могут экспортироваться в CSV, JSON, Parquet или специализированные геоформаты.

CSV-экспорт:

const toCSV = (data) => {
  const headers = Object.keys(data[0]).join(',');
  const rows = data.map(row =>
    Object.values(row).join(',')
  );
  return [headers, ...rows].join('\n');
};

JSON-экспорт обычно используется для сохранения полной структуры:

const exportJSON = (state) => JSON.stringify(state);

Для серверной аналитики часто используется упрощённая версия:

const minimalExport = (dataset) => ({
  id: dataset.id,
  rows: dataset.data
});

Управление версиями экспортируемых данных

При экспорте важно учитывать совместимость между версиями Kepler.gl. Изменения структуры visState или mapState могут приводить к несовместимости snapshot-файлов.

Для этого добавляется версия:

const versionedExport = (state) => ({
  version: '2.0',
  timestamp: Date.now(),
  state
});

Такая структура позволяет выполнять миграции данных при изменении схемы библиотеки.