Installed leaflet in extlib
This commit is contained in:
40
extlib/leaflet/src/layer/FeatureGroup.js
Normal file
40
extlib/leaflet/src/layer/FeatureGroup.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* L.FeatureGroup extends L.LayerGroup by introducing mouse events and bindPopup method shared between a group of layers.
|
||||
*/
|
||||
|
||||
L.FeatureGroup = L.LayerGroup.extend({
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
addLayer: function(layer) {
|
||||
this._initEvents(layer);
|
||||
L.LayerGroup.prototype.addLayer.call(this, layer);
|
||||
|
||||
if (this._popupContent && layer.bindPopup) {
|
||||
layer.bindPopup(this._popupContent);
|
||||
}
|
||||
},
|
||||
|
||||
bindPopup: function(content) {
|
||||
this._popupContent = content;
|
||||
|
||||
for (var i in this._layers) {
|
||||
if (this._layers.hasOwnProperty(i) && this._layers[i].bindPopup) {
|
||||
this._layers[i].bindPopup(content);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_events: ['click', 'dblclick', 'mouseover', 'mouseout'],
|
||||
|
||||
_initEvents: function(layer) {
|
||||
for (var i = 0, len = this._events.length; i < len; i++) {
|
||||
layer.on(this._events[i], this._propagateEvent, this);
|
||||
}
|
||||
},
|
||||
|
||||
_propagateEvent: function(e) {
|
||||
e.layer = e.target;
|
||||
e.target = this;
|
||||
this.fire(e.type, e);
|
||||
}
|
||||
});
|
||||
106
extlib/leaflet/src/layer/GeoJSON.js
Normal file
106
extlib/leaflet/src/layer/GeoJSON.js
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
L.GeoJSON = L.LayerGroup.extend({
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
initialize: function(geojson, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
this._geojson = geojson;
|
||||
this._layers = {};
|
||||
|
||||
if (geojson) {
|
||||
this.addGeoJSON(geojson);
|
||||
}
|
||||
},
|
||||
|
||||
addGeoJSON: function(geojson) {
|
||||
if (geojson.features) {
|
||||
for (var i = 0, len = geojson.features.length; i < len; i++) {
|
||||
this.addGeoJSON(geojson.features[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var isFeature = (geojson.type == 'Feature'),
|
||||
geometry = (isFeature ? geojson.geometry : geojson),
|
||||
layer = L.GeoJSON.geometryToLayer(geometry, this.options.pointToLayer);
|
||||
|
||||
this.fire('featureparse', {
|
||||
layer: layer,
|
||||
properties: geojson.properties,
|
||||
geometryType: geometry.type,
|
||||
bbox: geojson.bbox,
|
||||
id: geojson.id
|
||||
});
|
||||
|
||||
this.addLayer(layer);
|
||||
}
|
||||
});
|
||||
|
||||
L.Util.extend(L.GeoJSON, {
|
||||
geometryToLayer: function(geometry, pointToLayer) {
|
||||
var coords = geometry.coordinates,
|
||||
latlng, latlngs,
|
||||
i, len,
|
||||
layer,
|
||||
layers = [];
|
||||
|
||||
switch (geometry.type) {
|
||||
case 'Point':
|
||||
latlng = this.coordsToLatLng(coords);
|
||||
return pointToLayer ? pointToLayer(latlng) : new L.Marker(latlng);
|
||||
|
||||
case 'MultiPoint':
|
||||
for (i = 0, len = coords.length; i < len; i++) {
|
||||
latlng = this.coordsToLatLng(coords[i]);
|
||||
layer = pointToLayer ? pointToLayer(latlng) : new L.Marker(latlng);
|
||||
layers.push(layer);
|
||||
}
|
||||
return new L.FeatureGroup(layers);
|
||||
|
||||
case 'LineString':
|
||||
latlngs = this.coordsToLatLngs(coords);
|
||||
return new L.Polyline(latlngs);
|
||||
|
||||
case 'Polygon':
|
||||
latlngs = this.coordsToLatLngs(coords, 1);
|
||||
return new L.Polygon(latlngs);
|
||||
|
||||
case 'MultiLineString':
|
||||
latlngs = this.coordsToLatLngs(coords, 1);
|
||||
return new L.MultiPolyline(latlngs);
|
||||
|
||||
case "MultiPolygon":
|
||||
latlngs = this.coordsToLatLngs(coords, 2);
|
||||
return new L.MultiPolygon(latlngs);
|
||||
|
||||
case "GeometryCollection":
|
||||
for (i = 0, len = geometry.geometries.length; i < len; i++) {
|
||||
layer = this.geometryToLayer(geometry.geometries[i]);
|
||||
layers.push(layer);
|
||||
}
|
||||
return new L.FeatureGroup(layers);
|
||||
|
||||
default:
|
||||
throw new Error('Invalid GeoJSON object.');
|
||||
}
|
||||
},
|
||||
|
||||
coordsToLatLng: function(/*Array*/ coords, /*Boolean*/ reverse)/*: LatLng*/ {
|
||||
var lat = parseFloat(coords[reverse ? 0 : 1]),
|
||||
lng = parseFloat(coords[reverse ? 1 : 0]);
|
||||
return new L.LatLng(lat, lng);
|
||||
},
|
||||
|
||||
coordsToLatLngs: function(/*Array*/ coords, /*Number*/ levelsDeep, /*Boolean*/ reverse)/*: Array*/ {
|
||||
var latlng, latlngs = [],
|
||||
i, len = coords.length;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
latlng = levelsDeep ?
|
||||
this.coordsToLatLngs(coords[i], levelsDeep - 1, reverse) :
|
||||
this.coordsToLatLng(coords[i], reverse);
|
||||
latlngs.push(latlng);
|
||||
}
|
||||
return latlngs;
|
||||
}
|
||||
});
|
||||
58
extlib/leaflet/src/layer/ImageOverlay.js
Normal file
58
extlib/leaflet/src/layer/ImageOverlay.js
Normal file
@@ -0,0 +1,58 @@
|
||||
L.ImageOverlay = L.Class.extend({
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
initialize: function(/*String*/ url, /*LatLngBounds*/ bounds) {
|
||||
this._url = url;
|
||||
this._bounds = bounds;
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
this._map = map;
|
||||
|
||||
if (!this._image) {
|
||||
this._initImage();
|
||||
}
|
||||
|
||||
map.getPanes().overlayPane.appendChild(this._image);
|
||||
|
||||
map.on('viewreset', this._reset, this);
|
||||
this._reset();
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
map.getPanes().overlayPane.removeChild(this._image);
|
||||
map.off('viewreset', this._reset, this);
|
||||
},
|
||||
|
||||
_initImage: function() {
|
||||
this._image = L.DomUtil.create('img', 'leaflet-image-layer');
|
||||
|
||||
this._image.style.visibility = 'hidden';
|
||||
//TODO opacity option
|
||||
|
||||
//TODO createImage util method to remove duplication
|
||||
L.Util.extend(this._image, {
|
||||
galleryimg: 'no',
|
||||
onselectstart: L.Util.falseFn,
|
||||
onmousemove: L.Util.falseFn,
|
||||
onload: this._onImageLoad,
|
||||
src: this._url
|
||||
});
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
var topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
|
||||
bottomRight = this._map.latLngToLayerPoint(this._bounds.getSouthEast()),
|
||||
size = bottomRight.subtract(topLeft);
|
||||
|
||||
L.DomUtil.setPosition(this._image, topLeft);
|
||||
|
||||
this._image.style.width = size.x + 'px';
|
||||
this._image.style.height = size.y + 'px';
|
||||
},
|
||||
|
||||
_onImageLoad: function() {
|
||||
this.style.visibility = '';
|
||||
//TODO fire layerload
|
||||
}
|
||||
});
|
||||
58
extlib/leaflet/src/layer/LayerGroup.js
Normal file
58
extlib/leaflet/src/layer/LayerGroup.js
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* L.LayerGroup is a class to combine several layers so you can manipulate the group (e.g. add/remove it) as one layer.
|
||||
*/
|
||||
|
||||
L.LayerGroup = L.Class.extend({
|
||||
initialize: function(layers) {
|
||||
this._layers = {};
|
||||
|
||||
if (layers) {
|
||||
for (var i = 0, len = layers.length; i < len; i++) {
|
||||
this.addLayer(layers[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addLayer: function(layer) {
|
||||
var id = L.Util.stamp(layer);
|
||||
this._layers[id] = layer;
|
||||
|
||||
if (this._map) {
|
||||
this._map.addLayer(layer);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
removeLayer: function(layer) {
|
||||
var id = L.Util.stamp(layer);
|
||||
delete this._layers[id];
|
||||
|
||||
if (this._map) {
|
||||
this._map.removeLayer(layer);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
clearLayers: function() {
|
||||
this._iterateLayers(this.removeLayer, this);
|
||||
return this;
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
this._map = map;
|
||||
this._iterateLayers(map.addLayer, map);
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
this._iterateLayers(map.removeLayer, map);
|
||||
delete this._map;
|
||||
},
|
||||
|
||||
_iterateLayers: function(method, context) {
|
||||
for (var i in this._layers) {
|
||||
if (this._layers.hasOwnProperty(i)) {
|
||||
method.call(context, this._layers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
165
extlib/leaflet/src/layer/Popup.js
Normal file
165
extlib/leaflet/src/layer/Popup.js
Normal file
@@ -0,0 +1,165 @@
|
||||
|
||||
L.Popup = L.Class.extend({
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
options: {
|
||||
maxWidth: 300,
|
||||
autoPan: true,
|
||||
closeButton: true,
|
||||
|
||||
offset: new L.Point(0, 2),
|
||||
autoPanPadding: new L.Point(5, 5)
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
L.Util.setOptions(this, options);
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
this._map = map;
|
||||
if (!this._container) {
|
||||
this._initLayout();
|
||||
}
|
||||
this._updateContent();
|
||||
|
||||
this._container.style.opacity = '0';
|
||||
|
||||
this._map._panes.popupPane.appendChild(this._container);
|
||||
this._map.on('viewreset', this._updatePosition, this);
|
||||
if (this._map.options.closePopupOnClick) {
|
||||
this._map.on('preclick', this._close, this);
|
||||
}
|
||||
this._update();
|
||||
|
||||
this._container.style.opacity = '1'; //TODO fix ugly opacity hack
|
||||
|
||||
this._opened = true;
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
map._panes.popupPane.removeChild(this._container);
|
||||
map.off('viewreset', this._updatePosition, this);
|
||||
map.off('click', this._close, this);
|
||||
|
||||
this._container.style.opacity = '0';
|
||||
|
||||
this._opened = false;
|
||||
},
|
||||
|
||||
setLatLng: function(latlng) {
|
||||
this._latlng = latlng;
|
||||
if (this._opened) {
|
||||
this._update();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setContent: function(content) {
|
||||
this._content = content;
|
||||
if (this._opened) {
|
||||
this._update();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
_close: function() {
|
||||
if (this._opened) {
|
||||
this._map.removeLayer(this);
|
||||
}
|
||||
},
|
||||
|
||||
_initLayout: function() {
|
||||
this._container = L.DomUtil.create('div', 'leaflet-popup');
|
||||
|
||||
this._closeButton = L.DomUtil.create('a', 'leaflet-popup-close-button', this._container);
|
||||
this._closeButton.href = '#close';
|
||||
this._closeButton.onclick = L.Util.bind(this._onCloseButtonClick, this);
|
||||
|
||||
this._wrapper = L.DomUtil.create('div', 'leaflet-popup-content-wrapper', this._container);
|
||||
L.DomEvent.disableClickPropagation(this._wrapper);
|
||||
this._contentNode = L.DomUtil.create('div', 'leaflet-popup-content', this._wrapper);
|
||||
|
||||
this._tipContainer = L.DomUtil.create('div', 'leaflet-popup-tip-container', this._container);
|
||||
this._tip = L.DomUtil.create('div', 'leaflet-popup-tip', this._tipContainer);
|
||||
},
|
||||
|
||||
_update: function() {
|
||||
this._container.style.visibility = 'hidden';
|
||||
|
||||
this._updateContent();
|
||||
this._updateLayout();
|
||||
this._updatePosition();
|
||||
|
||||
this._container.style.visibility = '';
|
||||
|
||||
this._adjustPan();
|
||||
},
|
||||
|
||||
_updateContent: function() {
|
||||
if (!this._content) return;
|
||||
|
||||
if (typeof this._content == 'string') {
|
||||
this._contentNode.innerHTML = this._content;
|
||||
} else {
|
||||
this._contentNode.innerHTML = '';
|
||||
this._contentNode.appendChild(this._content);
|
||||
}
|
||||
},
|
||||
|
||||
_updateLayout: function() {
|
||||
this._container.style.width = '';
|
||||
this._container.style.whiteSpace = 'nowrap';
|
||||
|
||||
var width = this._container.offsetWidth;
|
||||
|
||||
this._container.style.width = (width > this.options.maxWidth ? this.options.maxWidth : width) + 'px';
|
||||
this._container.style.whiteSpace = '';
|
||||
|
||||
this._containerWidth = this._container.offsetWidth;
|
||||
},
|
||||
|
||||
_updatePosition: function() {
|
||||
var pos = this._map.latLngToLayerPoint(this._latlng);
|
||||
|
||||
this._containerBottom = -pos.y - this.options.offset.y;
|
||||
this._containerLeft = pos.x - Math.round(this._containerWidth/2) + this.options.offset.x;
|
||||
|
||||
this._container.style.bottom = this._containerBottom + 'px';
|
||||
this._container.style.left = this._containerLeft + 'px';
|
||||
},
|
||||
|
||||
_adjustPan: function() {
|
||||
if (!this.options.autoPan) { return; }
|
||||
|
||||
var containerHeight = this._container.offsetHeight,
|
||||
layerPos = new L.Point(
|
||||
this._containerLeft,
|
||||
-containerHeight - this._containerBottom),
|
||||
containerPos = this._map.layerPointToContainerPoint(layerPos),
|
||||
adjustOffset = new L.Point(0, 0),
|
||||
padding = this.options.autoPanPadding,
|
||||
size = this._map.getSize();
|
||||
|
||||
if (containerPos.x < 0) {
|
||||
adjustOffset.x = containerPos.x - padding.x;
|
||||
}
|
||||
if (containerPos.x + this._containerWidth > size.x) {
|
||||
adjustOffset.x = containerPos.x + this._containerWidth - size.x + padding.x;
|
||||
}
|
||||
if (containerPos.y < 0) {
|
||||
adjustOffset.y = containerPos.y - padding.y;
|
||||
}
|
||||
if (containerPos.y + containerHeight > size.y) {
|
||||
adjustOffset.y = containerPos.y + containerHeight - size.y + padding.y;
|
||||
}
|
||||
|
||||
if (adjustOffset.x || adjustOffset.y) {
|
||||
this._map.panBy(adjustOffset);
|
||||
}
|
||||
},
|
||||
|
||||
_onCloseButtonClick: function(e) {
|
||||
this._close();
|
||||
L.DomEvent.stop(e);
|
||||
}
|
||||
});
|
||||
56
extlib/leaflet/src/layer/marker/Icon.js
Normal file
56
extlib/leaflet/src/layer/marker/Icon.js
Normal file
@@ -0,0 +1,56 @@
|
||||
L.Icon = L.Class.extend({
|
||||
iconUrl: L.ROOT_URL + 'images/marker.png',
|
||||
shadowUrl: L.ROOT_URL + 'images/marker-shadow.png',
|
||||
|
||||
iconSize: new L.Point(25, 41),
|
||||
shadowSize: new L.Point(41, 41),
|
||||
|
||||
iconAnchor: new L.Point(13, 41),
|
||||
popupAnchor: new L.Point(0, -33),
|
||||
|
||||
initialize: function(iconUrl) {
|
||||
if (iconUrl) {
|
||||
this.iconUrl = iconUrl;
|
||||
}
|
||||
},
|
||||
|
||||
createIcon: function() {
|
||||
return this._createIcon('icon');
|
||||
},
|
||||
|
||||
createShadow: function() {
|
||||
return this._createIcon('shadow');
|
||||
},
|
||||
|
||||
_createIcon: function(name) {
|
||||
var size = this[name + 'Size'],
|
||||
src = this[name + 'Url'],
|
||||
img = this._createImg(src);
|
||||
|
||||
if (!src) { return null; }
|
||||
|
||||
img.className = 'leaflet-marker-' + name;
|
||||
|
||||
img.style.marginLeft = (-this.iconAnchor.x) + 'px';
|
||||
img.style.marginTop = (-this.iconAnchor.y) + 'px';
|
||||
|
||||
if (size) {
|
||||
img.style.width = size.x + 'px';
|
||||
img.style.height = size.y + 'px';
|
||||
}
|
||||
|
||||
return img;
|
||||
},
|
||||
|
||||
_createImg: function(src) {
|
||||
var el;
|
||||
if (!L.Browser.ie6) {
|
||||
el = document.createElement('img');
|
||||
el.src = src;
|
||||
} else {
|
||||
el = document.createElement('div');
|
||||
el.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + src + '")';
|
||||
}
|
||||
return el;
|
||||
}
|
||||
});
|
||||
28
extlib/leaflet/src/layer/marker/Marker.Popup.js
Normal file
28
extlib/leaflet/src/layer/marker/Marker.Popup.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Popup extension to L.Marker, adding openPopup & bindPopup methods.
|
||||
*/
|
||||
|
||||
L.Marker.include({
|
||||
openPopup: function() {
|
||||
this._popup.setLatLng(this._latlng);
|
||||
this._map.openPopup(this._popup);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
closePopup: function() {
|
||||
if (this._popup) {
|
||||
this._popup._close();
|
||||
}
|
||||
},
|
||||
|
||||
bindPopup: function(content, options) {
|
||||
options = L.Util.extend({offset: this.options.icon.popupAnchor}, options);
|
||||
|
||||
this._popup = new L.Popup(options);
|
||||
this._popup.setContent(content);
|
||||
this.on('click', this.openPopup, this);
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
123
extlib/leaflet/src/layer/marker/Marker.js
Normal file
123
extlib/leaflet/src/layer/marker/Marker.js
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* L.Marker is used to display clickable/draggable icons on the map.
|
||||
*/
|
||||
|
||||
L.Marker = L.Class.extend({
|
||||
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
options: {
|
||||
icon: new L.Icon(),
|
||||
title: '',
|
||||
clickable: true,
|
||||
draggable: false
|
||||
},
|
||||
|
||||
initialize: function(latlng, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
this._latlng = latlng;
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
this._map = map;
|
||||
|
||||
this._initIcon();
|
||||
|
||||
map.on('viewreset', this._reset, this);
|
||||
this._reset();
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
this._removeIcon();
|
||||
|
||||
map.off('viewreset', this._reset, this);
|
||||
},
|
||||
|
||||
getLatLng: function() {
|
||||
return this._latlng;
|
||||
},
|
||||
|
||||
setLatLng: function(latlng) {
|
||||
this._latlng = latlng;
|
||||
this._reset();
|
||||
},
|
||||
|
||||
setIcon: function(icon) {
|
||||
this._removeIcon();
|
||||
|
||||
this._icon = this._shadow = null;
|
||||
this.options.icon = icon;
|
||||
|
||||
this._initIcon();
|
||||
},
|
||||
|
||||
_initIcon: function() {
|
||||
if (!this._icon) {
|
||||
this._icon = this.options.icon.createIcon();
|
||||
|
||||
if (this.options.title) {
|
||||
this._icon.title = this.options.title;
|
||||
}
|
||||
|
||||
this._initInteraction();
|
||||
}
|
||||
if (!this._shadow) {
|
||||
this._shadow = this.options.icon.createShadow();
|
||||
}
|
||||
|
||||
this._map._panes.markerPane.appendChild(this._icon);
|
||||
if (this._shadow) {
|
||||
this._map._panes.shadowPane.appendChild(this._shadow);
|
||||
}
|
||||
},
|
||||
|
||||
_removeIcon: function() {
|
||||
this._map._panes.markerPane.removeChild(this._icon);
|
||||
if (this._shadow) {
|
||||
this._map._panes.shadowPane.removeChild(this._shadow);
|
||||
}
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
var pos = this._map.latLngToLayerPoint(this._latlng).round();
|
||||
|
||||
L.DomUtil.setPosition(this._icon, pos);
|
||||
if (this._shadow) {
|
||||
L.DomUtil.setPosition(this._shadow, pos);
|
||||
}
|
||||
|
||||
this._icon.style.zIndex = pos.y;
|
||||
},
|
||||
|
||||
_initInteraction: function() {
|
||||
if (this.options.clickable) {
|
||||
this._icon.className += ' leaflet-clickable';
|
||||
|
||||
L.DomEvent.addListener(this._icon, 'click', this._onMouseClick, this);
|
||||
|
||||
var events = ['dblclick', 'mousedown', 'mouseover', 'mouseout'];
|
||||
for (var i = 0; i < events.length; i++) {
|
||||
L.DomEvent.addListener(this._icon, events[i], this._fireMouseEvent, this);
|
||||
}
|
||||
}
|
||||
|
||||
if (L.Handler.MarkerDrag) {
|
||||
this.dragging = new L.Handler.MarkerDrag(this);
|
||||
|
||||
if (this.options.draggable) {
|
||||
this.dragging.enable();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseClick: function(e) {
|
||||
L.DomEvent.stopPropagation(e);
|
||||
if (this.dragging && this.dragging.moved()) { return; }
|
||||
this.fire(e.type);
|
||||
},
|
||||
|
||||
_fireMouseEvent: function(e) {
|
||||
this.fire(e.type);
|
||||
L.DomEvent.stopPropagation(e);
|
||||
}
|
||||
});
|
||||
41
extlib/leaflet/src/layer/tile/TileLayer.Canvas.js
Normal file
41
extlib/leaflet/src/layer/tile/TileLayer.Canvas.js
Normal file
@@ -0,0 +1,41 @@
|
||||
L.TileLayer.Canvas = L.TileLayer.extend({
|
||||
options: {
|
||||
async: false
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
L.Util.setOptions(this, options);
|
||||
},
|
||||
|
||||
_createTileProto: function() {
|
||||
this._canvasProto = L.DomUtil.create('canvas', 'leaflet-tile');
|
||||
|
||||
var tileSize = this.options.tileSize;
|
||||
this._canvasProto.width = tileSize;
|
||||
this._canvasProto.height = tileSize;
|
||||
},
|
||||
|
||||
_createTile: function() {
|
||||
var tile = this._canvasProto.cloneNode(false);
|
||||
tile.onselectstart = tile.onmousemove = L.Util.falseFn;
|
||||
return tile;
|
||||
},
|
||||
|
||||
_loadTile: function(tile, tilePoint, zoom) {
|
||||
tile._layer = this;
|
||||
|
||||
this.drawTile(tile, tilePoint, zoom);
|
||||
|
||||
if (!this.options.async) {
|
||||
this.tileDrawn(tile);
|
||||
}
|
||||
},
|
||||
|
||||
drawTile: function(tile, tilePoint, zoom) {
|
||||
// override with rendering code
|
||||
},
|
||||
|
||||
tileDrawn: function(tile) {
|
||||
this._tileOnLoad.call(tile);
|
||||
}
|
||||
});
|
||||
47
extlib/leaflet/src/layer/tile/TileLayer.WMS.js
Normal file
47
extlib/leaflet/src/layer/tile/TileLayer.WMS.js
Normal file
@@ -0,0 +1,47 @@
|
||||
L.TileLayer.WMS = L.TileLayer.extend({
|
||||
defaultWmsParams: {
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
version: '1.1.1',
|
||||
layers: '',
|
||||
styles: '',
|
||||
format: 'image/jpeg',
|
||||
transparent: false
|
||||
},
|
||||
|
||||
initialize: function(/*String*/ url, /*Object*/ options) {
|
||||
this._url = url;
|
||||
|
||||
this.wmsParams = L.Util.extend({}, this.defaultWmsParams);
|
||||
this.wmsParams.width = this.wmsParams.height = this.options.tileSize;
|
||||
|
||||
for (var i in options) {
|
||||
// all keys that are not TileLayer options go to WMS params
|
||||
if (!this.options.hasOwnProperty(i)) {
|
||||
this.wmsParams[i] = options[i];
|
||||
}
|
||||
}
|
||||
|
||||
L.Util.setOptions(this, options);
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
var projectionKey = (parseFloat(this.wmsParams.version) >= 1.3 ? 'crs' : 'srs');
|
||||
this.wmsParams[projectionKey] = map.options.crs.code;
|
||||
|
||||
L.TileLayer.prototype.onAdd.call(this, map);
|
||||
},
|
||||
|
||||
getTileUrl: function(/*Point*/ tilePoint, /*Number*/ zoom)/*-> String*/ {
|
||||
var tileSize = this.options.tileSize,
|
||||
nwPoint = tilePoint.multiplyBy(tileSize),
|
||||
sePoint = nwPoint.add(new L.Point(tileSize, tileSize)),
|
||||
nwMap = this._map.unproject(nwPoint, this._zoom, true),
|
||||
seMap = this._map.unproject(sePoint, this._zoom, true),
|
||||
nw = this._map.options.crs.project(nwMap),
|
||||
se = this._map.options.crs.project(seMap),
|
||||
bbox = [nw.x, se.y, se.x, nw.y].join(',');
|
||||
|
||||
return this._url + L.Util.getParamString(this.wmsParams) + "&bbox=" + bbox;
|
||||
}
|
||||
});
|
||||
262
extlib/leaflet/src/layer/tile/TileLayer.js
Normal file
262
extlib/leaflet/src/layer/tile/TileLayer.js
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* L.TileLayer is used for standard xyz-numbered tile layers.
|
||||
*/
|
||||
|
||||
L.TileLayer = L.Class.extend({
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
options: {
|
||||
minZoom: 0,
|
||||
maxZoom: 18,
|
||||
tileSize: 256,
|
||||
subdomains: 'abc',
|
||||
errorTileUrl: '',
|
||||
attribution: '',
|
||||
opacity: 1,
|
||||
scheme: 'xyz',
|
||||
noWrap: false,
|
||||
|
||||
unloadInvisibleTiles: L.Browser.mobileWebkit,
|
||||
updateWhenIdle: L.Browser.mobileWebkit
|
||||
},
|
||||
|
||||
initialize: function(url, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
|
||||
this._url = url;
|
||||
|
||||
if (typeof this.options.subdomains == 'string') {
|
||||
this.options.subdomains = this.options.subdomains.split('');
|
||||
}
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
this._map = map;
|
||||
|
||||
// create a container div for tiles
|
||||
this._initContainer();
|
||||
|
||||
// create an image to clone for tiles
|
||||
this._createTileProto();
|
||||
|
||||
// set up events
|
||||
map.on('viewreset', this._reset, this);
|
||||
|
||||
if (this.options.updateWhenIdle) {
|
||||
map.on('moveend', this._update, this);
|
||||
} else {
|
||||
this._limitedUpdate = L.Util.limitExecByInterval(this._update, 100, this);
|
||||
map.on('move', this._limitedUpdate, this);
|
||||
}
|
||||
|
||||
this._reset();
|
||||
this._update();
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
this._map.getPanes().tilePane.removeChild(this._container);
|
||||
this._container = null;
|
||||
|
||||
this._map.off('viewreset', this._reset, this);
|
||||
|
||||
if (this.options.updateWhenIdle) {
|
||||
this._map.off('moveend', this._update, this);
|
||||
} else {
|
||||
this._map.off('move', this._limitedUpdate, this);
|
||||
}
|
||||
},
|
||||
|
||||
getAttribution: function() {
|
||||
return this.options.attribution;
|
||||
},
|
||||
|
||||
setOpacity: function(opacity) {
|
||||
this.options.opacity = opacity;
|
||||
|
||||
this._setOpacity(opacity);
|
||||
|
||||
// stupid webkit hack to force redrawing of tiles
|
||||
if (L.Browser.webkit) {
|
||||
for (i in this._tiles) {
|
||||
this._tiles[i].style.webkitTransform += ' translate(0,0)';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_setOpacity: function(opacity) {
|
||||
if (opacity < 1) {
|
||||
L.DomUtil.setOpacity(this._container, opacity);
|
||||
}
|
||||
},
|
||||
|
||||
_initContainer: function() {
|
||||
var tilePane = this._map.getPanes().tilePane;
|
||||
|
||||
if (!this._container || tilePane.empty) {
|
||||
this._container = L.DomUtil.create('div', 'leaflet-layer', tilePane);
|
||||
|
||||
this._setOpacity(this.options.opacity);
|
||||
}
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
this._tiles = {};
|
||||
this._initContainer();
|
||||
this._container.innerHTML = '';
|
||||
},
|
||||
|
||||
_update: function() {
|
||||
var bounds = this._map.getPixelBounds(),
|
||||
tileSize = this.options.tileSize;
|
||||
|
||||
var nwTilePoint = new L.Point(
|
||||
Math.floor(bounds.min.x / tileSize),
|
||||
Math.floor(bounds.min.y / tileSize)),
|
||||
seTilePoint = new L.Point(
|
||||
Math.floor(bounds.max.x / tileSize),
|
||||
Math.floor(bounds.max.y / tileSize)),
|
||||
tileBounds = new L.Bounds(nwTilePoint, seTilePoint);
|
||||
|
||||
this._addTilesFromCenterOut(tileBounds);
|
||||
|
||||
if (this.options.unloadInvisibleTiles) {
|
||||
this._removeOtherTiles(tileBounds);
|
||||
}
|
||||
},
|
||||
|
||||
_addTilesFromCenterOut: function(bounds) {
|
||||
var queue = [],
|
||||
center = bounds.getCenter();
|
||||
|
||||
for (var j = bounds.min.y; j <= bounds.max.y; j++) {
|
||||
for (var i = bounds.min.x; i <= bounds.max.x; i++) {
|
||||
if ((i + ':' + j) in this._tiles) { continue; }
|
||||
queue.push(new L.Point(i, j));
|
||||
}
|
||||
}
|
||||
|
||||
// load tiles in order of their distance to center
|
||||
queue.sort(function(a, b) {
|
||||
return a.distanceTo(center) - b.distanceTo(center);
|
||||
});
|
||||
|
||||
this._tilesToLoad = queue.length;
|
||||
for (var k = 0, len = this._tilesToLoad; k < len; k++) {
|
||||
this._addTile(queue[k]);
|
||||
}
|
||||
},
|
||||
|
||||
_removeOtherTiles: function(bounds) {
|
||||
var kArr, x, y, key;
|
||||
|
||||
for (key in this._tiles) {
|
||||
if (this._tiles.hasOwnProperty(key)) {
|
||||
kArr = key.split(':');
|
||||
x = parseInt(kArr[0], 10);
|
||||
y = parseInt(kArr[1], 10);
|
||||
|
||||
// remove tile if it's out of bounds
|
||||
if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {
|
||||
this._tiles[key].src = '';
|
||||
if (this._tiles[key].parentNode == this._container) {
|
||||
this._container.removeChild(this._tiles[key]);
|
||||
}
|
||||
delete this._tiles[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_addTile: function(tilePoint) {
|
||||
var tilePos = this._getTilePos(tilePoint),
|
||||
zoom = this._map.getZoom(),
|
||||
key = tilePoint.x + ':' + tilePoint.y;
|
||||
|
||||
// wrap tile coordinates
|
||||
var tileLimit = (1 << zoom);
|
||||
if (!this.options.noWrap) {
|
||||
tilePoint.x = ((tilePoint.x % tileLimit) + tileLimit) % tileLimit;
|
||||
}
|
||||
if (tilePoint.y < 0 || tilePoint.y >= tileLimit) { return; }
|
||||
|
||||
// create tile
|
||||
var tile = this._createTile();
|
||||
L.DomUtil.setPosition(tile, tilePos);
|
||||
|
||||
this._tiles[key] = tile;
|
||||
|
||||
if (this.options.scheme == 'tms') {
|
||||
tilePoint.y = tileLimit - tilePoint.y - 1;
|
||||
}
|
||||
|
||||
this._loadTile(tile, tilePoint, zoom);
|
||||
|
||||
this._container.appendChild(tile);
|
||||
},
|
||||
|
||||
_getTilePos: function(tilePoint) {
|
||||
var origin = this._map.getPixelOrigin(),
|
||||
tileSize = this.options.tileSize;
|
||||
|
||||
return tilePoint.multiplyBy(tileSize).subtract(origin);
|
||||
},
|
||||
|
||||
// image-specific code (override to implement e.g. Canvas or SVG tile layer)
|
||||
|
||||
getTileUrl: function(tilePoint, zoom) {
|
||||
var subdomains = this.options.subdomains,
|
||||
s = this.options.subdomains[(tilePoint.x + tilePoint.y) % subdomains.length];
|
||||
|
||||
return this._url
|
||||
.replace('{s}', s)
|
||||
.replace('{z}', zoom)
|
||||
.replace('{x}', tilePoint.x)
|
||||
.replace('{y}', tilePoint.y);
|
||||
},
|
||||
|
||||
_createTileProto: function() {
|
||||
this._tileImg = L.DomUtil.create('img', 'leaflet-tile');
|
||||
this._tileImg.galleryimg = 'no';
|
||||
|
||||
var tileSize = this.options.tileSize;
|
||||
this._tileImg.style.width = tileSize + 'px';
|
||||
this._tileImg.style.height = tileSize + 'px';
|
||||
},
|
||||
|
||||
_createTile: function() {
|
||||
var tile = this._tileImg.cloneNode(false);
|
||||
tile.onselectstart = tile.onmousemove = L.Util.falseFn;
|
||||
return tile;
|
||||
},
|
||||
|
||||
_loadTile: function(tile, tilePoint, zoom) {
|
||||
tile._layer = this;
|
||||
tile.onload = this._tileOnLoad;
|
||||
tile.onerror = this._tileOnError;
|
||||
tile.src = this.getTileUrl(tilePoint, zoom);
|
||||
},
|
||||
|
||||
_tileOnLoad: function(e) {
|
||||
var layer = this._layer;
|
||||
|
||||
this.className += ' leaflet-tile-loaded';
|
||||
|
||||
layer.fire('tileload', {tile: this, url: this.src});
|
||||
|
||||
layer._tilesToLoad--;
|
||||
if (!layer._tilesToLoad) {
|
||||
layer.fire('load');
|
||||
}
|
||||
},
|
||||
|
||||
_tileOnError: function(e) {
|
||||
var layer = this._layer;
|
||||
|
||||
layer.fire('tileerror', {tile: this, url: this.src});
|
||||
|
||||
var newUrl = layer.options.errorTileUrl;
|
||||
if (newUrl) {
|
||||
this.src = newUrl;
|
||||
}
|
||||
}
|
||||
});
|
||||
51
extlib/leaflet/src/layer/vector/Circle.js
Normal file
51
extlib/leaflet/src/layer/vector/Circle.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* L.Circle is a circle overlay (with a certain radius in meters).
|
||||
*/
|
||||
|
||||
L.Circle = L.Path.extend({
|
||||
initialize: function(latlng, radius, options) {
|
||||
L.Path.prototype.initialize.call(this, options);
|
||||
|
||||
this._latlng = latlng;
|
||||
this._mRadius = radius;
|
||||
},
|
||||
|
||||
options: {
|
||||
fill: true
|
||||
},
|
||||
|
||||
setLatLng: function(latlng) {
|
||||
this._latlng = latlng;
|
||||
this._redraw();
|
||||
return this;
|
||||
},
|
||||
|
||||
setRadius: function(radius) {
|
||||
this._mRadius = radius;
|
||||
this._redraw();
|
||||
return this;
|
||||
},
|
||||
|
||||
projectLatlngs: function() {
|
||||
var equatorLength = 40075017,
|
||||
scale = this._map.options.scale(this._map._zoom);
|
||||
|
||||
this._point = this._map.latLngToLayerPoint(this._latlng);
|
||||
this._radius = (this._mRadius / equatorLength) * scale;
|
||||
},
|
||||
|
||||
getPathString: function() {
|
||||
var p = this._point,
|
||||
r = this._radius;
|
||||
|
||||
if (L.Path.SVG) {
|
||||
return "M" + p.x + "," + (p.y - r) +
|
||||
"A" + r + "," + r + ",0,1,1," +
|
||||
(p.x - 0.1) + "," + (p.y - r) + " z";
|
||||
} else {
|
||||
p._round();
|
||||
r = Math.round(r);
|
||||
return "AL " + p.x + "," + p.y + " " + r + "," + r + " 0," + (65535 * 360);
|
||||
}
|
||||
}
|
||||
});
|
||||
25
extlib/leaflet/src/layer/vector/CircleMarker.js
Normal file
25
extlib/leaflet/src/layer/vector/CircleMarker.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* L.CircleMarker is a circle overlay with a permanent pixel radius.
|
||||
*/
|
||||
|
||||
L.CircleMarker = L.Circle.extend({
|
||||
options: {
|
||||
radius: 10,
|
||||
weight: 2
|
||||
},
|
||||
|
||||
initialize: function(latlng, options) {
|
||||
L.Circle.prototype.initialize.call(this, latlng, null, options);
|
||||
this._radius = this.options.radius;
|
||||
},
|
||||
|
||||
projectLatlngs: function() {
|
||||
this._point = this._map.latLngToLayerPoint(this._latlng);
|
||||
},
|
||||
|
||||
setRadius: function(radius) {
|
||||
this._radius = radius;
|
||||
this._redraw();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
27
extlib/leaflet/src/layer/vector/MultiPoly.js
Normal file
27
extlib/leaflet/src/layer/vector/MultiPoly.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Contains L.MultiPolyline and L.MultiPolygon layers.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
function createMulti(klass) {
|
||||
return L.FeatureGroup.extend({
|
||||
initialize: function(latlngs, options) {
|
||||
this._layers = {};
|
||||
for (var i = 0, len = latlngs.length; i < len; i++) {
|
||||
this.addLayer(new klass(latlngs[i], options));
|
||||
}
|
||||
},
|
||||
|
||||
setStyle: function(style) {
|
||||
for (var i in this._layers) {
|
||||
if (this._layers.hasOwnProperty(i) && this._layers[i].setStyle) {
|
||||
this._layers[i].setStyle(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
L.MultiPolyline = createMulti(L.Polyline);
|
||||
L.MultiPolygon = createMulti(L.Polygon);
|
||||
}());
|
||||
24
extlib/leaflet/src/layer/vector/Path.Popup.js
Normal file
24
extlib/leaflet/src/layer/vector/Path.Popup.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Popup extension to L.Path (polylines, polygons, circles), adding bindPopup method.
|
||||
*/
|
||||
|
||||
L.Path.include({
|
||||
bindPopup: function(content, options) {
|
||||
if (!this._popup || this._popup.options !== options) {
|
||||
this._popup = new L.Popup(options);
|
||||
}
|
||||
this._popup.setContent(content);
|
||||
|
||||
if (!this._openPopupAdded) {
|
||||
this.on('click', this._openPopup, this);
|
||||
this._openPopupAdded = true;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_openPopup: function(e) {
|
||||
this._popup.setLatLng(e.latlng);
|
||||
this._map.openPopup(this._popup);
|
||||
}
|
||||
});
|
||||
91
extlib/leaflet/src/layer/vector/Path.VML.js
Normal file
91
extlib/leaflet/src/layer/vector/Path.VML.js
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Vector rendering for IE6-8 through VML.
|
||||
* Thanks to Dmitry Baranovsky and his Raphael library for inspiration!
|
||||
*/
|
||||
|
||||
L.Path.VML = (function() {
|
||||
var d = document.createElement('div'), s;
|
||||
d.innerHTML = '<v:shape adj="1"/>';
|
||||
s = d.firstChild;
|
||||
s.style.behavior = 'url(#default#VML)';
|
||||
|
||||
return (s && (typeof s.adj == 'object'));
|
||||
})();
|
||||
|
||||
L.Path = L.Path.SVG || !L.Path.VML ? L.Path : L.Path.extend({
|
||||
statics: {
|
||||
CLIP_PADDING: 0.02
|
||||
},
|
||||
|
||||
_createElement: (function() {
|
||||
try {
|
||||
document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml');
|
||||
return function(name) {
|
||||
return document.createElement('<lvml:' + name + ' class="lvml">');
|
||||
};
|
||||
} catch (e) {
|
||||
return function(name) {
|
||||
return document.createElement('<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">');
|
||||
};
|
||||
}
|
||||
})(),
|
||||
|
||||
_initRoot: function() {
|
||||
if (!this._map._pathRoot) {
|
||||
this._map._pathRoot = document.createElement('div');
|
||||
this._map._pathRoot.className = 'leaflet-vml-container';
|
||||
this._map._panes.overlayPane.appendChild(this._map._pathRoot);
|
||||
|
||||
this._map.on('moveend', this._updateViewport, this);
|
||||
this._updateViewport();
|
||||
}
|
||||
},
|
||||
|
||||
_initPath: function() {
|
||||
this._container = this._createElement('shape');
|
||||
this._container.className += ' leaflet-vml-shape' +
|
||||
(this.options.clickable ? ' leaflet-clickable' : '');
|
||||
this._container.coordsize = '1 1';
|
||||
|
||||
this._path = this._createElement('path');
|
||||
this._container.appendChild(this._path);
|
||||
|
||||
this._map._pathRoot.appendChild(this._container);
|
||||
},
|
||||
|
||||
_initStyle: function() {
|
||||
if (this.options.stroke) {
|
||||
this._stroke = this._createElement('stroke');
|
||||
this._stroke.endcap = 'round';
|
||||
this._container.appendChild(this._stroke);
|
||||
} else {
|
||||
this._container.stroked = false;
|
||||
}
|
||||
if (this.options.fill) {
|
||||
this._container.filled = true;
|
||||
this._fill = this._createElement('fill');
|
||||
this._container.appendChild(this._fill);
|
||||
} else {
|
||||
this._container.filled = false;
|
||||
}
|
||||
this._updateStyle();
|
||||
},
|
||||
|
||||
_updateStyle: function() {
|
||||
if (this.options.stroke) {
|
||||
this._stroke.weight = this.options.weight + 'px';
|
||||
this._stroke.color = this.options.color;
|
||||
this._stroke.opacity = this.options.opacity;
|
||||
}
|
||||
if (this.options.fill) {
|
||||
this._fill.color = this.options.fillColor || this.options.color;
|
||||
this._fill.opacity = this.options.fillOpacity;
|
||||
}
|
||||
},
|
||||
|
||||
_updatePath: function() {
|
||||
this._container.style.display = 'none';
|
||||
this._path.v = this.getPathString() + ' '; // the space fixes IE empty path string bug
|
||||
this._container.style.display = '';
|
||||
}
|
||||
});
|
||||
207
extlib/leaflet/src/layer/vector/Path.js
Normal file
207
extlib/leaflet/src/layer/vector/Path.js
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* L.Path is a base class for rendering vector paths on a map. It's inherited by Polyline, Circle, etc.
|
||||
*/
|
||||
|
||||
L.Path = L.Class.extend({
|
||||
includes: [L.Mixin.Events],
|
||||
|
||||
statics: (function() {
|
||||
var svgns = 'http://www.w3.org/2000/svg',
|
||||
ce = 'createElementNS';
|
||||
|
||||
return {
|
||||
SVG_NS: svgns,
|
||||
SVG: !!(document[ce] && document[ce](svgns, 'svg').createSVGRect),
|
||||
|
||||
// how much to extend the clip area around the map view
|
||||
// (relative to its size, e.g. 0.5 is half the screen in each direction)
|
||||
CLIP_PADDING: 0.5
|
||||
};
|
||||
})(),
|
||||
|
||||
options: {
|
||||
stroke: true,
|
||||
color: '#0033ff',
|
||||
weight: 5,
|
||||
opacity: 0.5,
|
||||
|
||||
fill: false,
|
||||
fillColor: null, //same as color by default
|
||||
fillOpacity: 0.2,
|
||||
|
||||
clickable: true,
|
||||
|
||||
updateOnMoveEnd: false
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
L.Util.setOptions(this, options);
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
this._map = map;
|
||||
|
||||
this._initElements();
|
||||
this._initEvents();
|
||||
this.projectLatlngs();
|
||||
this._updatePath();
|
||||
|
||||
map.on('viewreset', this.projectLatlngs, this);
|
||||
|
||||
this._updateTrigger = this.options.updateOnMoveEnd ? 'moveend' : 'viewreset';
|
||||
map.on(this._updateTrigger, this._updatePath, this);
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
map._pathRoot.removeChild(this._container);
|
||||
map.off('viewreset', this._projectLatlngs, this);
|
||||
map.off(this._updateTrigger, this._updatePath, this);
|
||||
},
|
||||
|
||||
projectLatlngs: function() {
|
||||
// do all projection stuff here
|
||||
},
|
||||
|
||||
getPathString: function() {
|
||||
// form path string here
|
||||
},
|
||||
|
||||
setStyle: function(style) {
|
||||
L.Util.setOptions(this, style);
|
||||
if (this._path) {
|
||||
this._updateStyle();
|
||||
}
|
||||
},
|
||||
|
||||
_initElements: function() {
|
||||
this._initRoot();
|
||||
this._initPath();
|
||||
this._initStyle();
|
||||
},
|
||||
|
||||
_initRoot: function() {
|
||||
if (!this._map._pathRoot) {
|
||||
this._map._pathRoot = this._createElement('svg');
|
||||
this._map._panes.overlayPane.appendChild(this._map._pathRoot);
|
||||
|
||||
this._map.on('moveend', this._updateSvgViewport, this);
|
||||
this._updateSvgViewport();
|
||||
}
|
||||
},
|
||||
|
||||
_updateSvgViewport: function() {
|
||||
this._updateViewport();
|
||||
|
||||
var vp = this._map._pathViewport,
|
||||
min = vp.min,
|
||||
max = vp.max,
|
||||
width = max.x - min.x,
|
||||
height = max.y - min.y,
|
||||
root = this._map._pathRoot,
|
||||
pane = this._map._panes.overlayPane;
|
||||
|
||||
// Hack to make flicker on drag end on mobile webkit less irritating
|
||||
// Unfortunately I haven't found a good workaround for this yet
|
||||
if (L.Browser.mobileWebkit) { pane.removeChild(root); }
|
||||
|
||||
L.DomUtil.setPosition(root, min);
|
||||
root.setAttribute('width', width);
|
||||
root.setAttribute('height', height);
|
||||
root.setAttribute('viewBox', [min.x, min.y, width, height].join(' '));
|
||||
|
||||
if (L.Browser.mobileWebkit) { pane.appendChild(root); }
|
||||
},
|
||||
|
||||
_updateViewport: function() {
|
||||
var p = L.Path.CLIP_PADDING,
|
||||
size = this._map.getSize(),
|
||||
//TODO this._map._getMapPanePos()
|
||||
panePos = L.DomUtil.getPosition(this._map._mapPane),
|
||||
min = panePos.multiplyBy(-1).subtract(size.multiplyBy(p)),
|
||||
max = min.add(size.multiplyBy(1 + p * 2));
|
||||
|
||||
this._map._pathViewport = new L.Bounds(min, max);
|
||||
},
|
||||
|
||||
_initPath: function() {
|
||||
this._container = this._createElement('g');
|
||||
|
||||
this._path = this._createElement('path');
|
||||
this._container.appendChild(this._path);
|
||||
|
||||
this._map._pathRoot.appendChild(this._container);
|
||||
},
|
||||
|
||||
_initStyle: function() {
|
||||
if (this.options.stroke) {
|
||||
this._path.setAttribute('stroke-linejoin', 'round');
|
||||
this._path.setAttribute('stroke-linecap', 'round');
|
||||
}
|
||||
if (this.options.fill) {
|
||||
this._path.setAttribute('fill-rule', 'evenodd');
|
||||
} else {
|
||||
this._path.setAttribute('fill', 'none');
|
||||
}
|
||||
this._updateStyle();
|
||||
},
|
||||
|
||||
_updateStyle: function() {
|
||||
if (this.options.stroke) {
|
||||
this._path.setAttribute('stroke', this.options.color);
|
||||
this._path.setAttribute('stroke-opacity', this.options.opacity);
|
||||
this._path.setAttribute('stroke-width', this.options.weight);
|
||||
}
|
||||
if (this.options.fill) {
|
||||
this._path.setAttribute('fill', this.options.fillColor || this.options.color);
|
||||
this._path.setAttribute('fill-opacity', this.options.fillOpacity);
|
||||
}
|
||||
},
|
||||
|
||||
_updatePath: function() {
|
||||
var str = this.getPathString();
|
||||
if (!str) {
|
||||
// fix webkit empty string parsing bug
|
||||
str = 'M0 0';
|
||||
}
|
||||
this._path.setAttribute('d', str);
|
||||
},
|
||||
|
||||
_createElement: function(name) {
|
||||
return document.createElementNS(L.Path.SVG_NS, name);
|
||||
},
|
||||
|
||||
// TODO remove duplication with L.Map
|
||||
_initEvents: function() {
|
||||
if (this.options.clickable) {
|
||||
if (!L.Path.VML) {
|
||||
this._path.setAttribute('class', 'leaflet-clickable');
|
||||
}
|
||||
|
||||
L.DomEvent.addListener(this._container, 'click', this._onMouseClick, this);
|
||||
|
||||
var events = ['dblclick', 'mousedown', 'mouseover', 'mouseout'];
|
||||
for (var i = 0; i < events.length; i++) {
|
||||
L.DomEvent.addListener(this._container, events[i], this._fireMouseEvent, this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseClick: function(e) {
|
||||
if (this._map.dragging && this._map.dragging.moved()) { return; }
|
||||
this._fireMouseEvent(e);
|
||||
},
|
||||
|
||||
_fireMouseEvent: function(e) {
|
||||
if (!this.hasEventListeners(e.type)) { return; }
|
||||
this.fire(e.type, {
|
||||
latlng: this._map.mouseEventToLatLng(e),
|
||||
layerPoint: this._map.mouseEventToLayerPoint(e)
|
||||
});
|
||||
L.DomEvent.stopPropagation(e);
|
||||
},
|
||||
|
||||
_redraw: function() {
|
||||
this.projectLatlngs();
|
||||
this._updatePath();
|
||||
}
|
||||
});
|
||||
58
extlib/leaflet/src/layer/vector/Polygon.js
Normal file
58
extlib/leaflet/src/layer/vector/Polygon.js
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* L.Polygon is used to display polygons on a map.
|
||||
*/
|
||||
|
||||
L.Polygon = L.Polyline.extend({
|
||||
options: {
|
||||
fill: true
|
||||
},
|
||||
|
||||
initialize: function(latlngs, options) {
|
||||
L.Polyline.prototype.initialize.call(this, latlngs, options);
|
||||
|
||||
if (latlngs[0] instanceof Array) {
|
||||
this._latlngs = latlngs[0];
|
||||
this._holes = latlngs.slice(1);
|
||||
}
|
||||
},
|
||||
|
||||
projectLatlngs: function() {
|
||||
L.Polyline.prototype.projectLatlngs.call(this);
|
||||
|
||||
// project polygon holes points
|
||||
// TODO move this logic to Polyline to get rid of duplication
|
||||
this._holePoints = [];
|
||||
|
||||
if (!this._holes) return;
|
||||
|
||||
for (var i = 0, len = this._holes.length, hole; i < len; i++) {
|
||||
this._holePoints[i] = [];
|
||||
|
||||
for(var j = 0, len2 = this._holes[i].length; j < len2; j++) {
|
||||
this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_clipPoints: function() {
|
||||
var points = this._originalPoints,
|
||||
newParts = [];
|
||||
|
||||
this._parts = [points].concat(this._holePoints);
|
||||
|
||||
if (this.options.noClip) return;
|
||||
|
||||
for (var i = 0, len = this._parts.length; i < len; i++) {
|
||||
var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport);
|
||||
if (!clipped.length) continue;
|
||||
newParts.push(clipped);
|
||||
}
|
||||
|
||||
this._parts = newParts;
|
||||
},
|
||||
|
||||
_getPathPartStr: function(points) {
|
||||
var str = L.Polyline.prototype._getPathPartStr.call(this, points);
|
||||
return str + (L.Path.SVG ? 'z' : 'x');
|
||||
}
|
||||
});
|
||||
112
extlib/leaflet/src/layer/vector/Polyline.js
Normal file
112
extlib/leaflet/src/layer/vector/Polyline.js
Normal file
@@ -0,0 +1,112 @@
|
||||
|
||||
L.Polyline = L.Path.extend({
|
||||
initialize: function(latlngs, options) {
|
||||
L.Path.prototype.initialize.call(this, options);
|
||||
this._latlngs = latlngs;
|
||||
},
|
||||
|
||||
options: {
|
||||
// how much to simplify the polyline on each zoom level
|
||||
// more = better performance and smoother look, less = more accurate
|
||||
smoothFactor: 1.0,
|
||||
noClip: false,
|
||||
|
||||
updateOnMoveEnd: true
|
||||
},
|
||||
|
||||
projectLatlngs: function() {
|
||||
this._originalPoints = [];
|
||||
|
||||
for (var i = 0, len = this._latlngs.length; i < len; i++) {
|
||||
this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]);
|
||||
}
|
||||
},
|
||||
|
||||
getPathString: function() {
|
||||
for (var i = 0, len = this._parts.length, str = ''; i < len; i++) {
|
||||
str += this._getPathPartStr(this._parts[i]);
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
getLatLngs: function() {
|
||||
return this._latlngs;
|
||||
},
|
||||
|
||||
setLatLngs: function(latlngs) {
|
||||
this._latlngs = latlngs;
|
||||
this._redraw();
|
||||
return this;
|
||||
},
|
||||
|
||||
addLatLng: function(latlng) {
|
||||
this._latlngs.push(latlng);
|
||||
this._redraw();
|
||||
return this;
|
||||
},
|
||||
|
||||
spliceLatLngs: function(index, howMany) {
|
||||
var removed = [].splice.apply(this._latlngs, arguments);
|
||||
this._redraw();
|
||||
return removed;
|
||||
},
|
||||
|
||||
_getPathPartStr: function(points) {
|
||||
var round = L.Path.VML;
|
||||
|
||||
for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) {
|
||||
p = points[j];
|
||||
if (round) p._round();
|
||||
str += (j ? 'L' : 'M') + p.x + ' ' + p.y;
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
_clipPoints: function() {
|
||||
var points = this._originalPoints,
|
||||
len = points.length,
|
||||
i, k, segment;
|
||||
|
||||
if (this.options.noClip) {
|
||||
this._parts = [points];
|
||||
return;
|
||||
}
|
||||
|
||||
this._parts = [];
|
||||
|
||||
var parts = this._parts,
|
||||
vp = this._map._pathViewport,
|
||||
lu = L.LineUtil;
|
||||
|
||||
for (i = 0, k = 0; i < len - 1; i++) {
|
||||
segment = lu.clipSegment(points[i], points[i+1], vp, i);
|
||||
if (!segment) continue;
|
||||
|
||||
parts[k] = parts[k] || [];
|
||||
parts[k].push(segment[0]);
|
||||
|
||||
// if segment goes out of screen, or it's the last one, it's the end of the line part
|
||||
if ((segment[1] != points[i+1]) || (i == len - 2)) {
|
||||
parts[k].push(segment[1]);
|
||||
k++;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// simplify each clipped part of the polyline
|
||||
_simplifyPoints: function() {
|
||||
var parts = this._parts,
|
||||
lu = L.LineUtil;
|
||||
|
||||
for (var i = 0, len = parts.length; i < len; i++) {
|
||||
parts[i] = lu.simplify(parts[i], this.options.smoothFactor);
|
||||
}
|
||||
},
|
||||
|
||||
_updatePath: function() {
|
||||
this._clipPoints();
|
||||
this._simplifyPoints();
|
||||
|
||||
L.Path.prototype._updatePath.call(this);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user