我正在使用Leaflet并且效果很好。我也使用leaflet.label,也很好用。问题是我想在标记的右侧显示两个标签。如果我拨打bindLabel
两次,那么第二次会覆盖第一次。我如何确保标记右侧有两个标签,第二个标签位于第一个标签上方?
这是我尝试的方式:
newMarker.bindLabel(result, { noHide: true }).bindLabel("secondlabel", { noHide: true });
由于
编辑:
我设法通过一次调用bindLabel
来显示文本,如下所示:
newMarker.bindLabel(result + "<br>secondLabel", { noHide: true });
但这似乎是一个过于苛刻的解决方案。 Here他们说这是不可能的,但这是在2014年写的。从那时起它可能是可能的。
答案 0 :(得分:4)
我设法解决了这个问题。我现在懒得把它推到他们的回购中,但我将来可能会这样做。解决方案的逻辑如下:
this.label
- &gt; this.labels
this.labels
是LeafletLabel
s this.label
this._labelNoHide
= options.noHide
移至if
以防止错误标签将对options
的子集采取类似的行动,该子集以单数/标记处理。很抱歉,将noHide
或opacity
标记为标记级别而非标记级别的人员超出了此问题的范围。我可能稍后解决这些问题。
代码如下:
/*
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 (factory, window) {
// define an AMD module that relies on 'leaflet'
if (typeof define === 'function' && define.amd) {
define(['leaflet'], factory);
// define a Common JS module that relies on 'leaflet'
} else if (typeof exports === 'object') {
module.exports = factory(require('leaflet'));
}
// attach your plugin to the global 'L' variable
if (typeof window !== 'undefined' && window.L) {
window.LeafletLabel = factory(L);
}
}(function (L) {
L.labelVersion = '0.2.4';
var LeafletLabel = L.Class.extend({
includes: L.Mixin.Events,
options: {
className: '',
clickable: false,
direction: 'right',
noHide: false,
offset: [12, -15], // 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;
}
},
_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);
}
}
});
/*global LeafletLabel */
// 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.labels && this._map) {
for (var labelIndex in this.labels) {
this.labels[labelIndex].setLatLng(this._latlng);
this._map.showLabel(this.labels[labelIndex]);
}
}
return this;
},
hideLabel: function () {
if (this.labels) {
for (var labelIndex in this.labels) {
this.labels[labelIndex].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) {
var labelAnchor = this.options.icon ? this.options.icon.options.labelAnchor : this.options.labelAnchor,
anchor = L.point(labelAnchor) || L.point(0, 0);
anchor = anchor.add(LeafletLabel.prototype.options.offset);
if (options && options.offset) {
anchor = anchor.add(options.offset);
}
options = L.Util.extend({ offset: anchor }, options);
if (!this.labels) {
this._labelNoHide = options.noHide;
this.labels = [];
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.labels.push(new LeafletLabel(options, this).setContent(content));
return this;
},
unbindLabel: function () {
if (this.labels) {
this.hideLabel();
this.labels = 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, index) {
if ((this.labels) && (index < this.labels.length)) {
this.labels[index].setContent(content);
}
},
getLabels: function () {
return this.labels;
},
_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(9, -20)
});
// 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.labels) {
for (var labelIndex in this.labels) {
this.labels[labelIndex].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.labels) {
for (var labelIndex in labels) {
this.labels[labelIndex].setOpacity(this.options.labelHasSemiTransparency ? this.options.opacity : absoluteOpacity);
}
}
},
_originalSetLatLng: L.Marker.prototype.setLatLng,
setLatLng: function (latlng) {
if (this.labels && !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(0, 0)
});
L.CircleMarker.include(L.BaseMarkerMethods);
/*global LeafletLabel */
L.Path.include({
bindLabel: function (content, options) {
if (!this.label || this.label.options !== options) {
this.label = new LeafletLabel(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);
}
});
return LeafletLabel;
}, window));