fixes leaflet-elevation in build
This commit is contained in:
314
web/static/vendor/leaflet-elevation/libs/leaflet-distance-marker.js
vendored
Normal file
314
web/static/vendor/leaflet-elevation/libs/leaflet-distance-marker.js
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (c) 2022, GPL-3.0+ Project, Raruto
|
||||
*
|
||||
* This file is free software: you may copy, redistribute and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see .
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright (c) 2014- Doroszlai Attila, 2016- Phil Whitehurst
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software
|
||||
* for any purpose with or without fee is hereby granted, provided
|
||||
* that the above copyright notice and this permission notice appear
|
||||
* in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
// TODO: the "L.DistanceMarker" (canvas marker) class could be alternatively provided by "leaflet-rotate"?
|
||||
|
||||
L.DistanceMarker = L.CircleMarker.extend({
|
||||
_updatePath: function () {
|
||||
let ctx = this._renderer._ctx;
|
||||
let p = this._point;
|
||||
|
||||
// Calculate image direction (rotation)
|
||||
this.options.rotation = this.options.rotation || 0;
|
||||
|
||||
// Draw circle marker (canvas point)
|
||||
if (this.options.radius && this._renderer._updateCircle) {
|
||||
this._renderer._updateCircle(this);
|
||||
}
|
||||
|
||||
// Draw image over circle (distance marker)
|
||||
if (this.options.icon && this.options.icon.url) {
|
||||
if (!this.options.icon.element) {
|
||||
const icon = document.createElement('img');
|
||||
this.options.icon = L.extend({ rotate: 0, size: [40, 40], offset: { x: 0, y: 0 } }, this.options.icon);
|
||||
this.options.icon.rotate += this.options.rotation;
|
||||
this.options.icon.element = icon;
|
||||
icon.src = this.options.icon.url;
|
||||
icon.onload = () => this.redraw();
|
||||
icon.onerror = () => this.options.icon = null;
|
||||
} else {
|
||||
const icon = this.options.icon;
|
||||
let cx = p.x + icon.offset.x;
|
||||
let cy = p.y + icon.offset.y;
|
||||
ctx.save();
|
||||
if (icon.rotate) {
|
||||
ctx.translate(p.x, p.y);
|
||||
ctx.rotate(icon.rotate);
|
||||
cx = 0;
|
||||
cy = 0;
|
||||
}
|
||||
ctx.drawImage(icon.element, cx - icon.size[0] / 2, cy - icon.size[1] / 2, icon.size[0], icon.size[1]);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
// Add a label inside the circle (distance marker)
|
||||
if (this.options.label) {
|
||||
let cx = p.x, cy = p.y;
|
||||
ctx.save();
|
||||
|
||||
ctx.font = this.options.font || 'normal 7pt "Helvetica Neue", Arial, Helvetica, sans-serif';
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = this.options.fillStyle || 'black';
|
||||
|
||||
// TODO rescale circle to fit text
|
||||
// let fontSize = Number(/[0-9\.]+/.exec(ctx.font)[0]);
|
||||
// let fontWidth = ctx.measureText(this.options.html).width;
|
||||
|
||||
if (this.options.rotation) {
|
||||
ctx.translate(p.x, p.y);
|
||||
ctx.rotate(this.options.rotation);
|
||||
cx = 0;
|
||||
cy = 0;
|
||||
}
|
||||
|
||||
// Temporary fix to prevent stroke blurs at higher zoom levels
|
||||
if (this._map.getZoom() > 17) {
|
||||
ctx.fillStyle = this.options.strokeStyle || 'black';
|
||||
}
|
||||
|
||||
ctx.fillText(this.options.label, cx, cy);
|
||||
|
||||
if (this.options.strokeStyle && this._map.getZoom() <= 17) {
|
||||
ctx.strokeStyle = this.options.strokeStyle;
|
||||
ctx.strokeText(this.options.label, cx, cy);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
L.DistanceMarkers = L.LayerGroup.extend({
|
||||
options: {
|
||||
cssClass: 'dist-marker',
|
||||
iconSize: [12, 12],
|
||||
arrowSize: [10, 10],
|
||||
arrowUrl: "data:image/svg+xml,%3Csvg transform='rotate(90)' xmlns='http://www.w3.org/2000/svg' width='560px' height='560px' viewBox='0 0 560 560'%3E%3Cpath stroke-width='35' fill='%23000' stroke='%23FFF' d='M280,40L522,525L280,420L38,525z'/%3E%3C/svg%3E",
|
||||
offset: 1000,
|
||||
showAll: 12,
|
||||
textFunction: (distance, i, offset) => i,
|
||||
distance: true,
|
||||
direction: true,
|
||||
},
|
||||
initialize: function (line, map, options) {
|
||||
|
||||
this._layers = {};
|
||||
this._zoomLayers = {};
|
||||
|
||||
options = L.setOptions(this, options);
|
||||
|
||||
let preferCanvas = map.options.preferCanvas;
|
||||
let showAll = Math.min(map.getMaxZoom(), options.showAll);
|
||||
|
||||
// You should use "leaflet-rotate" to show rotated arrow markers (preferCanvas: false)
|
||||
if (!preferCanvas && !map.options.rotate) {
|
||||
console.warn('Missing dependency: "leaflet-rotate"');
|
||||
}
|
||||
|
||||
// Get line coords as an array
|
||||
let coords = typeof line.getLatLngs == 'function' ? line.getLatLngs() : line;
|
||||
|
||||
// Handle "MultiLineString" features
|
||||
coords = L.LineUtil.isFlat(coords) ? [coords] : coords;
|
||||
|
||||
coords.forEach(latlngs => {
|
||||
// Get accumulated line lengths as well as overall length
|
||||
let accumulated = L.GeometryUtil.accumulatedLengths(latlngs);
|
||||
let length = accumulated.length > 0 ? accumulated[accumulated.length - 1] : 0;
|
||||
|
||||
// count = Number of distance markers to be added
|
||||
// j = Position in accumulated line length array
|
||||
for (let i = 1, count = Math.floor(length / options.offset), j = 0; i <= count; ++i) {
|
||||
|
||||
let distance = options.offset * i;
|
||||
|
||||
// Find the first accumulated distance that is greater than the distance of this marker
|
||||
while (j < accumulated.length - 1 && accumulated[j] < distance) ++j;
|
||||
|
||||
// Grab two nearest points either side marker position
|
||||
let p1 = latlngs[j - 1];
|
||||
let p2 = latlngs[j];
|
||||
let m_line = L.polyline([p1, p2]);
|
||||
|
||||
// and create a simple line to interpolate on
|
||||
let ratio = (distance - accumulated[j - 1]) / (accumulated[j] - accumulated[j - 1]);
|
||||
let position = L.GeometryUtil.interpolateOnLine(map, m_line, ratio);
|
||||
let delta = map.project(p2).subtract(map.project(p1));
|
||||
let angle = Math.atan2(delta.y, delta.x);
|
||||
|
||||
// Generate distance marker label
|
||||
let text = options.textFunction.call(this, distance, i, options.offset);
|
||||
|
||||
// Grouping layer of visible layers at zoom level (arrow + distance)
|
||||
let zoom = this._minimumZoomLevelForItem(i, showAll);
|
||||
let markers = this._zoomLayers[zoom] = this._zoomLayers[zoom] || L.layerGroup()
|
||||
|
||||
// create arrow markers
|
||||
if (options.direction && ((options.distance && i % 2 == 1) || !options.distance)) {
|
||||
if (preferCanvas) {
|
||||
markers.addLayer(
|
||||
new L.DistanceMarker(p1, {
|
||||
radius: 0,
|
||||
icon: {
|
||||
url: options.arrowUrl, //image link
|
||||
size: options.arrowSize, //image size ( default [40, 40] )
|
||||
rotate: 0, //image base rotate ( default 0 )
|
||||
offset: { x: 0, y: 0 }, //image offset ( default { x: 0, y: 0 } )
|
||||
},
|
||||
rotation: angle,
|
||||
interactive: false,
|
||||
// label: '⮞', //'➜',
|
||||
// font: 'normal 20pt "Helvetica Neue", Arial, Helvetica, sans-serif',
|
||||
// fillStyle: 'white',//'#3366CC',
|
||||
// strokeStyle: 'black',
|
||||
})
|
||||
);
|
||||
} else {
|
||||
markers.addLayer(
|
||||
L.marker(position.latLng, {
|
||||
icon: L.icon({
|
||||
iconUrl: options.arrowUrl,
|
||||
iconSize: options.arrowSize,
|
||||
}),
|
||||
// NB the following option is added by "leaflet-rotate"
|
||||
rotation: angle,
|
||||
interactive: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// create distance markers
|
||||
if (options.distance && i % 2 == 0) {
|
||||
if (preferCanvas) {
|
||||
markers.addLayer(
|
||||
new L.DistanceMarker(position.latLng, {
|
||||
label: text, // TODO: handle text rotation (leaflet-rotate)
|
||||
radius: 7,
|
||||
fillColor: '#fff',
|
||||
fillOpacity: 1,
|
||||
fillStyle: 'black',
|
||||
color: '#777',
|
||||
weight: 1,
|
||||
interactive: false,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
markers.addLayer(
|
||||
L.marker(position.latLng, {
|
||||
title: text,
|
||||
icon: L.divIcon({
|
||||
className: options.cssClass,
|
||||
html: text,
|
||||
iconSize: options.iconSize
|
||||
}),
|
||||
interactive: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const updateMarkerVisibility = () => {
|
||||
let oldZoom = this._lastZoomLevel || 0;
|
||||
let newZoom = map.getZoom();
|
||||
if (newZoom > oldZoom) {
|
||||
for (let i = oldZoom + 1; i <= newZoom; ++i) {
|
||||
if (this._zoomLayers[i] !== undefined) {
|
||||
this.addLayer(this._zoomLayers[i]);
|
||||
}
|
||||
}
|
||||
} else if (newZoom < oldZoom) {
|
||||
for (let i = oldZoom; i > newZoom; --i) {
|
||||
if (this._zoomLayers[i] !== undefined) {
|
||||
this.removeLayer(this._zoomLayers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._lastZoomLevel = newZoom;
|
||||
};
|
||||
map.on('zoomend', updateMarkerVisibility);
|
||||
updateMarkerVisibility();
|
||||
},
|
||||
|
||||
_minimumZoomLevelForItem: function (i, zoom) {
|
||||
while (i > 0 && i % 2 === 0) {
|
||||
--zoom;
|
||||
i = Math.floor(i / 2);
|
||||
}
|
||||
return zoom;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
L.Polyline.include({
|
||||
|
||||
_originalOnAdd: L.Polyline.prototype.onAdd,
|
||||
_originalOnRemove: L.Polyline.prototype.onRemove,
|
||||
|
||||
addDistanceMarkers: function () {
|
||||
if (this._map && this._distanceMarkers) {
|
||||
this._map.addLayer(this._distanceMarkers);
|
||||
}
|
||||
},
|
||||
|
||||
removeDistanceMarkers: function () {
|
||||
if (this._map && this._distanceMarkers) {
|
||||
this._map.removeLayer(this._distanceMarkers);
|
||||
}
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
this._originalOnAdd(map);
|
||||
|
||||
let opts = this.options.distanceMarkers || {};
|
||||
if (this.options.distanceMarkers) {
|
||||
this._distanceMarkers = this._distanceMarkers || new L.DistanceMarkers(this, map, opts);
|
||||
}
|
||||
if (opts.lazy === undefined || opts.lazy === false) {
|
||||
this.addDistanceMarkers();
|
||||
}
|
||||
},
|
||||
|
||||
onRemove: function (map) {
|
||||
this.removeDistanceMarkers();
|
||||
this._originalOnRemove(map);
|
||||
}
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user