I haven't found a solution using styling but I actually also found a workaround earlier (similar to TomazicM's answer):
- create a MultiPoint GeoJSON object using the LineString GeoJSON object
- add to a separate
L.geoJSON
layer
- use the same canvas to render the features
Note: I am going to accept TomazicM's answer. His solution can handle LineStrings and MultiLineStrings, and hides the point if small scale, and I just learnt about L.GeoJSON.coordsToLatLngs
.
Anyways, here is my workaround:
function createVerticesLayer(track, canvas) {
const vertices = {
type: "Feature",
properties: {
},
geometry: {
type: "MultiPoint",
coordinates: track.geometry.coordinates
}
};
const markerOptions = {
radius: 8,
fillColor: "#ff7800",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 0.8,
renderer: canvas,
};
const verticesLayer = L.geoJSON(vertices, {
pointToLayer: (feature, latlng) => {
return L.circleMarker(latlng, markerOptions);
}
});
return verticesLayer;
}
const map = L.map('map').setView([46.519833, 6.6335], 13);
async function initMap() {
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap'
}).addTo(map);
const trackCanvas = L.canvas({
padding: 0.5
});
const response = await fetch(`/tracks/1`);
const tracks = await response.json();
const trackLayer = L.geoJSON(tracks[0], {
style: feature => ({
color: "#000000",
weight: 2,
opacity: 0.7,
renderer: trackCanvas,
})
});
const verticesLayer = createVerticesLayer(tracks[0], trackCanvas);
trackLayer.addTo(map);
verticesLayer.addTo(map);
}
initMap();
Addendum: Since I have quite a few points to show/hide when zoom level is changed, I use a separate canvas and overlay pane which I then show and hide using CSS.
Switching from shown to hidden and vice versa feels faster.
const map = L.map('map').setView([44.608317, -63.471079], 13);
const detailOverlayPane = map.createPane('detailOverlayPane');
function createVerticesLayer(track, canvas) {
// ...
const verticesCanvas = L.canvas({
padding: 0.5,
pane: detailOverlayPane,
});
const markerOptions = {
// ...
renderer: verticesCanvas,
};
// ...
}
async function initMap() {
// ...
updateDetailVisibliy();
}
function updateDetailVisibliy() {
const displayValue = map.getZoom() >= 17 ? 'block' : 'none';
detailOverlayPane.style.display = displayValue;
}
map.on('zoomend', updateDetailVisibliy);
initMap();