Leaflet предоставляет механизм преобразования GeoJSON-геометрий в
визуальные слои карты через L.geoJSON. Одним из ключевых
расширений поведения при рендеринге точечных объектов является параметр
pointToLayer, определяющий способ создания слоя для каждого
Point-объекта.
Параметр pointToLayer используется для переопределения
стандартного поведения, при котором точечные GeoJSON-объекты
автоматически превращаются в L.marker.
Основная функция:
L.marker на
L.circleMarker, L.divIcon или пользовательский
слойpointToLayer: function (feature, latlng) {
return L.marker(latlng);
}
GeoJSON-объект текущего элемента слоя.
Содержит:
feature.type — тип геометрииfeature.properties — пользовательские данныеfeature.geometry — координаты и тип GeoJSONКлючевая роль — предоставление контекста для стилизации слоя.
Объект координат L.LatLng, полученный из GeoJSON
координат.
Используется для создания любых типов маркеров или слоёв, привязанных к точке.
Функция должна возвращать экземпляр слоя Leaflet:
L.MarkerL.CircleMarkerL.CircleL.DivIcon (через L.marker)L.LayerВозвращённый объект автоматически добавляется в слой
L.geoJSON.
Без pointToLayer точечные объекты обрабатываются
так:
L.geoJSON(data)
эквивалентно:
L.geoJSON(data, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng);
}
});
Таким образом, каждый Point становится стандартным
маркером.
L.geoJSON(geojsonData, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng);
}
}).addTo(map);
Такой вариант фактически не изменяет поведение, но фиксирует явную точку расширения.
Одним из наиболее распространённых сценариев является замена маркеров
на L.circleMarker для визуализации количественных
данных.
L.geoJSON(geojsonData, {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, {
radius: 6,
fillColor: "#3388ff",
color: "#1f5eff",
weight: 1,
opacity: 1,
fillOpacity: 0.8
});
}
}).addTo(map);
Преимущества такого подхода:
pointToLayer часто используется для условного оформления
точек на основе данных.
L.geoJSON(geojsonData, {
pointToLayer: function (feature, latlng) {
const value = feature.properties.value;
let color = "#2ecc71";
if (value > 100) color = "#e74c3c";
else if (value > 50) color = "#f1c40f";
return L.circleMarker(latlng, {
radius: 5 + value / 20,
color: color,
fillColor: color,
fillOpacity: 0.7,
weight: 1
});
}
}).addTo(map);
Используется:
const customIcon = L.icon({
iconUrl: 'icon.png',
iconSize: [24, 24],
iconAnchor: [12, 12]
});
L.geoJSON(geojsonData, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {
icon: customIcon
});
}
}).addTo(map);
Подход применяется при необходимости:
HTML-маркеры позволяют создавать сложные визуальные элементы.
L.geoJSON(geojsonData, {
pointToLayer: function (feature, latlng) {
const html = `
<div class="custom-pin">
${feature.properties.name}
</div>
`;
return L.marker(latlng, {
icon: L.divIcon({
html: html,
className: "custom-div-icon"
})
});
}
}).addTo(map);
Особенности:
circleMarkerЧастая ошибка — смешение pointToLayer и
style.
| Параметр | Применение |
|---|---|
style |
LineString и Polygon |
pointToLayer |
Point |
style не влияет на точки, тогда как
pointToLayer полностью определяет их отображение.
pointToLayer часто работает совместно с
filter:
L.geoJSON(geojsonData, {
filter: function (feature) {
return feature.properties.active === true;
},
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, {
radius: 4,
color: "#3498db"
});
}
}).addTo(map);
Фильтрация определяет набор данных, pointToLayer —
способ отображения.
При тысячах объектов выбор слоя критичен.
Рекомендуемые подходы:
L.circleMarker вместо L.markerDivIconpointToLayerПреимущество circleMarker:
Созданные слои можно сразу обогащать событиями:
L.geoJSON(geojsonData, {
pointToLayer: function (feature, latlng) {
const marker = L.circleMarker(latlng, {
radius: 6,
color: "#2c3e50"
});
marker.on("click", function () {
console.log(feature.properties.id);
});
return marker;
}
}).addTo(map);
Используется для:
Хотя pointToLayer не имеет прямого доступа к zoom,
логика может быть вынесена наружу:
function createLayer(feature, latlng, zoom) {
if (zoom > 10) {
return L.marker(latlng);
}
return L.circleMarker(latlng, { radius: 4 });
}
И затем:
L.geoJSON(data, {
pointToLayer: function (feature, latlng) {
return createLayer(feature, latlng, map.getZoom());
}
});
undefined вместо слояstyle для точек вместо
pointToLayerfunction layerFactory(feature) {
if (feature.properties.type === "city") {
return L.circleMarker;
}
return L.marker;
}
const geojsonOptions = {
pointToLayer: (feature, latlng) =>
L.circleMarker(latlng, config.style[feature.properties.category])
};
pointToLayer является точкой расширения между:
Именно на этом уровне происходит: