Ich habe es geschafft, es zu lösen. Ich bin faul, es jetzt zu ihrem Repo zu schieben, aber ich werde es wahrscheinlich in der Zukunft tun. Die Logik der Lösung ist wie folgt:
this.label
->this.labels
this.labels
ist ein Array von LeafletLabel
s
- die Änderung
this.label
- bewegen
this._labelNoHide
= options.noHide
in die if
enthält für Methoden gelten für Bugfix
Das Label ls wird ähnlich für die Teilmenge von options
handeln, die singularly/marker behandelt wird. Entschuldigung, Leute, die noHide
oder opacity
auf Label-Ebene statt Marker-Ebene vereinheitlichen, würde den Rahmen dieser Frage sprengen. Ich könnte diese später aber auflösen.
Der Code ist wie folgt:
/*
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));
persönlich nichts Ich sehe falsch in HTML-Code (einschließlich des '
' Tag für einen Zeilenumbruch) in dem Inhalt des Etiketts mehr Informationen zur Verfügung zu stellen ... Da für mehrere Etiketten Ich denke, es gibt immer noch nichts Out-of-the-Box. – ghybs
@ghybs, danke für den Kommentar. Wenn wir nicht die Möglichkeit haben, mehrere Labels zu binden, ist es unmöglich, einen nach links und einen nach rechts zu zeichnen. Ich weiß, dass das nicht mein gegenwärtiger Wunsch ist, aber das Fehlen dieser Möglichkeit ist nicht zu gut. Vielleicht lohnt es sich, in den Code des Plugins zu schauen und zu sehen, wie bindLabel funktioniert und das Plural macht. Ich weiß, dass es ein Hack ist, aber wenn es ein eleganter Code ist, könnten sie ihn zukünftigen Versionen hinzufügen. –
In der Tat könnte es interessant sein, eine "Gruppen" -Option zu haben, so dass jedes Etikett beispielsweise an eine Gruppe mit einer bestimmten Position angehängt werden kann. Jetzt ist dieses Plugin Open Source, was bedeutet, dass "sie" gerne Pull Requests erhalten würden! :-) – ghybs