Skip to content

Commit 5d4b462

Browse files
authored
Merge pull request #4 from geoblink/create-labels
Create labels & Add onEachFeature
2 parents 75da157 + 7fe5187 commit 5d4b462

3 files changed

Lines changed: 158 additions & 27 deletions

File tree

docs/demo-labels.html

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Leaflet Map Panes Example</title>
5+
<meta charset="utf-8" />
6+
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8+
9+
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.2/dist/leaflet.css" />
10+
<script src="https://unpkg.com/leaflet@1.0.2/dist/leaflet.js"></script>
11+
<script src="http://localhost:4567/Leaflet.VectorGrid.bundled.js"></script>
12+
</head>
13+
<body style='margin:0'>
14+
<div id="map" style="width: 100vw; height: 100vh"></div>
15+
16+
<script>
17+
18+
var map = L.map('map');
19+
20+
var url = 'https://{s}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw';
21+
22+
var vectorTileOptions = {
23+
rendererFactory: L.canvas.tile,
24+
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="https://www.mapbox.com/about/maps/">MapBox</a>',
25+
onEachFeature: (function () {
26+
var seen = {};
27+
return function (feature, featureLayer, vtLayer, tileCoords) {
28+
var id = feature.id;
29+
if (!seen[id]) {
30+
if (vtLayer.name === 'place_label' && feature.properties.localrank > 60) {
31+
var latlng = this.vtGeometryToLatLng(feature.geometry[0], vtLayer, tileCoords)
32+
marker = new L.CircleMarker(latlng, {stroke: false, fill: false});
33+
marker.bindTooltip(feature.properties.name, {permanent: true}).openTooltip();
34+
this.addUserLayer(marker, tileCoords);
35+
}
36+
seen[id] = true;
37+
}
38+
}
39+
}()),
40+
vectorTileLayerStyles: {
41+
42+
water: {
43+
weight: 0,
44+
fillColor: '#9bc2c4',
45+
fillOpacity: 1,
46+
fill: true,
47+
stroke: false
48+
},
49+
50+
admin: [],
51+
state_label: [],
52+
country_label: [],
53+
marine_label: [],
54+
state_label: [],
55+
place_label: function(properties) {
56+
if(properties.localrank > 60) {
57+
return {};
58+
} else {
59+
return [];
60+
}
61+
},
62+
waterway_label: [],
63+
landuse: [],
64+
landuse_overlay: [],
65+
road: [],
66+
poi_label: [],
67+
waterway: [],
68+
aeroway: [],
69+
tunnel: [],
70+
bridge: [],
71+
barrier_line: [],
72+
building: [],
73+
road_label: [],
74+
housenum_label: [],
75+
76+
}
77+
};
78+
79+
var pbfLayer = L.vectorGrid.protobuf(url, vectorTileOptions).addTo(map);
80+
81+
map.setView({ lat: 47.040182144806664, lng: 9.667968750000002 }, 6);
82+
83+
84+
</script>
85+
</body>
86+
</html>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@geoblink/leaflet.vectorgrid",
3-
"version": "1.4.1",
3+
"version": "1.5.0",
44
"description": "Display gridded vector data (sliced GeoJSON or protobuf vector tiles) in Leaflet 1.0",
55
"main": "dist/Leaflet.VectorGrid.bundled.min.js",
66
"scripts": {

src/Leaflet.VectorGrid.js

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ L.VectorGrid = L.GridLayer.extend({
2525
// A data structure holding initial symbolizer definitions for the vector features.
2626
vectorTileLayerStyles: {},
2727

28+
// Function that will execute per feature
29+
onEachFeature: null,
30+
2831
// 🍂option interactive: Boolean = false
2932
// Whether this `VectorGrid` fires `Interactive Layer` events.
3033
interactive: false,
@@ -41,27 +44,22 @@ L.VectorGrid = L.GridLayer.extend({
4144
if (this.options.getFeatureId) {
4245
this._vectorTiles = {};
4346
this._overriddenStyles = {};
44-
this.on('tileunload', function(e) {
45-
var key = this._tileCoordsToKey(e.coords),
46-
tile = this._vectorTiles[key];
47-
48-
if (tile && this._map) {
49-
tile.removeFrom(this._map);
50-
}
51-
delete this._vectorTiles[key];
52-
}, this);
5347
}
5448
this._dataLayerNames = {};
49+
this._userLayers = {};
50+
this.on('tileunload', function(e) {
51+
this._tileUnload(e);
52+
}, this);
5553
},
5654

5755
createTile: function(coords, done) {
58-
5956
var storeFeatures = this.options.getFeatureId;
57+
var onEachFeature = this.options.onEachFeature;
6058

6159
var tileSize = this.getTileSize();
6260
var renderer = this.options.rendererFactory(coords, tileSize, this.options);
6361

64-
var tileBounds = this._tileCoordsToBounds(coords);
62+
var tileBounds = this._tileCoordsToBounds(coords);
6563

6664
var vectorTilePromise = this._getVectorTilePromise(coords, tileBounds);
6765

@@ -77,16 +75,16 @@ L.VectorGrid = L.GridLayer.extend({
7775
for (var layerName in vectorTile.layers) {
7876
this._dataLayerNames[layerName] = true;
7977
var layer = vectorTile.layers[layerName];
80-
78+
8179
var pxPerExtent = this.getTileSize().divideBy(layer.extent);
82-
80+
8381
var layerStyle = this.options.vectorTileLayerStyles[ layerName ] ||
8482
L.Path.prototype.options;
85-
83+
8684
for (var i = 0; i < layer.features.length; i++) {
8785
var feat = layer.features[i];
8886
var id;
89-
87+
9088
var styleOptions = layerStyle;
9189
if (storeFeatures) {
9290
id = this.options.getFeatureId(feat);
@@ -99,47 +97,53 @@ L.VectorGrid = L.GridLayer.extend({
9997
}
10098
}
10199
}
102-
100+
103101
if (styleOptions instanceof Function) {
104102
styleOptions = styleOptions(feat.properties, coords.z);
105103
}
106-
104+
107105
if (!(styleOptions instanceof Array)) {
108106
styleOptions = [styleOptions];
109107
}
110-
108+
111109
if (!styleOptions.length) {
110+
if (onEachFeature) {
111+
onEachFeature.call(this, feat, null, layer, coords);
112+
}
112113
continue;
113114
}
114-
115+
115116
var featureLayer = this._createLayer(feat, pxPerExtent);
116-
117+
if (onEachFeature) {
118+
onEachFeature.call(this, feat, null, layer, coords);
119+
}
120+
117121
for (var j = 0; j < styleOptions.length; j++) {
118122
var style = L.extend({}, L.Path.prototype.options, styleOptions[j]);
119123
featureLayer.render(renderer, style);
120124
renderer._addPath(featureLayer);
121125
}
122-
126+
123127
if (this.options.interactive) {
124128
featureLayer.makeInteractive();
125129
}
126-
130+
127131
if (storeFeatures) {
128132
renderer._features[id] = {
129133
layerName: layerName,
130134
feature: featureLayer
131135
};
132136
}
133137
}
134-
138+
135139
}
136-
140+
137141
}
138-
142+
139143
if (this._map != null) {
140144
renderer.addTo(this._map);
141145
}
142-
146+
143147
L.Util.requestAnimFrame(done.bind(coords, null, null));
144148

145149
}.bind(this), function (err) {
@@ -205,6 +209,47 @@ L.VectorGrid = L.GridLayer.extend({
205209
return Object.keys(this._dataLayerNames);
206210
},
207211

212+
vtGeometryToPoint: function(geometry, vtLayer, tileCoords) {
213+
var pxPerExtent = this.getTileSize().x / vtLayer.extent;
214+
var tileSize = this.getTileSize();
215+
var offset = tileCoords.scaleBy(tileSize);
216+
var point;
217+
if (typeof geometry[0] === 'object' && 'x' in geometry[0]) {
218+
// Protobuf vector tiles return [{x: , y:}]
219+
point = L.point(offset.x + (geometry[0].x * pxPerExtent), offset.y + (geometry[0].y * pxPerExtent));
220+
} else {
221+
// Geojson-vt returns [,]
222+
point = L.point(offset.x + (geometry[0] * pxPerExtent), offset.y + (geometry[1] * pxPerExtent));
223+
}
224+
return point;
225+
},
226+
227+
vtGeometryToLatLng: function(geometry, vtLayer, tileCoords) {
228+
return this._map.unproject(this.vtGeometryToPoint(geometry, vtLayer, tileCoords), tileCoords.z);
229+
},
230+
231+
addUserLayer: function(userLayer, tileCoords) {
232+
var tileKey = this._tileCoordsToKey(tileCoords);
233+
this._userLayers[tileKey] = this._userLayers[tileKey] || [];
234+
this._userLayers[tileKey].push(userLayer);
235+
this._map.addLayer(userLayer);
236+
},
237+
238+
_tileUnload: function(e) {
239+
var tileKey = this._tileCoordsToKey(e.coords);
240+
if (this._vectorTiles) {
241+
delete this._vectorTiles[tileKey];
242+
}
243+
var userLayers = this._userLayers[tileKey];
244+
if (!userLayers) {
245+
return;
246+
}
247+
for(var i = 0; i < userLayers.length; i++) {
248+
this._map.removeLayer(userLayers[i]);
249+
}
250+
delete this._userLayers[tileKey];
251+
},
252+
208253
_updateStyles: function(feat, renderer, styleOptions) {
209254
styleOptions = (styleOptions instanceof Function) ?
210255
styleOptions(feat.properties, renderer.getCoord().z) :

0 commit comments

Comments
 (0)