lifo-dijkstraserv/htdocs/leafletjs/Leaflet.streetlabels.js
Markus Koch 771704bf15 Add basic support for city outlines
Use with load_geojson(
	"Cities (outline, demo)",
	"./geojson/cities_demo.json",
	"outline",
	"black",
	1,
	style_outlines);
2020-04-25 13:08:14 +02:00

196 lines
7.3 KiB
JavaScript

/*
*
*
*/
L.StreetLabels = L.LabelTextCollision
.extend({
options: {
/**
* Default property name to display the tooltip
*/
propertyName: 'name',
showLabelIf: null,
fontStyle: {
dynamicFontSize: false,
fontSize: 10,
fontSizeUnit: "px",
lineWidth: 4.0,
fillStyle: "black",
strokeStyle: "white",
},
},
initialize: function (options) {
L.LabelTextCollision.prototype.initialize.call(this, options);
L.Util.stamp(this);
this._layers = this._layers || {};
},
_initContainer: function (options) {
L.LabelTextCollision.prototype._initContainer.call(this, options);
//Register the add/remove layers event to update the annotations accordingly
if (this._map) {
var handleLayerChanges = function () {
this._reset();
this._redraw();
}.bind(this);
this._map.on("layerremove", L.Util.throttle(handleLayerChanges, 32, this));
}
},
_text: function (ctx, layer) {
if (layer && layer.feature && layer.feature.properties && layer.feature.properties[this.options.propertyName] !== 'undefined') {
if (this.options.showLabelIf) {
if (this.options.showLabelIf.call(this, layer.feature) === false) {
return;
}
}
var layerText = layer.feature.properties[this.options.propertyName];
ctx.globalAlpha = 1;
var p;
// polygon or polyline
if (layer._parts.length === 0 || layer._parts[0].length === 0) {
return;
}
if (layer instanceof L.Polygon && this._map.hasLayer(layer)) {
p = this._getCentroid(layer);
}
else {
p = this._getCenter(layer._parts[0]);
}
if (!p) {
return;
}
// label bounds offset
var offsetX = 0;
var offsetY = 0;
/**
* TODO setting for custom font
*/
ctx.lineWidth = this.options.fontStyle.lineWidth;
var fontSize = this.options.fontStyle.fontSize;
if (this._map && this.options.fontStyle.dynamicFontSize === true) {
fontSize = this._getDynamicFontSize(layer.feature);
}
ctx.font = fontSize + this.options.fontStyle.fontSizeUnit + " 'Helvetica Neue',Helvetica,Arial,sans-serif";
// Collision detection
var textWidth = (ctx.measureText(layerText).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.fillStyle = this.options.fontStyle.fillStyle;
ctx.strokeStyle = this.options.fontStyle.strokeStyle;
if (layer instanceof L.Polygon || layer instanceof L.CircleMarker) {
var textLength = ctx.measureText(layerText).width;
ctx.strokeText(layerText, p.x + offsetX - textLength / 2, p.y + offsetY);
ctx.fillText(layerText, p.x + offsetX - textLength / 2, p.y + offsetY);
} else if (layer instanceof L.Polyline) {
/**
* Render text alongside the polyline
* **/
var startCoords = layer.getLatLngs()[0];
var stopCoords = layer.getLatLngs()[layer.getLatLngs().length - 1];
//Flip lineString if bearing is negative
flip = (this._getBearing(startCoords, stopCoords) < 0);
if (layer._parts) {
ctx.textAlign = "center";
ctx.textBaseline = "middle";
//ctx.lineWidth = 3;
layer._parts.forEach(function (part) {
//Build the points list for the first part
var pathPoints = [];
for (var i = 0; i < part.length; i++) {
var linePart = (flip ? part[part.length - 1 - i] : part[i]);
pathPoints.push(linePart.x);
pathPoints.push(linePart.y);
}
ctx.textPath(layerText, pathPoints);
});
}
}
}
},
/***
* Returns the bearing in degrees clockwise from north (0 degrees)
from the first L.LatLng to the second, at the first LatLng
@param {L.LatLng} latlng1: origin point of the bearing
@param {L.LatLng} latlng2: destination point of the bearing
@returns {float} degrees clockwise from north.
Source: https://makinacorpus.github.io/Leaflet.GeometryUtil/leaflet.geometryutil.js.html
*/
_getBearing: function (startCoords, stopCoords) {
if (startCoords.lat == stopCoords.lat) {
if (startCoords.lng > stopCoords.lng)
return -180;
else
return 180;
}
if (startCoords.lng == stopCoords.lng) {
if (startCoords.lat > stopCoords.lat)
return -90;
else
return 90;
}
var angle = Math.atan(stopCoords.lng - startCoords.lng, stopCoords.lat - startCoords.lat) * 180 / Math.Pi;
return angle;
},
/**
Returns a clone with reversed coordinates.
@param {L.PolyLine} polyline polyline to reverse
@returns {L.PolyLine} polyline reversed
Source: https://makinacorpus.github.io/Leaflet.GeometryUtil/leaflet.geometryutil.js.html
*/
_getLineStringReverse: function (polyline) {
var latLngs = polyline.getLatLngs().slice(0).reverse();
polyline.setLatLngs(latLngs);
return polyline;
},
_getDynamicFontSize: function (layer) {
return parseInt(this._map.getZoom());
},
_getCentroid: function (layer) {
if (layer && layer.getCenter && this._map) {
var latlngCenter = layer.getCenter();
var containerPoint = this._map.latLngToContainerPoint(latlngCenter);
return this._map.containerPointToLayerPoint(containerPoint);
}
},
});