123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590 |
- /*
- Leaflet.label, a plugin that adds labels to markers and vectors for Leaflet powered maps.
- (c) 2012-2013, Jacob Toye, Smartrak
- https://github.com/Leaflet/Leaflet.label
- http://leafletjs.com
- https://github.com/jacobtoye
- */
- (function () {
- //var L = window.L;
- /*
- * Leaflet.label assumes that you have already included the Leaflet library.
- */
- //L.labelVersion = '0.2.2-dev';
- L.Label = (L.Layer ? L.Layer : L.Class).extend({
- // includes: L.Mixin.Events,
- includes: L.Events,
- options: {
- className: "",
- clickable: false,
- direction: "auto",
- noHide: false,
- offset: [13, -16], // 6 (width of the label triangle) + 6 (padding)
- opacity: 1,
- zoomAnimation: true,
- },
- initialize: function (options, source) {
- L.setOptions(this, options);
- this._source = source;
- this._animated = L.Browser.any3d && this.options.zoomAnimation;
- this._isOpen = false;
- },
- onAdd: function (map) {
- this._map = map;
- this._pane = this.options.pane
- ? map._panes[this.options.pane]
- : this._source instanceof L.Marker
- ? map._panes.markerPane
- : map._panes.popupPane;
- if (!this._container) {
- this._initLayout();
- }
- this._pane.appendChild(this._container);
- this._initInteraction();
- this._update();
- this.setOpacity(this.options.opacity);
- map
- .on("moveend", this._onMoveEnd, this)
- .on("viewreset", this._onViewReset, this);
- if (this._animated) {
- map.on("zoomanim", this._zoomAnimation, this);
- }
- if (L.Browser.touch && !this.options.noHide) {
- L.DomEvent.on(this._container, "click", this.close, this);
- map.on("click", this.close, this);
- }
- },
- onRemove: function (map) {
- this._pane.removeChild(this._container);
- map.off(
- {
- zoomanim: this._zoomAnimation,
- moveend: this._onMoveEnd,
- viewreset: this._onViewReset,
- },
- this
- );
- this._removeInteraction();
- this._map = null;
- },
- setLatLng: function (latlng) {
- this._latlng = L.latLng(latlng);
- if (this._map) {
- this._updatePosition();
- }
- return this;
- },
- setContent: function (content) {
- // Backup previous content and store new content
- this._previousContent = this._content;
- this._content = content;
- this._updateContent();
- return this;
- },
- close: function () {
- var map = this._map;
- if (map) {
- if (L.Browser.touch && !this.options.noHide) {
- L.DomEvent.off(this._container, "click", this.close);
- map.off("click", this.close, this);
- }
- map.removeLayer(this);
- }
- },
- updateZIndex: function (zIndex) {
- this._zIndex = zIndex;
- if (this._container && this._zIndex) {
- this._container.style.zIndex = zIndex;
- }
- },
- setOpacity: function (opacity) {
- this.options.opacity = opacity;
- if (this._container) {
- L.DomUtil.setOpacity(this._container, opacity);
- }
- },
- _initLayout: function () {
- this._container = L.DomUtil.create(
- "div",
- "leaflet-label " + this.options.className + " leaflet-zoom-animated"
- );
- this.updateZIndex(this._zIndex);
- },
- _update: function () {
- if (!this._map) {
- return;
- }
- this._container.style.visibility = "hidden";
- this._updateContent();
- this._updatePosition();
- this._container.style.visibility = "";
- },
- _updateContent: function () {
- if (!this._content || !this._map || this._prevContent === this._content) {
- return;
- }
- if (typeof this._content === "string") {
- this._container.innerHTML = this._content;
- this._prevContent = this._content;
- this._labelWidth = this._container.offsetWidth;
- } else {
- this._container.innerHTML = "";
- this._container.appendChild(this._content);
- this._prevContent = this._content;
- this._labelWidth = this._container.offsetWidth;
- }
- //==S== 修改标记
- L.DomUtil.create("div", "leaflet-label-tips", this._container);
- //==E== 修改标记
- },
- _updatePosition: function () {
- var pos = this._map.latLngToLayerPoint(this._latlng);
- this._setPosition(pos);
- },
- _setPosition: function (pos) {
- var map = this._map,
- container = this._container,
- centerPoint = map.latLngToContainerPoint(map.getCenter()),
- labelPoint = map.layerPointToContainerPoint(pos),
- direction = this.options.direction,
- labelWidth = this._labelWidth,
- offset = L.point(this.options.offset);
- // position to the right (right or auto & needs to)
- if (
- direction === "right" ||
- (direction === "auto" && labelPoint.x < centerPoint.x)
- ) {
- L.DomUtil.addClass(container, "leaflet-label-right");
- L.DomUtil.removeClass(container, "leaflet-label-left");
- pos = pos.add(offset);
- } else {
- // position to the left
- L.DomUtil.addClass(container, "leaflet-label-left");
- L.DomUtil.removeClass(container, "leaflet-label-right");
- pos = pos.add(L.point(-offset.x - labelWidth, offset.y));
- }
- L.DomUtil.setPosition(container, pos);
- },
- _zoomAnimation: function (opt) {
- var pos = this._map
- ._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center)
- .round();
- this._setPosition(pos);
- },
- _onMoveEnd: function () {
- if (!this._animated || this.options.direction === "auto") {
- this._updatePosition();
- }
- },
- _onViewReset: function (e) {
- /* if map resets hard, we must update the label */
- if (e && e.hard) {
- this._update();
- }
- },
- _initInteraction: function () {
- if (!this.options.clickable) {
- return;
- }
- var container = this._container,
- events = [
- "dblclick",
- "mousedown",
- "mouseover",
- "mouseout",
- "contextmenu",
- ];
- L.DomUtil.addClass(container, "leaflet-clickable");
- L.DomEvent.on(container, "click", this._onMouseClick, this);
- for (var i = 0; i < events.length; i++) {
- L.DomEvent.on(container, events[i], this._fireMouseEvent, this);
- }
- },
- _removeInteraction: function () {
- if (!this.options.clickable) {
- return;
- }
- var container = this._container,
- events = [
- "dblclick",
- "mousedown",
- "mouseover",
- "mouseout",
- "contextmenu",
- ];
- L.DomUtil.removeClass(container, "leaflet-clickable");
- L.DomEvent.off(container, "click", this._onMouseClick, this);
- for (var i = 0; i < events.length; i++) {
- L.DomEvent.off(container, events[i], this._fireMouseEvent, this);
- }
- },
- _onMouseClick: function (e) {
- if (this.hasEventListeners(e.type)) {
- L.DomEvent.stopPropagation(e);
- }
- this.fire(e.type, {
- originalEvent: e,
- });
- },
- _fireMouseEvent: function (e) {
- this.fire(e.type, {
- originalEvent: e,
- });
- // TODO proper custom event propagation
- // this line will always be called if marker is in a FeatureGroup
- if (e.type === "contextmenu" && this.hasEventListeners(e.type)) {
- L.DomEvent.preventDefault(e);
- }
- if (e.type !== "mousedown") {
- L.DomEvent.stopPropagation(e);
- } else {
- L.DomEvent.preventDefault(e);
- }
- },
- });
- // This object is a mixin for L.Marker and L.CircleMarker. We declare it here as both need to include the contents.
- L.BaseMarkerMethods = {
- showLabel: function () {
- if (this.label && this._map) {
- this.label.setLatLng(this._latlng);
- this._map.showLabel(this.label);
- }
- return this;
- },
- hideLabel: function () {
- if (this.label) {
- this.label.close();
- }
- return this;
- },
- setLabelNoHide: function (noHide) {
- if (this._labelNoHide === noHide) {
- return;
- }
- this._labelNoHide = noHide;
- if (noHide) {
- this._removeLabelRevealHandlers();
- this.showLabel();
- } else {
- this._addLabelRevealHandlers();
- this.hideLabel();
- }
- },
- bindLabel: function (content, options) {
- if (this.label) {
- return false;
- }
- var labelAnchor = this.options.icon
- ? this.options.icon.options.labelAnchor
- : this.options.labelAnchor,
- anchor = L.point(labelAnchor) || L.point(0, 0);
- anchor = anchor.add(L.Label.prototype.options.offset);
- if (options && options.offset) {
- anchor = anchor.add(options.offset);
- }
- options = L.Util.extend({ offset: anchor }, options);
- this._labelNoHide = options.noHide;
- if (!this.label) {
- if (!this._labelNoHide) {
- this._addLabelRevealHandlers();
- }
- this.on("remove", this.hideLabel, this)
- .on("move", this._moveLabel, this)
- .on("add", this._onMarkerAdd, this);
- this._hasLabelHandlers = true;
- }
- this.label = new L.Label(options, this).setContent(content);
- return this;
- },
- unbindLabel: function () {
- if (this.label) {
- this.hideLabel();
- this.label = null;
- if (this._hasLabelHandlers) {
- if (!this._labelNoHide) {
- this._removeLabelRevealHandlers();
- }
- this.off("remove", this.hideLabel, this)
- .off("move", this._moveLabel, this)
- .off("add", this._onMarkerAdd, this);
- }
- this._hasLabelHandlers = false;
- }
- return this;
- },
- updateLabelContent: function (content) {
- if (this.label) {
- this.label.setContent(content);
- }
- },
- getLabel: function () {
- return this.label;
- },
- _onMarkerAdd: function () {
- if (this._labelNoHide) {
- this.showLabel();
- }
- },
- _addLabelRevealHandlers: function () {
- this.on("mouseover", this.showLabel, this).on(
- "mouseout",
- this.hideLabel,
- this
- );
- if (L.Browser.touch) {
- this.on("click", this.showLabel, this);
- }
- },
- _removeLabelRevealHandlers: function () {
- this.off("mouseover", this.showLabel, this).off(
- "mouseout",
- this.hideLabel,
- this
- );
- if (L.Browser.touch) {
- this.off("click", this.showLabel, this);
- }
- },
- _moveLabel: function (e) {
- this.label.setLatLng(e.latlng);
- },
- };
- // Add in an option to icon that is used to set where the label anchor is
- L.Icon.Default.mergeOptions({
- labelAnchor: new L.Point(4, -15),
- });
- // Have to do this since Leaflet is loaded before this plugin and initializes
- // L.Marker.options.icon therefore missing our mixin above.
- L.Marker.mergeOptions({
- icon: new L.Icon.Default(),
- });
- L.Marker.include(L.BaseMarkerMethods);
- L.Marker.include({
- _originalUpdateZIndex: L.Marker.prototype._updateZIndex,
- _updateZIndex: function (offset) {
- var zIndex = this._zIndex + offset;
- this._originalUpdateZIndex(offset);
- if (this.label) {
- this.label.updateZIndex(zIndex);
- }
- },
- _originalSetOpacity: L.Marker.prototype.setOpacity,
- setOpacity: function (opacity, labelHasSemiTransparency) {
- this.options.labelHasSemiTransparency = labelHasSemiTransparency;
- this._originalSetOpacity(opacity);
- },
- _originalUpdateOpacity: L.Marker.prototype._updateOpacity,
- _updateOpacity: function () {
- var absoluteOpacity = this.options.opacity === 0 ? 0 : 1;
- this._originalUpdateOpacity();
- if (this.label) {
- this.label.setOpacity(
- this.options.labelHasSemiTransparency
- ? this.options.opacity
- : absoluteOpacity
- );
- }
- },
- _originalSetLatLng: L.Marker.prototype.setLatLng,
- setLatLng: function (latlng) {
- if (this.label && !this._labelNoHide) {
- this.hideLabel();
- }
- return this._originalSetLatLng(latlng);
- },
- });
- // Add in an option to icon that is used to set where the label anchor is
- L.CircleMarker.mergeOptions({
- labelAnchor: new L.Point(-5, 5),
- });
- L.CircleMarker.include(L.BaseMarkerMethods);
- L.Path.include({
- bindLabel: function (content, options) {
- if (!this.label || this.label.options !== options) {
- this.label = new L.Label(options, this);
- }
- this.label.setContent(content);
- if (!this._showLabelAdded) {
- this.on("mouseover", this._showLabel, this)
- .on("mousemove", this._moveLabel, this)
- .on("mouseout remove", this._hideLabel, this);
- if (L.Browser.touch) {
- this.on("click", this._showLabel, this);
- }
- this._showLabelAdded = true;
- }
- return this;
- },
- unbindLabel: function () {
- if (this.label) {
- this._hideLabel();
- this.label = null;
- this._showLabelAdded = false;
- this.off("mouseover", this._showLabel, this)
- .off("mousemove", this._moveLabel, this)
- .off("mouseout remove", this._hideLabel, this);
- }
- return this;
- },
- updateLabelContent: function (content) {
- if (this.label) {
- this.label.setContent(content);
- }
- },
- _showLabel: function (e) {
- this.label.setLatLng(e.latlng);
- this._map.showLabel(this.label);
- },
- _moveLabel: function (e) {
- this.label.setLatLng(e.latlng);
- },
- _hideLabel: function () {
- this.label.close();
- },
- });
- L.Map.include({
- showLabel: function (label) {
- return this.addLayer(label);
- },
- });
- L.FeatureGroup.include({
- // TODO: remove this when AOP is supported in Leaflet, need this as we cannot put code in removeLayer()
- clearLayers: function () {
- this.unbindLabel();
- this.eachLayer(this.removeLayer, this);
- return this;
- },
- bindLabel: function (content, options) {
- return this.invoke("bindLabel", content, options);
- },
- unbindLabel: function () {
- return this.invoke("unbindLabel");
- },
- updateLabelContent: function (content) {
- this.invoke("updateLabelContent", content);
- },
- });
- })(window, document);
|