You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

844 lines
31 KiB

<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" rel="stylesheet" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<script src="https://atlas.microsoft.com/sdk/javascript/service/2/atlas-service.min.js"></script>
<script>
/*
This module contains the HtmlMarkerLayer class, which is a layer that renders HTML markers on the map.
Source: https://learn.microsoft.com/en-us/samples/azure-samples/azure-maps-html-marker-layer/azure-maps-html-marker-layer-module/
azure-maps-html-marker-layer Version: 0.0.1
MIT License - Copyright (c) Microsoft Corporation.
*/
!function(e, y) {
"use strict";
var o = function(e, t) {
return (o = Object.setPrototypeOf || {
__proto__: []
}instanceof Array && function(e, t) {
e.__proto__ = t
}
|| function(e, t) {
for (var r in t)
t.hasOwnProperty(r) && (e[r] = t[r])
}
)(e, t)
};
function t(e, t) {
function r() {
this.constructor = e
}
o(e, t),
e.prototype = null === t ? Object.create(t) : (r.prototype = t.prototype,
new r)
}
var n = function() {
return (n = Object.assign || function(e) {
for (var t, r = 1, o = arguments.length; r < o; r++)
for (var a in t = arguments[r])
Object.prototype.hasOwnProperty.call(t, a) && (e[a] = t[a]);
return e
}
).apply(this, arguments)
};
function a(e, n, s, l) {
return new (s = s || Promise)(function(r, t) {
function o(e) {
try {
i(l.next(e))
} catch (e) {
t(e)
}
}
function a(e) {
try {
i(l.throw(e))
} catch (e) {
t(e)
}
}
function i(e) {
var t;
e.done ? r(e.value) : ((t = e.value)instanceof s ? t : new s(function(e) {
e(t)
}
)).then(o, a)
}
i((l = l.apply(e, n || [])).next())
}
)
}
function g(r, o) {
var a, i, n, e, s = {
label: 0,
sent: function() {
if (1 & n[0])
throw n[1];
return n[1]
},
trys: [],
ops: []
};
return e = {
next: t(0),
throw: t(1),
return: t(2)
},
"function" == typeof Symbol && (e[Symbol.iterator] = function() {
return this
}
),
e;
function t(t) {
return function(e) {
return function(t) {
if (a)
throw new TypeError("Generator is already executing.");
for (; s; )
try {
if (a = 1,
i && (n = 2 & t[0] ? i.return : t[0] ? i.throw || ((n = i.return) && n.call(i),
0) : i.next) && !(n = n.call(i, t[1])).done)
return n;
switch (i = 0,
n && (t = [2 & t[0], n.value]),
t[0]) {
case 0:
case 1:
n = t;
break;
case 4:
return s.label++,
{
value: t[1],
done: !1
};
case 5:
s.label++,
i = t[1],
t = [0];
continue;
case 7:
t = s.ops.pop(),
s.trys.pop();
continue;
default:
if (!(n = 0 < (n = s.trys).length && n[n.length - 1]) && (6 === t[0] || 2 === t[0])) {
s = 0;
continue
}
if (3 === t[0] && (!n || t[1] > n[0] && t[1] < n[3])) {
s.label = t[1];
break
}
if (6 === t[0] && s.label < n[1]) {
s.label = n[1],
n = t;
break
}
if (n && s.label < n[2]) {
s.label = n[2],
s.ops.push(t);
break
}
n[2] && s.ops.pop(),
s.trys.pop();
continue
}
t = o.call(r, s)
} catch (e) {
t = [6, e],
i = 0
} finally {
a = n = 0
}
if (5 & t[0])
throw t[1];
return {
value: t[0] ? t[1] : void 0,
done: !0
}
}([t, e])
}
}
}
var r = (i.merge = function(e, t) {
for (var r = window || global, o = 0, a = e.split("."); o < a.length; o++) {
var i = a[o];
if (!r[i])
return t;
r = r[i]
}
return n(n({}, r), t)
}
,
i);
function i() {}
var s, l = (t(u, s = y.layer.BubbleLayer),
u.prototype.getOptions = function() {
return Object.assign({}, this._options)
}
,
u.prototype.setOptions = function(e) {
var t = this._options
, r = {}
, o = !1;
e.source && t.source !== e.source && (t.source = e.source,
r.source = e.source,
o = !0),
e.sourceLayer && t.sourceLayer !== e.sourceLayer && (t.sourceLayer = e.sourceLayer,
r.sourceLayer = e.sourceLayer,
o = !0),
e.filter && t.filter !== e.filter && (t.filter = e.filter,
r.filter = e.filter,
o = !0),
"number" == typeof e.minZoom && t.minZoom !== e.minZoom && (t.minZoom = e.minZoom,
r.minZoom = e.minZoom),
"number" == typeof e.maxZoom && t.maxZoom !== e.maxZoom && (t.maxZoom = e.maxZoom,
r.maxZoom = e.maxZoom),
void 0 !== e.visible && t.visible !== e.visible && (t.visible = e.visible,
r.visible = e.visible),
e.markerCallback && t.markerCallback != e.markerCallback && (t.markerCallback = e.markerCallback,
o = !0),
"boolean" == typeof e.updateWhileMoving && t.updateWhileMoving !== e.updateWhileMoving && (t.updateWhileMoving = e.updateWhileMoving),
o ? this._clearCache(!0) : this._updateMarkers(),
s.prototype.setOptions.call(this, r)
}
,
u.prototype.update = function() {
this._clearCache(!0),
this._updateMarkers()
}
,
u.prototype.onAdd = function(e) {
var t = this
, r = e.events;
e && (r.remove("moveend", t._updateMarkers),
r.remove("move", t._mapMoved),
r.remove("sourcedata", t._sourceUpdated)),
(r = (t._map = e).events).add("moveend", t._updateMarkers),
r.add("move", t._mapMoved),
r.add("sourcedata", t._sourceUpdated),
s.prototype.onAdd.call(this, e)
}
,
u.prototype.onRemove = function() {
var e = this
, t = e._map;
if (t) {
var r = t.events;
r.remove("moveend", e._updateMarkers),
r.remove("move", e._mapMoved),
r.remove("sourcedata", e._sourceUpdated)
}
e._clearCache(!1),
e._map = null,
s.prototype.onRemove.call(this)
}
,
u.prototype._getSourceClass = function() {
var e = this.getSource();
return "string" == typeof e && null !== this._map ? this._map.sources.getById(e) : e instanceof y.source.Source ? e : null
}
,
u.prototype._clearCache = function(e) {
var t = this;
if (t._markerCache = {},
t._map)
for (var r = 0, o = t._markers.length; r < o; r++) {
var a = t._markers[r];
t._removeEvents(a),
a._eventsAttached = !1,
t._map.markers.remove(a)
}
t._markers = [],
t._markerIds = [],
e && t._updateMarkers()
}
,
u.prototype._getMarker = function(o, a, i) {
var n = this
, s = n._markerCache
, e = n._options;
if (o = o || a.join(",") + JSON.stringify(i || {}),
s[o])
return s[o];
var t = e.markerCallback(o, a, i);
if (!(t instanceof y.HtmlMarker))
return new Promise(function(r) {
t.then(function(e) {
var t = n._getExtendedMarker(e, o, a, i);
t && (s[o] = t,
r(t))
})
}
);
var r = n._getExtendedMarker(t, o, a, i);
return r ? (s[o] = r,
Promise.resolve(r)) : null
}
,
u.prototype._getExtendedMarker = function(e, t, r, o) {
var a = e;
return a ? (a.properties = o,
a.id = t,
a.setOptions({
position: r
}),
a) : null
}
,
u.prototype._addEvents = function(t) {
var r = this;
r._supportedEvents.forEach(function(e) {
r.map.events.add(e, t, r._wrappedEvent)
})
}
,
u.prototype._removeEvents = function(t) {
var r = this;
r._supportedEvents.forEach(function(e) {
r.map.events.remove(e, t, r._wrappedEvent)
})
}
,
u);
function u(e, t, r) {
var o = s.call(this, e, t) || this;
return o._options = {
minZoom: 0,
maxZoom: 24,
visible: !0,
updateWhileMoving: !1,
filter: ["==", ["geometry-type"], "Point"],
markerCallback: function(e, t, r) {
return r.cluster ? new y.HtmlMarker({
position: t,
text: r.point_count_abbreviated
}) : new y.HtmlMarker({
position: t
})
}
},
o._markers = [],
o._markerIds = [],
o._markerCache = {},
o._supportedEvents = ["click", "contextmenu", "dblclick", "drag", "dragstart", "dragend", "keydown", "keypress", "keyup", "mousedown", "mouseenter", "mouseleave", "mousemove", "mouseout", "mouseover", "mouseup"],
o._mapMoved = function() {
o._options.updateWhileMoving && o._updateMarkers()
}
,
o._sourceUpdated = function(e) {
var t = o._getSourceClass();
t && t.getId() === e.source.id && (o._timer && clearTimeout(o._timer),
o._timer = setTimeout(o._sourceUpdater, 33))
}
,
o._sourceUpdater = function() {
o._timer = null,
o._clearCache(!0)
}
,
o._updateMarkers = function() {
return a(o, void 0, void 0, function() {
var t, r, o, a, i, n, s, l, u, c, p, d, m, h, f, v, _, k;
return g(this, function(e) {
switch (e.label) {
case 0:
if (r = (t = this)._map,
o = t._markers,
a = t._options,
i = r ? r.getCamera().zoom : void 0,
!(a.visible && void 0 !== i && i >= a.minZoom && i <= a.maxZoom))
return [3, 5];
n = t.getSource(),
s = "string" == typeof n ? n : n.getId(),
l = r.map.querySourceFeatures(s, {
sourceLayer: t.getOptions().sourceLayer,
filter: a.filter
}),
u = [],
c = [],
v = f = h = m = d = p = void 0,
k = 0,
_ = l.length,
e.label = 1;
case 1:
return k < _ ? (p = v = null,
l[k]instanceof y.Shape ? "Point" === (h = l[k]).getType() && (m = h.getCoordinates(),
d = h.getProperties(),
p = h.getId()) : "Point" === (f = l[k]).geometry.type && (m = f.geometry.coordinates,
(d = f.properties) && d.cluster ? p = "cluster_" + f.properties.cluster_id : f.id && (p = f.id)),
m ? [4, t._getMarker(p, m, d)] : [3, 3]) : [3, 4];
case 2:
(v = e.sent())._eventsAttached || (t._addEvents(v),
v._eventsAttached = !0),
v && (v.id && c.push(v.id),
v.id && -1 !== t._markerIds.indexOf(v.id) || (u.push(v),
r.markers.add(v))),
e.label = 3;
case 3:
return k++,
[3, 1];
case 4:
for (k = o.length - 1; 0 <= k; k--)
o[k].id && -1 !== c.indexOf(o[k].id) || (r.markers.remove(o[k]),
o.splice(k, 1));
return t._markers = o.concat(u),
t._markerIds = c,
[3, 6];
case 5:
0 < t._markers.length && (r.markers.remove(t._markers),
t._markers = []),
e.label = 6;
case 6:
return [2]
}
})
})
}
,
o._wrappedEvent = function(e) {
o.map.events.invoke(e.type, o, e)
}
,
s.prototype.setOptions.call(o, {
color: "transparent",
radius: 0,
strokeWidth: 0
}),
o.setOptions(r || {}),
o
}
var b, c = Object.freeze({
__proto__: null,
HtmlMarkerLayer: l
}), p = (t(C, b = y.HtmlMarker),
C.prototype.getTotalValue = function() {
return this._total
}
,
C.prototype.getSliceValue = function(e) {
var t = this._options.values;
return 0 <= e && e < t.length ? t[e] : 0
}
,
C.prototype.getSlicePercentage = function(e) {
return 0 < this._total ? Math.round(this.getSliceValue(e) / this._total * 1e4) / 100 : 0
}
,
C.prototype.getOptions = function() {
return Object.assign({}, b.prototype.getOptions.call(this), this._options)
}
,
C.prototype.setOptions = function(e) {
var t = this._options
, r = JSON.stringify
, o = !1;
e.radius && 0 < e.radius && e.radius != t.radius && (t.radius = e.radius,
o = !0),
0 <= e.innerRadius && e.innerRadius != t.innerRadius && (t.innerRadius = e.innerRadius,
o = !0),
e.colors && r(e.colors) !== r(t.colors) && (t.colors = e.colors,
o = !0),
e.fillColor && r(e.fillColor) !== r(t.fillColor) && (t.fillColor = e.fillColor,
o = !0),
e.strokeColor && e.strokeColor !== t.strokeColor && (t.strokeColor = e.strokeColor,
o = !0),
0 <= e.strokeWidth && e.strokeWidth != t.strokeWidth && (t.strokeWidth = e.strokeWidth,
o = !0),
void 0 !== e.tooltipCallback && t.tooltipCallback != e.tooltipCallback && (t.tooltipCallback = e.tooltipCallback,
o = !0),
e.values && r(e.values) !== r(t.values) && (t.values = e.values,
o = !0),
void 0 !== e.text && e.text !== t.text && (b.prototype.setOptions.call(this, {
text: e.text
}),
o = !0),
void 0 !== e.textClassName && e.textClassName !== t.textClassName && (t.textClassName = e.textClassName,
o = !0),
o && this._render(),
b.prototype.setOptions.call(this, e)
}
,
C.prototype._render = function() {
var e = this
, t = e._options
, r = t.values
, o = t.radius
, a = 0
, i = 0;
if (r) {
e._total = r.reduce(function(e, t) {
return e + t
}, 0);
for (var n = C._moreColors, s = Math.random, l = Math.round, u = 0; r.length > t.colors.length; )
n.length < r.length && n.push("hsl(" + l(360 * s()) + "," + (l(20 * s()) + 70) + "%," + (l(40 * s()) + 30) + "%)"),
t.colors.push(n[u]),
u++;
var c = o + t.strokeWidth
, p = ['<svg xmlns="http://www.w3.org/2000/svg" width="' + 2 * c + 'px" height="' + 2 * c + 'px">']
, d = ""
, m = void 0;
if (0 < t.innerRadius && t.innerRadius <= t.radius && (m = "piechart-innercircle-" + l(1e7 * s()),
p.push('<defs><mask id="' + m + '"><rect width="100%" height="100%" fill="white"/><circle r="' + t.innerRadius + '" cx="' + c + '" cy="' + c + '" fill="black"/></mask></defs>\n <circle r="' + t.innerRadius + '" cx="' + c + '" cy="' + c + '" style="fill:' + t.fillColor + ";stroke:" + t.strokeColor + ";stroke-width:" + 2 * t.strokeWidth + 'px;"/>')),
0 < e._total)
for (var h = t.tooltipCallback, f = 2 * Math.PI / e._total, v = 0; v < r.length; v++) {
i = f * r[v],
h && (d = h(e, v));
var _ = v < t.colors.length ? t.colors[v] : n[v];
p.push(e._createSlice(c, c, o, a, i, _, d, m)),
a += i
}
var k = e.getOptions().text;
k && p.push('<text x="' + c + '" y="' + (c + 7) + '" style="font-size:16px;font-family:arial;fill:#000;font-weight:bold;" class="' + (t.textClassName || "") + '" text-anchor="middle">' + k + "</text>"),
p.push("</svg>"),
b.prototype.getOptions.call(this).htmlContent.innerHTML = p.join("")
}
}
,
C.prototype._createSlice = function(e, t, r, o, a, i, n, s) {
var l = this._options
, u = Math.PI
, c = "";
if (s && (c = ' mask="url(#' + s + '"'),
2 * u * .99 < a)
return '<circle r="' + r + '" cx="' + e + '" cy="' + t + '" style="fill:' + i + ";stroke:" + l.strokeColor + ";stroke-width:" + l.strokeWidth + 'px;"' + c + "><title>" + n + "</title></circle>";
var p = Math.sin
, d = Math.cos
, m = e + r * p(o)
, h = t - r * d(o)
, f = e + r * p(o + a)
, v = t - r * d(o + a)
, _ = (l.innerRadius,
p(o),
l.innerRadius,
d(o),
l.innerRadius,
p(o + a),
l.innerRadius,
d(o + a),
0);
return u < a && (_ = 1),
'<path d="M' + e + " " + t + " L " + m + " " + h + " A " + r + "," + r + " 0 " + _ + " 1 " + f + " " + v + 'z" style="fill:' + i + ";stroke:" + l.strokeColor + ";stroke-width:" + l.strokeWidth + 'px;"' + c + "><title>" + n + "</title></path>"
}
,
C._moreColors = [],
C);
function C(e) {
var t = b.call(this, e) || this;
return t._options = {
values: [],
radius: 40,
colors: ["#d7191c", "#fdae61", "#ffffbf", "#abdda4", "#2b83ba"],
fillColor: "transparent",
strokeWidth: 0,
strokeColor: "#666666",
innerRadius: 0
},
t._total = 0,
t.properties = {},
b.prototype.setOptions.call(t, {
htmlContent: document.createElement("div"),
pixelOffset: [0, 0],
anchor: "center"
}),
t.setOptions(e),
t
}
var d = r.merge("atlas.layer", c);
e.PieChartMarker = p,
e.layer = d
}(this.atlas = this.atlas || {}, atlas);
</script>
</head>
<style>
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
font-family: segoeui;
}
#mapContainer {
position: relative;
width: 100%;
height: 100%;
}
</style>
<body>
<div id="mapContainer"></div>
<script>
var map;
var symbolLayers = [];
var layersData = {};
var pointsData = {};
var dataSource;
var id = 1;
var controls = [];
function initializeMap(longitude, latitude, mapServiceToken) {
try {
//Initialize a map instance.
map = new atlas.Map('mapContainer', {
center: [longitude, latitude],
zoom: 3,
view: 'Auto',
//Add authentication details for connecting to Azure Maps.
// Note: an invalid token doesn't seem to throw any errors.
authOptions: {
authType: 'subscriptionKey',
subscriptionKey: mapServiceToken
}
});
map.events.add('ready', function () {
dataSource = new atlas.source.DataSource();
map.sources.add(dataSource);
});
}
catch (error) {
sendErrorInfo(error);
}
}
function addSymbolLayer() {
try {
var layerSource = new atlas.source.DataSource();
var newLayer = new atlas.layer.HtmlMarkerLayer(layerSource, null, {
markerCallback: (id, position, properties) => {
const pin = new atlas.HtmlMarker({
position: position,
id: id
});
pin.getElement().setAttribute('tabindex', 0);
return pin;
}
});
layersData[newLayer.getId()] = layerSource;
pointsData[newLayer.getId()] = {};
symbolLayers.push(newLayer);
map.events.add('ready', function () {
map.sources.add(layerSource);
map.layers.add(newLayer);
map.events.add('click', newLayer, sendPushpinClickInfo);
});
}
catch (error) {
sendErrorInfo(error);
}
return newLayer.getId();
}
function addPoint(longitude, latitude, layerId) {
var point = new atlas.data.Feature(new atlas.data.Point([longitude, latitude]), {name: 'MapElement'}, id);
id++;
try {
map.events.add('ready', function () {
layersData[layerId].add([point]);
pointsData[layerId][point.id] = point;
});
}
catch (error) {
sendErrorInfo(error);
}
return point.id;
}
function updatePoint(longitude, latitude, pointId, layerId) {
try {
map.events.add('ready', function () {
pointsData[layerId][pointId].setCoordinates([longitude, latitude]);
logSymbolLayers();
});
}
catch (error) {
sendErrorInfo(error);
}
}
function removePoint(pointId, layerId) {
try {
map.events.add('ready', function() {
layersData[layerId].remove(pointsData[layerId][pointId]);
delete pointsData[layerId][pointId];
});
}
catch (error) {
sendErrorInfo(error);
}
}
function clearLayer(layerId) {
try {
map.events.add( 'ready', function() {
layersData[layerId].clear();
pointsData[layerId] = {};
});
}
catch (error) {
sendErrorInfo(error);
}
}
function clearMap() {
try {
map.events.add( 'ready', function() {
symbolLayers = [];
layersData = {};
pointsData = {};
});
}
catch (error) {
sendErrorInfo(error);
}
}
function interactiveControlsVisible(enable) {
if (enable) {
controls = [
new atlas.control.ZoomControl(),
new atlas.control.CompassControl(),
new atlas.control.PitchControl(),
new atlas.control.StyleControl()
]
map.controls.add(controls, {
position: "top-right"
});
} else {
map.controls.remove(controls);
controls = [];
}
}
function updateCenter(latitude, longitude) {
try {
map.setCamera({
center: [longitude, latitude]
});
}
catch (error) {
sendErrorInfo(error);
}
}
function updateZoom(level) {
try {
map.setCamera({
zoom: level
});
}
catch (error) {
sendErrorInfo(error);
}
}
function updateMapServiceToken(mapServiceToken) {
try {
clearMap();
var location = map.getCamera().center;
longitude = location[0];
latitude = location[1];
// create a new map with the new API key
initializeMap(longitude, latitude, mapServiceToken);
} catch (error) {
sendErrorInfo(error);
}
}
function sendPushpinClickInfo(e) {
try {
const latitude = e.target.options.position[0];
const longitude = e.target.options.position[1];
const pointClicked = e.target.id || 'Unknown';
const coordinate = {
latitude,
longitude,
};
const message = {
type: 'pushpinClickEvent',
coordinate,
layer: 0,
point: pointClicked,
text: 'Pushpin clicked!',
};
console.log('Sending message:', message);
window.chrome.webview.postMessage(message);
} catch (error) {
sendErrorInfo(error);
}
}
function getMapLayers() {
try {
layers = map.layers.getLayers();
console.log("Number of layers: " + layers.length + "\n");
// print out the name and type of each layer
for (var i = 0; i < layers.length; i++) {
if (layers[i] instanceof atlas.layer.SymbolLayer) {
console.log(layers[i].getId() + " is a SymbolLayer\n");
console.log("Source: " + layers[i].getSource() + "\n");
}
}
}
catch (error) {
sendErrorInfo(error);
}
}
function logSymbolLayers() {
try {
// print out each symbolLayer in symbolLayers by id
console.log("Number of symbol layers: " + symbolLayers.length + "\n");
for (var i = 0; i < symbolLayers.length; i++) {
console.log("Id: " + symbolLayers[i].getId() + "\n");
}
}
catch (error) {
sendErrorInfo(error);
}
}
function getSymbolLayers() {
return symbolLayers;
}
function sendErrorInfo(e) {
console.log(e);
const coordinate = {
"latitude": 0,
"longitude": 0,
}
const message = {
"type": "javascriptError",
"coordinate": coordinate,
"text": e.stack
};
window.chrome.webview.postMessage(message);
}
</script>
</body>
</html>