`
- * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options.
- *
- * @example
- * ```js
- * var myIcon = L.divIcon({className: 'my-div-icon'});
- * // you can set .my-div-icon styles in CSS
- *
- * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
- * ```
- *
- * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.
- */
-
-L.DivIcon = L.Icon.extend({
- options: {
- // @section
- // @aka DivIcon options
- iconSize: [12, 12], // also can be set through CSS
-
- // iconAnchor: (Point),
- // popupAnchor: (Point),
-
- // @option html: String = ''
- // Custom HTML code to put inside the div element, empty by default.
- html: false,
-
- // @option bgPos: Point = [0, 0]
- // Optional relative position of the background, in pixels
- bgPos: null,
-
- className: 'leaflet-div-icon'
- },
-
- createIcon: function (oldIcon) {
- var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),
- options = this.options;
-
- div.innerHTML = options.html !== false ? options.html : '';
-
- if (options.bgPos) {
- var bgPos = L.point(options.bgPos);
- div.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px';
- }
- this._setIconStyles(div, 'icon');
-
- return div;
- },
-
- createShadow: function () {
- return null;
- }
-});
-
-// @factory L.divIcon(options: DivIcon options)
-// Creates a `DivIcon` instance with the given options.
-L.divIcon = function (options) {
- return new L.DivIcon(options);
-};
-
-
-
+
+
+
+/*
+ * @class DivIcon
+ * @aka L.DivIcon
+ * @inherits Icon
+ *
+ * Represents a lightweight icon for markers that uses a simple `
`
+ * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options.
+ *
+ * @example
+ * ```js
+ * var myIcon = L.divIcon({className: 'my-div-icon'});
+ * // you can set .my-div-icon styles in CSS
+ *
+ * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+ * ```
+ *
+ * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.
+ */
+
+L.DivIcon = L.Icon.extend({
+ options: {
+ // @section
+ // @aka DivIcon options
+ iconSize: [12, 12], // also can be set through CSS
+
+ // iconAnchor: (Point),
+ // popupAnchor: (Point),
+
+ // @option html: String = ''
+ // Custom HTML code to put inside the div element, empty by default.
+ html: false,
+
+ // @option bgPos: Point = [0, 0]
+ // Optional relative position of the background, in pixels
+ bgPos: null,
+
+ className: 'leaflet-div-icon'
+ },
+
+ createIcon: function (oldIcon) {
+ var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),
+ options = this.options;
+
+ div.innerHTML = options.html !== false ? options.html : '';
+
+ if (options.bgPos) {
+ var bgPos = L.point(options.bgPos);
+ div.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px';
+ }
+ this._setIconStyles(div, 'icon');
+
+ return div;
+ },
+
+ createShadow: function () {
+ return null;
+ }
+});
+
+// @factory L.divIcon(options: DivIcon options)
+// Creates a `DivIcon` instance with the given options.
+L.divIcon = function (options) {
+ return new L.DivIcon(options);
+};
+
+
+
/*
* @class DivOverlay
* @inherits Layer
@@ -6032,9 +6032,9 @@ L.DivOverlay = L.Layer.extend({
}
});
-
-
-
+
+
+
/*
* @class Popup
* @inherits DivOverlay
@@ -6369,184 +6369,184 @@ L.Map.include({
return this;
}
});
-
-
-
-/*
- * @namespace Layer
- * @section Popup methods example
- *
- * All layers share a set of methods convenient for binding popups to it.
- *
- * ```js
- * var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
- * layer.openPopup();
- * layer.closePopup();
- * ```
- *
- * Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.
- */
-
-// @section Popup methods
-L.Layer.include({
-
- // @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this
- // Binds a popup to the layer with the passed `content` and sets up the
- // neccessary event listeners. If a `Function` is passed it will receive
- // the layer as the first argument and should return a `String` or `HTMLElement`.
- bindPopup: function (content, options) {
-
- if (content instanceof L.Popup) {
- L.setOptions(content, options);
- this._popup = content;
- content._source = this;
- } else {
- if (!this._popup || options) {
- this._popup = new L.Popup(options, this);
- }
- this._popup.setContent(content);
- }
-
- if (!this._popupHandlersAdded) {
- this.on({
- click: this._openPopup,
- remove: this.closePopup,
- move: this._movePopup
- });
- this._popupHandlersAdded = true;
- }
-
- return this;
- },
-
- // @method unbindPopup(): this
- // Removes the popup previously bound with `bindPopup`.
- unbindPopup: function () {
- if (this._popup) {
- this.off({
- click: this._openPopup,
- remove: this.closePopup,
- move: this._movePopup
- });
- this._popupHandlersAdded = false;
- this._popup = null;
- }
- return this;
- },
-
- // @method openPopup(latlng?: LatLng): this
- // Opens the bound popup at the specificed `latlng` or at the default popup anchor if no `latlng` is passed.
- openPopup: function (layer, latlng) {
- if (!(layer instanceof L.Layer)) {
- latlng = layer;
- layer = this;
- }
-
- if (layer instanceof L.FeatureGroup) {
- for (var id in this._layers) {
- layer = this._layers[id];
- break;
- }
- }
-
- if (!latlng) {
- latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng();
- }
-
- if (this._popup && this._map) {
- // set popup source to this layer
- this._popup._source = layer;
-
- // update the popup (content, layout, ect...)
- this._popup.update();
-
- // open the popup on the map
- this._map.openPopup(this._popup, latlng);
- }
-
- return this;
- },
-
- // @method closePopup(): this
- // Closes the popup bound to this layer if it is open.
- closePopup: function () {
- if (this._popup) {
- this._popup._close();
- }
- return this;
- },
-
- // @method togglePopup(): this
- // Opens or closes the popup bound to this layer depending on its current state.
- togglePopup: function (target) {
- if (this._popup) {
- if (this._popup._map) {
- this.closePopup();
- } else {
- this.openPopup(target);
- }
- }
- return this;
- },
-
- // @method isPopupOpen(): boolean
- // Returns `true` if the popup bound to this layer is currently open.
- isPopupOpen: function () {
- return this._popup.isOpen();
- },
-
- // @method setPopupContent(content: String|HTMLElement|Popup): this
- // Sets the content of the popup bound to this layer.
- setPopupContent: function (content) {
- if (this._popup) {
- this._popup.setContent(content);
- }
- return this;
- },
-
- // @method getPopup(): Popup
- // Returns the popup bound to this layer.
- getPopup: function () {
- return this._popup;
- },
-
- _openPopup: function (e) {
- var layer = e.layer || e.target;
-
- if (!this._popup) {
- return;
- }
-
- if (!this._map) {
- return;
- }
-
- // prevent map click
- L.DomEvent.stop(e);
-
- // if this inherits from Path its a vector and we can just
- // open the popup at the new location
- if (layer instanceof L.Path) {
- this.openPopup(e.layer || e.target, e.latlng);
- return;
- }
-
- // otherwise treat it like a marker and figure out
- // if we should toggle it open/closed
- if (this._map.hasLayer(this._popup) && this._popup._source === layer) {
- this.closePopup();
- } else {
- this.openPopup(layer, e.latlng);
- }
- },
-
- _movePopup: function (e) {
- this._popup.setLatLng(e.latlng);
- }
-});
-
-
-
+
+
+
+/*
+ * @namespace Layer
+ * @section Popup methods example
+ *
+ * All layers share a set of methods convenient for binding popups to it.
+ *
+ * ```js
+ * var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
+ * layer.openPopup();
+ * layer.closePopup();
+ * ```
+ *
+ * Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.
+ */
+
+// @section Popup methods
+L.Layer.include({
+
+ // @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this
+ // Binds a popup to the layer with the passed `content` and sets up the
+ // neccessary event listeners. If a `Function` is passed it will receive
+ // the layer as the first argument and should return a `String` or `HTMLElement`.
+ bindPopup: function (content, options) {
+
+ if (content instanceof L.Popup) {
+ L.setOptions(content, options);
+ this._popup = content;
+ content._source = this;
+ } else {
+ if (!this._popup || options) {
+ this._popup = new L.Popup(options, this);
+ }
+ this._popup.setContent(content);
+ }
+
+ if (!this._popupHandlersAdded) {
+ this.on({
+ click: this._openPopup,
+ remove: this.closePopup,
+ move: this._movePopup
+ });
+ this._popupHandlersAdded = true;
+ }
+
+ return this;
+ },
+
+ // @method unbindPopup(): this
+ // Removes the popup previously bound with `bindPopup`.
+ unbindPopup: function () {
+ if (this._popup) {
+ this.off({
+ click: this._openPopup,
+ remove: this.closePopup,
+ move: this._movePopup
+ });
+ this._popupHandlersAdded = false;
+ this._popup = null;
+ }
+ return this;
+ },
+
+ // @method openPopup(latlng?: LatLng): this
+ // Opens the bound popup at the specificed `latlng` or at the default popup anchor if no `latlng` is passed.
+ openPopup: function (layer, latlng) {
+ if (!(layer instanceof L.Layer)) {
+ latlng = layer;
+ layer = this;
+ }
+
+ if (layer instanceof L.FeatureGroup) {
+ for (var id in this._layers) {
+ layer = this._layers[id];
+ break;
+ }
+ }
+
+ if (!latlng) {
+ latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng();
+ }
+
+ if (this._popup && this._map) {
+ // set popup source to this layer
+ this._popup._source = layer;
+
+ // update the popup (content, layout, ect...)
+ this._popup.update();
+
+ // open the popup on the map
+ this._map.openPopup(this._popup, latlng);
+ }
+
+ return this;
+ },
+
+ // @method closePopup(): this
+ // Closes the popup bound to this layer if it is open.
+ closePopup: function () {
+ if (this._popup) {
+ this._popup._close();
+ }
+ return this;
+ },
+
+ // @method togglePopup(): this
+ // Opens or closes the popup bound to this layer depending on its current state.
+ togglePopup: function (target) {
+ if (this._popup) {
+ if (this._popup._map) {
+ this.closePopup();
+ } else {
+ this.openPopup(target);
+ }
+ }
+ return this;
+ },
+
+ // @method isPopupOpen(): boolean
+ // Returns `true` if the popup bound to this layer is currently open.
+ isPopupOpen: function () {
+ return this._popup.isOpen();
+ },
+
+ // @method setPopupContent(content: String|HTMLElement|Popup): this
+ // Sets the content of the popup bound to this layer.
+ setPopupContent: function (content) {
+ if (this._popup) {
+ this._popup.setContent(content);
+ }
+ return this;
+ },
+
+ // @method getPopup(): Popup
+ // Returns the popup bound to this layer.
+ getPopup: function () {
+ return this._popup;
+ },
+
+ _openPopup: function (e) {
+ var layer = e.layer || e.target;
+
+ if (!this._popup) {
+ return;
+ }
+
+ if (!this._map) {
+ return;
+ }
+
+ // prevent map click
+ L.DomEvent.stop(e);
+
+ // if this inherits from Path its a vector and we can just
+ // open the popup at the new location
+ if (layer instanceof L.Path) {
+ this.openPopup(e.layer || e.target, e.latlng);
+ return;
+ }
+
+ // otherwise treat it like a marker and figure out
+ // if we should toggle it open/closed
+ if (this._map.hasLayer(this._popup) && this._popup._source === layer) {
+ this.closePopup();
+ } else {
+ this.openPopup(layer, e.latlng);
+ }
+ },
+
+ _movePopup: function (e) {
+ this._popup.setLatLng(e.latlng);
+ }
+});
+
+
+
/*
* Popup extension to L.Marker, adding popup-related methods.
*/
@@ -6556,422 +6556,422 @@ L.Marker.include({
return this.options.icon.options.popupAnchor || [0, 0];
}
});
-
-
-
-/*
- * @class Tooltip
- * @inherits DivOverlay
- * @aka L.Tooltip
- * Used to display small texts on top of map layers.
- *
- * @example
- *
- * ```js
- * marker.bindTooltip("my tooltip text").openTooltip();
- * ```
- * Note about tooltip offset. Leaflet takes two options in consideration
- * for computing tooltip offseting:
- * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.
- * Add a positive x offset to move the tooltip to the right, and a positive y offset to
- * move it to the bottom. Negatives will move to the left and top.
- * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You
- * should adapt this value if you use a custom icon.
- */
-
-
-// @namespace Tooltip
-L.Tooltip = L.DivOverlay.extend({
-
- // @section
- // @aka Tooltip options
- options: {
- // @option pane: String = 'tooltipPane'
- // `Map pane` where the tooltip will be added.
- pane: 'tooltipPane',
-
- // @option offset: Point = Point(0, 0)
- // Optional offset of the tooltip position.
- offset: [0, 0],
-
- // @option direction: String = 'auto'
- // Direction where to open the tooltip. Possible values are: `right`, `left`,
- // `top`, `bottom`, `center`, `auto`.
- // `auto` will dynamicaly switch between `right` and `left` according to the tooltip
- // position on the map.
- direction: 'auto',
-
- // @option permanent: Boolean = false
- // Whether to open the tooltip permanently or only on mouseover.
- permanent: false,
-
- // @option sticky: Boolean = false
- // If true, the tooltip will follow the mouse instead of being fixed at the feature center.
- sticky: false,
-
- // @option interactive: Boolean = false
- // If true, the tooltip will listen to the feature events.
- interactive: false,
-
- // @option opacity: Number = 0.9
- // Tooltip container opacity.
- opacity: 0.9
- },
-
- onAdd: function (map) {
- L.DivOverlay.prototype.onAdd.call(this, map);
- this.setOpacity(this.options.opacity);
-
- // @namespace Map
- // @section Tooltip events
- // @event tooltipopen: TooltipEvent
- // Fired when a tooltip is opened in the map.
- map.fire('tooltipopen', {tooltip: this});
-
- if (this._source) {
- // @namespace Layer
- // @section Tooltip events
- // @event tooltipopen: TooltipEvent
- // Fired when a tooltip bound to this layer is opened.
- this._source.fire('tooltipopen', {tooltip: this}, true);
- }
- },
-
- onRemove: function (map) {
- L.DivOverlay.prototype.onRemove.call(this, map);
-
- // @namespace Map
- // @section Tooltip events
- // @event tooltipclose: TooltipEvent
- // Fired when a tooltip in the map is closed.
- map.fire('tooltipclose', {tooltip: this});
-
- if (this._source) {
- // @namespace Layer
- // @section Tooltip events
- // @event tooltipclose: TooltipEvent
- // Fired when a tooltip bound to this layer is closed.
- this._source.fire('tooltipclose', {tooltip: this}, true);
- }
- },
-
- getEvents: function () {
- var events = L.DivOverlay.prototype.getEvents.call(this);
-
- if (L.Browser.touch && !this.options.permanent) {
- events.preclick = this._close;
- }
-
- return events;
- },
-
- _close: function () {
- if (this._map) {
- this._map.closeTooltip(this);
- }
- },
-
- _initLayout: function () {
- var prefix = 'leaflet-tooltip',
- className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');
-
- this._contentNode = this._container = L.DomUtil.create('div', className);
- },
-
- _updateLayout: function () {},
-
- _adjustPan: function () {},
-
- _setPosition: function (pos) {
- var map = this._map,
- container = this._container,
- centerPoint = map.latLngToContainerPoint(map.getCenter()),
- tooltipPoint = map.layerPointToContainerPoint(pos),
- direction = this.options.direction,
- tooltipWidth = container.offsetWidth,
- tooltipHeight = container.offsetHeight,
- offset = L.point(this.options.offset),
- anchor = this._getAnchor();
-
- if (direction === 'top') {
- pos = pos.add(L.point(-tooltipWidth / 2 + offset.x, -tooltipHeight + offset.y + anchor.y));
- } else if (direction === 'bottom') {
- pos = pos.subtract(L.point(tooltipWidth / 2 - offset.x, -offset.y));
- } else if (direction === 'center') {
- pos = pos.subtract(L.point(tooltipWidth / 2 + offset.x, tooltipHeight / 2 - anchor.y + offset.y));
- } else if (direction === 'right' || direction === 'auto' && tooltipPoint.x < centerPoint.x) {
- direction = 'right';
- pos = pos.add([offset.x + anchor.x, anchor.y - tooltipHeight / 2 + offset.y]);
- } else {
- direction = 'left';
- pos = pos.subtract(L.point(tooltipWidth + anchor.x - offset.x, tooltipHeight / 2 - anchor.y - offset.y));
- }
-
- L.DomUtil.removeClass(container, 'leaflet-tooltip-right');
- L.DomUtil.removeClass(container, 'leaflet-tooltip-left');
- L.DomUtil.removeClass(container, 'leaflet-tooltip-top');
- L.DomUtil.removeClass(container, 'leaflet-tooltip-bottom');
- L.DomUtil.addClass(container, 'leaflet-tooltip-' + direction);
- L.DomUtil.setPosition(container, pos);
- },
-
- _updatePosition: function () {
- var pos = this._map.latLngToLayerPoint(this._latlng);
- this._setPosition(pos);
- },
-
- setOpacity: function (opacity) {
- this.options.opacity = opacity;
-
- if (this._container) {
- L.DomUtil.setOpacity(this._container, opacity);
- }
- },
-
- _animateZoom: function (e) {
- var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
- this._setPosition(pos);
- },
-
- _getAnchor: function () {
- // Where should we anchor the tooltip on the source layer?
- return L.point(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
- }
-
-});
-
-// @namespace Tooltip
-// @factory L.tooltip(options?: Tooltip options, source?: Layer)
-// Instantiates a Tooltip object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers.
-L.tooltip = function (options, source) {
- return new L.Tooltip(options, source);
-};
-
-// @namespace Map
-// @section Methods for Layers and Controls
-L.Map.include({
-
- // @method openTooltip(tooltip: Tooltip): this
- // Opens the specified tooltip.
- // @alternative
- // @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this
- // Creates a tooltip with the specified content and options and open it.
- openTooltip: function (tooltip, latlng, options) {
- if (!(tooltip instanceof L.Tooltip)) {
- tooltip = new L.Tooltip(options).setContent(tooltip);
- }
-
- if (latlng) {
- tooltip.setLatLng(latlng);
- }
-
- if (this.hasLayer(tooltip)) {
- return this;
- }
-
- return this.addLayer(tooltip);
- },
-
- // @method closeTooltip(tooltip?: Tooltip): this
- // Closes the tooltip given as parameter.
- closeTooltip: function (tooltip) {
- if (tooltip) {
- this.removeLayer(tooltip);
- }
- return this;
- }
-
-});
-
-
-
-/*
- * @namespace Layer
- * @section Tooltip methods example
- *
- * All layers share a set of methods convenient for binding tooltips to it.
- *
- * ```js
- * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
- * layer.openTooltip();
- * layer.closeTooltip();
- * ```
- */
-
-// @section Tooltip methods
-L.Layer.include({
-
- // @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this
- // Binds a tooltip to the layer with the passed `content` and sets up the
- // neccessary event listeners. If a `Function` is passed it will receive
- // the layer as the first argument and should return a `String` or `HTMLElement`.
- bindTooltip: function (content, options) {
-
- if (content instanceof L.Tooltip) {
- L.setOptions(content, options);
- this._tooltip = content;
- content._source = this;
- } else {
- if (!this._tooltip || options) {
- this._tooltip = L.tooltip(options, this);
- }
- this._tooltip.setContent(content);
-
- }
-
- this._initTooltipInteractions();
-
- if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) {
- this.openTooltip();
- }
-
- return this;
- },
-
- // @method unbindTooltip(): this
- // Removes the tooltip previously bound with `bindTooltip`.
- unbindTooltip: function () {
- if (this._tooltip) {
- this._initTooltipInteractions(true);
- this.closeTooltip();
- this._tooltip = null;
- }
- return this;
- },
-
- _initTooltipInteractions: function (remove) {
- if (!remove && this._tooltipHandlersAdded) { return; }
- var onOff = remove ? 'off' : 'on',
- events = {
- remove: this.closeTooltip,
- move: this._moveTooltip
- };
- if (!this._tooltip.options.permanent) {
- events.mouseover = this._openTooltip;
- events.mouseout = this.closeTooltip;
- if (this._tooltip.options.sticky) {
- events.mousemove = this._moveTooltip;
- }
- if (L.Browser.touch) {
- events.click = this._openTooltip;
- }
- } else {
- events.add = this._openTooltip;
- }
- this[onOff](events);
- this._tooltipHandlersAdded = !remove;
- },
-
- // @method openTooltip(latlng?: LatLng): this
- // Opens the bound tooltip at the specificed `latlng` or at the default tooltip anchor if no `latlng` is passed.
- openTooltip: function (layer, latlng) {
- if (!(layer instanceof L.Layer)) {
- latlng = layer;
- layer = this;
- }
-
- if (layer instanceof L.FeatureGroup) {
- for (var id in this._layers) {
- layer = this._layers[id];
- break;
- }
- }
-
- if (!latlng) {
- latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng();
- }
-
- if (this._tooltip && this._map) {
-
- // set tooltip source to this layer
- this._tooltip._source = layer;
-
- // update the tooltip (content, layout, ect...)
- this._tooltip.update();
-
- // open the tooltip on the map
- this._map.openTooltip(this._tooltip, latlng);
-
- // Tooltip container may not be defined if not permanent and never
- // opened.
- if (this._tooltip.options.interactive && this._tooltip._container) {
- L.DomUtil.addClass(this._tooltip._container, 'leaflet-clickable');
- this.addInteractiveTarget(this._tooltip._container);
- }
- }
-
- return this;
- },
-
- // @method closeTooltip(): this
- // Closes the tooltip bound to this layer if it is open.
- closeTooltip: function () {
- if (this._tooltip) {
- this._tooltip._close();
- if (this._tooltip.options.interactive && this._tooltip._container) {
- L.DomUtil.removeClass(this._tooltip._container, 'leaflet-clickable');
- this.removeInteractiveTarget(this._tooltip._container);
- }
- }
- return this;
- },
-
- // @method toggleTooltip(): this
- // Opens or closes the tooltip bound to this layer depending on its current state.
- toggleTooltip: function (target) {
- if (this._tooltip) {
- if (this._tooltip._map) {
- this.closeTooltip();
- } else {
- this.openTooltip(target);
- }
- }
- return this;
- },
-
- // @method isTooltipOpen(): boolean
- // Returns `true` if the tooltip bound to this layer is currently open.
- isTooltipOpen: function () {
- return this._tooltip.isOpen();
- },
-
- // @method setTooltipContent(content: String|HTMLElement|Tooltip): this
- // Sets the content of the tooltip bound to this layer.
- setTooltipContent: function (content) {
- if (this._tooltip) {
- this._tooltip.setContent(content);
- }
- return this;
- },
-
- // @method getTooltip(): Tooltip
- // Returns the tooltip bound to this layer.
- getTooltip: function () {
- return this._tooltip;
- },
-
- _openTooltip: function (e) {
- var layer = e.layer || e.target;
-
- if (!this._tooltip || !this._map) {
- return;
- }
- this.openTooltip(layer, this._tooltip.options.sticky ? e.latlng : undefined);
- },
-
- _moveTooltip: function (e) {
- var latlng = e.latlng, containerPoint, layerPoint;
- if (this._tooltip.options.sticky && e.originalEvent) {
- containerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);
- layerPoint = this._map.containerPointToLayerPoint(containerPoint);
- latlng = this._map.layerPointToLatLng(layerPoint);
- }
- this._tooltip.setLatLng(latlng);
- }
-});
-
-
-
+
+
+
+/*
+ * @class Tooltip
+ * @inherits DivOverlay
+ * @aka L.Tooltip
+ * Used to display small texts on top of map layers.
+ *
+ * @example
+ *
+ * ```js
+ * marker.bindTooltip("my tooltip text").openTooltip();
+ * ```
+ * Note about tooltip offset. Leaflet takes two options in consideration
+ * for computing tooltip offseting:
+ * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.
+ * Add a positive x offset to move the tooltip to the right, and a positive y offset to
+ * move it to the bottom. Negatives will move to the left and top.
+ * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You
+ * should adapt this value if you use a custom icon.
+ */
+
+
+// @namespace Tooltip
+L.Tooltip = L.DivOverlay.extend({
+
+ // @section
+ // @aka Tooltip options
+ options: {
+ // @option pane: String = 'tooltipPane'
+ // `Map pane` where the tooltip will be added.
+ pane: 'tooltipPane',
+
+ // @option offset: Point = Point(0, 0)
+ // Optional offset of the tooltip position.
+ offset: [0, 0],
+
+ // @option direction: String = 'auto'
+ // Direction where to open the tooltip. Possible values are: `right`, `left`,
+ // `top`, `bottom`, `center`, `auto`.
+ // `auto` will dynamicaly switch between `right` and `left` according to the tooltip
+ // position on the map.
+ direction: 'auto',
+
+ // @option permanent: Boolean = false
+ // Whether to open the tooltip permanently or only on mouseover.
+ permanent: false,
+
+ // @option sticky: Boolean = false
+ // If true, the tooltip will follow the mouse instead of being fixed at the feature center.
+ sticky: false,
+
+ // @option interactive: Boolean = false
+ // If true, the tooltip will listen to the feature events.
+ interactive: false,
+
+ // @option opacity: Number = 0.9
+ // Tooltip container opacity.
+ opacity: 0.9
+ },
+
+ onAdd: function (map) {
+ L.DivOverlay.prototype.onAdd.call(this, map);
+ this.setOpacity(this.options.opacity);
+
+ // @namespace Map
+ // @section Tooltip events
+ // @event tooltipopen: TooltipEvent
+ // Fired when a tooltip is opened in the map.
+ map.fire('tooltipopen', {tooltip: this});
+
+ if (this._source) {
+ // @namespace Layer
+ // @section Tooltip events
+ // @event tooltipopen: TooltipEvent
+ // Fired when a tooltip bound to this layer is opened.
+ this._source.fire('tooltipopen', {tooltip: this}, true);
+ }
+ },
+
+ onRemove: function (map) {
+ L.DivOverlay.prototype.onRemove.call(this, map);
+
+ // @namespace Map
+ // @section Tooltip events
+ // @event tooltipclose: TooltipEvent
+ // Fired when a tooltip in the map is closed.
+ map.fire('tooltipclose', {tooltip: this});
+
+ if (this._source) {
+ // @namespace Layer
+ // @section Tooltip events
+ // @event tooltipclose: TooltipEvent
+ // Fired when a tooltip bound to this layer is closed.
+ this._source.fire('tooltipclose', {tooltip: this}, true);
+ }
+ },
+
+ getEvents: function () {
+ var events = L.DivOverlay.prototype.getEvents.call(this);
+
+ if (L.Browser.touch && !this.options.permanent) {
+ events.preclick = this._close;
+ }
+
+ return events;
+ },
+
+ _close: function () {
+ if (this._map) {
+ this._map.closeTooltip(this);
+ }
+ },
+
+ _initLayout: function () {
+ var prefix = 'leaflet-tooltip',
+ className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');
+
+ this._contentNode = this._container = L.DomUtil.create('div', className);
+ },
+
+ _updateLayout: function () {},
+
+ _adjustPan: function () {},
+
+ _setPosition: function (pos) {
+ var map = this._map,
+ container = this._container,
+ centerPoint = map.latLngToContainerPoint(map.getCenter()),
+ tooltipPoint = map.layerPointToContainerPoint(pos),
+ direction = this.options.direction,
+ tooltipWidth = container.offsetWidth,
+ tooltipHeight = container.offsetHeight,
+ offset = L.point(this.options.offset),
+ anchor = this._getAnchor();
+
+ if (direction === 'top') {
+ pos = pos.add(L.point(-tooltipWidth / 2 + offset.x, -tooltipHeight + offset.y + anchor.y));
+ } else if (direction === 'bottom') {
+ pos = pos.subtract(L.point(tooltipWidth / 2 - offset.x, -offset.y));
+ } else if (direction === 'center') {
+ pos = pos.subtract(L.point(tooltipWidth / 2 + offset.x, tooltipHeight / 2 - anchor.y + offset.y));
+ } else if (direction === 'right' || direction === 'auto' && tooltipPoint.x < centerPoint.x) {
+ direction = 'right';
+ pos = pos.add([offset.x + anchor.x, anchor.y - tooltipHeight / 2 + offset.y]);
+ } else {
+ direction = 'left';
+ pos = pos.subtract(L.point(tooltipWidth + anchor.x - offset.x, tooltipHeight / 2 - anchor.y - offset.y));
+ }
+
+ L.DomUtil.removeClass(container, 'leaflet-tooltip-right');
+ L.DomUtil.removeClass(container, 'leaflet-tooltip-left');
+ L.DomUtil.removeClass(container, 'leaflet-tooltip-top');
+ L.DomUtil.removeClass(container, 'leaflet-tooltip-bottom');
+ L.DomUtil.addClass(container, 'leaflet-tooltip-' + direction);
+ L.DomUtil.setPosition(container, pos);
+ },
+
+ _updatePosition: function () {
+ var pos = this._map.latLngToLayerPoint(this._latlng);
+ this._setPosition(pos);
+ },
+
+ setOpacity: function (opacity) {
+ this.options.opacity = opacity;
+
+ if (this._container) {
+ L.DomUtil.setOpacity(this._container, opacity);
+ }
+ },
+
+ _animateZoom: function (e) {
+ var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
+ this._setPosition(pos);
+ },
+
+ _getAnchor: function () {
+ // Where should we anchor the tooltip on the source layer?
+ return L.point(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
+ }
+
+});
+
+// @namespace Tooltip
+// @factory L.tooltip(options?: Tooltip options, source?: Layer)
+// Instantiates a Tooltip object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers.
+L.tooltip = function (options, source) {
+ return new L.Tooltip(options, source);
+};
+
+// @namespace Map
+// @section Methods for Layers and Controls
+L.Map.include({
+
+ // @method openTooltip(tooltip: Tooltip): this
+ // Opens the specified tooltip.
+ // @alternative
+ // @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this
+ // Creates a tooltip with the specified content and options and open it.
+ openTooltip: function (tooltip, latlng, options) {
+ if (!(tooltip instanceof L.Tooltip)) {
+ tooltip = new L.Tooltip(options).setContent(tooltip);
+ }
+
+ if (latlng) {
+ tooltip.setLatLng(latlng);
+ }
+
+ if (this.hasLayer(tooltip)) {
+ return this;
+ }
+
+ return this.addLayer(tooltip);
+ },
+
+ // @method closeTooltip(tooltip?: Tooltip): this
+ // Closes the tooltip given as parameter.
+ closeTooltip: function (tooltip) {
+ if (tooltip) {
+ this.removeLayer(tooltip);
+ }
+ return this;
+ }
+
+});
+
+
+
+/*
+ * @namespace Layer
+ * @section Tooltip methods example
+ *
+ * All layers share a set of methods convenient for binding tooltips to it.
+ *
+ * ```js
+ * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
+ * layer.openTooltip();
+ * layer.closeTooltip();
+ * ```
+ */
+
+// @section Tooltip methods
+L.Layer.include({
+
+ // @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this
+ // Binds a tooltip to the layer with the passed `content` and sets up the
+ // neccessary event listeners. If a `Function` is passed it will receive
+ // the layer as the first argument and should return a `String` or `HTMLElement`.
+ bindTooltip: function (content, options) {
+
+ if (content instanceof L.Tooltip) {
+ L.setOptions(content, options);
+ this._tooltip = content;
+ content._source = this;
+ } else {
+ if (!this._tooltip || options) {
+ this._tooltip = L.tooltip(options, this);
+ }
+ this._tooltip.setContent(content);
+
+ }
+
+ this._initTooltipInteractions();
+
+ if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) {
+ this.openTooltip();
+ }
+
+ return this;
+ },
+
+ // @method unbindTooltip(): this
+ // Removes the tooltip previously bound with `bindTooltip`.
+ unbindTooltip: function () {
+ if (this._tooltip) {
+ this._initTooltipInteractions(true);
+ this.closeTooltip();
+ this._tooltip = null;
+ }
+ return this;
+ },
+
+ _initTooltipInteractions: function (remove) {
+ if (!remove && this._tooltipHandlersAdded) { return; }
+ var onOff = remove ? 'off' : 'on',
+ events = {
+ remove: this.closeTooltip,
+ move: this._moveTooltip
+ };
+ if (!this._tooltip.options.permanent) {
+ events.mouseover = this._openTooltip;
+ events.mouseout = this.closeTooltip;
+ if (this._tooltip.options.sticky) {
+ events.mousemove = this._moveTooltip;
+ }
+ if (L.Browser.touch) {
+ events.click = this._openTooltip;
+ }
+ } else {
+ events.add = this._openTooltip;
+ }
+ this[onOff](events);
+ this._tooltipHandlersAdded = !remove;
+ },
+
+ // @method openTooltip(latlng?: LatLng): this
+ // Opens the bound tooltip at the specificed `latlng` or at the default tooltip anchor if no `latlng` is passed.
+ openTooltip: function (layer, latlng) {
+ if (!(layer instanceof L.Layer)) {
+ latlng = layer;
+ layer = this;
+ }
+
+ if (layer instanceof L.FeatureGroup) {
+ for (var id in this._layers) {
+ layer = this._layers[id];
+ break;
+ }
+ }
+
+ if (!latlng) {
+ latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng();
+ }
+
+ if (this._tooltip && this._map) {
+
+ // set tooltip source to this layer
+ this._tooltip._source = layer;
+
+ // update the tooltip (content, layout, ect...)
+ this._tooltip.update();
+
+ // open the tooltip on the map
+ this._map.openTooltip(this._tooltip, latlng);
+
+ // Tooltip container may not be defined if not permanent and never
+ // opened.
+ if (this._tooltip.options.interactive && this._tooltip._container) {
+ L.DomUtil.addClass(this._tooltip._container, 'leaflet-clickable');
+ this.addInteractiveTarget(this._tooltip._container);
+ }
+ }
+
+ return this;
+ },
+
+ // @method closeTooltip(): this
+ // Closes the tooltip bound to this layer if it is open.
+ closeTooltip: function () {
+ if (this._tooltip) {
+ this._tooltip._close();
+ if (this._tooltip.options.interactive && this._tooltip._container) {
+ L.DomUtil.removeClass(this._tooltip._container, 'leaflet-clickable');
+ this.removeInteractiveTarget(this._tooltip._container);
+ }
+ }
+ return this;
+ },
+
+ // @method toggleTooltip(): this
+ // Opens or closes the tooltip bound to this layer depending on its current state.
+ toggleTooltip: function (target) {
+ if (this._tooltip) {
+ if (this._tooltip._map) {
+ this.closeTooltip();
+ } else {
+ this.openTooltip(target);
+ }
+ }
+ return this;
+ },
+
+ // @method isTooltipOpen(): boolean
+ // Returns `true` if the tooltip bound to this layer is currently open.
+ isTooltipOpen: function () {
+ return this._tooltip.isOpen();
+ },
+
+ // @method setTooltipContent(content: String|HTMLElement|Tooltip): this
+ // Sets the content of the tooltip bound to this layer.
+ setTooltipContent: function (content) {
+ if (this._tooltip) {
+ this._tooltip.setContent(content);
+ }
+ return this;
+ },
+
+ // @method getTooltip(): Tooltip
+ // Returns the tooltip bound to this layer.
+ getTooltip: function () {
+ return this._tooltip;
+ },
+
+ _openTooltip: function (e) {
+ var layer = e.layer || e.target;
+
+ if (!this._tooltip || !this._map) {
+ return;
+ }
+ this.openTooltip(layer, this._tooltip.options.sticky ? e.latlng : undefined);
+ },
+
+ _moveTooltip: function (e) {
+ var latlng = e.latlng, containerPoint, layerPoint;
+ if (this._tooltip.options.sticky && e.originalEvent) {
+ containerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);
+ layerPoint = this._map.containerPointToLayerPoint(containerPoint);
+ latlng = this._map.layerPointToLatLng(layerPoint);
+ }
+ this._tooltip.setLatLng(latlng);
+ }
+});
+
+
+
/*
* Tooltip extension to L.Marker, adding tooltip-related methods.
*/
@@ -6981,9 +6981,9 @@ L.Marker.include({
return this.options.icon.options.tooltipAnchor || [0, 0];
}
});
-
-
-
+
+
+
/*
* @class LayerGroup
* @aka L.LayerGroup
@@ -7143,9 +7143,9 @@ L.LayerGroup = L.Layer.extend({
L.layerGroup = function (layers) {
return new L.LayerGroup(layers);
};
-
-
-
+
+
+
/*
* @class FeatureGroup
* @aka L.FeatureGroup
@@ -7237,307 +7237,307 @@ L.FeatureGroup = L.LayerGroup.extend({
L.featureGroup = function (layers) {
return new L.FeatureGroup(layers);
};
-
-
-
-/*
- * @class Renderer
- * @inherits Layer
- * @aka L.Renderer
- *
- * Base class for vector renderer implementations (`SVG`, `Canvas`). Handles the
- * DOM container of the renderer, its bounds, and its zoom animation.
- *
- * A `Renderer` works as an implicit layer group for all `Path`s - the renderer
- * itself can be added or removed to the map. All paths use a renderer, which can
- * be implicit (the map will decide the type of renderer and use it automatically)
- * or explicit (using the [`renderer`](#path-renderer) option of the path).
- *
- * Do not use this class directly, use `SVG` and `Canvas` instead.
- *
- * @event update: Event
- * Fired when the renderer updates its bounds, center and zoom, for example when
- * its map has moved
- */
-
-L.Renderer = L.Layer.extend({
-
- // @section
- // @aka Renderer options
- options: {
- // @option padding: Number = 0.1
- // How much to extend the clip area around the map view (relative to its size)
- // e.g. 0.1 would be 10% of map view in each direction
- padding: 0.1
- },
-
- initialize: function (options) {
- L.setOptions(this, options);
- L.stamp(this);
- },
-
- onAdd: function () {
- if (!this._container) {
- this._initContainer(); // defined by renderer implementations
-
- if (this._zoomAnimated) {
- L.DomUtil.addClass(this._container, 'leaflet-zoom-animated');
- }
- }
-
- this.getPane().appendChild(this._container);
- this._update();
- },
-
- onRemove: function () {
- L.DomUtil.remove(this._container);
- },
-
- getEvents: function () {
- var events = {
- viewreset: this._reset,
- zoom: this._onZoom,
- moveend: this._update
- };
- if (this._zoomAnimated) {
- events.zoomanim = this._onAnimZoom;
- }
- return events;
- },
-
- _onAnimZoom: function (ev) {
- this._updateTransform(ev.center, ev.zoom);
- },
-
- _onZoom: function () {
- this._updateTransform(this._map.getCenter(), this._map.getZoom());
- },
-
- _updateTransform: function (center, zoom) {
- var scale = this._map.getZoomScale(zoom, this._zoom),
- position = L.DomUtil.getPosition(this._container),
- viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding),
- currentCenterPoint = this._map.project(this._center, zoom),
- destCenterPoint = this._map.project(center, zoom),
- centerOffset = destCenterPoint.subtract(currentCenterPoint),
-
- topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(viewHalf).subtract(centerOffset);
-
- if (L.Browser.any3d) {
- L.DomUtil.setTransform(this._container, topLeftOffset, scale);
- } else {
- L.DomUtil.setPosition(this._container, topLeftOffset);
- }
- },
-
- _reset: function () {
- this._update();
- this._updateTransform(this._center, this._zoom);
- },
-
- _update: function () {
- // Update pixel bounds of renderer container (for positioning/sizing/clipping later)
- // Subclasses are responsible of firing the 'update' event.
- var p = this.options.padding,
- size = this._map.getSize(),
- min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();
-
- this._bounds = new L.Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round());
-
- this._center = this._map.getCenter();
- this._zoom = this._map.getZoom();
- }
-});
-
-
-L.Map.include({
- // @namespace Map; @method getRenderer(layer: Path): Renderer
- // Returns the instance of `Renderer` that should be used to render the given
- // `Path`. It will ensure that the `renderer` options of the map and paths
- // are respected, and that the renderers do exist on the map.
- getRenderer: function (layer) {
- // @namespace Path; @option renderer: Renderer
- // Use this specific instance of `Renderer` for this path. Takes
- // precedence over the map's [default renderer](#map-renderer).
- var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;
-
- if (!renderer) {
- // @namespace Map; @option preferCanvas: Boolean = false
- // Whether `Path`s should be rendered on a `Canvas` renderer.
- // By default, all `Path`s are rendered in a `SVG` renderer.
- renderer = this._renderer = (this.options.preferCanvas && L.canvas()) || L.svg();
- }
-
- if (!this.hasLayer(renderer)) {
- this.addLayer(renderer);
- }
- return renderer;
- },
-
- _getPaneRenderer: function (name) {
- if (name === 'overlayPane' || name === undefined) {
- return false;
- }
-
- var renderer = this._paneRenderers[name];
- if (renderer === undefined) {
- renderer = (L.SVG && L.svg({pane: name})) || (L.Canvas && L.canvas({pane: name}));
- this._paneRenderers[name] = renderer;
- }
- return renderer;
- }
-});
-
-
-
-/*
- * @class Path
- * @aka L.Path
- * @inherits Interactive layer
- *
- * An abstract class that contains options and constants shared between vector
- * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.
- */
-
-L.Path = L.Layer.extend({
-
- // @section
- // @aka Path options
- options: {
- // @option stroke: Boolean = true
- // Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.
- stroke: true,
-
- // @option color: String = '#3388ff'
- // Stroke color
- color: '#3388ff',
-
- // @option weight: Number = 3
- // Stroke width in pixels
- weight: 3,
-
- // @option opacity: Number = 1.0
- // Stroke opacity
- opacity: 1,
-
- // @option lineCap: String= 'round'
- // A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.
- lineCap: 'round',
-
- // @option lineJoin: String = 'round'
- // A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.
- lineJoin: 'round',
-
- // @option dashArray: String = null
- // A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
- dashArray: null,
-
- // @option dashOffset: String = null
- // A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
- dashOffset: null,
-
- // @option fill: Boolean = depends
- // Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.
- fill: false,
-
- // @option fillColor: String = *
- // Fill color. Defaults to the value of the [`color`](#path-color) option
- fillColor: null,
-
- // @option fillOpacity: Number = 0.2
- // Fill opacity.
- fillOpacity: 0.2,
-
- // @option fillRule: String = 'evenodd'
- // A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.
- fillRule: 'evenodd',
-
- // className: '',
-
- // Option inherited from "Interactive layer" abstract class
- interactive: true
- },
-
- beforeAdd: function (map) {
- // Renderer is set here because we need to call renderer.getEvents
- // before this.getEvents.
- this._renderer = map.getRenderer(this);
- },
-
- onAdd: function () {
- this._renderer._initPath(this);
- this._reset();
- this._renderer._addPath(this);
- this._renderer.on('update', this._update, this);
- },
-
- onRemove: function () {
- this._renderer._removePath(this);
- this._renderer.off('update', this._update, this);
- },
-
- getEvents: function () {
- return {
- zoomend: this._project,
- viewreset: this._reset
- };
- },
-
- // @method redraw(): this
- // Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.
- redraw: function () {
- if (this._map) {
- this._renderer._updatePath(this);
- }
- return this;
- },
-
- // @method setStyle(style: Path options): this
- // Changes the appearance of a Path based on the options in the `Path options` object.
- setStyle: function (style) {
- L.setOptions(this, style);
- if (this._renderer) {
- this._renderer._updateStyle(this);
- }
- return this;
- },
-
- // @method bringToFront(): this
- // Brings the layer to the top of all path layers.
- bringToFront: function () {
- if (this._renderer) {
- this._renderer._bringToFront(this);
- }
- return this;
- },
-
- // @method bringToBack(): this
- // Brings the layer to the bottom of all path layers.
- bringToBack: function () {
- if (this._renderer) {
- this._renderer._bringToBack(this);
- }
- return this;
- },
-
- getElement: function () {
- return this._path;
- },
-
- _reset: function () {
- // defined in children classes
- this._project();
- this._update();
- },
-
- _clickTolerance: function () {
- // used when doing hit detection for Canvas layers
- return (this.options.stroke ? this.options.weight / 2 : 0) + (L.Browser.touch ? 10 : 0);
- }
-});
-
-
-
+
+
+
+/*
+ * @class Renderer
+ * @inherits Layer
+ * @aka L.Renderer
+ *
+ * Base class for vector renderer implementations (`SVG`, `Canvas`). Handles the
+ * DOM container of the renderer, its bounds, and its zoom animation.
+ *
+ * A `Renderer` works as an implicit layer group for all `Path`s - the renderer
+ * itself can be added or removed to the map. All paths use a renderer, which can
+ * be implicit (the map will decide the type of renderer and use it automatically)
+ * or explicit (using the [`renderer`](#path-renderer) option of the path).
+ *
+ * Do not use this class directly, use `SVG` and `Canvas` instead.
+ *
+ * @event update: Event
+ * Fired when the renderer updates its bounds, center and zoom, for example when
+ * its map has moved
+ */
+
+L.Renderer = L.Layer.extend({
+
+ // @section
+ // @aka Renderer options
+ options: {
+ // @option padding: Number = 0.1
+ // How much to extend the clip area around the map view (relative to its size)
+ // e.g. 0.1 would be 10% of map view in each direction
+ padding: 0.1
+ },
+
+ initialize: function (options) {
+ L.setOptions(this, options);
+ L.stamp(this);
+ },
+
+ onAdd: function () {
+ if (!this._container) {
+ this._initContainer(); // defined by renderer implementations
+
+ if (this._zoomAnimated) {
+ L.DomUtil.addClass(this._container, 'leaflet-zoom-animated');
+ }
+ }
+
+ this.getPane().appendChild(this._container);
+ this._update();
+ },
+
+ onRemove: function () {
+ L.DomUtil.remove(this._container);
+ },
+
+ getEvents: function () {
+ var events = {
+ viewreset: this._reset,
+ zoom: this._onZoom,
+ moveend: this._update
+ };
+ if (this._zoomAnimated) {
+ events.zoomanim = this._onAnimZoom;
+ }
+ return events;
+ },
+
+ _onAnimZoom: function (ev) {
+ this._updateTransform(ev.center, ev.zoom);
+ },
+
+ _onZoom: function () {
+ this._updateTransform(this._map.getCenter(), this._map.getZoom());
+ },
+
+ _updateTransform: function (center, zoom) {
+ var scale = this._map.getZoomScale(zoom, this._zoom),
+ position = L.DomUtil.getPosition(this._container),
+ viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding),
+ currentCenterPoint = this._map.project(this._center, zoom),
+ destCenterPoint = this._map.project(center, zoom),
+ centerOffset = destCenterPoint.subtract(currentCenterPoint),
+
+ topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(viewHalf).subtract(centerOffset);
+
+ if (L.Browser.any3d) {
+ L.DomUtil.setTransform(this._container, topLeftOffset, scale);
+ } else {
+ L.DomUtil.setPosition(this._container, topLeftOffset);
+ }
+ },
+
+ _reset: function () {
+ this._update();
+ this._updateTransform(this._center, this._zoom);
+ },
+
+ _update: function () {
+ // Update pixel bounds of renderer container (for positioning/sizing/clipping later)
+ // Subclasses are responsible of firing the 'update' event.
+ var p = this.options.padding,
+ size = this._map.getSize(),
+ min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();
+
+ this._bounds = new L.Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round());
+
+ this._center = this._map.getCenter();
+ this._zoom = this._map.getZoom();
+ }
+});
+
+
+L.Map.include({
+ // @namespace Map; @method getRenderer(layer: Path): Renderer
+ // Returns the instance of `Renderer` that should be used to render the given
+ // `Path`. It will ensure that the `renderer` options of the map and paths
+ // are respected, and that the renderers do exist on the map.
+ getRenderer: function (layer) {
+ // @namespace Path; @option renderer: Renderer
+ // Use this specific instance of `Renderer` for this path. Takes
+ // precedence over the map's [default renderer](#map-renderer).
+ var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;
+
+ if (!renderer) {
+ // @namespace Map; @option preferCanvas: Boolean = false
+ // Whether `Path`s should be rendered on a `Canvas` renderer.
+ // By default, all `Path`s are rendered in a `SVG` renderer.
+ renderer = this._renderer = (this.options.preferCanvas && L.canvas()) || L.svg();
+ }
+
+ if (!this.hasLayer(renderer)) {
+ this.addLayer(renderer);
+ }
+ return renderer;
+ },
+
+ _getPaneRenderer: function (name) {
+ if (name === 'overlayPane' || name === undefined) {
+ return false;
+ }
+
+ var renderer = this._paneRenderers[name];
+ if (renderer === undefined) {
+ renderer = (L.SVG && L.svg({pane: name})) || (L.Canvas && L.canvas({pane: name}));
+ this._paneRenderers[name] = renderer;
+ }
+ return renderer;
+ }
+});
+
+
+
+/*
+ * @class Path
+ * @aka L.Path
+ * @inherits Interactive layer
+ *
+ * An abstract class that contains options and constants shared between vector
+ * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.
+ */
+
+L.Path = L.Layer.extend({
+
+ // @section
+ // @aka Path options
+ options: {
+ // @option stroke: Boolean = true
+ // Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.
+ stroke: true,
+
+ // @option color: String = '#3388ff'
+ // Stroke color
+ color: '#3388ff',
+
+ // @option weight: Number = 3
+ // Stroke width in pixels
+ weight: 3,
+
+ // @option opacity: Number = 1.0
+ // Stroke opacity
+ opacity: 1,
+
+ // @option lineCap: String= 'round'
+ // A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.
+ lineCap: 'round',
+
+ // @option lineJoin: String = 'round'
+ // A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.
+ lineJoin: 'round',
+
+ // @option dashArray: String = null
+ // A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
+ dashArray: null,
+
+ // @option dashOffset: String = null
+ // A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
+ dashOffset: null,
+
+ // @option fill: Boolean = depends
+ // Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.
+ fill: false,
+
+ // @option fillColor: String = *
+ // Fill color. Defaults to the value of the [`color`](#path-color) option
+ fillColor: null,
+
+ // @option fillOpacity: Number = 0.2
+ // Fill opacity.
+ fillOpacity: 0.2,
+
+ // @option fillRule: String = 'evenodd'
+ // A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.
+ fillRule: 'evenodd',
+
+ // className: '',
+
+ // Option inherited from "Interactive layer" abstract class
+ interactive: true
+ },
+
+ beforeAdd: function (map) {
+ // Renderer is set here because we need to call renderer.getEvents
+ // before this.getEvents.
+ this._renderer = map.getRenderer(this);
+ },
+
+ onAdd: function () {
+ this._renderer._initPath(this);
+ this._reset();
+ this._renderer._addPath(this);
+ this._renderer.on('update', this._update, this);
+ },
+
+ onRemove: function () {
+ this._renderer._removePath(this);
+ this._renderer.off('update', this._update, this);
+ },
+
+ getEvents: function () {
+ return {
+ zoomend: this._project,
+ viewreset: this._reset
+ };
+ },
+
+ // @method redraw(): this
+ // Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.
+ redraw: function () {
+ if (this._map) {
+ this._renderer._updatePath(this);
+ }
+ return this;
+ },
+
+ // @method setStyle(style: Path options): this
+ // Changes the appearance of a Path based on the options in the `Path options` object.
+ setStyle: function (style) {
+ L.setOptions(this, style);
+ if (this._renderer) {
+ this._renderer._updateStyle(this);
+ }
+ return this;
+ },
+
+ // @method bringToFront(): this
+ // Brings the layer to the top of all path layers.
+ bringToFront: function () {
+ if (this._renderer) {
+ this._renderer._bringToFront(this);
+ }
+ return this;
+ },
+
+ // @method bringToBack(): this
+ // Brings the layer to the bottom of all path layers.
+ bringToBack: function () {
+ if (this._renderer) {
+ this._renderer._bringToBack(this);
+ }
+ return this;
+ },
+
+ getElement: function () {
+ return this._path;
+ },
+
+ _reset: function () {
+ // defined in children classes
+ this._project();
+ this._update();
+ },
+
+ _clickTolerance: function () {
+ // used when doing hit detection for Canvas layers
+ return (this.options.stroke ? this.options.weight / 2 : 0) + (L.Browser.touch ? 10 : 0);
+ }
+});
+
+
+
/*
* @namespace LineUtil
*
@@ -7766,309 +7766,309 @@ L.LineUtil = {
return sqDist ? dx * dx + dy * dy : new L.Point(x, y);
}
};
-
-
-
-/*
- * @class Polyline
- * @aka L.Polyline
- * @inherits Path
- *
- * A class for drawing polyline overlays on a map. Extends `Path`.
- *
- * @example
- *
- * ```js
- * // create a red polyline from an array of LatLng points
- * var latlngs = [
- * [-122.68, 45.51],
- * [-122.43, 37.77],
- * [-118.2, 34.04]
- * ];
- *
- * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
- *
- * // zoom the map to the polyline
- * map.fitBounds(polyline.getBounds());
- * ```
- *
- * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:
- *
- * ```js
- * // create a red polyline from an array of arrays of LatLng points
- * var latlngs = [
- * [[-122.68, 45.51],
- * [-122.43, 37.77],
- * [-118.2, 34.04]],
- * [[-73.91, 40.78],
- * [-87.62, 41.83],
- * [-96.72, 32.76]]
- * ];
- * ```
- */
-
-L.Polyline = L.Path.extend({
-
- // @section
- // @aka Polyline options
- options: {
- // @option smoothFactor: Number = 1.0
- // How much to simplify the polyline on each zoom level. More means
- // better performance and smoother look, and less means more accurate representation.
- smoothFactor: 1.0,
-
- // @option noClip: Boolean = false
- // Disable polyline clipping.
- noClip: false
- },
-
- initialize: function (latlngs, options) {
- L.setOptions(this, options);
- this._setLatLngs(latlngs);
- },
-
- // @method getLatLngs(): LatLng[]
- // Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.
- getLatLngs: function () {
- return this._latlngs;
- },
-
- // @method setLatLngs(latlngs: LatLng[]): this
- // Replaces all the points in the polyline with the given array of geographical points.
- setLatLngs: function (latlngs) {
- this._setLatLngs(latlngs);
- return this.redraw();
- },
-
- // @method isEmpty(): Boolean
- // Returns `true` if the Polyline has no LatLngs.
- isEmpty: function () {
- return !this._latlngs.length;
- },
-
- closestLayerPoint: function (p) {
- var minDistance = Infinity,
- minPoint = null,
- closest = L.LineUtil._sqClosestPointOnSegment,
- p1, p2;
-
- for (var j = 0, jLen = this._parts.length; j < jLen; j++) {
- var points = this._parts[j];
-
- for (var i = 1, len = points.length; i < len; i++) {
- p1 = points[i - 1];
- p2 = points[i];
-
- var sqDist = closest(p, p1, p2, true);
-
- if (sqDist < minDistance) {
- minDistance = sqDist;
- minPoint = closest(p, p1, p2);
- }
- }
- }
- if (minPoint) {
- minPoint.distance = Math.sqrt(minDistance);
- }
- return minPoint;
- },
-
- // @method getCenter(): LatLng
- // Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline.
- getCenter: function () {
- // throws error when not yet added to map as this center calculation requires projected coordinates
- if (!this._map) {
- throw new Error('Must add layer to map before using getCenter()');
- }
-
- var i, halfDist, segDist, dist, p1, p2, ratio,
- points = this._rings[0],
- len = points.length;
-
- if (!len) { return null; }
-
- // polyline centroid algorithm; only uses the first ring if there are multiple
-
- for (i = 0, halfDist = 0; i < len - 1; i++) {
- halfDist += points[i].distanceTo(points[i + 1]) / 2;
- }
-
- // The line is so small in the current view that all points are on the same pixel.
- if (halfDist === 0) {
- return this._map.layerPointToLatLng(points[0]);
- }
-
- for (i = 0, dist = 0; i < len - 1; i++) {
- p1 = points[i];
- p2 = points[i + 1];
- segDist = p1.distanceTo(p2);
- dist += segDist;
-
- if (dist > halfDist) {
- ratio = (dist - halfDist) / segDist;
- return this._map.layerPointToLatLng([
- p2.x - ratio * (p2.x - p1.x),
- p2.y - ratio * (p2.y - p1.y)
- ]);
- }
- }
- },
-
- // @method getBounds(): LatLngBounds
- // Returns the `LatLngBounds` of the path.
- getBounds: function () {
- return this._bounds;
- },
-
- // @method addLatLng(latlng: LatLng, latlngs? LatLng[]): this
- // Adds a given point to the polyline. By default, adds to the first ring of
- // the polyline in case of a multi-polyline, but can be overridden by passing
- // a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).
- addLatLng: function (latlng, latlngs) {
- latlngs = latlngs || this._defaultShape();
- latlng = L.latLng(latlng);
- latlngs.push(latlng);
- this._bounds.extend(latlng);
- return this.redraw();
- },
-
- _setLatLngs: function (latlngs) {
- this._bounds = new L.LatLngBounds();
- this._latlngs = this._convertLatLngs(latlngs);
- },
-
- _defaultShape: function () {
- return L.Polyline._flat(this._latlngs) ? this._latlngs : this._latlngs[0];
- },
-
- // recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
- _convertLatLngs: function (latlngs) {
- var result = [],
- flat = L.Polyline._flat(latlngs);
-
- for (var i = 0, len = latlngs.length; i < len; i++) {
- if (flat) {
- result[i] = L.latLng(latlngs[i]);
- this._bounds.extend(result[i]);
- } else {
- result[i] = this._convertLatLngs(latlngs[i]);
- }
- }
-
- return result;
- },
-
- _project: function () {
- var pxBounds = new L.Bounds();
- this._rings = [];
- this._projectLatlngs(this._latlngs, this._rings, pxBounds);
-
- var w = this._clickTolerance(),
- p = new L.Point(w, w);
-
- if (this._bounds.isValid() && pxBounds.isValid()) {
- pxBounds.min._subtract(p);
- pxBounds.max._add(p);
- this._pxBounds = pxBounds;
- }
- },
-
- // recursively turns latlngs into a set of rings with projected coordinates
- _projectLatlngs: function (latlngs, result, projectedBounds) {
- var flat = latlngs[0] instanceof L.LatLng,
- len = latlngs.length,
- i, ring;
-
- if (flat) {
- ring = [];
- for (i = 0; i < len; i++) {
- ring[i] = this._map.latLngToLayerPoint(latlngs[i]);
- projectedBounds.extend(ring[i]);
- }
- result.push(ring);
- } else {
- for (i = 0; i < len; i++) {
- this._projectLatlngs(latlngs[i], result, projectedBounds);
- }
- }
- },
-
- // clip polyline by renderer bounds so that we have less to render for performance
- _clipPoints: function () {
- var bounds = this._renderer._bounds;
-
- this._parts = [];
- if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
- return;
- }
-
- if (this.options.noClip) {
- this._parts = this._rings;
- return;
- }
-
- var parts = this._parts,
- i, j, k, len, len2, segment, points;
-
- for (i = 0, k = 0, len = this._rings.length; i < len; i++) {
- points = this._rings[i];
-
- for (j = 0, len2 = points.length; j < len2 - 1; j++) {
- segment = L.LineUtil.clipSegment(points[j], points[j + 1], bounds, j, true);
-
- 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[j + 1]) || (j === len2 - 2)) {
- parts[k].push(segment[1]);
- k++;
- }
- }
- }
- },
-
- // simplify each clipped part of the polyline for performance
- _simplifyPoints: function () {
- var parts = this._parts,
- tolerance = this.options.smoothFactor;
-
- for (var i = 0, len = parts.length; i < len; i++) {
- parts[i] = L.LineUtil.simplify(parts[i], tolerance);
- }
- },
-
- _update: function () {
- if (!this._map) { return; }
-
- this._clipPoints();
- this._simplifyPoints();
- this._updatePath();
- },
-
- _updatePath: function () {
- this._renderer._updatePoly(this);
- }
-});
-
-// @factory L.polyline(latlngs: LatLng[], options?: Polyline options)
-// Instantiates a polyline object given an array of geographical points and
-// optionally an options object. You can create a `Polyline` object with
-// multiple separate lines (`MultiPolyline`) by passing an array of arrays
-// of geographic points.
-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');
-};
-
-
-
+
+
+
+/*
+ * @class Polyline
+ * @aka L.Polyline
+ * @inherits Path
+ *
+ * A class for drawing polyline overlays on a map. Extends `Path`.
+ *
+ * @example
+ *
+ * ```js
+ * // create a red polyline from an array of LatLng points
+ * var latlngs = [
+ * [-122.68, 45.51],
+ * [-122.43, 37.77],
+ * [-118.2, 34.04]
+ * ];
+ *
+ * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
+ *
+ * // zoom the map to the polyline
+ * map.fitBounds(polyline.getBounds());
+ * ```
+ *
+ * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:
+ *
+ * ```js
+ * // create a red polyline from an array of arrays of LatLng points
+ * var latlngs = [
+ * [[-122.68, 45.51],
+ * [-122.43, 37.77],
+ * [-118.2, 34.04]],
+ * [[-73.91, 40.78],
+ * [-87.62, 41.83],
+ * [-96.72, 32.76]]
+ * ];
+ * ```
+ */
+
+L.Polyline = L.Path.extend({
+
+ // @section
+ // @aka Polyline options
+ options: {
+ // @option smoothFactor: Number = 1.0
+ // How much to simplify the polyline on each zoom level. More means
+ // better performance and smoother look, and less means more accurate representation.
+ smoothFactor: 1.0,
+
+ // @option noClip: Boolean = false
+ // Disable polyline clipping.
+ noClip: false
+ },
+
+ initialize: function (latlngs, options) {
+ L.setOptions(this, options);
+ this._setLatLngs(latlngs);
+ },
+
+ // @method getLatLngs(): LatLng[]
+ // Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.
+ getLatLngs: function () {
+ return this._latlngs;
+ },
+
+ // @method setLatLngs(latlngs: LatLng[]): this
+ // Replaces all the points in the polyline with the given array of geographical points.
+ setLatLngs: function (latlngs) {
+ this._setLatLngs(latlngs);
+ return this.redraw();
+ },
+
+ // @method isEmpty(): Boolean
+ // Returns `true` if the Polyline has no LatLngs.
+ isEmpty: function () {
+ return !this._latlngs.length;
+ },
+
+ closestLayerPoint: function (p) {
+ var minDistance = Infinity,
+ minPoint = null,
+ closest = L.LineUtil._sqClosestPointOnSegment,
+ p1, p2;
+
+ for (var j = 0, jLen = this._parts.length; j < jLen; j++) {
+ var points = this._parts[j];
+
+ for (var i = 1, len = points.length; i < len; i++) {
+ p1 = points[i - 1];
+ p2 = points[i];
+
+ var sqDist = closest(p, p1, p2, true);
+
+ if (sqDist < minDistance) {
+ minDistance = sqDist;
+ minPoint = closest(p, p1, p2);
+ }
+ }
+ }
+ if (minPoint) {
+ minPoint.distance = Math.sqrt(minDistance);
+ }
+ return minPoint;
+ },
+
+ // @method getCenter(): LatLng
+ // Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline.
+ getCenter: function () {
+ // throws error when not yet added to map as this center calculation requires projected coordinates
+ if (!this._map) {
+ throw new Error('Must add layer to map before using getCenter()');
+ }
+
+ var i, halfDist, segDist, dist, p1, p2, ratio,
+ points = this._rings[0],
+ len = points.length;
+
+ if (!len) { return null; }
+
+ // polyline centroid algorithm; only uses the first ring if there are multiple
+
+ for (i = 0, halfDist = 0; i < len - 1; i++) {
+ halfDist += points[i].distanceTo(points[i + 1]) / 2;
+ }
+
+ // The line is so small in the current view that all points are on the same pixel.
+ if (halfDist === 0) {
+ return this._map.layerPointToLatLng(points[0]);
+ }
+
+ for (i = 0, dist = 0; i < len - 1; i++) {
+ p1 = points[i];
+ p2 = points[i + 1];
+ segDist = p1.distanceTo(p2);
+ dist += segDist;
+
+ if (dist > halfDist) {
+ ratio = (dist - halfDist) / segDist;
+ return this._map.layerPointToLatLng([
+ p2.x - ratio * (p2.x - p1.x),
+ p2.y - ratio * (p2.y - p1.y)
+ ]);
+ }
+ }
+ },
+
+ // @method getBounds(): LatLngBounds
+ // Returns the `LatLngBounds` of the path.
+ getBounds: function () {
+ return this._bounds;
+ },
+
+ // @method addLatLng(latlng: LatLng, latlngs? LatLng[]): this
+ // Adds a given point to the polyline. By default, adds to the first ring of
+ // the polyline in case of a multi-polyline, but can be overridden by passing
+ // a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).
+ addLatLng: function (latlng, latlngs) {
+ latlngs = latlngs || this._defaultShape();
+ latlng = L.latLng(latlng);
+ latlngs.push(latlng);
+ this._bounds.extend(latlng);
+ return this.redraw();
+ },
+
+ _setLatLngs: function (latlngs) {
+ this._bounds = new L.LatLngBounds();
+ this._latlngs = this._convertLatLngs(latlngs);
+ },
+
+ _defaultShape: function () {
+ return L.Polyline._flat(this._latlngs) ? this._latlngs : this._latlngs[0];
+ },
+
+ // recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
+ _convertLatLngs: function (latlngs) {
+ var result = [],
+ flat = L.Polyline._flat(latlngs);
+
+ for (var i = 0, len = latlngs.length; i < len; i++) {
+ if (flat) {
+ result[i] = L.latLng(latlngs[i]);
+ this._bounds.extend(result[i]);
+ } else {
+ result[i] = this._convertLatLngs(latlngs[i]);
+ }
+ }
+
+ return result;
+ },
+
+ _project: function () {
+ var pxBounds = new L.Bounds();
+ this._rings = [];
+ this._projectLatlngs(this._latlngs, this._rings, pxBounds);
+
+ var w = this._clickTolerance(),
+ p = new L.Point(w, w);
+
+ if (this._bounds.isValid() && pxBounds.isValid()) {
+ pxBounds.min._subtract(p);
+ pxBounds.max._add(p);
+ this._pxBounds = pxBounds;
+ }
+ },
+
+ // recursively turns latlngs into a set of rings with projected coordinates
+ _projectLatlngs: function (latlngs, result, projectedBounds) {
+ var flat = latlngs[0] instanceof L.LatLng,
+ len = latlngs.length,
+ i, ring;
+
+ if (flat) {
+ ring = [];
+ for (i = 0; i < len; i++) {
+ ring[i] = this._map.latLngToLayerPoint(latlngs[i]);
+ projectedBounds.extend(ring[i]);
+ }
+ result.push(ring);
+ } else {
+ for (i = 0; i < len; i++) {
+ this._projectLatlngs(latlngs[i], result, projectedBounds);
+ }
+ }
+ },
+
+ // clip polyline by renderer bounds so that we have less to render for performance
+ _clipPoints: function () {
+ var bounds = this._renderer._bounds;
+
+ this._parts = [];
+ if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
+ return;
+ }
+
+ if (this.options.noClip) {
+ this._parts = this._rings;
+ return;
+ }
+
+ var parts = this._parts,
+ i, j, k, len, len2, segment, points;
+
+ for (i = 0, k = 0, len = this._rings.length; i < len; i++) {
+ points = this._rings[i];
+
+ for (j = 0, len2 = points.length; j < len2 - 1; j++) {
+ segment = L.LineUtil.clipSegment(points[j], points[j + 1], bounds, j, true);
+
+ 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[j + 1]) || (j === len2 - 2)) {
+ parts[k].push(segment[1]);
+ k++;
+ }
+ }
+ }
+ },
+
+ // simplify each clipped part of the polyline for performance
+ _simplifyPoints: function () {
+ var parts = this._parts,
+ tolerance = this.options.smoothFactor;
+
+ for (var i = 0, len = parts.length; i < len; i++) {
+ parts[i] = L.LineUtil.simplify(parts[i], tolerance);
+ }
+ },
+
+ _update: function () {
+ if (!this._map) { return; }
+
+ this._clipPoints();
+ this._simplifyPoints();
+ this._updatePath();
+ },
+
+ _updatePath: function () {
+ this._renderer._updatePoly(this);
+ }
+});
+
+// @factory L.polyline(latlngs: LatLng[], options?: Polyline options)
+// Instantiates a polyline object given an array of geographical points and
+// optionally an options object. You can create a `Polyline` object with
+// multiple separate lines (`MultiPolyline`) by passing an array of arrays
+// of geographic points.
+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');
+};
+
+
+
/*
* @namespace PolyUtil
* Various utility functions for polygon geometries.
@@ -8125,1198 +8125,1198 @@ L.PolyUtil.clipPolygon = function (points, bounds, round) {
return points;
};
-
-
-
-/*
- * @class Polygon
- * @aka L.Polygon
- * @inherits Polyline
- *
- * A class for drawing polygon overlays on a map. Extends `Polyline`.
- *
- * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.
- *
- *
- * @example
- *
- * ```js
- * // create a red polygon from an array of LatLng points
- * var latlngs = [[-111.03, 41],[-111.04, 45],[-104.05, 45],[-104.05, 41]];
- *
- * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
- *
- * // zoom the map to the polygon
- * map.fitBounds(polygon.getBounds());
- * ```
- *
- * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:
- *
- * ```js
- * var latlngs = [
- * [[-111.03, 41],[-111.04, 45],[-104.05, 45],[-104.05, 41]], // outer ring
- * [[-108.58,37.29],[-108.58,40.71],[-102.50,40.71],[-102.50,37.29]] // hole
- * ];
- * ```
- *
- * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.
- *
- * ```js
- * var latlngs = [
- * [ // first polygon
- * [[-111.03, 41],[-111.04, 45],[-104.05, 45],[-104.05, 41]], // outer ring
- * [[-108.58,37.29],[-108.58,40.71],[-102.50,40.71],[-102.50,37.29]] // hole
- * ],
- * [ // second polygon
- * [[-109.05, 37],[-109.03, 41],[-102.05, 41],[-102.04, 37],[-109.05, 38]]
- * ]
- * ];
- * ```
- */
-
-L.Polygon = L.Polyline.extend({
-
- options: {
- fill: true
- },
-
- isEmpty: function () {
- return !this._latlngs.length || !this._latlngs[0].length;
- },
-
- getCenter: function () {
- // throws error when not yet added to map as this center calculation requires projected coordinates
- if (!this._map) {
- throw new Error('Must add layer to map before using getCenter()');
- }
-
- var i, j, p1, p2, f, area, x, y, center,
- points = this._rings[0],
- len = points.length;
-
- if (!len) { return null; }
-
- // polygon centroid algorithm; only uses the first ring if there are multiple
-
- area = x = y = 0;
-
- for (i = 0, j = len - 1; i < len; j = i++) {
- p1 = points[i];
- p2 = points[j];
-
- f = p1.y * p2.x - p2.y * p1.x;
- x += (p1.x + p2.x) * f;
- y += (p1.y + p2.y) * f;
- area += f * 3;
- }
-
- if (area === 0) {
- // Polygon is so small that all points are on same pixel.
- center = points[0];
- } else {
- center = [x / area, y / area];
- }
- return this._map.layerPointToLatLng(center);
- },
-
- _convertLatLngs: function (latlngs) {
- var result = L.Polyline.prototype._convertLatLngs.call(this, latlngs),
- len = result.length;
-
- // remove last point if it equals first one
- if (len >= 2 && result[0] instanceof L.LatLng && result[0].equals(result[len - 1])) {
- result.pop();
- }
- return result;
- },
-
- _setLatLngs: function (latlngs) {
- L.Polyline.prototype._setLatLngs.call(this, latlngs);
- if (L.Polyline._flat(this._latlngs)) {
- this._latlngs = [this._latlngs];
- }
- },
-
- _defaultShape: function () {
- return L.Polyline._flat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];
- },
-
- _clipPoints: function () {
- // polygons need a different clipping algorithm so we redefine that
-
- var bounds = this._renderer._bounds,
- w = this.options.weight,
- p = new L.Point(w, w);
-
- // increase clip padding by stroke width to avoid stroke on clip edges
- bounds = new L.Bounds(bounds.min.subtract(p), bounds.max.add(p));
-
- this._parts = [];
- if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
- return;
- }
-
- if (this.options.noClip) {
- this._parts = this._rings;
- return;
- }
-
- for (var i = 0, len = this._rings.length, clipped; i < len; i++) {
- clipped = L.PolyUtil.clipPolygon(this._rings[i], bounds, true);
- if (clipped.length) {
- this._parts.push(clipped);
- }
- }
- },
-
- _updatePath: function () {
- this._renderer._updatePoly(this, true);
- }
-});
-
-
-// @factory L.polygon(latlngs: LatLng[], options?: Polyline options)
-L.polygon = function (latlngs, options) {
- return new L.Polygon(latlngs, options);
-};
-
-
-
-/*
- * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object.
- */
-
-/*
- * @class Rectangle
- * @aka L.Retangle
- * @inherits Polygon
- *
- * A class for drawing rectangle overlays on a map. Extends `Polygon`.
- *
- * @example
- *
- * ```js
- * // define rectangle geographical bounds
- * var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
- *
- * // create an orange rectangle
- * L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
- *
- * // zoom the map to the rectangle bounds
- * map.fitBounds(bounds);
- * ```
- *
- */
-
-
-L.Rectangle = L.Polygon.extend({
- initialize: function (latLngBounds, options) {
- L.Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options);
- },
-
- // @method setBounds(latLngBounds: LatLngBounds): this
- // Redraws the rectangle with the passed bounds.
- setBounds: function (latLngBounds) {
- return this.setLatLngs(this._boundsToLatLngs(latLngBounds));
- },
-
- _boundsToLatLngs: function (latLngBounds) {
- latLngBounds = L.latLngBounds(latLngBounds);
- return [
- latLngBounds.getSouthWest(),
- latLngBounds.getNorthWest(),
- latLngBounds.getNorthEast(),
- latLngBounds.getSouthEast()
- ];
- }
-});
-
-
-// @factory L.rectangle(latLngBounds: LatLngBounds, options?: Polyline options)
-L.rectangle = function (latLngBounds, options) {
- return new L.Rectangle(latLngBounds, options);
-};
-
-
-
-/*
- * @class CircleMarker
- * @aka L.CircleMarker
- * @inherits Path
- *
- * A circle of a fixed size with radius specified in pixels. Extends `Path`.
- */
-
-L.CircleMarker = L.Path.extend({
-
- // @section
- // @aka CircleMarker options
- options: {
- fill: true,
-
- // @option radius: Number = 10
- // Radius of the circle marker, in pixels
- radius: 10
- },
-
- initialize: function (latlng, options) {
- L.setOptions(this, options);
- this._latlng = L.latLng(latlng);
- this._radius = this.options.radius;
- },
-
- // @method setLatLng(latLng: LatLng): this
- // Sets the position of a circle marker to a new location.
- setLatLng: function (latlng) {
- this._latlng = L.latLng(latlng);
- this.redraw();
- return this.fire('move', {latlng: this._latlng});
- },
-
- // @method getLatLng(): LatLng
- // Returns the current geographical position of the circle marker
- getLatLng: function () {
- return this._latlng;
- },
-
- // @method setRadius(radius: Number): this
- // Sets the radius of a circle marker. Units are in pixels.
- setRadius: function (radius) {
- this.options.radius = this._radius = radius;
- return this.redraw();
- },
-
- // @method getRadius(): Number
- // Returns the current radius of the circle
- getRadius: function () {
- return this._radius;
- },
-
- setStyle : function (options) {
- var radius = options && options.radius || this._radius;
- L.Path.prototype.setStyle.call(this, options);
- this.setRadius(radius);
- return this;
- },
-
- _project: function () {
- this._point = this._map.latLngToLayerPoint(this._latlng);
- this._updateBounds();
- },
-
- _updateBounds: function () {
- var r = this._radius,
- r2 = this._radiusY || r,
- w = this._clickTolerance(),
- p = [r + w, r2 + w];
- this._pxBounds = new L.Bounds(this._point.subtract(p), this._point.add(p));
- },
-
- _update: function () {
- if (this._map) {
- this._updatePath();
- }
- },
-
- _updatePath: function () {
- this._renderer._updateCircle(this);
- },
-
- _empty: function () {
- return this._radius && !this._renderer._bounds.intersects(this._pxBounds);
- }
-});
-
-
-// @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)
-// Instantiates a circle marker object given a geographical point, and an optional options object.
-L.circleMarker = function (latlng, options) {
- return new L.CircleMarker(latlng, options);
-};
-
-
-
-/*
- * @class Circle
- * @aka L.Circle
- * @inherits CircleMarker
- *
- * A class for drawing circle overlays on a map. Extends `CircleMarker`.
- *
- * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).
- *
- * @example
- *
- * ```js
- * L.circle([50.5, 30.5], {radius: 200}).addTo(map);
- * ```
- */
-
-L.Circle = L.CircleMarker.extend({
-
- initialize: function (latlng, options, legacyOptions) {
- if (typeof options === 'number') {
- // Backwards compatibility with 0.7.x factory (latlng, radius, options?)
- options = L.extend({}, legacyOptions, {radius: options});
- }
- L.setOptions(this, options);
- this._latlng = L.latLng(latlng);
-
- if (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }
-
- // @section
- // @aka Circle options
- // @option radius: Number; Radius of the circle, in meters.
- this._mRadius = this.options.radius;
- },
-
- // @method setRadius(radius: Number): this
- // Sets the radius of a circle. Units are in meters.
- setRadius: function (radius) {
- this._mRadius = radius;
- return this.redraw();
- },
-
- // @method getRadius(): Number
- // Returns the current radius of a circle. Units are in meters.
- getRadius: function () {
- return this._mRadius;
- },
-
- // @method getBounds(): LatLngBounds
- // Returns the `LatLngBounds` of the path.
- getBounds: function () {
- var half = [this._radius, this._radiusY || this._radius];
-
- return new L.LatLngBounds(
- this._map.layerPointToLatLng(this._point.subtract(half)),
- this._map.layerPointToLatLng(this._point.add(half)));
- },
-
- setStyle: L.Path.prototype.setStyle,
-
- _project: function () {
-
- var lng = this._latlng.lng,
- lat = this._latlng.lat,
- map = this._map,
- crs = map.options.crs;
-
- if (crs.distance === L.CRS.Earth.distance) {
- var d = Math.PI / 180,
- latR = (this._mRadius / L.CRS.Earth.R) / d,
- top = map.project([lat + latR, lng]),
- bottom = map.project([lat - latR, lng]),
- p = top.add(bottom).divideBy(2),
- lat2 = map.unproject(p).lat,
- lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /
- (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;
-
- if (isNaN(lngR) || lngR === 0) {
- lngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425
- }
-
- this._point = p.subtract(map.getPixelOrigin());
- this._radius = isNaN(lngR) ? 0 : Math.max(Math.round(p.x - map.project([lat2, lng - lngR]).x), 1);
- this._radiusY = Math.max(Math.round(p.y - top.y), 1);
-
- } else {
- var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));
-
- this._point = map.latLngToLayerPoint(this._latlng);
- this._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;
- }
-
- this._updateBounds();
- }
-});
-
-// @factory L.circle(latlng: LatLng, options?: Circle options)
-// Instantiates a circle object given a geographical point, and an options object
-// which contains the circle radius.
-// @alternative
-// @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)
-// Obsolete way of instantiating a circle, for compatibility with 0.7.x code.
-// Do not use in new applications or plugins.
-L.circle = function (latlng, options, legacyOptions) {
- return new L.Circle(latlng, options, legacyOptions);
-};
-
-
-
-/*
- * @class SVG
- * @inherits Renderer
- * @aka L.SVG
- *
- * Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG).
- * Inherits `Renderer`.
- *
- * Due to [technical limitations](http://caniuse.com/#search=svg), SVG is not
- * available in all web browsers, notably Android 2.x and 3.x.
- *
- * Although SVG is not available on IE7 and IE8, these browsers support
- * [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language)
- * (a now deprecated technology), and the SVG renderer will fall back to VML in
- * this case.
- *
- * @example
- *
- * Use SVG by default for all paths in the map:
- *
- * ```js
- * var map = L.map('map', {
- * renderer: L.svg()
- * });
- * ```
- *
- * Use a SVG renderer with extra padding for specific vector geometries:
- *
- * ```js
- * var map = L.map('map');
- * var myRenderer = L.svg({ padding: 0.5 });
- * var line = L.polyline( coordinates, { renderer: myRenderer } );
- * var circle = L.circle( center, { renderer: myRenderer } );
- * ```
- */
-
-L.SVG = L.Renderer.extend({
-
- getEvents: function () {
- var events = L.Renderer.prototype.getEvents.call(this);
- events.zoomstart = this._onZoomStart;
- return events;
- },
-
- _initContainer: function () {
- this._container = L.SVG.create('svg');
-
- // makes it possible to click through svg root; we'll reset it back in individual paths
- this._container.setAttribute('pointer-events', 'none');
-
- this._rootGroup = L.SVG.create('g');
- this._container.appendChild(this._rootGroup);
- },
-
- _onZoomStart: function () {
- // Drag-then-pinch interactions might mess up the center and zoom.
- // In this case, the easiest way to prevent this is re-do the renderer
- // bounds and padding when the zooming starts.
- this._update();
- },
-
- _update: function () {
- if (this._map._animatingZoom && this._bounds) { return; }
-
- L.Renderer.prototype._update.call(this);
-
- var b = this._bounds,
- size = b.getSize(),
- container = this._container;
-
- // set size of svg-container if changed
- if (!this._svgSize || !this._svgSize.equals(size)) {
- this._svgSize = size;
- container.setAttribute('width', size.x);
- container.setAttribute('height', size.y);
- }
-
- // movement: update container viewBox so that we don't have to change coordinates of individual layers
- L.DomUtil.setPosition(container, b.min);
- container.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));
-
- this.fire('update');
- },
-
- // methods below are called by vector layers implementations
-
- _initPath: function (layer) {
- var path = layer._path = L.SVG.create('path');
-
- // @namespace Path
- // @option className: String = null
- // Custom class name set on an element. Only for SVG renderer.
- if (layer.options.className) {
- L.DomUtil.addClass(path, layer.options.className);
- }
-
- if (layer.options.interactive) {
- L.DomUtil.addClass(path, 'leaflet-interactive');
- }
-
- this._updateStyle(layer);
- },
-
- _addPath: function (layer) {
- this._rootGroup.appendChild(layer._path);
- layer.addInteractiveTarget(layer._path);
- },
-
- _removePath: function (layer) {
- L.DomUtil.remove(layer._path);
- layer.removeInteractiveTarget(layer._path);
- },
-
- _updatePath: function (layer) {
- layer._project();
- layer._update();
- },
-
- _updateStyle: function (layer) {
- var path = layer._path,
- options = layer.options;
-
- if (!path) { return; }
-
- if (options.stroke) {
- path.setAttribute('stroke', options.color);
- path.setAttribute('stroke-opacity', options.opacity);
- path.setAttribute('stroke-width', options.weight);
- path.setAttribute('stroke-linecap', options.lineCap);
- path.setAttribute('stroke-linejoin', options.lineJoin);
-
- if (options.dashArray) {
- path.setAttribute('stroke-dasharray', options.dashArray);
- } else {
- path.removeAttribute('stroke-dasharray');
- }
-
- if (options.dashOffset) {
- path.setAttribute('stroke-dashoffset', options.dashOffset);
- } else {
- path.removeAttribute('stroke-dashoffset');
- }
- } else {
- path.setAttribute('stroke', 'none');
- }
-
- if (options.fill) {
- path.setAttribute('fill', options.fillColor || options.color);
- path.setAttribute('fill-opacity', options.fillOpacity);
- path.setAttribute('fill-rule', options.fillRule || 'evenodd');
- } else {
- path.setAttribute('fill', 'none');
- }
- },
-
- _updatePoly: function (layer, closed) {
- this._setPath(layer, L.SVG.pointsToPath(layer._parts, closed));
- },
-
- _updateCircle: function (layer) {
- var p = layer._point,
- r = layer._radius,
- r2 = layer._radiusY || r,
- arc = 'a' + r + ',' + r2 + ' 0 1,0 ';
-
- // drawing a circle with two half-arcs
- var d = layer._empty() ? 'M0 0' :
- 'M' + (p.x - r) + ',' + p.y +
- arc + (r * 2) + ',0 ' +
- arc + (-r * 2) + ',0 ';
-
- this._setPath(layer, d);
- },
-
- _setPath: function (layer, path) {
- layer._path.setAttribute('d', path);
- },
-
- // SVG does not have the concept of zIndex so we resort to changing the DOM order of elements
- _bringToFront: function (layer) {
- L.DomUtil.toFront(layer._path);
- },
-
- _bringToBack: function (layer) {
- L.DomUtil.toBack(layer._path);
- }
-});
-
-
-// @namespace SVG; @section
-// There are several static functions which can be called without instantiating L.SVG:
-L.extend(L.SVG, {
- // @function create(name: String): SVGElement
- // Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement),
- // corresponding to the class name passed. For example, using 'line' will return
- // an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement).
- create: function (name) {
- return document.createElementNS('http://www.w3.org/2000/svg', name);
- },
-
- // @function pointsToPath(rings: Point[], closed: Boolean): String
- // Generates a SVG path string for multiple rings, with each ring turning
- // into "M..L..L.." instructions
- pointsToPath: function (rings, closed) {
- var str = '',
- i, j, len, len2, points, p;
-
- for (i = 0, len = rings.length; i < len; i++) {
- points = rings[i];
-
- for (j = 0, len2 = points.length; j < len2; j++) {
- p = points[j];
- str += (j ? 'L' : 'M') + p.x + ' ' + p.y;
- }
-
- // closes the ring for polygons; "x" is VML syntax
- str += closed ? (L.Browser.svg ? 'z' : 'x') : '';
- }
-
- // SVG complains about empty path strings
- return str || 'M0 0';
- }
-});
-
-// @namespace Browser; @property svg: Boolean
-// `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG).
-L.Browser.svg = !!(document.createElementNS && L.SVG.create('svg').createSVGRect);
-
-
-// @namespace SVG
-// @factory L.svg(options?: Renderer options)
-// Creates a SVG renderer with the given options.
-L.svg = function (options) {
- return L.Browser.svg || L.Browser.vml ? new L.SVG(options) : null;
-};
-
-
-
-/*
- * Thanks to Dmitry Baranovsky and his Raphael library for inspiration!
- */
-
-/*
- * @class SVG
- *
- * Although SVG is not available on IE7 and IE8, these browsers support [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language), and the SVG renderer will fall back to VML in this case.
- *
- * VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility
- * with old versions of Internet Explorer.
- */
-
-// @namespace Browser; @property vml: Boolean
-// `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language).
-L.Browser.vml = !L.Browser.svg && (function () {
- try {
- var div = document.createElement('div');
- div.innerHTML = '';
-
- var shape = div.firstChild;
- shape.style.behavior = 'url(#default#VML)';
-
- return shape && (typeof shape.adj === 'object');
-
- } catch (e) {
- return false;
- }
-}());
-
-// redefine some SVG methods to handle VML syntax which is similar but with some differences
-L.SVG.include(!L.Browser.vml ? {} : {
-
- _initContainer: function () {
- this._container = L.DomUtil.create('div', 'leaflet-vml-container');
- },
-
- _update: function () {
- if (this._map._animatingZoom) { return; }
- L.Renderer.prototype._update.call(this);
- this.fire('update');
- },
-
- _initPath: function (layer) {
- var container = layer._container = L.SVG.create('shape');
-
- L.DomUtil.addClass(container, 'leaflet-vml-shape ' + (this.options.className || ''));
-
- container.coordsize = '1 1';
-
- layer._path = L.SVG.create('path');
- container.appendChild(layer._path);
-
- this._updateStyle(layer);
- },
-
- _addPath: function (layer) {
- var container = layer._container;
- this._container.appendChild(container);
-
- if (layer.options.interactive) {
- layer.addInteractiveTarget(container);
- }
- },
-
- _removePath: function (layer) {
- var container = layer._container;
- L.DomUtil.remove(container);
- layer.removeInteractiveTarget(container);
- },
-
- _updateStyle: function (layer) {
- var stroke = layer._stroke,
- fill = layer._fill,
- options = layer.options,
- container = layer._container;
-
- container.stroked = !!options.stroke;
- container.filled = !!options.fill;
-
- if (options.stroke) {
- if (!stroke) {
- stroke = layer._stroke = L.SVG.create('stroke');
- }
- container.appendChild(stroke);
- stroke.weight = options.weight + 'px';
- stroke.color = options.color;
- stroke.opacity = options.opacity;
-
- if (options.dashArray) {
- stroke.dashStyle = L.Util.isArray(options.dashArray) ?
- options.dashArray.join(' ') :
- options.dashArray.replace(/( *, *)/g, ' ');
- } else {
- stroke.dashStyle = '';
- }
- stroke.endcap = options.lineCap.replace('butt', 'flat');
- stroke.joinstyle = options.lineJoin;
-
- } else if (stroke) {
- container.removeChild(stroke);
- layer._stroke = null;
- }
-
- if (options.fill) {
- if (!fill) {
- fill = layer._fill = L.SVG.create('fill');
- }
- container.appendChild(fill);
- fill.color = options.fillColor || options.color;
- fill.opacity = options.fillOpacity;
-
- } else if (fill) {
- container.removeChild(fill);
- layer._fill = null;
- }
- },
-
- _updateCircle: function (layer) {
- var p = layer._point.round(),
- r = Math.round(layer._radius),
- r2 = Math.round(layer._radiusY || r);
-
- this._setPath(layer, layer._empty() ? 'M0 0' :
- 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360));
- },
-
- _setPath: function (layer, path) {
- layer._path.v = path;
- },
-
- _bringToFront: function (layer) {
- L.DomUtil.toFront(layer._container);
- },
-
- _bringToBack: function (layer) {
- L.DomUtil.toBack(layer._container);
- }
-});
-
-if (L.Browser.vml) {
- L.SVG.create = (function () {
- try {
- document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml');
- return function (name) {
- return document.createElement('');
- };
- } catch (e) {
- return function (name) {
- return document.createElement('<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">');
- };
- }
- })();
-}
-
-
-
-/*
- * @class Canvas
- * @inherits Renderer
- * @aka L.Canvas
- *
- * Allows vector layers to be displayed with [`