OpenLayers использует объектную модель стилей, в которой визуальное
представление точечных объектов определяется через комбинацию классов
ol.style.Style, ol.style.Circle,
ol.style.Fill, ol.style.Stroke, а также
функций динамической стилизации. Такой подход позволяет управлять
отображением геометрий на основе свойств объектов, масштаба карты и
внешних условий.
Точечные объекты векторного слоя отображаются через стиль, связанный
либо с самим слоем, либо с отдельной геометрией. Основной класс,
определяющий внешний вид, — ol.style.Style. Он
инкапсулирует визуальные параметры для различных типов геометрий,
включая точки.
Типичный минимальный стиль точки задаётся через image,
внутри которого используется ol.style.Circle:
import Style from 'ol/style/Style.js';
import CircleStyle from 'ol/style/Circle.js';
import Fill from 'ol/style/Fill.js';
import Stroke from 'ol/style/Stroke.js';
const pointStyle = new Style({
image: new CircleStyle({
radius: 6,
fill: new Fill({
color: 'rgba(30, 144, 255, 0.8)'
}),
stroke: new Stroke({
color: '#1e90ff',
width: 2
})
})
});
Такой стиль определяет точку как круг с заливкой и обводкой. Параметр
radius задаёт размер в пикселях в экранной системе
координат.
ol.style.Circle представляет собой один из наиболее
часто используемых способов рендеринга точечных данных. Его
свойства:
ol.style.Fill)ol.style.Stroke)При этом визуальный результат не зависит от географической системы координат, так как отрисовка выполняется в экранных единицах.
Пример изменения визуальной плотности:
const largePoint = new Style({
image: new CircleStyle({
radius: 12,
fill: new Fill({ color: 'rgba(255, 0, 0, 0.6)' }),
stroke: new Stroke({ color: '#ff0000', width: 3 })
})
});
Fill определяет внутреннюю часть символа точки, тогда
как Stroke управляет границей.
new Fill({
color: 'rgba(0, 200, 0, 0.5)'
})
Поддерживаются форматы:
new Stroke({
color: '#333333',
width: 1.5,
lineCap: 'round',
lineJoin: 'round'
})
Параметры lineCap и lineJoin особенно
заметны при использовании сложных символов или при увеличенных
радиусах.
На практике статические стили применяются редко. Основной механизм
гибкости — функция стиля, возвращающая Style или массив
стилей на основе объекта feature и текущего масштаба.
const dynamicStyle = function(feature, resolution) {
const type = feature.get('type');
if (type === 'city') {
return new Style({
image: new CircleStyle({
radius: 10,
fill: new Fill({ color: 'blue' })
})
});
}
if (type === 'village') {
return new Style({
image: new CircleStyle({
radius: 5,
fill: new Fill({ color: 'green' })
})
});
}
};
Функция принимает:
feature — объект слояresolution — текущее разрешение картыПараметр resolution позволяет изменять визуализацию в
зависимости от уровня масштабирования карты. Чем больше значение
resolution, тем менее детализированная карта.
Пример адаптивного изменения размера точки:
const scaleDependentStyle = function(feature, resolution) {
const baseRadius = 10;
const radius = Math.max(baseRadius / resolution, 2);
return new Style({
image: new CircleStyle({
radius: radius,
fill: new Fill({ color: 'rgba(0, 0, 255, 0.6)' })
})
});
};
Такой подход позволяет сохранять видимость точек на разных уровнях масштаба.
Текст добавляется через свойство text объекта
Style. Он применяется поверх или рядом с точкой.
import Text from 'ol/style/Text.js';
const labeledStyle = new Style({
image: new CircleStyle({
radius: 6,
fill: new Fill({ color: '#ffcc00' })
}),
text: new Text({
text: 'Объект',
offsetY: -15,
fill: new Fill({
color: '#000'
}),
stroke: new Stroke({
color: '#fff',
width: 3
})
})
});
Параметры текста:
font — шрифт CSStext — содержимоеoffsetX, offsetY — смещениеrotation — поворот текстаscale — масштабированиеСтили часто зависят от атрибутов объекта:
const propertyBasedStyle = function(feature) {
const population = feature.get('population');
let radius = 5;
if (population > 1000000) radius = 15;
else if (population > 100000) radius = 10;
return new Style({
image: new CircleStyle({
radius: radius,
fill: new Fill({ color: 'rgba(200, 0, 0, 0.6)' })
})
});
};
Такой подход обеспечивает визуальную иерархию точек.
Feature может возвращать массив стилей, что позволяет накладывать эффекты:
const multiStyle = function(feature) {
return [
new Style({
image: new CircleStyle({
radius: 8,
fill: new Fill({ color: 'blue' })
})
}),
new Style({
image: new CircleStyle({
radius: 14,
stroke: new Stroke({
color: 'rgba(0, 0, 255, 0.3)',
width: 6
})
})
})
];
};
Это используется для создания эффекта свечения или внешнего ореола.
При большом количестве точек критически важно учитывать стоимость вычисления стиля. Основные принципы:
StyleПример кэширования:
const cache = {};
function getStyle(type) {
if (!cache[type]) {
cache[type] = new Style({
image: new CircleStyle({
radius: 6,
fill: new Fill({
color: type === 'A' ? 'red' : 'green'
})
})
});
}
return cache[type];
}
При работе с плотными наборами данных применяется кластеризация. В этом случае стиль определяется не отдельной точкой, а группой объектов.
const clusterStyle = function(feature) {
const size = feature.get('features').length;
return new Style({
image: new CircleStyle({
radius: 10 + size,
fill: new Fill({
color: 'rgba(0, 150, 136, 0.6)'
})
}),
text: new Text({
text: size.toString(),
fill: new Fill({ color: '#fff' })
})
});
};
Размер и текст визуально отражают количество объектов в кластере.
Стили точек часто используют цвет как носитель информации. Семантическое кодирование реализуется через сопоставление значений атрибутов цветам.
function getColor(status) {
switch (status) {
case 'active': return 'green';
case 'inactive': return 'gray';
case 'error': return 'red';
default: return 'blue';
}
}
const statusStyle = function(feature) {
return new Style({
image: new CircleStyle({
radius: 7,
fill: new Fill({
color: getColor(feature.get('status'))
})
})
});
};
Такой подход упрощает визуальную интерпретацию данных.
Хотя точка является базовой геометрией, стиль может имитировать сложные маркеры за счёт комбинации нескольких окружностей и текста. Это позволяет создавать кастомные маркеры без внешних изображений, что повышает производительность и уменьшает зависимость от ресурсов.