-
Notifications
You must be signed in to change notification settings - Fork 202
Add a hook to be notified when point features are added #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>Leaflet Map Panes Example</title> | ||
| <meta charset="utf-8" /> | ||
|
|
||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
|
|
||
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.2/dist/leaflet.css" /> | ||
| <script src="https://unpkg.com/leaflet@1.0.2/dist/leaflet.js"></script> | ||
| <script src="http://localhost:4567/Leaflet.VectorGrid.bundled.js"></script> | ||
| </head> | ||
| <body style='margin:0'> | ||
| <div id="map" style="width: 100vw; height: 100vh"></div> | ||
|
|
||
| <script> | ||
|
|
||
| var map = L.map('map'); | ||
|
|
||
| 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: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="https://www.mapbox.com/about/maps/">MapBox</a>', | ||
| 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); | ||
| } | ||
| } | ||
| }, | ||
| vectorTileLayerStyles: { | ||
|
|
||
| water: { | ||
| weight: 0, | ||
| fillColor: '#9bc2c4', | ||
| fillOpacity: 1, | ||
| fill: true, | ||
| stroke: false | ||
| }, | ||
|
|
||
| admin: [], | ||
| state_label: [], | ||
| country_label: [], | ||
| marine_label: [], | ||
| state_label: [], | ||
| place_label: function(properties) { | ||
| if(properties.localrank > 60) { | ||
| return {}; | ||
| } else { | ||
| return []; | ||
| } | ||
| }, | ||
| waterway_label: [], | ||
| landuse: [], | ||
| landuse_overlay: [], | ||
| road: [], | ||
| poi_label: [], | ||
| waterway: [], | ||
| aeroway: [], | ||
| tunnel: [], | ||
| bridge: [], | ||
| barrier_line: [], | ||
| building: [], | ||
| road_label: [], | ||
| housenum_label: [], | ||
|
|
||
| } | ||
| }; | ||
|
|
||
| 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); | ||
|
|
||
|
|
||
| </script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you see any particular reason this should only be done for points? IMHO, adding this functionality for any feature would be more powerful and avoid cluttering the API with type specific hooks. If added as
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Features other than points can be split into multiple tiles no ? So the callback will be called multiple times for the same actual object on the map right ? It seemed to me that it would not be easy to manage for the user. Points are straightforward. Butl I agree, I would love to make it more generic. It did not feel right to pass the created layer or the vt feature as they are not standard objects and their geometries are relative to the tile they are in. I did not want to let the user make the calculations to transform coords in the tiles into coords in the map. Also if the user chooses to configure empty style on a vt layer and create a marker manually instead of letting VectorGrid render a pseudo marker, then there is no layer to be created, rendered and sent back to the user by VectorGrid. |
||
| 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); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer this to be
oneachfeature, to align better withL.GeoJSON- it's essentially the same functionality.Also, I'd prefer to keep it simple and allow one hook - again, keep things similar to existing API to avoid surprises.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few reasons why I did it this way: