iwmlib/lib/pixi/maps/geographics.html

402 lines
30 KiB
HTML
Raw Normal View History

<!doctype html>
2019-12-09 14:27:32 +01:00
<html lang='en' class="dark-mode">
<head>
<meta charset='UTF-8'>
<title>GeoGraphics</title>
<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'>
<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>
<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>
</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>
<!--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>
; (function () {
createApp(geopoint_canvas).then(app => {
let capitalContainer = new PIXI.Container()
let capitalLayer = new GeoLayer(capitalContainer)
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()
}
})
capitalContainer.addChild(capitalPoint)
}
enableSwitch(geopoint_switch, app)
app.mapLayer.addLayer(capitalLayer)
}).catch(console.error)
})()
</script>
</section>
2019-12-05 17:06:50 +01:00
<section id="geoline">
<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>
<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">
; (function () {
createApp(geoline_canvas).then(app => {
2019-12-05 17:06:50 +01:00
let geoLayer = new GeoLayer(new PIXI.Container())
//// 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)
// 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)
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)
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">
(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" })
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)
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>
</body>
2019-11-05 11:07:36 +01:00
</html>