@senx/discovery-widgets
Version:
Discovery Widgets Elements
973 lines (972 loc) • 59.2 kB
JavaScript
/*
* Copyright 2022-2025 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { h } from "@stencil/core";
import { DataModel } from "../../model/types";
import { Param } from "../../model/param";
import { Logger } from "../../utils/logger";
import { GTSLib } from "../../utils/gts.lib";
import { Utils } from "../../utils/utils";
import Leaflet from "leaflet";
import { MapLib } from "../../utils/map-lib";
import { ColorLib } from "../../utils/color-lib";
import { AntPath, antPath } from "leaflet-ant-path";
import domtoimage from "dom-to-image";
import "leaflet-edgebuffer";
import "leaflet.heat";
import "leaflet.markercluster";
import { v4 } from "uuid";
export class DiscoveryMapComponent {
constructor() {
this.options = new Param();
this.debug = false;
this.parsing = false;
this.toDisplay = [];
this.defOptions = Object.assign(Object.assign({}, new Param()), { map: {
tiles: [],
animate: false,
} });
this.divider = 1000;
this.pathData = [];
this.positionData = [];
this.geoJson = [];
this.pathDataLayer = Leaflet.featureGroup();
this.positionDataLayer = Leaflet.featureGroup();
this.tileLayerGroup = Leaflet.featureGroup();
this.geoJsonLayer = Leaflet.featureGroup();
this.poiLayer = new Leaflet.LayerGroup();
this.heatmapLayer = Leaflet.featureGroup();
this.shadowHeatmapLayer = Leaflet.featureGroup();
this.firstDraw = true;
this.initial = true;
this.hidden = {};
this.markerOver = false;
this.tileLayers = [];
this.pois = [];
}
updateRes(newValue, oldValue) {
if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
this.result = GTSLib.getData(this.result);
this.initial = true;
setTimeout(() => { var _a; return this.drawMap((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel(), true, true); });
}
}
optionsUpdate(newValue, oldValue) {
var _a, _b;
(_a = this.LOG) === null || _a === void 0 ? void 0 : _a.debug(['optionsUpdate'], newValue, oldValue);
let opts = newValue;
if (!!newValue && typeof newValue === 'string') {
opts = JSON.parse(newValue);
}
if (!Utils.deepEqual(opts, this.innerOptions)) {
this.innerOptions = Utils.clone(opts);
setTimeout(() => { var _a; return this.drawMap((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel(), true, true); });
(_b = this.LOG) === null || _b === void 0 ? void 0 : _b.debug(['optionsUpdate 2'], { options: this.innerOptions, newValue, oldValue });
}
}
async resize() {
const dims = Utils.getContentBounds(this.el.parentElement);
this.width = dims.w;
this.height = dims.h;
if (this.map) {
this.map.invalidateSize();
}
return Promise.resolve();
}
async export(_type = 'png') {
return await domtoimage.toPng(this.mapElement, { height: this.height, width: this.width });
}
async show(regexp) {
var _a, _b;
GTSLib.flatDeep(((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel()).data).forEach(gts => {
var _a, _b, _c, _d;
const gtsName = (_d = (_c = ((_b = ((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel()).params) !== null && _b !== void 0 ? _b : [])[gts.id]) === null || _c === void 0 ? void 0 : _c.key) !== null && _d !== void 0 ? _d : GTSLib.serializeGtsMetadata(gts);
if (new RegExp(regexp).test(gtsName)) {
this.hidden[gts.id] = false;
}
});
this.drawMap((_b = this.result) !== null && _b !== void 0 ? _b : new DataModel(), true);
return Promise.resolve();
}
async hide(regexp) {
var _a, _b;
GTSLib.flatDeep(((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel()).data).forEach(gts => {
var _a, _b, _c, _d;
const gtsName = (_d = (_c = ((_b = ((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel()).params) !== null && _b !== void 0 ? _b : [])[gts.id]) === null || _c === void 0 ? void 0 : _c.key) !== null && _d !== void 0 ? _d : GTSLib.serializeGtsMetadata(gts);
if (new RegExp(regexp).test(gtsName)) {
this.hidden[gts.id] = true;
}
});
this.drawMap((_b = this.result) !== null && _b !== void 0 ? _b : new DataModel(), true);
return Promise.resolve();
}
async hideById(id) {
var _a;
Object.keys(this.hidden).forEach(k => {
if (new RegExp(id.toString()).test(k)) {
this.hidden[k] = true;
}
});
this.drawMap((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel(), true);
return Promise.resolve();
}
async showById(id) {
var _a;
Object.keys(this.hidden).forEach(k => {
if (new RegExp(id.toString()).test(k)) {
this.hidden[k] = false;
}
});
this.drawMap((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel(), true);
return Promise.resolve();
}
// noinspection JSUnusedGlobalSymbols
componentWillLoad() {
var _a, _b;
this.parsing = true;
this.LOG = new Logger(DiscoveryMapComponent, this.debug);
if (typeof this.options === 'string') {
this.innerOptions = JSON.parse(this.options);
}
else {
this.innerOptions = this.options;
}
this.result = GTSLib.getData(this.result);
this.divider = GTSLib.getDivider((_a = this.innerOptions.timeUnit) !== null && _a !== void 0 ? _a : 'us');
(_b = this.LOG) === null || _b === void 0 ? void 0 : _b.debug(['componentWillLoad'], {
type: this.type,
options: this.innerOptions,
toDisplay: this.toDisplay,
});
const dims = Utils.getContentBounds(this.el.parentElement);
this.width = dims.w;
this.height = dims.h - 100;
this.parsing = false;
}
// noinspection JSUnusedGlobalSymbols
componentDidLoad() {
var _a;
this.drawMap((_a = this.result) !== null && _a !== void 0 ? _a : new DataModel());
}
drawMap(data, isRefresh = false, optionUpdate) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22;
let tilesPromise;
let zoomPromise;
this.tileLayers = [];
let options = Utils.mergeDeep(this.defOptions, (_a = this.innerOptions) !== null && _a !== void 0 ? _a : {});
(_b = this.LOG) === null || _b === void 0 ? void 0 : _b.debug(['drawMap', 'this.options 2 '], Object.assign({}, data.globalParams));
options = Utils.mergeDeep(options, (_c = data.globalParams) !== null && _c !== void 0 ? _c : {});
optionUpdate = JSON.stringify(options) !== JSON.stringify(this.innerOptions);
this.innerOptions = Utils.clone(options);
this.divider = GTSLib.getDivider((_d = this.innerOptions.timeUnit) !== null && _d !== void 0 ? _d : 'us');
if (this.map) {
this.map.invalidateSize(true);
}
(_e = this.LOG) === null || _e === void 0 ? void 0 : _e.debug(['drawMap', 'data'], data);
(_f = this.LOG) === null || _f === void 0 ? void 0 : _f.debug(['drawMap', 'this.height'], this.height);
(_g = this.LOG) === null || _g === void 0 ? void 0 : _g.debug(['drawMap', 'this.options'], Object.assign({}, this.innerOptions));
const dataList = GTSLib.flatDeep(GTSLib.flattenGtsIdArray(data.data, 0).res);
data.params = (_h = data.params) !== null && _h !== void 0 ? _h : [];
const params = data.params;
this.mapOpts = (_j = this.innerOptions.map) !== null && _j !== void 0 ? _j : {};
dataList.forEach(g => {
if (GTSLib.isGts(g)) {
if (!this.hidden[g.id]) {
this.hidden[g.id] = false;
}
}
});
this.pathData = (_k = MapLib.toLeafletMapPaths({
gts: dataList,
params,
globalParams: this.innerOptions,
}, this.hidden, this.innerOptions.scheme)) !== null && _k !== void 0 ? _k : [];
this.positionData = (_l = MapLib.toLeafletMapPositionArray({
gts: dataList,
params,
globalParams: this.innerOptions,
}, this.hidden, this.innerOptions.scheme)) !== null && _l !== void 0 ? _l : [];
this.geoJson = MapLib.toGeoJSON({ gts: dataList, params });
if (this.mapOpts.mapType !== 'NONE') {
const map = (_m = MapLib.mapTypes[this.mapOpts.mapType || 'DEFAULT']) !== null && _m !== void 0 ? _m : MapLib.mapTypes.DEFAULT;
const mapOpts = {
maxNativeZoom: (_o = this.mapOpts.maxNativeZoom) !== null && _o !== void 0 ? _o : 19,
maxZoom: (_p = this.mapOpts.maxZoom) !== null && _p !== void 0 ? _p : 40,
edgeBufferTiles: 5,
};
if (map.attribution) {
mapOpts.attribution = map.attribution;
}
if (map.subdomains) {
mapOpts.subdomains = map.subdomains;
}
(_q = this.LOG) === null || _q === void 0 ? void 0 : _q.debug(['displayMap'], { isRefresh, optionUpdate });
if (!isRefresh || optionUpdate) {
(_r = this.LOG) === null || _r === void 0 ? void 0 : _r.debug(['displayMap'], 'map', map);
this.tileLayers.push(map.link);
if (!!this.tilesLayer && this.tilesLayer._url !== map.link) {
this.tileLayerGroup.removeLayer(this.tilesLayer);
this.tilesLayer = undefined;
}
if (!this.tilesLayer) {
this.tilesLayer = Leaflet.tileLayer(map.link, mapOpts);
this.tilesLayer.addTo(this.tileLayerGroup);
tilesPromise = new Promise(resolve => setTimeout(() => this.tilesLayer.on('load', () => resolve())));
}
}
}
if (this.map) {
(_s = this.LOG) === null || _s === void 0 ? void 0 : _s.debug(['displayMap'], 'map exists');
this.pathDataLayer.clearLayers();
this.positionDataLayer.clearLayers();
this.geoJsonLayer.clearLayers();
this.heatmapLayer.clearLayers();
this.shadowHeatmapLayer.clearLayers();
this.poiLayer.clearLayers();
}
else {
this.mainLayer = new Leaflet.LayerGroup([this.tileLayerGroup, this.heatmapLayer, this.geoJsonLayer, this.pathDataLayer, this.positionDataLayer]);
this.map = Leaflet.map(this.mapElement, {
preferCanvas: true,
layers: this.mainLayer,
zoomAnimation: true,
maxBoundsViscocity: 1,
worldCopyJump: true,
maxBounds: new Leaflet.LatLngBounds(new Leaflet.latLng(-89.98155760646617, -180), new Leaflet.LatLng(89.99346179538875, 180)),
maxZoom: (_t = this.mapOpts.maxZoom) !== null && _t !== void 0 ? _t : 19,
});
this.geoJsonLayer.bringToBack();
Leaflet.control.scale().addTo(this.map);
this.map.on('load', () => { var _a; return (_a = this.LOG) === null || _a === void 0 ? void 0 : _a.debug(['displayMap', 'load'], this.map.getCenter().lng, this.currentLong, this.map.getZoom()); });
this.map.on('zoomend', () => {
if (!this.firstDraw) {
this.currentZoom = this.map.getZoom();
this.geoBounds.emit(this.map.getBounds().toBBoxString());
}
});
this.map.on('moveend', () => {
if (!this.firstDraw) {
this.currentLat = this.map.getCenter().lat;
this.currentLong = this.map.getCenter().lng;
}
});
}
const pathDataSize = ((_u = this.pathData) !== null && _u !== void 0 ? _u : []).length;
for (let i = 0; i < pathDataSize; i++) {
const path = this.pathData[i];
if (path) {
this.updateGtsPath(path, data.params[i]);
}
}
(_v = this.LOG) === null || _v === void 0 ? void 0 : _v.debug(['displayMap'], 'pathData', this.pathData);
const positionsSize = ((_w = this.positionData) !== null && _w !== void 0 ? _w : []).length;
for (let i = 0; i < positionsSize; i++) {
const pData = this.positionData[i];
if (pData) {
this.updatePositionArray(pData, data.params[i], i);
}
}
(_x = this.LOG) === null || _x === void 0 ? void 0 : _x.debug(['displayMap'], 'positionData', this.positionData);
((_y = this.mapOpts.tiles) !== null && _y !== void 0 ? _y : []).forEach(t => {
var _a, _b, _c, _d, _e, _f, _g, _h;
(_a = this.LOG) === null || _a === void 0 ? void 0 : _a.debug(['displayMap'], t);
const tile = {
subdomains: 'abcd',
maxNativeZoom: (_b = this.mapOpts.maxNativeZoom) !== null && _b !== void 0 ? _b : 19,
maxZoom: (_c = this.mapOpts.maxZoom) !== null && _c !== void 0 ? _c : 19,
};
if (typeof t === 'string') {
tile.url = t;
}
else if (typeof t === 'object') {
tile.url = t.url;
tile.maxZoom = (_d = this.mapOpts.maxZoom) !== null && _d !== void 0 ? _d : 19;
tile.maxNativeZoom = (_f = (_e = t.maxNativeZoom) !== null && _e !== void 0 ? _e : this.mapOpts.maxNativeZoom) !== null && _f !== void 0 ? _f : 19;
}
this.tileLayers.push(tile.url);
const l = Leaflet.tileLayer(tile.url, {
subdomains: 'abcd',
maxNativeZoom: (_g = tile.maxNativeZoom) !== null && _g !== void 0 ? _g : 19,
maxZoom: (_h = this.mapOpts.maxZoom) !== null && _h !== void 0 ? _h : 19,
});
if (!this.tileLayerGroup.getLayers().find((l) => l._url === t.url)) {
this.tileLayerGroup.addLayer(l);
}
});
if (!isRefresh || optionUpdate) {
this.tileLayerGroup.getLayers().forEach((l) => {
if (!this.tileLayers.includes(l._url)) {
this.tileLayerGroup.removeLayer(l);
}
});
}
const geoJsonSize = ((_z = this.geoJson) !== null && _z !== void 0 ? _z : []).length;
for (let i = 0; i < geoJsonSize; i++) {
const m = this.geoJson[i];
if (m) {
const color = ColorLib.getColor(i, this.innerOptions.scheme);
const opts = {
style: () => {
var _a, _b;
return ({
color: (data.params && data.params[i]) ? (_a = data.params[i].datasetColor) !== null && _a !== void 0 ? _a : color : color,
fillColor: (data.params && data.params[i])
? ColorLib.transparentize((_b = data.params[i].fillColor) !== null && _b !== void 0 ? _b : color)
: ColorLib.transparentize(color),
});
},
};
if (m.geometry.type === 'Point') {
opts.pointToLayer = (geoJsonPoint, latlng) => {
var _a;
return Leaflet.marker(latlng, {
icon: this.icon(color, (data.params && data.params[i]) ? ((_a = data.params[i].map) !== null && _a !== void 0 ? _a : { marker: 'circle' }).marker : 'circle', (data.params && data.params[i]), 0),
riseOnHover: true,
opacity: 1,
});
};
}
let display = '';
const geoShape = Leaflet.geoJSON(m, opts);
if (m.properties) {
Object.keys(m.properties).forEach(k => display += `<b>${k}</b>: ${m.properties[k]}<br />`);
geoShape.bindPopup(display);
}
geoShape.addTo(this.geoJsonLayer);
}
}
let hasHeatmap = false;
// HeatMap
const size = (dataList !== null && dataList !== void 0 ? dataList : []).length;
for (let i = 0; i < size; i++) {
let p = (params !== null && params !== void 0 ? params : [])[i];
if (!p) {
p = Object.assign({}, new Param());
}
if (!!((_0 = p.map) === null || _0 === void 0 ? void 0 : _0.heatmap) && dataList[i].v[0] && dataList[i].v[0].length >= 3) {
const g = dataList[i];
let max = Number.MIN_SAFE_INTEGER;
let min = Number.MAX_SAFE_INTEGER;
hasHeatmap = true;
const hasHeatmapData = g.v.map((v) => {
max = Math.max(max, v[v.length - 1]);
min = Math.min(min, v[v.length - 1]);
Leaflet.circleMarker([v[1], v[2]], { radius: 1 }).addTo(this.shadowHeatmapLayer);
return [v[1], v[2], v[v.length - 1]];
});
Leaflet.heatLayer(hasHeatmapData, {
radius: (_4 = (_2 = (_1 = p.map) === null || _1 === void 0 ? void 0 : _1.heatRadius) !== null && _2 !== void 0 ? _2 : (_3 = this.innerOptions.map) === null || _3 === void 0 ? void 0 : _3.heatRadius) !== null && _4 !== void 0 ? _4 : 25,
minOpacity: (_8 = (_6 = (_5 = p.map) === null || _5 === void 0 ? void 0 : _5.heatOpacity) !== null && _6 !== void 0 ? _6 : (_7 = this.innerOptions.map) === null || _7 === void 0 ? void 0 : _7.heatOpacity) !== null && _8 !== void 0 ? _8 : 0.05,
maxZoom: 0,
max,
blur: (_12 = (_10 = (_9 = p.map) === null || _9 === void 0 ? void 0 : _9.heatBlur) !== null && _10 !== void 0 ? _10 : (_11 = this.innerOptions.map) === null || _11 === void 0 ? void 0 : _11.heatBlur) !== null && _12 !== void 0 ? _12 : 15,
}).addTo(this.heatmapLayer);
}
}
if (this.pathData.length > 0 || this.positionData.length > 0 || this.geoJson.length > 0 || hasHeatmap) {
// Fit map to curves
const group = Leaflet.featureGroup([this.geoJsonLayer, this.positionDataLayer, this.pathDataLayer, this.shadowHeatmapLayer]);
this.bounds = group.getBounds();
setTimeout(() => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
if (!!this.bounds && this.bounds.isValid()) {
if ((this.currentLat || this.mapOpts.startLat) && (this.currentLong || this.mapOpts.startLong)) {
(_a = this.LOG) === null || _a === void 0 ? void 0 : _a.debug(['displayMap', 'setView'], 'fitBounds', 'already have bounds');
if (this.mapOpts.track) {
this.map.setView({
lat: (_c = (_b = this.mapOpts.startLat) !== null && _b !== void 0 ? _b : this.bounds.getCenter().lat) !== null && _c !== void 0 ? _c : 0,
lng: (_e = (_d = this.mapOpts.startLong) !== null && _d !== void 0 ? _d : this.bounds.getCenter().lng) !== null && _e !== void 0 ? _e : 0,
}, (_g = (_f = this.mapOpts.startZoom) !== null && _f !== void 0 ? _f : this.map.getBoundsZoom(this.bounds)) !== null && _g !== void 0 ? _g : 10, { animate: true });
}
else {
this.map.setView({
lat: (_j = (_h = this.currentLat) !== null && _h !== void 0 ? _h : this.mapOpts.startLat) !== null && _j !== void 0 ? _j : 0,
lng: (_l = (_k = this.currentLong) !== null && _k !== void 0 ? _k : this.mapOpts.startLong) !== null && _l !== void 0 ? _l : 0,
}, (_o = (_m = this.currentZoom) !== null && _m !== void 0 ? _m : this.mapOpts.startZoom) !== null && _o !== void 0 ? _o : 10, { animate: false });
}
}
else if (this.map && this.bounds) {
(_p = this.LOG) === null || _p === void 0 ? void 0 : _p.debug(['displayMap', 'setView'], 'fitBounds', 'this.bounds', this.bounds);
this.map.fitBounds(this.bounds, { padding: [1, 1], animate: false, duration: 0 });
}
this.currentLat = this.map.getCenter().lat;
this.currentLong = this.map.getCenter().lng;
}
else {
(_q = this.LOG) === null || _q === void 0 ? void 0 : _q.debug(['displayMap', 'setView'], 'invalid bounds', { lat: this.currentLat, lng: this.currentLong });
this.map.setView({
lat: (_s = (_r = this.currentLat) !== null && _r !== void 0 ? _r : this.mapOpts.startLat) !== null && _s !== void 0 ? _s : 0,
lng: (_u = (_t = this.currentLong) !== null && _t !== void 0 ? _t : this.mapOpts.startLong) !== null && _u !== void 0 ? _u : 0,
}, (_w = (_v = this.currentZoom) !== null && _v !== void 0 ? _v : this.mapOpts.startZoom) !== null && _w !== void 0 ? _w : 10, {
animate: false,
duration: 0,
});
zoomPromise = new Promise(resolve => this.map.once('moveend zoomend', () => resolve()));
}
}, 10);
}
else {
(_13 = this.LOG) === null || _13 === void 0 ? void 0 : _13.debug(['displayMap', 'no data'], 'lost', this.currentZoom, this.mapOpts.startZoom);
if (!this.mapOpts.track) {
this.currentLat = (_14 = this.mapOpts.startLat) !== null && _14 !== void 0 ? _14 : 0;
this.currentLong = (_15 = this.mapOpts.startLong) !== null && _15 !== void 0 ? _15 : 0;
this.currentZoom = (_16 = this.mapOpts.startZoom) !== null && _16 !== void 0 ? _16 : 2;
}
this.map.setView([
(_18 = (_17 = this.currentLat) !== null && _17 !== void 0 ? _17 : this.mapOpts.startLat) !== null && _18 !== void 0 ? _18 : 0,
(_20 = (_19 = this.currentLong) !== null && _19 !== void 0 ? _19 : this.mapOpts.startLong) !== null && _20 !== void 0 ? _20 : 0,
], (_22 = (_21 = this.currentZoom) !== null && _21 !== void 0 ? _21 : this.mapOpts.startZoom) !== null && _22 !== void 0 ? _22 : 2, {
animate: false,
duration: 0,
});
zoomPromise = new Promise(resolve => setTimeout(() => this.map.once('moveend zoomend', () => resolve())));
}
this.firstDraw = false;
this.poiLayer.addTo(this.map);
// this.patchMapTileGapBug();
void Promise.all([zoomPromise, tilesPromise])
.then(() => setTimeout(() => {
if (this.initial) {
this.draw.emit();
this.initial = false;
}
}, 500));
}
icon(color, marker = '', param, i) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
const c = `${ColorLib.sanitizeColor(color).slice(1)}`;
let iconUrl;
let iconSize = [20, 20];
let iconAnchor = [10, 10];
if (((_a = param === null || param === void 0 ? void 0 : param.map) === null || _a === void 0 ? void 0 : _a.iconSize) || ((_c = (_b = this.innerOptions) === null || _b === void 0 ? void 0 : _b.map) === null || _c === void 0 ? void 0 : _c.iconSize)) {
const size = (_h = (_e = (_d = param === null || param === void 0 ? void 0 : param.map) === null || _d === void 0 ? void 0 : _d.iconSize) !== null && _e !== void 0 ? _e : (_g = (_f = this.innerOptions) === null || _f === void 0 ? void 0 : _f.map) === null || _g === void 0 ? void 0 : _g.iconSize) !== null && _h !== void 0 ? _h : [48, 48];
iconSize = GTSLib.isArray(size) ? size : [size, size];
iconAnchor = [iconSize[0] / 2, iconSize[0] / 2];
}
const mark = GTSLib.isArray(marker) ? (_j = marker[i]) !== null && _j !== void 0 ? _j : 'circle' : (_k = marker) !== null && _k !== void 0 ? _k : 'circle';
if (mark.startsWith('http') || mark.startsWith('data:image')) {
iconUrl = mark;
}
else if (mark.startsWith('<svg')) {
iconUrl = 'data:image/svg+xml;base64,' + window.btoa(mark);
}
else {
iconAnchor = [10, 22];
const margin = 2;
if (((_l = param === null || param === void 0 ? void 0 : param.map) === null || _l === void 0 ? void 0 : _l.iconSize) || ((_o = (_m = this.innerOptions) === null || _m === void 0 ? void 0 : _m.map) === null || _o === void 0 ? void 0 : _o.iconSize)) {
const size = (_t = (_q = (_p = param === null || param === void 0 ? void 0 : param.map) === null || _p === void 0 ? void 0 : _p.iconSize) !== null && _q !== void 0 ? _q : (_s = (_r = this.innerOptions) === null || _r === void 0 ? void 0 : _r.map) === null || _s === void 0 ? void 0 : _s.iconSize) !== null && _t !== void 0 ? _t : iconSize;
iconSize = GTSLib.isArray(size) ? size : [size, size];
iconAnchor = [iconSize[0] / 2, iconSize[1] - margin];
}
iconUrl = `https://www.mapmarker.io/api/v2/font-awesome/v5/pin?icon=fa-${mark}-solid&size=${iconSize[0]}&color=fff&background=${c}`;
}
return Leaflet.icon({ iconUrl, iconAnchor, iconSize });
}
getGTSDots(gts, param) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const dots = [];
let icon;
let size;
switch (gts.render) {
case 'path': {
icon = this.icon(gts.color, gts.marker, param, 0);
size = ((_a = gts.path) !== null && _a !== void 0 ? _a : []).length;
for (let i = 0; i < size; i++) {
const g = gts.path[i];
if (i < size - 1 || !gts.marker) {
const marker = Leaflet.circleMarker(g, {
radius: (_b = gts.baseRadius) !== null && _b !== void 0 ? _b : MapLib.BASE_RADIUS,
color: gts.color,
fillColor: gts.color,
fillOpacity: 1,
riseOnHover: true,
});
this.addPopup(gts, g.val, g.ts, marker, 0);
dots.push(marker);
}
else {
const marker = Leaflet.marker(g, { icon, riseOnHover: true, opacity: 1 });
this.addPopup(gts, g.val, g.ts, marker, icon.options.iconAnchor[1] * -1);
dots.push(marker);
}
}
break;
}
case 'marker':
if (!GTSLib.isArray(gts.marker)) {
icon = this.icon(gts.color, gts.marker, param, 0);
}
size = ((_c = gts.path) !== null && _c !== void 0 ? _c : []).length;
for (let i = 0; i < size; i++) {
if (GTSLib.isArray(gts.marker)) {
icon = this.icon(gts.color, gts.marker, param, i);
}
const g = gts.path[i];
const marker = Leaflet.marker(g, { icon, riseOnHover: true, opacity: 1 });
this.addPopup(gts, g.val, g.ts, marker, 0);
dots.push(marker);
}
break;
case 'weightedDots':
size = ((_d = gts.path) !== null && _d !== void 0 ? _d : []).length;
for (let i = 0; i < size; i++) {
const p = gts.path[i];
let v = parseInt(p.val, 10);
if (isNaN(v)) {
v = 0;
}
const radius = 50 * v / (((_e = gts.maxValue) !== null && _e !== void 0 ? _e : 1) - ((_f = gts.minValue) !== null && _f !== void 0 ? _f : 0));
const marker = Leaflet.circleMarker(p, {
radius: radius === 0 ? 1 : radius,
color: (_g = gts.borderColor) !== null && _g !== void 0 ? _g : 'transparent',
fillColor: gts.color, fillOpacity: 0.5,
riseOnHover: true,
weight: 1,
});
this.addPopup(gts, p.val, p.ts, marker, 0);
dots.push(marker);
}
break;
case 'dots':
default:
size = ((_h = gts.path) !== null && _h !== void 0 ? _h : []).length;
for (let i = 0; i < size; i++) {
const g = gts.path[i];
const marker = Leaflet.circleMarker(g, {
radius: (_j = gts.baseRadius) !== null && _j !== void 0 ? _j : MapLib.BASE_RADIUS,
color: gts.color,
riseOnHover: true,
fillColor: gts.color,
fillOpacity: 1,
});
this.addPopup(gts, g.val, g.ts, marker, 0);
dots.push(marker);
}
break;
}
return dots;
}
updateGtsPath(gts, param) {
const path = MapLib.pathDataToLeaflet(gts.path);
const group = Leaflet.featureGroup();
if ((path !== null && path !== void 0 ? path : []).length > 1 && !!gts.line && (gts.render === 'dots' || gts.render === 'path')) {
if (this.mapOpts.animate) {
group.addLayer(new AntPath(path !== null && path !== void 0 ? path : [], {
delay: 800, dashArray: [10, 100],
weight: 5, color: ColorLib.transparentize(gts.color, 0.5),
pulseColor: gts.color,
paused: false, reverse: false, hardwareAccelerated: true, hardwareAcceleration: true,
}));
}
else {
group.addLayer(Leaflet.polyline(path !== null && path !== void 0 ? path : [], { color: gts.color, opacity: 0.5 }));
}
}
const dots = this.getGTSDots(gts, param);
const size = (dots !== null && dots !== void 0 ? dots : []).length;
for (let i = 0; i < size; i++) {
group.addLayer(dots[i]);
}
this.pathDataLayer.addLayer(group);
}
addPopup(positionData, value, ts, marker, offset) {
var _a, _b, _c, _d;
if (positionData) {
let date = ts;
if (ts && ((_a = this.innerOptions.timeMode) !== null && _a !== void 0 ? _a : 'date') === 'date') {
date = ((_b = GTSLib.toISOString(ts !== null && ts !== void 0 ? ts : 0, this.divider, this.innerOptions.timeZone, this.innerOptions.timeFormat)) !== null && _b !== void 0 ? _b : '')
.replace('T', ' ').replace(/\+[0-9]{2}:[0-9]{2}$/gi, '');
}
let content = '';
content = `${date ? `<p>${date}</p>` : ''}<p><b>${positionData.key}</b>: ${value === 0 ? 0 : value !== null && value !== void 0 ? value : 'na'}</p>`;
Object.keys((_c = positionData.properties) !== null && _c !== void 0 ? _c : [])
.forEach(k => content += `<b>${k}</b>: ${decodeURIComponent(positionData.properties[k])}<br />`);
if (positionData.tooltip[ts]) {
content += positionData.tooltip[ts];
}
marker.on('mouseover', () => {
var _a;
marker.openPopup();
this.markerOver = true;
if (this.popupTimeout) {
clearTimeout(this.popupTimeout);
}
this.popupTimeout = setTimeout(() => {
if (marker.isPopupOpen() && !this.markerOver)
marker.closePopup();
}, (_a = this.innerOptions.tooltipDelay) !== null && _a !== void 0 ? _a : 3000);
this.dataPointOver.emit({
date: ts,
name: positionData.key,
value,
meta: positionData.properties,
});
});
this.markersRef = Object.assign({}, (_d = this.markersRef) !== null && _d !== void 0 ? _d : {});
if (!this.markersRef[positionData.key]) {
this.markersRef[positionData.key] = {};
}
this.markersRef[positionData.key][ts] = marker;
marker.bindPopup(content, { autoClose: true, offset: new Leaflet.Point(0, offset) });
}
marker.on('mouseout', () => this.markerOver = false);
marker.on('click', () => {
const date = this.innerOptions.timeMode === 'date'
? GTSLib.zonedTimeToUtc(ts, 1, this.innerOptions.timeZone) * this.divider
: ts;
this.dataPointSelected.emit({ date, name: positionData.key, value, meta: positionData.properties });
if (this.innerOptions.poi) {
if (this.pois.find(p => p.lat === marker.getLatLng().lat && p.lng === marker.getLatLng().lng && p.name === positionData.key)) {
this.pois = this.pois.filter(p => p.lat !== marker.getLatLng().lat && p.lng !== marker.getLatLng().lng && p.name !== positionData.key);
}
else {
this.pois.push({
date,
name: positionData.key,
value,
meta: positionData.properties,
uid: v4(),
lat: marker.getLatLng().lat,
lng: marker.getLatLng().lng,
});
}
this.poiLayer.clearLayers();
this.poi.emit(this.pois);
this.pois.forEach(p => {
const icon = this.icon(this.innerOptions.poiColor, undefined, this.innerOptions, 0);
const m = Leaflet.marker([p.lat, p.lng], { icon, riseOnHover: true, opacity: 1 });
this.poiLayer.addLayer(m);
});
}
});
}
async setFocus(regexp, ts) {
var _a;
Object.keys((_a = this.markersRef) !== null && _a !== void 0 ? _a : {})
.filter(s => new RegExp(regexp).test(s))
.forEach(k => {
if (this.markersRef[k][ts]) {
this.markersRef[k][ts].openPopup();
}
});
return Promise.resolve();
}
async unFocus() {
Object.keys(this.markersRef)
.forEach(k => {
var _a;
(Object.keys((_a = this.markersRef[k]) !== null && _a !== void 0 ? _a : {}))
.forEach(ts => {
if (this.markersRef[k][ts]) {
if (this.markersRef[k][ts].isPopupOpen() && !this.markerOver)
this.markersRef[k][ts].closePopup();
}
});
});
return Promise.resolve();
}
updatePositionArray(positionData, param, dataIndex) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
const opts = {};
if ((_a = this.mapOpts) === null || _a === void 0 ? void 0 : _a.maxClusterRadius)
opts.maxClusterRadius = this.mapOpts.maxClusterRadius;
if ((_b = this.mapOpts) === null || _b === void 0 ? void 0 : _b.clusterCustomIcon) {
opts.iconCreateFunction = (cluster) => {
var _a;
const ico = this.icon(GTSLib.isArray(positionData.color) ? (_a = positionData.color[0]) !== null && _a !== void 0 ? _a : ColorLib.getColor(dataIndex, this.innerOptions.scheme) : positionData.color, positionData.marker, param, 0);
const icoHtmlElt = ico.createIcon();
const icoW = parseInt(icoHtmlElt.style.getPropertyValue('width'), 10);
const icoH = parseInt(icoHtmlElt.style.getPropertyValue('height'), 10);
const icoMarginLeft = icoHtmlElt.style.getPropertyValue('margin-left');
const icoMarginTop = icoHtmlElt.style.getPropertyValue('margin-top');
// remove shift from ico, to apply it to the parent div later on
icoHtmlElt.style.removeProperty('margin-left');
icoHtmlElt.style.removeProperty('margin-top');
// 30 pixel is hardcoded for the cluster child count indicator
const html = `<div style="margin-left:${icoMarginLeft};margin-top:${icoMarginTop};">
<div style="position:absolute">${icoHtmlElt.outerHTML}</div>
<div style="position:absolute;left:${(icoW / 2) - 15}px;top:${(icoH / 2) - 15}px;width:30px;height:30px;border-radius:50%;background-color:rgba(255,255,255,0.8);text-align:center;line-height: 30px;">
${cluster.getChildCount()}
</div>
</div>`;
return Leaflet.divIcon({ html: html });
};
}
const group = ((_c = this.innerOptions.map) === null || _c === void 0 ? void 0 : _c.cluster)
? Leaflet.markerClusterGroup(opts)
: Leaflet.featureGroup();
const path = MapLib.updatePositionArrayToLeaflet(positionData.positions);
if (((_d = positionData.positions) !== null && _d !== void 0 ? _d : []).length > 1 && !!positionData.line) {
if (this.mapOpts.animate) {
group.addLayer(antPath(path !== null && path !== void 0 ? path : [], {
delay: 800, dashArray: [10, 100],
weight: 5, color: ColorLib.transparentize(positionData.color, 0.5),
pulseColor: positionData.color,
paused: false, reverse: false, hardwareAccelerated: true, hardwareAcceleration: true,
}));
}
else {
group.addLayer(Leaflet.polyline(path !== null && path !== void 0 ? path : [], { color: positionData.color, opacity: 0.5 }));
}
}
let icon;
let result;
let inStep;
let size;
(_e = this.LOG) === null || _e === void 0 ? void 0 : _e.debug(['updatePositionArray'], positionData);
switch (positionData.render) {
case 'marker':
size = ((_f = positionData.positions) !== null && _f !== void 0 ? _f : []).length;
for (let i = 0; i < size; i++) {
const p = positionData.positions[i];
icon = this.icon(GTSLib.isArray(positionData.color) ? (_g = positionData.color[i]) !== null && _g !== void 0 ? _g : ColorLib.getColor(dataIndex, this.innerOptions.scheme) : positionData.color, positionData.marker, param, GTSLib.isArray(positionData.marker) ? i : 0);
const marker = Leaflet.marker({ lat: p[0], lng: p[1] }, { icon, riseOnHover: true, opacity: 1 });
this.addPopup(positionData, p[2], undefined, marker, 0);
group.addLayer(marker);
}
(_h = this.LOG) === null || _h === void 0 ? void 0 : _h.debug(['updatePositionArray', 'build marker'], icon);
break;
case 'coloredWeightedDots':
(_j = this.LOG) === null || _j === void 0 ? void 0 : _j.debug(['updatePositionArray', 'coloredWeightedDots'], positionData);
result = [];
inStep = [];
for (let j = 0; j < positionData.numColorSteps; j++) {
result[j] = 0;
inStep[j] = 0;
}
size = ((_k = positionData.positions) !== null && _k !== void 0 ? _k : []).length;
for (let i = 0; i < size; i++) {
const p = positionData.positions[i];
const radius = (parseInt(p[2], 10) - ((_l = positionData.minValue) !== null && _l !== void 0 ? _l : 0)) * 50 / ((_m = positionData.maxValue) !== null && _m !== void 0 ? _m : 50);
(_o = this.LOG) === null || _o === void 0 ? void 0 : _o.debug(['updatePositionArray', 'coloredWeightedDots', 'radius'], positionData.baseRadius * p[4]);
const marker = Leaflet.circleMarker({ lat: p[0], lng: p[1] }, {
radius,
color: (_p = positionData.borderColor) !== null && _p !== void 0 ? _p : positionData.color,
fillColor: ColorLib.rgb2hex(positionData.colorGradient[p[5]].r, positionData.colorGradient[p[5]].g, positionData.colorGradient[p[5]].b),
riseOnHover: true,
fillOpacity: 0.3,
});
this.addPopup(positionData, p[2], undefined, marker, 0);
group.addLayer(marker);
}
break;
case 'weightedDots':
size = ((_q = positionData.positions) !== null && _q !== void 0 ? _q : []).length;
for (let i = 0; i < size; i++) {
const p = positionData.positions[i];
const radius = (parseInt(p[2], 10) - ((_r = positionData.minValue) !== null && _r !== void 0 ? _r : 0)) * 50 / ((_s = positionData.maxValue) !== null && _s !== void 0 ? _s : 50);
const marker = Leaflet.circleMarker({ lat: p[0], lng: p[1] }, {
radius,
color: (_t = positionData.borderColor) !== null && _t !== void 0 ? _t : positionData.color,
fillColor: positionData.color,
weight: 2,
riseOnHover: true,
fillOpacity: 0.3,
});
this.addPopup(positionData, p[2], undefined, marker, 0);
group.addLayer(marker);
}
break;
case 'dots':
default:
size = ((_u = positionData.positions) !== null && _u !== void 0 ? _u : []).length;
for (let i = 0; i < size; i++) {
const p = positionData.positions[i];
const marker = Leaflet.circleMarker({ lat: p[0], lng: p[1] }, {
radius: (_v = positionData.baseRadius) !== null && _v !== void 0 ? _v : MapLib.BASE_RADIUS,
color: (_w = positionData.borderColor) !== null && _w !== void 0 ? _w : positionData.color,
fillColor: positionData.color,
weight: 2,
riseOnHover: true,
fillOpacity: 0.7,
});
this.addPopup(positionData, p[2] === 0 ? 0 : (_x = p[2]) !== null && _x !== void 0 ? _x : 'na', undefined, marker, 0);
group.addLayer(marker);
}
break;
}
this.positionDataLayer.addLayer(group);
}
render() {
return h("div", { key: '7a2a0f31132339588f1563ad12c8b9582551ec32', class: "map-container" }, h("div", { key: '771c2e0a0d8442a7c7c5abbc3ea337ece0efcefd', ref: (el) => this.mapElement = el }));
}
static get is() { return "discovery-map"; }
static get encapsulation() { return "shadow"; }
static get originalStyleUrls() {
return {
"$": ["discovery-map.scss"]
};
}
static get styleUrls() {
return {
"$": ["discovery-map.css"]
};
}
static get properties() {
return {
"result": {
"type": "string",
"mutable": true,
"complexType": {
"original": "DataModel | string",
"resolved": "DataModel | string",
"references": {
"DataModel": {
"location": "import",
"path": "../../model/types",
"id": "src/model/types.ts::DataModel"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "result",
"reflect": false
},
"type": {
"type": "string",
"mutable": false,
"complexType": {
"original": "ChartType",
"resolved": "string",
"references": {
"ChartType": {
"location": "import",
"path": "../../model/types",
"id": "src/model/types.ts::ChartType"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "type",
"reflect": false
},
"options": {
"type": "string",
"mutable": false,
"complexType": {
"original": "Param | string",
"resolved": "Param | string",
"references": {
"Param": {
"location": "import",
"path": "../../model/param",
"id": "src/model/param.ts::Param"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "options",
"reflect": false,
"defaultValue": "new Param()"
},
"width": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "width",
"reflect": false
},
"height": {
"type": "number",
"mutable": true,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "height",
"reflect": false
},
"debug": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "debug",
"reflect": false,
"defaultValue": "false"
}
};
}
static get states() {
return {
"width": {},
"height": {},
"parsing": {},
"toDisplay": {},
"innerOptions": {}
};
}
static get events() {
return [{
"method": "draw",
"name": "draw",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],