Leaflet/src/layer/GeoJSON.js

287 lines
7.0 KiB
JavaScript
Raw Normal View History

/*
* L.GeoJSON turns any GeoJSON data into a Leaflet layer.
*/
L.GeoJSON = L.FeatureGroup.extend({
2011-12-09 22:51:31 +08:00
initialize: function (geojson, options) {
L.setOptions(this, options);
2012-02-15 19:17:25 +08:00
2011-06-10 19:26:16 +08:00
this._layers = {};
2011-12-08 23:53:17 +08:00
2011-06-10 19:26:16 +08:00
if (geojson) {
this.addData(geojson);
2011-06-10 19:26:16 +08:00
}
},
2011-12-08 23:53:17 +08:00
addData: function (geojson) {
2013-01-21 08:13:43 +08:00
var features = L.Util.isArray(geojson) ? geojson : geojson.features,
i, len, feature;
2012-02-15 19:17:25 +08:00
if (features) {
for (i = 0, len = features.length; i < len; i++) {
// Only add this if geometry or geometries are set and not null
feature = features[i];
if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
this.addData(features[i]);
}
2011-06-10 19:26:16 +08:00
}
return this;
2011-06-10 19:26:16 +08:00
}
2011-12-08 23:53:17 +08:00
var options = this.options;
2011-12-08 23:53:17 +08:00
if (options.filter && !options.filter(geojson)) { return; }
2011-12-08 23:53:17 +08:00
var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng, options);
layer.feature = L.GeoJSON.asFeature(geojson);
layer.defaultOptions = layer.options;
this.resetStyle(layer);
if (options.onEachFeature) {
options.onEachFeature(geojson, layer);
}
return this.addLayer(layer);
},
resetStyle: function (layer) {
var style = this.options.style;
if (style) {
// reset any custom styles
L.Util.extend(layer.options, layer.defaultOptions);
this._setLayerStyle(layer, style);
}
},
setStyle: function (style) {
this.eachLayer(function (layer) {
this._setLayerStyle(layer, style);
}, this);
},
_setLayerStyle: function (layer, style) {
if (typeof style === 'function') {
style = style(layer.feature);
}
if (layer.setStyle) {
layer.setStyle(style);
}
2011-06-10 19:26:16 +08:00
}
});
L.extend(L.GeoJSON, {
geometryToLayer: function (geojson, pointToLayer, coordsToLatLng, vectorOptions) {
var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
coords = geometry.coordinates,
layers = [],
latlng, latlngs, i, len;
2011-06-10 19:26:16 +08:00
coordsToLatLng = coordsToLatLng || this.coordsToLatLng;
2011-06-10 19:26:16 +08:00
switch (geometry.type) {
2011-12-08 23:53:17 +08:00
case 'Point':
latlng = coordsToLatLng(coords);
return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);
2011-12-08 23:53:17 +08:00
case 'MultiPoint':
for (i = 0, len = coords.length; i < len; i++) {
latlng = coordsToLatLng(coords[i]);
layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng));
2011-12-08 23:53:17 +08:00
}
return new L.FeatureGroup(layers);
case 'LineString':
latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng);
return new L.Polyline(latlngs, vectorOptions);
2011-12-08 23:53:17 +08:00
case 'Polygon':
if (coords.length === 2 && !coords[1].length) {
throw new Error('Invalid GeoJSON object.');
}
latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng);
return new L.Polygon(latlngs, vectorOptions);
2011-12-08 23:53:17 +08:00
case 'MultiLineString':
latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng);
return new L.MultiPolyline(latlngs, vectorOptions);
2011-12-08 23:53:17 +08:00
case 'MultiPolygon':
latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng);
return new L.MultiPolygon(latlngs, vectorOptions);
2011-12-08 23:53:17 +08:00
case 'GeometryCollection':
2011-12-08 23:53:17 +08:00
for (i = 0, len = geometry.geometries.length; i < len; i++) {
layers.push(this.geometryToLayer({
geometry: geometry.geometries[i],
type: 'Feature',
properties: geojson.properties
}, pointToLayer, coordsToLatLng, vectorOptions));
2011-12-08 23:53:17 +08:00
}
return new L.FeatureGroup(layers);
default:
throw new Error('Invalid GeoJSON object.');
2011-06-10 19:26:16 +08:00
}
},
coordsToLatLng: function (coords) { // (Array[, Boolean]) -> LatLng
return new L.LatLng(coords[1], coords[0], coords[2]);
2011-06-10 19:26:16 +08:00
},
coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) { // (Array[, Number, Function]) -> Array
var latlng, i, len,
latlngs = [];
2011-12-08 23:53:17 +08:00
2012-02-15 19:17:25 +08:00
for (i = 0, len = coords.length; i < len; i++) {
2011-12-08 23:53:17 +08:00
latlng = levelsDeep ?
this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) :
2013-04-20 20:49:04 +08:00
(coordsToLatLng || this.coordsToLatLng)(coords[i]);
2011-06-10 19:26:16 +08:00
latlngs.push(latlng);
}
2012-02-15 19:17:25 +08:00
2011-06-10 19:26:16 +08:00
return latlngs;
},
2012-07-05 19:45:06 +08:00
latLngToCoords: function (latlng) {
var coords = [latlng.lng, latlng.lat];
2013-11-07 05:34:23 +08:00
if (latlng.alt !== undefined) {
coords.push(latlng.alt);
}
return coords;
},
latLngsToCoords: function (latLngs) {
var coords = [];
for (var i = 0, len = latLngs.length; i < len; i++) {
coords.push(L.GeoJSON.latLngToCoords(latLngs[i]));
}
return coords;
},
getFeature: function (layer, newGeometry) {
return layer.feature ? L.extend({}, layer.feature, {geometry: newGeometry}) : L.GeoJSON.asFeature(newGeometry);
},
asFeature: function (geoJSON) {
if (geoJSON.type === 'Feature') {
return geoJSON;
}
return {
type: 'Feature',
properties: {},
geometry: geoJSON
};
}
});
2013-06-26 00:43:22 +08:00
var PointToGeoJSON = {
toGeoJSON: function () {
return L.GeoJSON.getFeature(this, {
type: 'Point',
coordinates: L.GeoJSON.latLngToCoords(this.getLatLng())
});
}
2013-06-26 00:43:22 +08:00
};
L.Marker.include(PointToGeoJSON);
L.Circle.include(PointToGeoJSON);
L.CircleMarker.include(PointToGeoJSON);
L.Polyline.include({
toGeoJSON: function () {
return L.GeoJSON.getFeature(this, {
type: 'LineString',
coordinates: L.GeoJSON.latLngsToCoords(this.getLatLngs())
});
}
});
L.Polygon.include({
toGeoJSON: function () {
var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())],
i, len, hole;
coords[0].push(coords[0][0]);
if (this._holes) {
for (i = 0, len = this._holes.length; i < len; i++) {
hole = L.GeoJSON.latLngsToCoords(this._holes[i]);
hole.push(hole[0]);
coords.push(hole);
}
}
return L.GeoJSON.getFeature(this, {
type: 'Polygon',
coordinates: coords
});
}
});
(function () {
function multiToGeoJSON(type) {
return function () {
var coords = [];
this.eachLayer(function (layer) {
coords.push(layer.toGeoJSON().geometry.coordinates);
});
return L.GeoJSON.getFeature(this, {
type: type,
coordinates: coords
});
};
}
L.MultiPolyline.include({toGeoJSON: multiToGeoJSON('MultiLineString')});
L.MultiPolygon.include({toGeoJSON: multiToGeoJSON('MultiPolygon')});
L.LayerGroup.include({
toGeoJSON: function () {
var geometry = this.feature && this.feature.geometry,
jsons = [],
json;
if (geometry && geometry.type === 'MultiPoint') {
return multiToGeoJSON('MultiPoint').call(this);
}
var isGeometryCollection = geometry && geometry.type === 'GeometryCollection';
this.eachLayer(function (layer) {
if (layer.toGeoJSON) {
json = layer.toGeoJSON();
jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json));
}
});
if (isGeometryCollection) {
return L.GeoJSON.getFeature(this, {
geometries: jsons,
type: 'GeometryCollection'
});
}
return {
type: 'FeatureCollection',
features: jsons
};
}
});
}());
2012-07-05 19:45:06 +08:00
L.geoJson = function (geojson, options) {
return new L.GeoJSON(geojson, options);
};