Add progressive web app companion for cross-platform access
Vite + TypeScript PWA that mirrors the Android app's core features: - Pre-processed shelter data (build-time UTM33N→WGS84 conversion) - Leaflet map with shelter markers, user location, and offline tiles - Canvas compass arrow (ported from DirectionArrowView.kt) - IndexedDB shelter cache with 7-day staleness check - Service worker with CacheFirst tiles and precached app shell - i18n for en, nb, nn (ported from Android strings.xml) - iOS/Android compass handling with low-pass filter - Respects user map interaction (no auto-snap on pan/zoom) - Build revision cache-breaker for reliable SW updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
46365b713b
commit
e8428de775
12051 changed files with 1799735 additions and 0 deletions
207
pwa/node_modules/leaflet/src/layer/vector/SVG.js
generated
vendored
Normal file
207
pwa/node_modules/leaflet/src/layer/vector/SVG.js
generated
vendored
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
import {Renderer} from './Renderer';
|
||||
import * as DomUtil from '../../dom/DomUtil';
|
||||
import * as DomEvent from '../../dom/DomEvent';
|
||||
import Browser from '../../core/Browser';
|
||||
import {stamp} from '../../core/Util';
|
||||
import {svgCreate, pointsToPath} from './SVG.Util';
|
||||
export {pointsToPath};
|
||||
import {vmlMixin, vmlCreate} from './SVG.VML';
|
||||
|
||||
export var create = Browser.vml ? vmlCreate : svgCreate;
|
||||
|
||||
/*
|
||||
* @class SVG
|
||||
* @inherits Renderer
|
||||
* @aka L.SVG
|
||||
*
|
||||
* Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG).
|
||||
* Inherits `Renderer`.
|
||||
*
|
||||
* Due to [technical limitations](https://caniuse.com/svg), SVG is not
|
||||
* available in all web browsers, notably Android 2.x and 3.x.
|
||||
*
|
||||
* Although SVG is not available on IE7 and IE8, these browsers support
|
||||
* [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language)
|
||||
* (a now deprecated technology), and the SVG renderer will fall back to VML in
|
||||
* this case.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* Use SVG by default for all paths in the map:
|
||||
*
|
||||
* ```js
|
||||
* var map = L.map('map', {
|
||||
* renderer: L.svg()
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Use a SVG renderer with extra padding for specific vector geometries:
|
||||
*
|
||||
* ```js
|
||||
* var map = L.map('map');
|
||||
* var myRenderer = L.svg({ padding: 0.5 });
|
||||
* var line = L.polyline( coordinates, { renderer: myRenderer } );
|
||||
* var circle = L.circle( center, { renderer: myRenderer } );
|
||||
* ```
|
||||
*/
|
||||
|
||||
export var SVG = Renderer.extend({
|
||||
|
||||
_initContainer: function () {
|
||||
this._container = create('svg');
|
||||
|
||||
// makes it possible to click through svg root; we'll reset it back in individual paths
|
||||
this._container.setAttribute('pointer-events', 'none');
|
||||
|
||||
this._rootGroup = create('g');
|
||||
this._container.appendChild(this._rootGroup);
|
||||
},
|
||||
|
||||
_destroyContainer: function () {
|
||||
DomUtil.remove(this._container);
|
||||
DomEvent.off(this._container);
|
||||
delete this._container;
|
||||
delete this._rootGroup;
|
||||
delete this._svgSize;
|
||||
},
|
||||
|
||||
_update: function () {
|
||||
if (this._map._animatingZoom && this._bounds) { return; }
|
||||
|
||||
Renderer.prototype._update.call(this);
|
||||
|
||||
var b = this._bounds,
|
||||
size = b.getSize(),
|
||||
container = this._container;
|
||||
|
||||
// set size of svg-container if changed
|
||||
if (!this._svgSize || !this._svgSize.equals(size)) {
|
||||
this._svgSize = size;
|
||||
container.setAttribute('width', size.x);
|
||||
container.setAttribute('height', size.y);
|
||||
}
|
||||
|
||||
// movement: update container viewBox so that we don't have to change coordinates of individual layers
|
||||
DomUtil.setPosition(container, b.min);
|
||||
container.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));
|
||||
|
||||
this.fire('update');
|
||||
},
|
||||
|
||||
// methods below are called by vector layers implementations
|
||||
|
||||
_initPath: function (layer) {
|
||||
var path = layer._path = create('path');
|
||||
|
||||
// @namespace Path
|
||||
// @option className: String = null
|
||||
// Custom class name set on an element. Only for SVG renderer.
|
||||
if (layer.options.className) {
|
||||
DomUtil.addClass(path, layer.options.className);
|
||||
}
|
||||
|
||||
if (layer.options.interactive) {
|
||||
DomUtil.addClass(path, 'leaflet-interactive');
|
||||
}
|
||||
|
||||
this._updateStyle(layer);
|
||||
this._layers[stamp(layer)] = layer;
|
||||
},
|
||||
|
||||
_addPath: function (layer) {
|
||||
if (!this._rootGroup) { this._initContainer(); }
|
||||
this._rootGroup.appendChild(layer._path);
|
||||
layer.addInteractiveTarget(layer._path);
|
||||
},
|
||||
|
||||
_removePath: function (layer) {
|
||||
DomUtil.remove(layer._path);
|
||||
layer.removeInteractiveTarget(layer._path);
|
||||
delete this._layers[stamp(layer)];
|
||||
},
|
||||
|
||||
_updatePath: function (layer) {
|
||||
layer._project();
|
||||
layer._update();
|
||||
},
|
||||
|
||||
_updateStyle: function (layer) {
|
||||
var path = layer._path,
|
||||
options = layer.options;
|
||||
|
||||
if (!path) { return; }
|
||||
|
||||
if (options.stroke) {
|
||||
path.setAttribute('stroke', options.color);
|
||||
path.setAttribute('stroke-opacity', options.opacity);
|
||||
path.setAttribute('stroke-width', options.weight);
|
||||
path.setAttribute('stroke-linecap', options.lineCap);
|
||||
path.setAttribute('stroke-linejoin', options.lineJoin);
|
||||
|
||||
if (options.dashArray) {
|
||||
path.setAttribute('stroke-dasharray', options.dashArray);
|
||||
} else {
|
||||
path.removeAttribute('stroke-dasharray');
|
||||
}
|
||||
|
||||
if (options.dashOffset) {
|
||||
path.setAttribute('stroke-dashoffset', options.dashOffset);
|
||||
} else {
|
||||
path.removeAttribute('stroke-dashoffset');
|
||||
}
|
||||
} else {
|
||||
path.setAttribute('stroke', 'none');
|
||||
}
|
||||
|
||||
if (options.fill) {
|
||||
path.setAttribute('fill', options.fillColor || options.color);
|
||||
path.setAttribute('fill-opacity', options.fillOpacity);
|
||||
path.setAttribute('fill-rule', options.fillRule || 'evenodd');
|
||||
} else {
|
||||
path.setAttribute('fill', 'none');
|
||||
}
|
||||
},
|
||||
|
||||
_updatePoly: function (layer, closed) {
|
||||
this._setPath(layer, pointsToPath(layer._parts, closed));
|
||||
},
|
||||
|
||||
_updateCircle: function (layer) {
|
||||
var p = layer._point,
|
||||
r = Math.max(Math.round(layer._radius), 1),
|
||||
r2 = Math.max(Math.round(layer._radiusY), 1) || r,
|
||||
arc = 'a' + r + ',' + r2 + ' 0 1,0 ';
|
||||
|
||||
// drawing a circle with two half-arcs
|
||||
var d = layer._empty() ? 'M0 0' :
|
||||
'M' + (p.x - r) + ',' + p.y +
|
||||
arc + (r * 2) + ',0 ' +
|
||||
arc + (-r * 2) + ',0 ';
|
||||
|
||||
this._setPath(layer, d);
|
||||
},
|
||||
|
||||
_setPath: function (layer, path) {
|
||||
layer._path.setAttribute('d', path);
|
||||
},
|
||||
|
||||
// SVG does not have the concept of zIndex so we resort to changing the DOM order of elements
|
||||
_bringToFront: function (layer) {
|
||||
DomUtil.toFront(layer._path);
|
||||
},
|
||||
|
||||
_bringToBack: function (layer) {
|
||||
DomUtil.toBack(layer._path);
|
||||
}
|
||||
});
|
||||
|
||||
if (Browser.vml) {
|
||||
SVG.include(vmlMixin);
|
||||
}
|
||||
|
||||
// @namespace SVG
|
||||
// @factory L.svg(options?: Renderer options)
|
||||
// Creates a SVG renderer with the given options.
|
||||
export function svg(options) {
|
||||
return Browser.svg || Browser.vml ? new SVG(options) : null;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue