Merge branch 'master' into nested-polygons
This commit is contained in:
commit
8b97b905e8
4
FAQ.md
4
FAQ.md
@ -30,7 +30,7 @@ with over seventy different layers to choose from.
|
||||
Popular commercial options, free up to a particular number of requests, include
|
||||
[MapBox](http://mapbox.com),
|
||||
[Bing Maps](http://www.microsoft.com/maps/choose-your-bing-maps-API.aspx) (using a [plugin](https://github.com/shramov/leaflet-plugins)),
|
||||
[Esri ArcGIS](http://www.arcgis.com/features/maps/imagery.html) ([official plugin](https://github.com/Esri/esri-leaflet))
|
||||
[Esri ArcGIS](http://www.esri.com/software/arcgis/arcgisonline/maps/maps-and-map-layers) ([official plugin](https://github.com/Esri/esri-leaflet))
|
||||
and [Nokia Here](http://developer.here.com/web-experiences).
|
||||
A notable exception is [MapQuest Open](http://developer.mapquest.com/web/products/open/map), which is free for any number of requests.
|
||||
|
||||
@ -40,7 +40,7 @@ Always be sure to **read the terms of use** of a chosen tile provider, **know it
|
||||
|
||||
[MapBox](http://mapbox.com),
|
||||
[Bing Maps](http://www.microsoft.com/maps/choose-your-bing-maps-API.aspx),
|
||||
[ArcGIS](http://www.arcgis.com/features/maps/imagery.html)
|
||||
[ArcGIS](http://www.esri.com/software/arcgis/arcgisonline/maps/maps-and-map-layers)
|
||||
and [MapQuest Open](http://developer.mapquest.com/web/products/open/map) provide satellite imagery among others.
|
||||
|
||||
#### I want to use Google Maps API tiles with Leaflet, can I do that?
|
||||
|
@ -33,6 +33,8 @@
|
||||
var latlngs = L.rectangle(bounds).getLatLngs();
|
||||
L.polyline(latlngs.concat([latlngs[0]])).addTo(map);
|
||||
|
||||
map.setMaxBounds(bounds); // Should not enter infinite recursion
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -27,6 +27,7 @@
|
||||
<button id="kyiv">Kyiv</button> -->
|
||||
<button id="dc">DC</button>
|
||||
<button id="sf">SF</button>
|
||||
<button id="trd">TRD</button>
|
||||
<button id="stop">stop</button>
|
||||
</div>
|
||||
|
||||
@ -36,6 +37,7 @@
|
||||
london = [51.51, -0.12],
|
||||
sf = [37.77, -122.42],
|
||||
dc = [38.91, -77.04];
|
||||
trd = [63.41, 10.41];
|
||||
|
||||
var map = L.map('map').setView(dc, 10);
|
||||
|
||||
@ -51,6 +53,7 @@
|
||||
|
||||
document.getElementById('dc').onclick = function () { map.flyTo(dc, 10); };
|
||||
document.getElementById('sf').onclick = function () { map.flyTo(sf, 10); };
|
||||
document.getElementById('trd').onclick = function () { map.flyTo(trd, 10, {duration: 20}); };
|
||||
document.getElementById('stop').onclick = function () { map.stop(); };
|
||||
// document.getElementById('london').onclick = function () { map.flyTo(london); };
|
||||
// document.getElementById('kyiv').onclick = function () { map.flyTo(kyiv); };
|
||||
|
@ -63,6 +63,14 @@ describe("CRS.EPSG3857", function () {
|
||||
expect(crs.wrapLatLng(new L.LatLng(0, 180)).lng).to.eql(180);
|
||||
});
|
||||
|
||||
it("does not drop altitude", function () {
|
||||
expect(crs.wrapLatLng(new L.LatLng(0, 190, 1234)).lng).to.eql(-170);
|
||||
expect(crs.wrapLatLng(new L.LatLng(0, 190, 1234)).alt).to.eql(1234);
|
||||
|
||||
expect(crs.wrapLatLng(new L.LatLng(0, 380, 1234)).lng).to.eql(20);
|
||||
expect(crs.wrapLatLng(new L.LatLng(0, 380, 1234)).alt).to.eql(1234);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -116,4 +116,25 @@ describe('LatLng', function () {
|
||||
expect(L.latLng({lat: 50, lon: 30, alt: 100})).to.eql(new L.LatLng(50, 30, 100));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clone', function () {
|
||||
|
||||
it('should clone attributes', function () {
|
||||
var a = new L.LatLng(50.5, 30.5, 100);
|
||||
var b = a.clone();
|
||||
|
||||
expect(b.lat).to.equal(50.5);
|
||||
expect(b.lng).to.equal(30.5);
|
||||
expect(b.alt).to.equal(100);
|
||||
});
|
||||
|
||||
it('should create another reference', function () {
|
||||
var a = new L.LatLng(50.5, 30.5, 100);
|
||||
var b = a.clone();
|
||||
|
||||
expect(a === b).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -108,4 +108,29 @@ describe('Polyline', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('#_flat', function () {
|
||||
var layer = L.polyline([]);
|
||||
|
||||
it('should return true for an array of LatLngs', function () {
|
||||
expect(L.Polyline._flat([L.latLng([0, 0])])).to.be(true);
|
||||
});
|
||||
|
||||
it('should return true for an array of LatLngs arrays', function () {
|
||||
expect(L.Polyline._flat([[0, 0]])).to.be(true);
|
||||
});
|
||||
|
||||
it('should return true for an empty array', function () {
|
||||
expect(L.Polyline._flat([])).to.be(true);
|
||||
});
|
||||
|
||||
it('should return false for a nested array of LatLngs', function () {
|
||||
expect(L.Polyline._flat([[L.latLng([0, 0])]])).to.be(false);
|
||||
});
|
||||
|
||||
it('should return false for a nested empty array', function () {
|
||||
expect(L.Polyline._flat([[]])).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -13,8 +13,9 @@
|
||||
phantomjs = ua.indexOf('phantom') !== -1,
|
||||
android23 = ua.search('android [23]') !== -1,
|
||||
chrome = ua.indexOf('chrome') !== -1,
|
||||
gecko = ua.indexOf('gecko') !== -1 && !webkit && !window.opera && !ie,
|
||||
|
||||
mobile = typeof orientation !== 'undefined',
|
||||
mobile = typeof orientation !== 'undefined' || ua.indexOf('mobile') !== -1,
|
||||
msPointer = navigator.msPointerEnabled && navigator.msMaxTouchPoints && !window.PointerEvent,
|
||||
pointer = (window.PointerEvent && navigator.pointerEnabled && navigator.maxTouchPoints) || msPointer,
|
||||
|
||||
@ -30,7 +31,7 @@
|
||||
ie: ie,
|
||||
ielt9: ie && !document.addEventListener,
|
||||
webkit: webkit,
|
||||
gecko: (ua.indexOf('gecko') !== -1) && !webkit && !window.opera && !ie,
|
||||
gecko: gecko,
|
||||
android: ua.indexOf('android') !== -1,
|
||||
android23: android23,
|
||||
chrome: chrome,
|
||||
@ -46,6 +47,7 @@
|
||||
mobileWebkit: mobile && webkit,
|
||||
mobileWebkit3d: mobile && webkit3d,
|
||||
mobileOpera: mobile && window.opera,
|
||||
mobileGecko: mobile && gecko,
|
||||
|
||||
touch: !!touch,
|
||||
msPointer: !!msPointer,
|
||||
|
@ -49,6 +49,10 @@ L.LatLng.prototype = {
|
||||
return L.latLngBounds(
|
||||
[this.lat - latAccuracy, this.lng - lngAccuracy],
|
||||
[this.lat + latAccuracy, this.lng + lngAccuracy]);
|
||||
},
|
||||
|
||||
clone: function () {
|
||||
return new L.LatLng(this.lat, this.lng, this.alt);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -56,8 +56,9 @@ L.CRS = {
|
||||
// wraps geo coords in certain ranges if applicable
|
||||
wrapLatLng: function (latlng) {
|
||||
var lng = this.wrapLng ? L.Util.wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng,
|
||||
lat = this.wrapLat ? L.Util.wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat;
|
||||
lat = this.wrapLat ? L.Util.wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat,
|
||||
alt = latlng.alt;
|
||||
|
||||
return L.latLng(lat, lng);
|
||||
return L.latLng(lat, lng, alt);
|
||||
}
|
||||
};
|
||||
|
@ -190,7 +190,7 @@ L.Circle.include(PointToGeoJSON);
|
||||
L.CircleMarker.include(PointToGeoJSON);
|
||||
|
||||
L.Polyline.prototype.toGeoJSON = function () {
|
||||
var multi = !this._flat(this._latlngs);
|
||||
var multi = !L.Polyline._flat(this._latlngs);
|
||||
|
||||
var coords = L.GeoJSON.latLngsToCoords(this._latlngs, multi ? 1 : 0);
|
||||
|
||||
@ -201,8 +201,8 @@ L.Polyline.prototype.toGeoJSON = function () {
|
||||
};
|
||||
|
||||
L.Polygon.prototype.toGeoJSON = function () {
|
||||
var holes = !this._flat(this._latlngs),
|
||||
multi = holes && !this._flat(this._latlngs[0]);
|
||||
var holes = !L.Polyline._flat(this._latlngs),
|
||||
multi = holes && !L.Polyline._flat(this._latlngs[0]);
|
||||
|
||||
var coords = L.GeoJSON.latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true);
|
||||
|
||||
|
@ -98,7 +98,7 @@ L.Polyline = L.Path.extend({
|
||||
// recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
|
||||
_convertLatLngs: function (latlngs) {
|
||||
var result = [],
|
||||
flat = this._flat(latlngs);
|
||||
flat = L.Polyline._flat(latlngs);
|
||||
|
||||
for (var i = 0, len = latlngs.length; i < len; i++) {
|
||||
if (flat) {
|
||||
@ -112,11 +112,6 @@ L.Polyline = L.Path.extend({
|
||||
return result;
|
||||
},
|
||||
|
||||
_flat: function (latlngs) {
|
||||
// true if it's a flat array of latlngs; false if nested
|
||||
return !L.Util.isArray(latlngs[0]) || typeof latlngs[0][0] !== 'object';
|
||||
},
|
||||
|
||||
_project: function () {
|
||||
this._rings = [];
|
||||
this._projectLatlngs(this._latlngs, this._rings);
|
||||
@ -211,3 +206,8 @@ L.Polyline = L.Path.extend({
|
||||
L.polyline = function (latlngs, options) {
|
||||
return new L.Polyline(latlngs, options);
|
||||
};
|
||||
|
||||
L.Polyline._flat = function (latlngs) {
|
||||
// true if it's a flat array of latlngs; false if nested
|
||||
return !L.Util.isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined');
|
||||
};
|
||||
|
@ -88,7 +88,7 @@ L.Map = L.Evented.extend({
|
||||
return this.setView(newCenter, zoom, {zoom: options});
|
||||
},
|
||||
|
||||
fitBounds: function (bounds, options) {
|
||||
_getBoundsCenterZoom: function (bounds, options) {
|
||||
|
||||
options = options || {};
|
||||
bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds);
|
||||
@ -106,7 +106,15 @@ L.Map = L.Evented.extend({
|
||||
nePoint = this.project(bounds.getNorthEast(), zoom),
|
||||
center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);
|
||||
|
||||
return this.setView(center, zoom, options);
|
||||
return {
|
||||
center: center,
|
||||
zoom: zoom
|
||||
};
|
||||
},
|
||||
|
||||
fitBounds: function (bounds, options) {
|
||||
var target = this._getBoundsCenterZoom(bounds, options);
|
||||
return this.setView(target.center, target.zoom, options);
|
||||
},
|
||||
|
||||
fitWorld: function (options) {
|
||||
@ -130,12 +138,14 @@ L.Map = L.Evented.extend({
|
||||
setMaxBounds: function (bounds) {
|
||||
bounds = L.latLngBounds(bounds);
|
||||
|
||||
this.options.maxBounds = bounds;
|
||||
|
||||
if (!bounds) {
|
||||
return this.off('moveend', this._panInsideMaxBounds);
|
||||
} else if (this.options.maxBounds) {
|
||||
this.off('moveend', this._panInsideMaxBounds);
|
||||
}
|
||||
|
||||
this.options.maxBounds = bounds;
|
||||
|
||||
if (this._loaded) {
|
||||
this._panInsideMaxBounds();
|
||||
}
|
||||
|
@ -1,6 +1,11 @@
|
||||
|
||||
L.Map.include({
|
||||
flyTo: function (targetCenter, targetZoom) {
|
||||
flyTo: function (targetCenter, targetZoom, options) {
|
||||
|
||||
options = options || {};
|
||||
if (options.animate === false) {
|
||||
return this.setView(targetCenter, targetZoom, options);
|
||||
}
|
||||
|
||||
this.stop();
|
||||
|
||||
@ -36,7 +41,7 @@ L.Map.include({
|
||||
|
||||
var start = Date.now(),
|
||||
S = (r(1) - r0) / rho,
|
||||
duration = 1000 * S * 0.8;
|
||||
duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8;
|
||||
|
||||
function frame() {
|
||||
var t = (Date.now() - start) / duration,
|
||||
@ -56,5 +61,11 @@ L.Map.include({
|
||||
|
||||
this.fire('zoomstart');
|
||||
frame.call(this);
|
||||
return this;
|
||||
},
|
||||
|
||||
flyToBounds: function(bounds, options) {
|
||||
var target = this._getBoundsCenterZoom(bounds, options);
|
||||
return this.flyTo(target.center, target.zoom, options);
|
||||
}
|
||||
});
|
||||
|
@ -16,7 +16,7 @@ L.Map.include({
|
||||
|
||||
options = this._locateOptions = L.extend({}, this._defaultLocateOptions, options);
|
||||
|
||||
if (!navigator.geolocation) {
|
||||
if (!('geolocation' in navigator)) {
|
||||
this._handleGeolocationError({
|
||||
code: 0,
|
||||
message: 'Geolocation not supported.'
|
||||
|
Loading…
Reference in New Issue
Block a user