UNPKG

leaflet

Version:

JavaScript library for mobile-friendly interactive maps

343 lines (262 loc) 8.34 kB
/* * @class Marker * @inherits Interactive layer * @aka L.Marker * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`. * * @example * * ```js * L.marker([50.5, 30.5]).addTo(map); * ``` */ L.Marker = L.Layer.extend({ // @section // @aka Marker options options: { // @option icon: Icon = * // Icon class to use for rendering the marker. See [Icon documentation](#L.Icon) for details on how to customize the marker icon. If not specified, a new `L.Icon.Default` is used. icon: new L.Icon.Default(), // Option inherited from "Interactive layer" abstract class interactive: true, // @option draggable: Boolean = false // Whether the marker is draggable with mouse/touch or not. draggable: false, // @option keyboard: Boolean = true // Whether the marker can be tabbed to with a keyboard and clicked by pressing enter. keyboard: true, // @option title: String = '' // Text for the browser tooltip that appear on marker hover (no tooltip by default). title: '', // @option alt: String = '' // Text for the `alt` attribute of the icon image (useful for accessibility). alt: '', // @option zIndexOffset: Number = 0 // By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively). zIndexOffset: 0, // @option opacity: Number = 1.0 // The opacity of the marker. opacity: 1, // @option riseOnHover: Boolean = false // If `true`, the marker will get on top of others when you hover the mouse over it. riseOnHover: false, // @option riseOffset: Number = 250 // The z-index offset used for the `riseOnHover` feature. riseOffset: 250, // @option pane: String = 'markerPane' // `Map pane` where the markers icon will be added. pane: 'markerPane', // FIXME: shadowPane is no longer a valid option nonBubblingEvents: ['click', 'dblclick', 'mouseover', 'mouseout', 'contextmenu'] }, /* @section * * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods: */ initialize: function (latlng, options) { L.setOptions(this, options); this._latlng = L.latLng(latlng); }, onAdd: function (map) { this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation; if (this._zoomAnimated) { map.on('zoomanim', this._animateZoom, this); } this._initIcon(); this.update(); }, onRemove: function (map) { if (this.dragging && this.dragging.enabled()) { this.options.draggable = true; this.dragging.removeHooks(); } if (this._zoomAnimated) { map.off('zoomanim', this._animateZoom, this); } this._removeIcon(); this._removeShadow(); }, getEvents: function () { return { zoom: this.update, viewreset: this.update }; }, // @method getLatLng: LatLng // Returns the current geographical position of the marker. getLatLng: function () { return this._latlng; }, // @method setLatLng(latlng: LatLng): this // Changes the marker position to the given point. setLatLng: function (latlng) { var oldLatLng = this._latlng; this._latlng = L.latLng(latlng); this.update(); // @event move: Event // Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`. return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng}); }, // @method setZIndexOffset(offset: Number): this // Changes the [zIndex offset](#marker-zindexoffset) of the marker. setZIndexOffset: function (offset) { this.options.zIndexOffset = offset; return this.update(); }, // @method setIcon(icon: Icon): this // Changes the marker icon. setIcon: function (icon) { this.options.icon = icon; if (this._map) { this._initIcon(); this.update(); } if (this._popup) { this.bindPopup(this._popup, this._popup.options); } return this; }, getElement: function () { return this._icon; }, update: function () { if (this._icon) { var pos = this._map.latLngToLayerPoint(this._latlng).round(); this._setPos(pos); } return this; }, _initIcon: function () { var options = this.options, classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide'); var icon = options.icon.createIcon(this._icon), addIcon = false; // if we're not reusing the icon, remove the old one and init new one if (icon !== this._icon) { if (this._icon) { this._removeIcon(); } addIcon = true; if (options.title) { icon.title = options.title; } if (options.alt) { icon.alt = options.alt; } } L.DomUtil.addClass(icon, classToAdd); if (options.keyboard) { icon.tabIndex = '0'; } this._icon = icon; if (options.riseOnHover) { this.on({ mouseover: this._bringToFront, mouseout: this._resetZIndex }); } var newShadow = options.icon.createShadow(this._shadow), addShadow = false; if (newShadow !== this._shadow) { this._removeShadow(); addShadow = true; } if (newShadow) { L.DomUtil.addClass(newShadow, classToAdd); newShadow.alt = ''; } this._shadow = newShadow; if (options.opacity < 1) { this._updateOpacity(); } if (addIcon) { this.getPane().appendChild(this._icon); } this._initInteraction(); if (newShadow && addShadow) { this.getPane('shadowPane').appendChild(this._shadow); } }, _removeIcon: function () { if (this.options.riseOnHover) { this.off({ mouseover: this._bringToFront, mouseout: this._resetZIndex }); } L.DomUtil.remove(this._icon); this.removeInteractiveTarget(this._icon); this._icon = null; }, _removeShadow: function () { if (this._shadow) { L.DomUtil.remove(this._shadow); } this._shadow = null; }, _setPos: function (pos) { L.DomUtil.setPosition(this._icon, pos); if (this._shadow) { L.DomUtil.setPosition(this._shadow, pos); } this._zIndex = pos.y + this.options.zIndexOffset; this._resetZIndex(); }, _updateZIndex: function (offset) { this._icon.style.zIndex = this._zIndex + offset; }, _animateZoom: function (opt) { var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); this._setPos(pos); }, _initInteraction: function () { if (!this.options.interactive) { return; } L.DomUtil.addClass(this._icon, 'leaflet-interactive'); this.addInteractiveTarget(this._icon); if (L.Handler.MarkerDrag) { var draggable = this.options.draggable; if (this.dragging) { draggable = this.dragging.enabled(); this.dragging.disable(); } this.dragging = new L.Handler.MarkerDrag(this); if (draggable) { this.dragging.enable(); } } }, // @method setOpacity(opacity: Number): this // Changes the opacity of the marker. setOpacity: function (opacity) { this.options.opacity = opacity; if (this._map) { this._updateOpacity(); } return this; }, _updateOpacity: function () { var opacity = this.options.opacity; L.DomUtil.setOpacity(this._icon, opacity); if (this._shadow) { L.DomUtil.setOpacity(this._shadow, opacity); } }, _bringToFront: function () { this._updateZIndex(this.options.riseOffset); }, _resetZIndex: function () { this._updateZIndex(0); }, _getPopupAnchor: function () { return this.options.icon.options.popupAnchor || [0, 0]; }, _getTooltipAnchor: function () { return this.options.icon.options.tooltipAnchor || [0, 0]; } }); // factory L.marker(latlng: LatLng, options? : Marker options) // @factory L.marker(latlng: LatLng, options? : Marker options) // Instantiates a Marker object given a geographical point and optionally an options object. L.marker = function (latlng, options) { return new L.Marker(latlng, options); };