Non puoi selezionare più di 25 argomenti
Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
232 righe
8.4 KiB
232 righe
8.4 KiB
2 anni fa
|
L.LabelTextCollision = L.Canvas
|
||
|
.extend({
|
||
|
|
||
|
options : {
|
||
|
/**
|
||
|
* Collision detection
|
||
|
*/
|
||
|
collisionFlg : true
|
||
|
},
|
||
|
|
||
|
initialize : function(options) {
|
||
|
options = L.Util.setOptions(this, options);
|
||
|
},
|
||
|
|
||
|
_handleMouseHover : function(e, point) {
|
||
|
var id, layer;
|
||
|
|
||
|
for (id in this._drawnLayers) {
|
||
|
layer = this._drawnLayers[id];
|
||
|
if (layer.options.interactive
|
||
|
&& layer._containsPoint(point)) {
|
||
|
L.DomUtil.addClass(this._containerText,
|
||
|
'leaflet-interactive'); // change cursor
|
||
|
this._fireEvent([ layer ], e, 'mouseover');
|
||
|
this._hoveredLayer = layer;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (this._hoveredLayer) {
|
||
|
this._fireEvent([ this._hoveredLayer ], e);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_handleMouseOut : function(e, point) {
|
||
|
var layer = this._hoveredLayer;
|
||
|
if (layer
|
||
|
&& (e.type === 'mouseout' || !layer
|
||
|
._containsPoint(point))) {
|
||
|
// if we're leaving the layer, fire mouseout
|
||
|
L.DomUtil.removeClass(this._containerText,
|
||
|
'leaflet-interactive');
|
||
|
this._fireEvent([ layer ], e, 'mouseout');
|
||
|
this._hoveredLayer = null;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_updateTransform : function(center, zoom) {
|
||
|
|
||
|
L.Canvas.prototype._updateTransform.call(this, center, zoom);
|
||
|
|
||
|
var scale = this._map.getZoomScale(zoom, this._zoom), position = L.DomUtil
|
||
|
.getPosition(this._container), viewHalf = this._map
|
||
|
.getSize().multiplyBy(0.5 + this.options.padding), currentCenterPoint = this._map
|
||
|
.project(this._center, zoom), destCenterPoint = this._map
|
||
|
.project(center, zoom), centerOffset = destCenterPoint
|
||
|
.subtract(currentCenterPoint),
|
||
|
|
||
|
topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(
|
||
|
viewHalf).subtract(centerOffset);
|
||
|
|
||
|
if (L.Browser.any3d) {
|
||
|
L.DomUtil.setTransform(this._containerText, topLeftOffset,
|
||
|
scale);
|
||
|
} else {
|
||
|
L.DomUtil.setPosition(this._containerText, topLeftOffset);
|
||
|
}
|
||
|
},
|
||
|
_initContainer : function(options) {
|
||
|
L.Canvas.prototype._initContainer.call(this);
|
||
|
|
||
|
this._containerText = document.createElement('canvas');
|
||
|
|
||
|
L.DomEvent.on(this._containerText, 'mousemove',
|
||
|
L.Util.throttle(this._onMouseMove, 32, this), this).on(
|
||
|
this._containerText,
|
||
|
'click dblclick mousedown mouseup contextmenu',
|
||
|
this._onClick, this).on(this._containerText,
|
||
|
'mouseout', this._handleMouseOut, this);
|
||
|
|
||
|
this._ctxLabel = this._containerText.getContext('2d');
|
||
|
|
||
|
L.DomUtil
|
||
|
.addClass(this._containerText, 'leaflet-zoom-animated');
|
||
|
this.getPane().appendChild(this._containerText);
|
||
|
|
||
|
},
|
||
|
|
||
|
_update : function() {
|
||
|
// textList
|
||
|
this._textList = [];
|
||
|
|
||
|
L.Renderer.prototype._update.call(this);
|
||
|
var b = this._bounds, container = this._containerText, size = b
|
||
|
.getSize(), m = L.Browser.retina ? 2 : 1;
|
||
|
|
||
|
L.DomUtil.setPosition(container, b.min);
|
||
|
|
||
|
// set canvas size (also clearing it); use double size on retina
|
||
|
container.width = m * size.x;
|
||
|
container.height = m * size.y;
|
||
|
container.style.width = size.x + 'px';
|
||
|
container.style.height = size.y + 'px';
|
||
|
|
||
|
// display text on the whole surface
|
||
|
container.style.zIndex = '4';
|
||
|
this._container.style.zIndex = '3';
|
||
|
|
||
|
if (L.Browser.retina) {
|
||
|
this._ctxLabel.scale(2, 2);
|
||
|
}
|
||
|
|
||
|
// translate so we use the same path coordinates after canvas
|
||
|
// element moves
|
||
|
this._ctxLabel.translate(-b.min.x, -b.min.y);
|
||
|
L.Canvas.prototype._update.call(this);
|
||
|
|
||
|
},
|
||
|
|
||
|
_updatePoly : function(layer, closed) {
|
||
|
L.Canvas.prototype._updatePoly.call(this, layer, closed);
|
||
|
this._text(this._ctxLabel, layer);
|
||
|
},
|
||
|
|
||
|
_updateCircle : function(layer) {
|
||
|
L.Canvas.prototype._updateCircle.call(this, layer);
|
||
|
this._text(this._ctxLabel, layer);
|
||
|
},
|
||
|
|
||
|
_text : function(ctx, layer) {
|
||
|
|
||
|
if (layer.options.text != undefined) {
|
||
|
|
||
|
ctx.globalAlpha = 1;
|
||
|
|
||
|
var p = layer._point;
|
||
|
var textPoint;
|
||
|
|
||
|
if (p == undefined) {
|
||
|
// polygon or polyline
|
||
|
if (layer._parts.length == 0
|
||
|
|| layer._parts[0].length == 0) {
|
||
|
return;
|
||
|
}
|
||
|
p = this._getCenter(layer._parts[0]);
|
||
|
}
|
||
|
|
||
|
// label bounds offset
|
||
|
var offsetX = 0;
|
||
|
var offsetY = 0;
|
||
|
|
||
|
/**
|
||
|
* TODO setting for custom font
|
||
|
*/
|
||
|
ctx.lineWidth = 4.0;
|
||
|
ctx.font = "16px 'Meiryo'";
|
||
|
|
||
|
// Collision detection
|
||
|
var textWidth = (ctx.measureText(layer.options.text).width)
|
||
|
+ p.x;// + offsetX;
|
||
|
|
||
|
var textHeight = p.y + offsetY + 20;
|
||
|
|
||
|
var bounds = L.bounds(
|
||
|
L.point(p.x + offsetX, p.y + offsetY), L.point(
|
||
|
textWidth, textHeight));
|
||
|
|
||
|
if (this.options.collisionFlg) {
|
||
|
|
||
|
for ( var index in this._textList) {
|
||
|
var pointBounds = this._textList[index];
|
||
|
if (pointBounds.intersects(bounds)) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this._textList.push(bounds);
|
||
|
|
||
|
ctx.strokeStyle = "white";
|
||
|
ctx.strokeText(layer.options.text, p.x + offsetX, p.y
|
||
|
+ offsetY);
|
||
|
|
||
|
if (layer.options.textColor == undefined) {
|
||
|
ctx.fillStyle = "blue";
|
||
|
} else {
|
||
|
ctx.fillStyle = layer.options.textColor;
|
||
|
}
|
||
|
|
||
|
ctx.fillText(layer.options.text, p.x + offsetX, p.y
|
||
|
+ offsetY);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_getCenter : function(points) {
|
||
|
|
||
|
var i, halfDist, segDist, dist, p1, p2, ratio, len = points.length;
|
||
|
|
||
|
if (!len) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// polyline centroid algorithm; only uses the first ring if
|
||
|
// there are multiple
|
||
|
|
||
|
for (i = 0, halfDist = 0; i < len - 1; i++) {
|
||
|
halfDist += points[i].distanceTo(points[i + 1]) / 2;
|
||
|
}
|
||
|
|
||
|
// The line is so small in the current view that all points are
|
||
|
// on the same pixel.
|
||
|
if (halfDist === 0) {
|
||
|
return points[0];
|
||
|
}
|
||
|
|
||
|
for (i = 0, dist = 0; i < len - 1; i++) {
|
||
|
p1 = points[i];
|
||
|
p2 = points[i + 1];
|
||
|
segDist = p1.distanceTo(p2);
|
||
|
dist += segDist;
|
||
|
|
||
|
if (dist > halfDist) {
|
||
|
ratio = (dist - halfDist) / segDist;
|
||
|
var resutl = [ p2.x - ratio * (p2.x - p1.x),
|
||
|
p2.y - ratio * (p2.y - p1.y) ];
|
||
|
|
||
|
return L.point(resutl[0], resutl[1]);
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
});
|