Стилизация объектов Data Layer

Роль Data Layer в архитектуре карты

Data Layer представляет собой слой отображения и управления геопространственными данными, построенный поверх базовой карты. Он оперирует объектами GeoJSON и внутренними геометрическими сущностями API, предоставляя механизм связывания данных и визуального представления.

Каждый объект Data Layer включает:

  • геометрию (Point, LineString, Polygon, MultiGeometry)
  • набор свойств (properties)
  • идентификатор feature
  • состояние отображения

Стилизация Data Layer отделяет данные от визуального представления, позволяя динамически изменять внешний вид объектов без модификации исходного GeoJSON.


Базовый механизм стилизации через setStyle

Основной инструмент управления внешним видом объектов Data Layer — метод setStyle. Он принимает либо объект стиля, либо функцию, возвращающую стиль для каждого feature.

Фиксированный стиль применяется ко всем объектам слоя:

map.data.setStyle({
  fillColor: "#2E86DE",
  fillOpacity: 0.5,
  strokeColor: "#1B4F72",
  strokeWeight: 2,
  clickable: true
});

Поддерживаемые параметры стиля включают:

  • fillColor — цвет заливки полигонов
  • fillOpacity — прозрачность заливки
  • strokeColor — цвет границы
  • strokeOpacity — прозрачность линии
  • strokeWeight — толщина линии
  • icon — иконка для точечных объектов
  • zIndex — порядок наложения
  • visible — отображение объекта
  • clickable — интерактивность

Функциональная стилизация на основе feature

Функция стилизации позволяет задавать внешний вид в зависимости от свойств объекта:

map.data.setStyle((feature) => {
  const type = feature.getProperty("type");

  if (type === "park") {
    return {
      fillColor: "#27AE60",
      strokeColor: "#145A32",
      fillOpacity: 0.6
    };
  }

  if (type === "water") {
    return {
      fillColor: "#3498DB",
      strokeColor: "#21618C",
      fillOpacity: 0.4
    };
  }

  return {
    fillColor: "#BDC3C7",
    strokeColor: "#7F8C8D"
  };
});

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


Использование свойств feature для стилизации

GeoJSON-объекты, загружаемые в Data Layer, могут содержать произвольные свойства:

map.data.addGeoJson({
  type: "Feature",
  geometry: {
    type: "Polygon",
    coordinates: [...]
  },
  properties: {
    population: 120000,
    region: "north"
  }
});

Стилизация на основе числовых диапазонов:

map.data.setStyle((feature) => {
  const population = feature.getProperty("population");

  return {
    fillColor: population > 100000 ? "#E74C3C" : "#F1C40F",
    fillOpacity: 0.5,
    strokeWeight: 1
  };
});

Применение порогов и категорий позволяет формировать хлороплетные карты и аналитические визуализации.


Динамическая стилизация через события

Data Layer поддерживает события взаимодействия с объектами, что позволяет изменять стиль в реальном времени.

map.data.addListener("mouseover", (event) => {
  map.data.overrideStyle(event.feature, {
    fillColor: "#8E44AD",
    strokeWeight: 3
  });
});

map.data.addListener("mouseout", (event) => {
  map.data.revertStyle(event.feature);
});

Методы:

  • overrideStyle(feature, style) — временное переопределение
  • revertStyle(feature) — возврат к базовому стилю

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


Приоритеты стилей и иерархия применения

Стили Data Layer применяются в следующем порядке:

  1. Базовый стиль, заданный через setStyle
  2. Функциональный стиль (если setStyle принимает функцию)
  3. Локальный override через overrideStyle
  4. Встроенные состояния взаимодействия (hover, click)

Override всегда имеет наивысший приоритет до момента сброса.


Стилизация точечных объектов (Point features)

Для точечных объектов используется параметр icon, который поддерживает как растровые иконки, так и SVG-описания:

map.data.setStyle((feature) => {
  const category = feature.getProperty("category");

  return {
    icon: {
      url: category === "restaurant"
        ? "/icons/restaurant.png"
        : "/icons/default.png",
      scaledSize: new google.maps.Size(24, 24)
    }
  };
});

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

icon: {
  path: google.maps.SymbolPath.CIRCLE,
  scale: 6,
  fillColor: "#2C3E50",
  fillOpacity: 1,
  strokeWeight: 1
}

Стилевые функции и производительность

Функция стиля вызывается для каждого feature при рендеринге. При большом объёме данных критично избегать:

  • сложных вычислений внутри функции
  • обращения к DOM
  • синхронных сетевых запросов

Оптимизированный подход — предварительная индексация свойств:

const styleCache = {
  high: { fillColor: "#E74C3C" },
  medium: { fillColor: "#F39C12" },
  low: { fillColor: "#2ECC71" }
};

map.data.setStyle((feature) => {
  return styleCache[feature.getProperty("level")] || {};
});

Условная прозрачность и визуальная иерархия

Использование прозрачности позволяет формировать многослойную визуализацию:

map.data.setStyle((feature) => {
  const importance = feature.getProperty("importance");

  return {
    fillOpacity: importance === "high" ? 0.7 : 0.2,
    strokeOpacity: importance === "high" ? 1 : 0.3
  };
});

Такой подход используется для выделения ключевых зон без скрытия контекста карты.


Стилизация линий и маршрутов

LineString-объекты требуют настройки strokeWeight, strokeColor и strokeOpacity.

map.data.setStyle((feature) => {
  const routeType = feature.getProperty("route");

  return {
    strokeColor: routeType === "main" ? "#C0392B" : "#7F8C8D",
    strokeWeight: routeType === "main" ? 4 : 2,
    strokeOpacity: 0.9
  };
});

Дополнительный эффект достигается использованием пунктирных линий через icons в полилиниях.


Стилизация на основе масштаба карты

Хотя Data Layer не предоставляет прямого события масштаба в стиле, изменение стилей возможно через слушатель zoom_changed:

map.addListener("zoom_changed", () => {
  const zoom = map.getZoom();

  map.data.setStyle({
    strokeWeight: zoom > 10 ? 3 : 1,
    fillOpacity: zoom > 12 ? 0.6 : 0.3
  });
});

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


Комбинирование категориальной и числовой логики

Сложные визуализации часто объединяют несколько факторов:

map.data.setStyle((feature) => {
  const type = feature.getProperty("type");
  const value = feature.getProperty("value");

  let baseColor = "#95A5A6";

  if (type === "urban") baseColor = "#2980B9";
  if (type === "rural") baseColor = "#27AE60";

  return {
    fillColor: baseColor,
    fillOpacity: value > 50 ? 0.7 : 0.3,
    strokeWeight: value > 50 ? 2 : 1
  };
});

Управление видимостью объектов

Свойство visible позволяет исключать объекты из рендеринга без удаления из слоя:

map.data.setStyle((feature) => {
  const active = feature.getProperty("active");

  return {
    visible: active === true
  };
});

Этот механизм используется для фильтрации данных на клиенте.


Сброс и переопределение стилей

Полный сброс стилизации возвращает Data Layer к базовому состоянию:

map.data.setStyle(null);

При этом все override-стили также очищаются:

map.data.revertStyle();

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

При проектировании сложных картовых систем стилизация Data Layer обычно выносится в отдельный модуль:

  • таблицы соответствия свойств и цветов
  • функции маппинга доменных категорий
  • кэширование вычисленных стилей
  • разделение логики взаимодействия и визуализации

Такой подход снижает связность и упрощает поддержку больших GeoJSON-наборов, где количество features измеряется тысячами или десятками тысяч объектов.