From 211c5a707e8ffd10f06800341ce3cb3e2b82299d Mon Sep 17 00:00:00 2001 From: Alban Mouton Date: Wed, 1 Feb 2017 22:03:58 +0100 Subject: [PATCH 1/3] Add a hook to be notified when point features are added --- demo/demo-labels.html | 107 ++++++++++++++++++++++++++++++++++++++ src/Leaflet.VectorGrid.js | 18 +++++++ 2 files changed, 125 insertions(+) create mode 100644 demo/demo-labels.html diff --git a/demo/demo-labels.html b/demo/demo-labels.html new file mode 100644 index 0000000..1c1cf15 --- /dev/null +++ b/demo/demo-labels.html @@ -0,0 +1,107 @@ + + + + Leaflet Map Panes Example + + + + + + + + + +
+ + + + diff --git a/src/Leaflet.VectorGrid.js b/src/Leaflet.VectorGrid.js index c950c9b..0955126 100644 --- a/src/Leaflet.VectorGrid.js +++ b/src/Leaflet.VectorGrid.js @@ -5,6 +5,7 @@ L.VectorGrid = L.GridLayer.extend({ options: { rendererFactory: L.svg.tile, vectorTileLayerStyles: {}, + pointFeatureHooks: [], interactive: false }, @@ -43,6 +44,8 @@ L.VectorGrid = L.GridLayer.extend({ var layerStyle = this.options.vectorTileLayerStyles[ layerName ] || L.Path.prototype.options; + const pointFeatureHook = this.options.pointFeatureHooks[ layerName ] + for (var i in layer.features) { var feat = layer.features[i]; var id; @@ -60,6 +63,21 @@ L.VectorGrid = L.GridLayer.extend({ } } + // The user asked to be notified if point type features added to the current vt layer + if (pointFeatureHook && feat.type === 1) { + var pointCoord = feat.geometry[0]; + var offset = coords.scaleBy(tileSize); + var point; + if (typeof pointCoord[0] === 'object' && 'x' in pointCoord[0]) { + // Protobuf vector tiles return [{x: , y:}] + point = L.point(offset.x + (pointCoord[0].x * pxPerExtent), offset.y + (pointCoord[0].y * pxPerExtent)); + } else { + // Geojson-vt returns [,] + point = L.point(offset.x + (pointCoord[0] * pxPerExtent), offset.y + (pointCoord[1] * pxPerExtent)); + } + var userDefinedLayer = pointFeatureHook(feat.properties, coords, point) + } + if (styleOptions instanceof Function) { styleOptions = styleOptions(feat.properties, coords.z); } From c7314865309338a43260d3cd9e2995e280d5bdc1 Mon Sep 17 00:00:00 2001 From: Alban Mouton Date: Thu, 2 Feb 2017 12:27:43 +0100 Subject: [PATCH 2/3] work on onEachFeature hook --- demo/demo-labels.html | 15 ++++++------- src/Leaflet.VectorGrid.js | 46 ++++++++++++++++++++++++--------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/demo/demo-labels.html b/demo/demo-labels.html index 1c1cf15..7daf0a5 100644 --- a/demo/demo-labels.html +++ b/demo/demo-labels.html @@ -45,14 +45,13 @@ var vectorTileOptions = { rendererFactory: L.canvas.tile, attribution: '© OpenStreetMap contributors, © MapBox', - pointFeatureHooks: { - place_label: function(properties, tileCoords, point) { - if(properties.localrank > 60) { - marker = new L.Marker(map.unproject(point)); - marker.bindTooltip(properties.name).openTooltip(); - map.addLayer(marker); - setMarkerToCache(tileCoords, marker); - } + onEachFeature: function(feature, featureLayer, vtLayer, tileCoords) { + if(vtLayer.name === 'place_label' && feature.properties.localrank > 60) { + var latlng = this.vtGeometryToLatLng(feature.geometry[0], vtLayer, tileCoords) + marker = new L.Marker(latlng); + marker.bindTooltip(feature.properties.name).openTooltip(); + map.addLayer(marker); + setMarkerToCache(tileCoords, marker); } }, vectorTileLayerStyles: { diff --git a/src/Leaflet.VectorGrid.js b/src/Leaflet.VectorGrid.js index 0955126..6608aed 100644 --- a/src/Leaflet.VectorGrid.js +++ b/src/Leaflet.VectorGrid.js @@ -5,7 +5,7 @@ L.VectorGrid = L.GridLayer.extend({ options: { rendererFactory: L.svg.tile, vectorTileLayerStyles: {}, - pointFeatureHooks: [], + onEachFeature: null, interactive: false }, @@ -23,6 +23,7 @@ L.VectorGrid = L.GridLayer.extend({ createTile: function(coords, done) { var storeFeatures = this.options.getFeatureId; + var onEachFeature = this.options.onEachFeature; var tileSize = this.getTileSize(); var renderer = this.options.rendererFactory(coords, tileSize, this.options); @@ -44,8 +45,6 @@ L.VectorGrid = L.GridLayer.extend({ var layerStyle = this.options.vectorTileLayerStyles[ layerName ] || L.Path.prototype.options; - const pointFeatureHook = this.options.pointFeatureHooks[ layerName ] - for (var i in layer.features) { var feat = layer.features[i]; var id; @@ -63,21 +62,6 @@ L.VectorGrid = L.GridLayer.extend({ } } - // The user asked to be notified if point type features added to the current vt layer - if (pointFeatureHook && feat.type === 1) { - var pointCoord = feat.geometry[0]; - var offset = coords.scaleBy(tileSize); - var point; - if (typeof pointCoord[0] === 'object' && 'x' in pointCoord[0]) { - // Protobuf vector tiles return [{x: , y:}] - point = L.point(offset.x + (pointCoord[0].x * pxPerExtent), offset.y + (pointCoord[0].y * pxPerExtent)); - } else { - // Geojson-vt returns [,] - point = L.point(offset.x + (pointCoord[0] * pxPerExtent), offset.y + (pointCoord[1] * pxPerExtent)); - } - var userDefinedLayer = pointFeatureHook(feat.properties, coords, point) - } - if (styleOptions instanceof Function) { styleOptions = styleOptions(feat.properties, coords.z); } @@ -87,11 +71,18 @@ L.VectorGrid = L.GridLayer.extend({ } if (!styleOptions.length) { + if (onEachFeature) { + onEachFeature.call(this, feat, null, layer, coords); + } continue; } var featureLayer = this._createLayer(feat, pxPerExtent); + if (onEachFeature) { + onEachFeature.call(this, feat, null, layer, coords); + } + for (var j in styleOptions) { var style = L.extend({}, L.Path.prototype.options, styleOptions[j]); featureLayer.render(renderer, style); @@ -166,6 +157,25 @@ L.VectorGrid = L.GridLayer.extend({ } }, + vtGeometryToPoint: function(geometry, vtLayer, tileCoords) { + var pxPerExtent = this.getTileSize().x / vtLayer.extent; + var tileSize = this.getTileSize(); + var offset = tileCoords.scaleBy(tileSize); + var point; + if (typeof geometry[0] === 'object' && 'x' in geometry[0]) { + // Protobuf vector tiles return [{x: , y:}] + point = L.point(offset.x + (geometry[0].x * pxPerExtent), offset.y + (geometry[0].y * pxPerExtent)); + } else { + // Geojson-vt returns [,] + point = L.point(offset.x + (geometry[0] * pxPerExtent), offset.y + (geometry[1] * pxPerExtent)); + } + return point; + }, + + vtGeometryToLatLng: function(geometry, vtLayer, tileCoords) { + return this._map.unproject(this.vtGeometryToPoint(geometry, vtLayer, tileCoords)); + }, + _updateStyles: function(feat, renderer, styleOptions) { if (!(styleOptions instanceof Array)) { styleOptions = [styleOptions]; From 23c9c308e598d6ec76ee16b6ca6333988ff449b3 Mon Sep 17 00:00:00 2001 From: Alban Mouton Date: Thu, 2 Feb 2017 12:41:45 +0100 Subject: [PATCH 3/3] keep a cache of leaflet layers added by the user on top of the tiles --- demo/demo-labels.html | 29 +---------------------------- src/Leaflet.VectorGrid.js | 30 +++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/demo/demo-labels.html b/demo/demo-labels.html index 7daf0a5..b4cbac6 100644 --- a/demo/demo-labels.html +++ b/demo/demo-labels.html @@ -19,29 +19,6 @@ var url = 'https://{s}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw'; - // Keep references of the markers created on a tile so that they can be - // removed when the tile is unloaded - function tileCoordsToKey(coords) { - return coords.x + ':' + coords.y + ':' + coords.z; - } - var markersCache = {} - function setMarkerToCache(tileCoords, marker) { - var tileKey = tileCoordsToKey(tileCoords); - markersCache[tileKey] = markersCache[tileKey] || []; - markersCache[tileKey].push(marker); - } - function clearTileMarkers(tileCoords) { - var tileKey = tileCoordsToKey(tileCoords); - var markers = markersCache[tileKey] - if (!markers) { - return; - } - for(var i = 0; i < markers.length; i++) { - map.removeLayer(markers[i]); - } - delete markersCache[tileKey]; - } - var vectorTileOptions = { rendererFactory: L.canvas.tile, attribution: '© OpenStreetMap contributors, © MapBox', @@ -50,8 +27,7 @@ var latlng = this.vtGeometryToLatLng(feature.geometry[0], vtLayer, tileCoords) marker = new L.Marker(latlng); marker.bindTooltip(feature.properties.name).openTooltip(); - map.addLayer(marker); - setMarkerToCache(tileCoords, marker); + this.addUserLayer(marker, tileCoords); } }, vectorTileLayerStyles: { @@ -94,9 +70,6 @@ }; var pbfLayer = L.vectorGrid.protobuf(url, vectorTileOptions).addTo(map); - pbfLayer.on('tileunload', function(e) { - clearTileMarkers(e.coords); - }) map.setView({ lat: 47.040182144806664, lng: 9.667968750000002 }, 6); diff --git a/src/Leaflet.VectorGrid.js b/src/Leaflet.VectorGrid.js index 6608aed..208cfb1 100644 --- a/src/Leaflet.VectorGrid.js +++ b/src/Leaflet.VectorGrid.js @@ -15,10 +15,11 @@ L.VectorGrid = L.GridLayer.extend({ if (this.options.getFeatureId) { this._vectorTiles = {}; this._overriddenStyles = {}; - this.on('tileunload', function(e) { - delete this._vectorTiles[this._tileCoordsToKey(e.coords)]; - }, this); } + this._userLayers = {}; + this.on('tileunload', function(e) { + this._tileUnload(e); + }, this); }, createTile: function(coords, done) { @@ -176,6 +177,29 @@ L.VectorGrid = L.GridLayer.extend({ return this._map.unproject(this.vtGeometryToPoint(geometry, vtLayer, tileCoords)); }, + addUserLayer: function(userLayer, tileCoords) { + var tileKey = this._tileCoordsToKey(tileCoords); + this._userLayers[tileKey] = this._userLayers[tileKey] || []; + this._userLayers[tileKey].push(userLayer); + this._map.addLayer(userLayer); + }, + + _tileUnload: function(e) { + var tileKey = this._tileCoordsToKey(e.coords); + if (this._vectorTiles) { + delete this._vectorTiles[tileKey]; + } + var userLayers = this._userLayers[tileKey]; + if (!userLayers) { + return; + } + for(var i = 0; i < userLayers.length; i++) { + console.log('remove layer'); + this._map.removeLayer(userLayers[i]); + } + delete this._userLayers[tileKey]; + }, + _updateStyles: function(feat, renderer, styleOptions) { if (!(styleOptions instanceof Array)) { styleOptions = [styleOptions];