diff --git a/dist/leaflet.label-src.js b/dist/leaflet.label-src.js index fe70ac0..4af1ddf 100644 --- a/dist/leaflet.label-src.js +++ b/dist/leaflet.label-src.js @@ -29,6 +29,8 @@ var LeafletLabel = L.Class.extend({ includes: L.Mixin.Events, + _directions: [ 'top', 'right', 'bottom', 'left' ], + options: { className: '', clickable: false, @@ -36,6 +38,9 @@ var LeafletLabel = L.Class.extend({ noHide: false, offset: [12, -15], // 6 (width of the label triangle) + 6 (padding) opacity: 1, + textsize: "10px", + textOnly: false, + style: null, zoomAnimation: true }, @@ -47,11 +52,15 @@ var LeafletLabel = L.Class.extend({ this._isOpen = false; }, + _isOnMarker: function () { + return this._source instanceof L.Marker; + }, + 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; + this._isOnMarker() ? map._panes.markerPane : map._panes.popupPane; if (!this._container) { this._initLayout(); @@ -142,6 +151,15 @@ var LeafletLabel = L.Class.extend({ _initLayout: function () { this._container = L.DomUtil.create('div', 'leaflet-label ' + this.options.className + ' leaflet-zoom-animated'); + this._container.style.fontSize = this.options.textsize; + if (this.options.textOnly) { L.DomUtil.addClass(this._container, 'leaflet-label-text-only'); } + if (this.options.style) { + for (var property in this.options.style) { + if (this.options.style.hasOwnProperty(property)) { + this._container.style[property] = this.options.style[property]; + } + } + } this.updateZIndex(this._zIndex); }, @@ -176,31 +194,67 @@ var LeafletLabel = L.Class.extend({ this._setPosition(pos); }, + _getIconHeight: function () { + return this._source.options.icon ? this._source.options.icon.options.iconSize[1] : 0; + }, + _setPosition: function (pos) { var map = this._map, container = this._container, centerPoint = map.latLngToContainerPoint(map.getCenter()), labelPoint = map.layerPointToContainerPoint(pos), - direction = this.options.direction, + direction = this._getDirection(), labelWidth = this._labelWidth, - offset = L.point(this.options.offset); + offset = L.point(this.options.offset), + verticalOffset = offset.y; - // 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'); + if (direction === 'top') { + verticalOffset -= this._isOnMarker() ? this._getIconHeight() : 0; - 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(-labelWidth / 2, verticalOffset)); + } else if (direction === 'bottom') { + verticalOffset += this._isOnMarker ? this._getIconHeight() : 0; + pos = pos.add(L.point(-labelWidth / 2, verticalOffset)); + } else if (direction === 'right' || direction === 'auto' && labelPoint.x < centerPoint.x) { + direction = 'right'; + pos = pos.add(offset); + } else { + direction = 'left'; pos = pos.add(L.point(-offset.x - labelWidth, offset.y)); } + this._setProperClass(pos, direction); L.DomUtil.setPosition(container, pos); }, + _generateLabelClass: function (direction) { + return 'leaflet-label-' + direction; + }, + + _setProperClass: function (pos, _direction) { + var map = this._map, + container = this._container, + direction = _direction || this._getDirection(), + labelPoint = map.layerPointToContainerPoint(pos), + centerPoint = map.latLngToContainerPoint(map.getCenter()), + classToAdd = this._generateLabelClass(direction); + + for (var i = 0; i < this._directions.length; i++) { + var d = this._directions[i]; + if (d !== direction) { + var classToRemove = this._generateLabelClass(d); + L.DomUtil.removeClass(container, classToRemove); + } + } + + L.DomUtil.addClass(container, classToAdd); + }, + + _getDirection: function () { + return this.options.direction; + }, + _zoomAnimation: function (opt) { var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); @@ -208,7 +262,7 @@ var LeafletLabel = L.Class.extend({ }, _onMoveEnd: function () { - if (!this._animated || this.options.direction === 'auto') { + if (!this._animated || this._getDirection() === 'auto') { this._updatePosition(); } }, diff --git a/dist/leaflet.label.css b/dist/leaflet.label.css index 95e6096..44053d0 100644 --- a/dist/leaflet.label.css +++ b/dist/leaflet.label.css @@ -31,6 +31,7 @@ .leaflet-label:after { border-top: 6px solid transparent; border-bottom: 6px solid transparent; + border-right: 6px solid transparent; content: none; position: absolute; top: 5px; @@ -45,10 +46,74 @@ .leaflet-label:after { border-left: 6px solid black; border-left-color: inherit; - right: -10px; + right: -16px; } +.leaflet-label-top:after, +.leaflet-label-top:before { + left: -50%; + border-top-color: black; + border-top-color: rgba(0,0,0,0.25); + position: relative; + top: 29px; +} + +.leaflet-label-top:before { + display: none; + border-right-color: transparent; + border-bottom-color: transparent; + border-left-color: transparent; + border-top-color: transparent; +} + +.leaflet-label-top:after { + content: ' '; + border-right-color: transparent; + border-bottom-color: transparent; + border-left-color: transparent; +} + +.leaflet-label-bottom:before { + display: none; + border-right-color: transparent; + border-bottom-color: transparent; + border-left-color: transparent; + border-top-color: transparent; +} + +.leaflet-label-bottom:after, +.leaflet-label-bottom:before { + left: -50%; + border-bottom-color: black; + border-bottom-color: rgba(0,0,0,0.25); + position: relative; + top: -28px; +} + +.leaflet-label-bottom:after { + border-right-color: transparent; + border-top-color: transparent; + border-left-color: transparent; +} + +.leaflet-label-bottom:after, +.leaflet-label-top:after, .leaflet-label-right:before, .leaflet-label-left:after { content: ""; } + +.leaflet-label.leaflet-label-text-only, +.leaflet-label.leaflet-label-text-only:before, +.leaflet-label.leaflet-label-text-only:after { + background: none; + border: none; +} + +.leaflet-label.leaflet-label-text-only.leaflet-label-left { + margin-right: -10px; +} + +.leaflet-label.leaflet-label-text-only.leaflet-label-right { + margin-left: -10px; +} diff --git a/dist/leaflet.label.js b/dist/leaflet.label.js index c1edbdb..749599f 100644 --- a/dist/leaflet.label.js +++ b/dist/leaflet.label.js @@ -6,4 +6,4 @@ http://leafletjs.com https://github.com/jacobtoye */ -(function(t,e){"function"==typeof define&&define.amd?define(["leaflet"],t):"object"==typeof exports&&(module.exports=t(require("leaflet"))),e!==void 0&&e.L&&(e.LeafletLabel=t(L))})(function(t){t.labelVersion="0.2.4";var e=t.Class.extend({includes:t.Mixin.Events,options:{className:"",clickable:!1,direction:"right",noHide:!1,offset:[12,-15],opacity:1,zoomAnimation:!0},initialize:function(e,i){t.setOptions(this,e),this._source=i,this._animated=t.Browser.any3d&&this.options.zoomAnimation,this._isOpen=!1},onAdd:function(e){this._map=e,this._pane=this.options.pane?e._panes[this.options.pane]:this._source instanceof t.Marker?e._panes.markerPane:e._panes.popupPane,this._container||this._initLayout(),this._pane.appendChild(this._container),this._initInteraction(),this._update(),this.setOpacity(this.options.opacity),e.on("moveend",this._onMoveEnd,this).on("viewreset",this._onViewReset,this),this._animated&&e.on("zoomanim",this._zoomAnimation,this),t.Browser.touch&&!this.options.noHide&&(t.DomEvent.on(this._container,"click",this.close,this),e.on("click",this.close,this))},onRemove:function(t){this._pane.removeChild(this._container),t.off({zoomanim:this._zoomAnimation,moveend:this._onMoveEnd,viewreset:this._onViewReset},this),this._removeInteraction(),this._map=null},setLatLng:function(e){return this._latlng=t.latLng(e),this._map&&this._updatePosition(),this},setContent:function(t){return this._previousContent=this._content,this._content=t,this._updateContent(),this},close:function(){var e=this._map;e&&(t.Browser.touch&&!this.options.noHide&&(t.DomEvent.off(this._container,"click",this.close),e.off("click",this.close,this)),e.removeLayer(this))},updateZIndex:function(t){this._zIndex=t,this._container&&this._zIndex&&(this._container.style.zIndex=t)},setOpacity:function(e){this.options.opacity=e,this._container&&t.DomUtil.setOpacity(this._container,e)},_initLayout:function(){this._container=t.DomUtil.create("div","leaflet-label "+this.options.className+" leaflet-zoom-animated"),this.updateZIndex(this._zIndex)},_update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updatePosition(),this._container.style.visibility="")},_updateContent:function(){this._content&&this._map&&this._prevContent!==this._content&&"string"==typeof this._content&&(this._container.innerHTML=this._content,this._prevContent=this._content,this._labelWidth=this._container.offsetWidth)},_updatePosition:function(){var t=this._map.latLngToLayerPoint(this._latlng);this._setPosition(t)},_setPosition:function(e){var i=this._map,n=this._container,o=i.latLngToContainerPoint(i.getCenter()),s=i.layerPointToContainerPoint(e),a=this.options.direction,l=this._labelWidth,h=t.point(this.options.offset);"right"===a||"auto"===a&&s.xn;n++)t.DomEvent.on(e,i[n],this._fireMouseEvent,this)}},_removeInteraction:function(){if(this.options.clickable){var e=this._container,i=["dblclick","mousedown","mouseover","mouseout","contextmenu"];t.DomUtil.removeClass(e,"leaflet-clickable"),t.DomEvent.off(e,"click",this._onMouseClick,this);for(var n=0;i.length>n;n++)t.DomEvent.off(e,i[n],this._fireMouseEvent,this)}},_onMouseClick:function(e){this.hasEventListeners(e.type)&&t.DomEvent.stopPropagation(e),this.fire(e.type,{originalEvent:e})},_fireMouseEvent:function(e){this.fire(e.type,{originalEvent:e}),"contextmenu"===e.type&&this.hasEventListeners(e.type)&&t.DomEvent.preventDefault(e),"mousedown"!==e.type?t.DomEvent.stopPropagation(e):t.DomEvent.preventDefault(e)}});return t.BaseMarkerMethods={showLabel:function(){return this.label&&this._map&&(this.label.setLatLng(this._latlng),this._map.showLabel(this.label)),this},hideLabel:function(){return this.label&&this.label.close(),this},setLabelNoHide:function(t){this._labelNoHide!==t&&(this._labelNoHide=t,t?(this._removeLabelRevealHandlers(),this.showLabel()):(this._addLabelRevealHandlers(),this.hideLabel()))},bindLabel:function(i,n){var o=this.options.icon?this.options.icon.options.labelAnchor:this.options.labelAnchor,s=t.point(o)||t.point(0,0);return s=s.add(e.prototype.options.offset),n&&n.offset&&(s=s.add(n.offset)),n=t.Util.extend({offset:s},n),this._labelNoHide=n.noHide,this.label||(this._labelNoHide||this._addLabelRevealHandlers(),this.on("remove",this.hideLabel,this).on("move",this._moveLabel,this).on("add",this._onMarkerAdd,this),this._hasLabelHandlers=!0),this.label=new e(n,this).setContent(i),this},unbindLabel:function(){return this.label&&(this.hideLabel(),this.label=null,this._hasLabelHandlers&&(this._labelNoHide||this._removeLabelRevealHandlers(),this.off("remove",this.hideLabel,this).off("move",this._moveLabel,this).off("add",this._onMarkerAdd,this)),this._hasLabelHandlers=!1),this},updateLabelContent:function(t){this.label&&this.label.setContent(t)},getLabel:function(){return this.label},_onMarkerAdd:function(){this._labelNoHide&&this.showLabel()},_addLabelRevealHandlers:function(){this.on("mouseover",this.showLabel,this).on("mouseout",this.hideLabel,this),t.Browser.touch&&this.on("click",this.showLabel,this)},_removeLabelRevealHandlers:function(){this.off("mouseover",this.showLabel,this).off("mouseout",this.hideLabel,this),t.Browser.touch&&this.off("click",this.showLabel,this)},_moveLabel:function(t){this.label.setLatLng(t.latlng)}},t.Icon.Default.mergeOptions({labelAnchor:new t.Point(9,-20)}),t.Marker.mergeOptions({icon:new t.Icon.Default}),t.Marker.include(t.BaseMarkerMethods),t.Marker.include({_originalUpdateZIndex:t.Marker.prototype._updateZIndex,_updateZIndex:function(t){var e=this._zIndex+t;this._originalUpdateZIndex(t),this.label&&this.label.updateZIndex(e)},_originalSetOpacity:t.Marker.prototype.setOpacity,setOpacity:function(t,e){this.options.labelHasSemiTransparency=e,this._originalSetOpacity(t)},_originalUpdateOpacity:t.Marker.prototype._updateOpacity,_updateOpacity:function(){var t=0===this.options.opacity?0:1;this._originalUpdateOpacity(),this.label&&this.label.setOpacity(this.options.labelHasSemiTransparency?this.options.opacity:t)},_originalSetLatLng:t.Marker.prototype.setLatLng,setLatLng:function(t){return this.label&&!this._labelNoHide&&this.hideLabel(),this._originalSetLatLng(t)}}),t.CircleMarker.mergeOptions({labelAnchor:new t.Point(0,0)}),t.CircleMarker.include(t.BaseMarkerMethods),t.Path.include({bindLabel:function(i,n){return this.label&&this.label.options===n||(this.label=new e(n,this)),this.label.setContent(i),this._showLabelAdded||(this.on("mouseover",this._showLabel,this).on("mousemove",this._moveLabel,this).on("mouseout remove",this._hideLabel,this),t.Browser.touch&&this.on("click",this._showLabel,this),this._showLabelAdded=!0),this},unbindLabel:function(){return this.label&&(this._hideLabel(),this.label=null,this._showLabelAdded=!1,this.off("mouseover",this._showLabel,this).off("mousemove",this._moveLabel,this).off("mouseout remove",this._hideLabel,this)),this},updateLabelContent:function(t){this.label&&this.label.setContent(t)},_showLabel:function(t){this.label.setLatLng(t.latlng),this._map.showLabel(this.label)},_moveLabel:function(t){this.label.setLatLng(t.latlng)},_hideLabel:function(){this.label.close()}}),t.Map.include({showLabel:function(t){return this.addLayer(t)}}),t.FeatureGroup.include({clearLayers:function(){return this.unbindLabel(),this.eachLayer(this.removeLayer,this),this},bindLabel:function(t,e){return this.invoke("bindLabel",t,e)},unbindLabel:function(){return this.invoke("unbindLabel")},updateLabelContent:function(t){this.invoke("updateLabelContent",t)}}),e},window); \ No newline at end of file +!function(t,e){"function"==typeof define&&define.amd?define(["leaflet"],t):"object"==typeof exports&&(module.exports=t(require("leaflet"))),"undefined"!=typeof e&&e.L&&(e.LeafletLabel=t(L))}(function(t){t.labelVersion="0.2.4";var e=t.Class.extend({includes:t.Mixin.Events,_directions:["top","right","bottom","left"],options:{className:"",clickable:!1,direction:"right",noHide:!1,offset:[12,-15],opacity:1,textsize:"10px",textOnly:!1,style:null,zoomAnimation:!0},initialize:function(e,i){t.setOptions(this,e),this._source=i,this._animated=t.Browser.any3d&&this.options.zoomAnimation,this._isOpen=!1},_isOnMarker:function(){return this._source instanceof t.Marker},onAdd:function(e){this._map=e,this._pane=this.options.pane?e._panes[this.options.pane]:this._isOnMarker()?e._panes.markerPane:e._panes.popupPane,this._container||this._initLayout(),this._pane.appendChild(this._container),this._initInteraction(),this._update(),this.setOpacity(this.options.opacity),e.on("moveend",this._onMoveEnd,this).on("viewreset",this._onViewReset,this),this._animated&&e.on("zoomanim",this._zoomAnimation,this),t.Browser.touch&&!this.options.noHide&&(t.DomEvent.on(this._container,"click",this.close,this),e.on("click",this.close,this))},onRemove:function(t){this._pane.removeChild(this._container),t.off({zoomanim:this._zoomAnimation,moveend:this._onMoveEnd,viewreset:this._onViewReset},this),this._removeInteraction(),this._map=null},setLatLng:function(e){return this._latlng=t.latLng(e),this._map&&this._updatePosition(),this},setContent:function(t){return this._previousContent=this._content,this._content=t,this._updateContent(),this},close:function(){var e=this._map;e&&(t.Browser.touch&&!this.options.noHide&&(t.DomEvent.off(this._container,"click",this.close),e.off("click",this.close,this)),e.removeLayer(this))},updateZIndex:function(t){this._zIndex=t,this._container&&this._zIndex&&(this._container.style.zIndex=t)},setOpacity:function(e){this.options.opacity=e,this._container&&t.DomUtil.setOpacity(this._container,e)},_initLayout:function(){if(this._container=t.DomUtil.create("div","leaflet-label "+this.options.className+" leaflet-zoom-animated"),this._container.style.fontSize=this.options.textsize,this.options.textOnly&&t.DomUtil.addClass(this._container,"leaflet-label-text-only"),this.options.style)for(var e in this.options.style)this.options.style.hasOwnProperty(e)&&(this._container.style[e]=this.options.style[e]);this.updateZIndex(this._zIndex)},_update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updatePosition(),this._container.style.visibility="")},_updateContent:function(){this._content&&this._map&&this._prevContent!==this._content&&"string"==typeof this._content&&(this._container.innerHTML=this._content,this._prevContent=this._content,this._labelWidth=this._container.offsetWidth)},_updatePosition:function(){var t=this._map.latLngToLayerPoint(this._latlng);this._setPosition(t)},_getIconHeight:function(){return this._source.options.icon?this._source.options.icon.options.iconSize[1]:0},_setPosition:function(e){var i=this._map,n=this._container,o=i.latLngToContainerPoint(i.getCenter()),s=i.layerPointToContainerPoint(e),a=this._getDirection(),h=this._labelWidth,l=t.point(this.options.offset),r=l.y;"top"===a?(r-=this._isOnMarker()?this._getIconHeight():0,e=e.add(t.point(-h/2,r))):"bottom"===a?(r+=this._isOnMarker?this._getIconHeight():0,e=e.add(t.point(-h/2,r))):"right"===a||"auto"===a&&s.x