2019-11-04 10:59:08 +01:00
|
|
|
<!doctype html>
|
2019-12-09 14:27:32 +01:00
|
|
|
<html lang='en' class="dark-mode">
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
<head>
|
|
|
|
<meta charset='UTF-8'>
|
|
|
|
<title>GeoGraphics</title>
|
|
|
|
|
2019-11-13 12:42:06 +01:00
|
|
|
<script src="../../3rdparty/highlight/highlight.pack.js"></script>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../../fonts/material-icon-font/material-icons.css">
|
|
|
|
<link rel='stylesheet' href='../../3rdparty/highlight/styles/vs2015.css'>
|
2019-11-04 10:59:08 +01:00
|
|
|
<link rel='stylesheet' href='../../../css/doctest.css'>
|
|
|
|
|
|
|
|
<script src="../../../dist/iwmlib.3rdparty.js"></script>
|
|
|
|
<script src="../../../dist/iwmlib.js"></script>
|
|
|
|
<script src="../../../dist/iwmlib.pixi.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.inline-showcase {
|
|
|
|
display: flex
|
|
|
|
}
|
|
|
|
|
|
|
|
.map-example {
|
|
|
|
display: inline-block;
|
|
|
|
width: 256px;
|
|
|
|
margin: 5px;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<body onload='Doctest.run()'>
|
|
|
|
<h1>GeoGraphics</h1>
|
|
|
|
<p> GeoGraphics are graphical objects, that does not store the graphics information
|
|
|
|
in screen space, but in geographical coordinates. Therefore GeoGraphics must be
|
|
|
|
placed on GeoLayers to work properly. </p>
|
|
|
|
<p><i>
|
|
|
|
Note: As GeoLayers are always children of a map layer. When the map is changed
|
|
|
|
all GeoLayers are notified via the 'adaptTo(map)' method.</i></p>
|
|
|
|
<p>
|
|
|
|
The geolayers forward this 'adaptTo' to all children that are GeoGraphics.
|
|
|
|
Which adjust their so called 'point' data to the new map.</p>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<nav>
|
2019-12-09 14:27:32 +01:00
|
|
|
<h3>Content</h3>
|
|
|
|
<ol>
|
2019-11-04 10:59:08 +01:00
|
|
|
<li><a href="#geopoint">Gep Point</a></li>
|
|
|
|
<li><a href="#geoline">Geo Line</a></li>
|
|
|
|
<li><a href="#geoshape">Geo Shape</a></li>
|
2019-12-09 14:27:32 +01:00
|
|
|
</ol>
|
2019-11-04 10:59:08 +01:00
|
|
|
</nav>
|
2019-12-09 14:27:32 +01:00
|
|
|
|
|
|
|
|
|
|
|
<!-- Hidden Scripts -->
|
|
|
|
<script>
|
|
|
|
window.apps = []
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<section>
|
|
|
|
<h2>Data & Functions</h2>
|
|
|
|
<!-- Capitals Data. -->
|
|
|
|
<script class="doctest" data-collapsible data-collapsed data-title="Capitals Data">
|
|
|
|
|
|
|
|
// Some random capitals of the world.
|
|
|
|
// Coordinates taken from Google Maps.
|
|
|
|
let capitals = {
|
|
|
|
abidjan: { x: 5.349470, y: -4.006472 },
|
|
|
|
berlin: { x: 52.525430, y: 13.385291 },
|
|
|
|
canberra: { x: -35.282025, y: 149.128648 },
|
|
|
|
capetown: { x: -33.925448, y: 18.416962 },
|
|
|
|
moscow: { x: 55.750892, y: 37.622799 },
|
|
|
|
washington: { x: 38.895650, y: -77.031407 },
|
|
|
|
rio: { x: -22.871400, y: -43.280490 },
|
|
|
|
tokio: { x: 35.696278, y: 139.731366 }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
<script class="doctest" data-collapsible data-collapsed data-title="enableSwitch(button, app)">
|
|
|
|
|
|
|
|
// Adds an eventlistener to a button, that it changes the map.
|
|
|
|
function enableSwitch(button, app) {
|
|
|
|
button.addEventListener("click", () => {
|
|
|
|
// Always call the next map.
|
|
|
|
let next = app.mapLayer.next()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<script class="doctest" data-collapsible data-collapsed data-title="createApp(view)">
|
|
|
|
|
|
|
|
// Creates a MapApp with two predefined maps on a specified canvas element.
|
|
|
|
function createApp(canvas, options) {
|
|
|
|
|
|
|
|
// Create MapApp.
|
|
|
|
let app = window.GeoPointApp = new MapApp(Object.assign({
|
|
|
|
view: canvas,
|
|
|
|
focus: { x: 0, y: 0 },
|
|
|
|
zoom: 1,
|
|
|
|
width: 512,
|
|
|
|
height: 512,
|
|
|
|
coordsLogging: true
|
|
|
|
}, options))
|
|
|
|
|
|
|
|
// Images used for the maps.
|
|
|
|
const osmworld = "../assets/maps/osm/0/0/0.png"
|
|
|
|
const wikimedia = "../assets/maps/wikimedia-world-robinson/2000px-BlankMap-World.png"
|
|
|
|
|
|
|
|
|
|
|
|
// ImageMaps need to be loaded first. Therefore we return a promise.
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
|
|
// Add a timeout that cancels the promise when it takes too long.
|
|
|
|
setTimeout(() => {
|
|
|
|
reject("Creating app timed out.")
|
|
|
|
}, 3000)
|
|
|
|
|
|
|
|
// The app's loader loads the sprites.
|
|
|
|
app.loadSprites([
|
|
|
|
osmworld,
|
|
|
|
wikimedia
|
|
|
|
], (sprites) => {
|
|
|
|
|
|
|
|
// For demonstration of the geographics capability,
|
|
|
|
// Two different projections are used.
|
|
|
|
const MercatorProjection = new Projection.Mercator()
|
|
|
|
const RobinsonProjection = new Projection.Robinson(10)
|
|
|
|
|
|
|
|
// In the MapDataOptions specific behaviour can be enforced.
|
|
|
|
// E.g. Setting cover to false removes the enforcement of the map to cover the
|
|
|
|
// whole mapLayer.
|
|
|
|
const mapDataOptions = { cover: true, debug: true }
|
|
|
|
|
|
|
|
|
|
|
|
// Specifies a common zoom height for both maps.
|
|
|
|
// Otherwise the zoomFactor would differ and on mapchange it
|
|
|
|
// would appear as the map zoomes drastically in and out.
|
|
|
|
const osmHeight = sprites.get(osmworld).height
|
|
|
|
const mapOptions = {
|
|
|
|
baseZoomHeight: osmHeight
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the actual map objects.
|
|
|
|
let osmMap = new ImageMap(sprites.get(osmworld), new MapData(MercatorProjection, mapDataOptions), mapOptions)
|
|
|
|
let wikimediaMap = new ImageMap(sprites.get(wikimedia), new MapData(RobinsonProjection, mapDataOptions), mapOptions)
|
|
|
|
|
|
|
|
// Add the maps to the mapapp.
|
|
|
|
// An object is used to have a key, that identifies the maps.
|
|
|
|
app.addMaps({
|
|
|
|
"osm": osmMap, "wiki": wikimediaMap
|
|
|
|
})
|
|
|
|
|
|
|
|
// Select a specific map.
|
|
|
|
// The addMaps function sets a 'random' map as startmap.
|
|
|
|
app.selectMap("osm")
|
|
|
|
|
|
|
|
// Run the app after the maps were set.
|
|
|
|
app.setup().run()
|
|
|
|
|
|
|
|
// [DEBUG] Save the app in a global array.
|
|
|
|
window.apps.push(app)
|
|
|
|
|
|
|
|
// Resolve the promise.
|
|
|
|
resolve(app)
|
|
|
|
}, {
|
|
|
|
// Tell the loader to not load the images resolution dependent.
|
|
|
|
// That results in 'weird' naming of the textures.
|
|
|
|
resolutionDependent: false
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</section>
|
|
|
|
|
2019-11-04 10:59:08 +01:00
|
|
|
<!--GeoPoint -->
|
|
|
|
<section id="geopoint">
|
|
|
|
<h2>GeoPoint</h2>
|
|
|
|
<p>GeoPoint is a single coordinate in the map.</p>
|
|
|
|
<canvas id="geopoint_canvas"></canvas>
|
|
|
|
<div class=" controls">
|
|
|
|
<button id="geopoint_switch">Change Map</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
2019-12-09 14:27:32 +01:00
|
|
|
<script class="doctest" data-title="GeoPoint Example" data-collapsible>
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
; (function () {
|
|
|
|
createApp(geopoint_canvas).then(app => {
|
2019-11-04 18:20:32 +01:00
|
|
|
|
|
|
|
let capitalContainer = new PIXI.Container()
|
|
|
|
let capitalLayer = new GeoLayer(capitalContainer)
|
2019-11-04 10:59:08 +01:00
|
|
|
for (key in capitals) {
|
|
|
|
let capitalPoint = new GeoPoint(capitals[key], {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* To style GeoGraphics, the fill has to be set in the
|
|
|
|
* onDraw callback.
|
|
|
|
*
|
|
|
|
* Note: GeoPoints are the only GeoGraphic with no
|
|
|
|
* initial geometry attached. These have to be drawn to
|
|
|
|
* the graphics object manually.
|
|
|
|
*/
|
|
|
|
onDraw: function () {
|
|
|
|
this.graphics.beginFill(0xFF0000)
|
|
|
|
this.graphics.drawCircle(0, 0, 5)
|
|
|
|
this.graphics.endFill()
|
|
|
|
}
|
|
|
|
})
|
2019-11-04 18:20:32 +01:00
|
|
|
capitalContainer.addChild(capitalPoint)
|
2019-11-04 10:59:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
enableSwitch(geopoint_switch, app)
|
|
|
|
|
2019-11-04 18:20:32 +01:00
|
|
|
app.mapLayer.addLayer(capitalLayer)
|
2019-11-04 10:59:08 +01:00
|
|
|
}).catch(console.error)
|
|
|
|
})()
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</section>
|
2019-12-05 17:06:50 +01:00
|
|
|
<section id="geoline">
|
2019-11-04 10:59:08 +01:00
|
|
|
<h2>GeoLine</h2>
|
|
|
|
<p>Geo line is a set of points, that are rendered as a line and can be updated individually.</p>
|
|
|
|
<canvas id="geoline_canvas"></canvas>
|
|
|
|
<div class="controls">
|
|
|
|
<button id="geoline_switch">Change Map</button>
|
2019-12-09 14:27:32 +01:00
|
|
|
<label>
|
2019-11-04 10:59:08 +01:00
|
|
|
<input type="checkbox" id="geoline_close_toggle">
|
2019-12-09 14:27:32 +01:00
|
|
|
<div class="checkbox"></div>
|
|
|
|
<span>Close Line</span>
|
|
|
|
</label> </div>
|
|
|
|
<script class="doctest" data-title="GeoLine Example">
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
; (function () {
|
|
|
|
createApp(geoline_canvas).then(app => {
|
2019-12-05 17:06:50 +01:00
|
|
|
let geoLayer = new GeoLayer(new PIXI.Container())
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
//// You can initialize the GeoLine with a set of coordinates.
|
|
|
|
let newYorkRooseveltAirField = { x: 40.738473, y: -73.613131 }
|
|
|
|
let aeroport_de_Paris_le_bourget = { x: 48.960373, y: 2.436891 }
|
|
|
|
|
|
|
|
// Instantiate the geo line.
|
|
|
|
let lindberghTransatlanticFlight = new GeoLine([
|
|
|
|
newYorkRooseveltAirField,
|
|
|
|
aeroport_de_Paris_le_bourget
|
|
|
|
], {
|
|
|
|
// Define how the line should be drawn.
|
|
|
|
// Note: This is called everytime the GeoGraphic
|
|
|
|
// has to adapt.
|
|
|
|
onDraw: function () {
|
|
|
|
this.graphics.lineStyle(3, 0xf8baea)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Just place it on a GeoLayer.
|
2019-12-05 17:06:50 +01:00
|
|
|
geoLayer.addChild(lindberghTransatlanticFlight)
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
// Another option is to add points with the *addPoint()* method.
|
|
|
|
// This is useful for dynamic lines.
|
|
|
|
let geoline = new GeoLine([], {
|
|
|
|
onDraw: function () {
|
|
|
|
this.graphics.lineStyle(3, 0x00cc54, 0.5)
|
|
|
|
}
|
|
|
|
})
|
2019-12-05 17:06:50 +01:00
|
|
|
geoLayer.addChild(geoline)
|
2019-11-04 10:59:08 +01:00
|
|
|
for (let [name, coordinates] of Object.entries(capitals)) {
|
|
|
|
geoline.addPoint(coordinates)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't forget to add the geolayer to the maplayer.
|
2019-12-05 17:06:50 +01:00
|
|
|
app.mapLayer.addLayer(geoLayer)
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
enableSwitch(geoline_switch, app)
|
|
|
|
|
|
|
|
geoline_close_toggle.addEventListener("input", () => {
|
|
|
|
|
|
|
|
geoline.closed = geoline_close_toggle.checked
|
|
|
|
})
|
|
|
|
|
|
|
|
}).catch(console.error)
|
|
|
|
})()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</section>
|
|
|
|
|
|
|
|
<section id="geoshape">
|
|
|
|
|
|
|
|
<h2>Geoshape</h2>
|
|
|
|
<p>GeoGraphics represent Polygons, that are drawn on a map. If the map change, the graphic adapts to the new map
|
|
|
|
and represents
|
|
|
|
the same geographical shape.</p>
|
|
|
|
<div class="inline-showcase">
|
|
|
|
<div class="map-example">
|
|
|
|
<canvas id="geoshape_canvas"></canvas>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<button id="geoshape_switch">Change Map</button>
|
|
|
|
|
2019-12-09 14:27:32 +01:00
|
|
|
<script class='doctest' data-title="GeoShape Example">
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
(function () {
|
|
|
|
createApp(geoshape_canvas).then((app) => {
|
|
|
|
|
|
|
|
let triangle = [
|
|
|
|
[capitals.berlin,
|
|
|
|
capitals.moscow,
|
|
|
|
capitals.tokio,
|
|
|
|
capitals.canberra,
|
|
|
|
capitals.capetown]
|
|
|
|
]
|
|
|
|
|
2019-12-05 17:06:50 +01:00
|
|
|
let countryLayer = new GeoLayer(new PIXI.Container(), { name: "Country Layer" })
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
let shape = new GeoShape(triangle, {
|
|
|
|
onDraw: function () {
|
|
|
|
this.graphics.beginFill(0xFF0000)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The following click handler should trigger when either the
|
|
|
|
* shape or a hole is clicked. This is the default and intended
|
|
|
|
* behaviour, as holes are considered to be contained by the
|
|
|
|
* desired geometry and should not interefere with any userinteraction.
|
|
|
|
*/
|
|
|
|
shape.graphics.interactive = true
|
|
|
|
shape.graphics.on("pointerdown", () => {
|
|
|
|
app.showNotification("Shape was clicked!")
|
|
|
|
})
|
|
|
|
|
2019-12-05 17:06:50 +01:00
|
|
|
countryLayer.addChild(shape)
|
|
|
|
app.mapLayer.addLayer(countryLayer)
|
2019-11-04 10:59:08 +01:00
|
|
|
|
|
|
|
enableSwitch(geoshape_switch, app)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}).catch(console.error)
|
|
|
|
})()
|
|
|
|
|
|
|
|
</script>
|
2019-12-05 17:06:50 +01:00
|
|
|
</section>
|
|
|
|
|
|
|
|
<section>
|
|
|
|
<h2>GeoGraphics & GeoJson</h2>
|
|
|
|
<p>The GeoGraphics work together with the GeoJson class. To convert the standardized format to PIXI elements.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<div class="wrapper">
|
|
|
|
<canvas id="geojson_canvas"></canvas>
|
|
|
|
</div>
|
2019-12-09 14:27:32 +01:00
|
|
|
<button id="geojson_switch">Change Map</button>
|
2019-12-05 17:06:50 +01:00
|
|
|
|
|
|
|
<script class="doctest" data-title="GeoJson Raw Data" data-collapsed data-collapsible>
|
|
|
|
|
|
|
|
window.usaFeatureCollection = { "type": "FeatureCollection", "features": [{ "type": "Feature", "properties": { "scalerank": 1, "featurecla": "Admin-0 country", "labelrank": 2, "sovereignt": "United States of America", "sov_a3": "US1", "adm0_dif": 1, "level": 2, "type": "Country", "admin": "United States of America", "adm0_a3": "USA", "geou_dif": 0, "geounit": "United States of America", "gu_a3": "USA", "su_dif": 0, "subunit": "United States of America", "su_a3": "USA", "brk_diff": 0, "name": "United States", "name_long": "United States", "brk_a3": "USA", "brk_name": "United States", "brk_group": null, "abbrev": "U.S.A.", "postal": "US", "formal_en": "United States of America", "formal_fr": null, "note_adm0": null, "note_brk": null, "name_sort": "United States of America", "name_alt": null, "mapcolor7": 4, "mapcolor8": 5, "mapcolor9": 1, "mapcolor13": 1, "pop_est": 313973000, "gdp_md_est": 15094000, "pop_year": 0, "lastcensus": 2010, "gdp_year": 0, "economy": "1. Developed region: G7", "income_grp": "1. High income: OECD", "wikipedia": 0, "fips_10": null, "iso_a2": "US", "iso_a3": "USA", "iso_n3": "840", "un_a3": "840", "wb_a2": "US", "wb_a3": "USA", "woe_id": -99, "adm0_a3_is": "USA", "adm0_a3_us": "USA", "adm0_a3_un": -99, "adm0_a3_wb": -99, "continent": "North America", "region_un": "Americas", "subregion": "Northern America", "region_wb": "North America", "name_len": 13, "long_len": 13, "abbrev_len": 6, "tiny": -99, "homepart": 1, "filename": "USA.geojson" }, "geometry": { "type": "MultiPolygon", "coordinates": [[[[-155.54211, 19.08348], [-155.68817, 18.91619], [-155.93665, 19.05939], [-155.90806, 19.33888], [-156.07347, 19.70294], [-156.02368, 19.81422], [-155.85008, 19.97729], [-155.91907, 20.17395], [-155.86108, 20.26721], [-155.78505, 20.2487], [-155.40214, 20.07975], [-155.22452, 19.99302], [-155.06226, 19.8591], [-154.80741, 19.50871], [-154.83147, 19.45328], [-155.22217, 19.23972], [-155.54211, 19.08348]]], [[[-156.07926, 20.64397], [-156.41445, 20.57241], [-156.58673, 20.783], [-156.70167, 20.8643], [-156.71055, 20.92676], [-156.61258, 21.01249], [-156.25711, 20.91745], [-155.99566, 20.76404], [-156.07926, 20.64397]]], [[[-156.75824, 21.17684], [-156.78933, 21.06873], [-157.32521, 21.09777], [-157.25027, 21.21958], [-156.75824, 21.17684]]], [[[-157.65283, 21.32217], [-157.70703, 21.26442], [-157.7786, 21.27729], [-158.12667, 21.31244], [-158.2538, 21.53919], [-158.29265, 21.57912], [-158.0252, 21.71696], [-157.94161, 21.65272], [-157.65283, 21.32217]]], [[[-159.34512, 21.982], [-159.46372, 21.88299], [-159.80051, 22.06533], [-159.74877, 22.1382], [-159.5962, 22.23618], [-159.36569, 22.21494], [-159.34512, 21.982]]], [[[-94.81758, 49.38905], [-94.63999999999987, 48.84000000000012], [-94.32914, 48.67074000000011], [-93.63087, 48.60926], [-92.61, 48.45], [-91.64, 48.14], [-90.82999999999986, 48.27], [-89.6, 48.010000000000105], [-89.27291744663668, 48.01980825458284], [-88.37811418328653, 48.30291758889382], [-87.43979262330024, 47.94], [-86.46199083122815, 47.55333801939204], [-85.65236324740323, 47.22021881773051], [-84.87607988151485, 46.90008331968238], [-84.77923824739983, 46.63710195574913], [-84.54374874544567, 46.53868419044923], [-84.6049, 46.4396], [-84.3367, 46.40877000000011], [-84.1421195136733, 46.51222585711574], [-84.09185126416148, 46.27541860613826], [-83.89076534700567, 46.116926988299156], [-83.6161309475905, 46.116926988299156], [-83.46955074739463, 45.99468638771259], [-83.59285071484308, 45.81689362241255], [-82.55092464875818, 45.34751658790545], [-82.33776312543108, 44.44], [-82.13764238150397, 43.57108755144], [-82.43, 42.9800000000001], [-82.89999999999989, 42.43000000000015], [-83.11999999999989, 42.08], [-83.14199968131256, 41.975681057293], [-83.02981014680694, 41.83279572200601], [-82.69008928092018, 41.675105088867326], [-82.43927771679162, 41.675105088867326], [-81.27774654816707, 42.20902598730686], [-80.24744767934784, 42.36619985612267], [-78.9393621487437, 42.86361135514812], [-78.92, 42.965], [-79.00999999999988, 43.27], [-79.17167355011188, 43.46633942318431], [
|
|
|
|
|
|
|
|
</script>
|
|
|
|
<script class="doctest" data-title="GeoJson Example" data-collapsible>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; (function () {
|
|
|
|
|
2019-12-09 14:27:32 +01:00
|
|
|
createApp(geojson_canvas, {
|
|
|
|
zoom: 6,
|
|
|
|
focus: { x: 50.99, y: -119.9 }
|
|
|
|
}).then(app => {
|
2019-12-05 17:06:50 +01:00
|
|
|
let geoLayer = new GeoLayer(new PIXI.Container())
|
|
|
|
|
|
|
|
let geographics = GeoUtils.transformToGeoGraphics([usaFeatureCollection])
|
|
|
|
|
|
|
|
|
|
|
|
geographics.forEach(geographics => {
|
|
|
|
geoLayer.addChild(geographics)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// Don't forget to add the geolayer to the maplayer.
|
|
|
|
app.mapLayer.addLayer(geoLayer)
|
|
|
|
|
|
|
|
enableSwitch(geojson_switch, app)
|
|
|
|
|
|
|
|
}).catch(console.error)
|
|
|
|
})()
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</section>
|
2019-11-04 10:59:08 +01:00
|
|
|
</body>
|
|
|
|
|
2019-11-05 11:07:36 +01:00
|
|
|
</html>
|