Compare commits
No commits in common. "65fac2f40652ab67dd41d72093f54af607a167fd" and "8745554cee18c9f5c183102e47509cd78884fb84" have entirely different histories.
65fac2f406
...
8745554cee
6
.gitignore
vendored
6
.gitignore
vendored
@ -80,9 +80,3 @@ typings/
|
|||||||
*.code-workspace
|
*.code-workspace
|
||||||
.history/
|
.history/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
|
||||||
# ignore generated contents-
|
|
||||||
/doc/out/*
|
|
||||||
**/thumbnails
|
|
||||||
**/thumbnail.png
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.0 KiB |
130
css/doctest.css
130
css/doctest.css
@ -1,47 +1,15 @@
|
|||||||
:root {
|
|
||||||
--white: rgb(250, 250, 250);
|
|
||||||
--light-gray: rgb(219, 219, 219);
|
|
||||||
--gray: rgb(66, 66, 66);
|
|
||||||
--black: rgb(20, 20, 20);
|
|
||||||
--dark-background: rgb(50, 50, 50);
|
|
||||||
|
|
||||||
--border-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
background: var(--white);
|
background: white;
|
||||||
color: var(--black);
|
color: #000;
|
||||||
font-family: 'Open Sans', Arial, sans-serif;
|
font-family: 'Open Sans', Arial, sans-serif;
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-mode nav{
|
|
||||||
border-color: var(--white);
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
margin-top: 50px;
|
|
||||||
min-width: 30%;
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
display: inline-block;
|
|
||||||
padding: 20px 30px;
|
|
||||||
/* background-color: var(--light-gray); */
|
|
||||||
border: 1px solid var(--black);
|
|
||||||
}
|
|
||||||
|
|
||||||
nav > h3 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav > ol a {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.dark-mode {
|
html.dark-mode {
|
||||||
background: var(--dark-background);
|
background: rgb(51, 51, 51);
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +22,8 @@ html.dark-mode {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
.dark-mode a{
|
||||||
color: #569cd6;
|
color: #569CD6;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,92 +31,6 @@ a {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-mode button {
|
|
||||||
border: 1px solid rgb(211, 211, 211);
|
|
||||||
color: rgb(211, 211, 211);
|
|
||||||
background: linear-gradient(to top, rgb(53, 53, 53), rgb(73, 73, 73));
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background-color: var(--white);
|
|
||||||
border: 1px solid var(--gray);
|
|
||||||
color: var(--gray);
|
|
||||||
padding: 10px 20px;
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: transform 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
user-select: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type='checkbox'] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
input[type='checkbox'] + .checkbox {
|
|
||||||
position: relative;
|
|
||||||
margin-right: 10px;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls > * {
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-mode .checkbox {
|
|
||||||
background-color: var(--gray);
|
|
||||||
border: 1px solid var(--white);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox {
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 3px;
|
|
||||||
background-color: var(--white);
|
|
||||||
border: 1px solid var(--black);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox:after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type='checkbox']:checked + .checkbox {
|
|
||||||
background-color: rgb(174, 238, 78);
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type='checkbox']:checked + .checkbox:after {
|
|
||||||
left: 11px;
|
|
||||||
top: 6px;
|
|
||||||
width: 5px;
|
|
||||||
height: 12px;
|
|
||||||
border: solid var(--white);
|
|
||||||
border-width: 0 4px 4px 0;
|
|
||||||
-webkit-transform: rotate(45deg);
|
|
||||||
-ms-transform: rotate(45deg);
|
|
||||||
transform: rotate(45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
button:active {
|
|
||||||
transform: scale(0.98);
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover {
|
|
||||||
filter: brightness(0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus {
|
|
||||||
box-shadow: 0 0 3px 1px #569cd6;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a{
|
a{
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
@ -189,7 +71,7 @@ a {
|
|||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.doctest-titlebar {
|
.doctest-collapsible-toggle {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: whitesmoke;
|
color: whitesmoke;
|
||||||
|
34
dist/iwmlib.js
vendored
34
dist/iwmlib.js
vendored
@ -239,29 +239,18 @@
|
|||||||
let container = document.createElement('div');
|
let container = document.createElement('div');
|
||||||
container.className = 'doctest-wrapper';
|
container.className = 'doctest-wrapper';
|
||||||
|
|
||||||
if (doctest.hasAttribute('data-title') || doctest.hasAttribute('data-collapsible')) {
|
let titleParent = container;
|
||||||
let titlebar = document.createElement('div');
|
|
||||||
titlebar.className = 'doctest-titlebar';
|
|
||||||
titlebar.style = 'min-height: 10px;';
|
|
||||||
container.appendChild(titlebar);
|
|
||||||
|
|
||||||
if (doctest.hasAttribute('data-title')) {
|
|
||||||
let title = document.createElement('h6');
|
|
||||||
title.innerText = doctest.getAttribute('data-title');
|
|
||||||
title.className = 'doctest-section-title';
|
|
||||||
titlebar.appendChild(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doctest.hasAttribute('data-collapsible')) {
|
if (doctest.hasAttribute('data-collapsible')) {
|
||||||
|
let collapsibleToggle = document.createElement('div');
|
||||||
|
|
||||||
let icon = document.createElement('i');
|
let icon = document.createElement('i');
|
||||||
icon.className = 'material-icons';
|
icon.className = 'material-icons';
|
||||||
titlebar.classList.add('doctest-collapsible-toggle');
|
collapsibleToggle.appendChild(icon);
|
||||||
|
|
||||||
if (titlebar.childNodes.length > 0) {
|
collapsibleToggle.className = 'doctest-collapsible-toggle';
|
||||||
titlebar.insertBefore(icon, titlebar.childNodes[0]);
|
collapsibleToggle.style = 'min-height: 10px;';
|
||||||
} else {
|
titleParent = collapsibleToggle;
|
||||||
titlebar.appendChild(icon);
|
container.appendChild(collapsibleToggle);
|
||||||
}
|
|
||||||
|
|
||||||
const collapsedClass = 'collapsed';
|
const collapsedClass = 'collapsed';
|
||||||
|
|
||||||
@ -280,8 +269,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
setToggleMode(doctest.hasAttribute('data-collapsed'));
|
setToggleMode(doctest.hasAttribute('data-collapsed'));
|
||||||
titlebar.addEventListener('click', determineToggleMode);
|
collapsibleToggle.addEventListener('click', determineToggleMode);
|
||||||
}
|
}
|
||||||
|
if (doctest.hasAttribute('data-title')) {
|
||||||
|
let title = document.createElement('h6');
|
||||||
|
title.innerText = doctest.getAttribute('data-title');
|
||||||
|
title.className = 'doctest-section-title';
|
||||||
|
titleParent.appendChild(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pre = document.createElement('pre');
|
let pre = document.createElement('pre');
|
||||||
|
312
dist/iwmlib.pixi.js
vendored
312
dist/iwmlib.pixi.js
vendored
@ -17444,7 +17444,7 @@
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @param {Projection}[projection] - Specifies the projection of the map (e.g. Mercator Projection).
|
* @param {Projection}[projection] - Specifies the projection of the map (e.g. Mercator Projection).
|
||||||
* @param {object}[opts] - Addiditonal options.
|
* @param {object}[opts] - Addiditonal options.
|
||||||
* @param {array}[opts.bounds] - Describes the minimum and maximum coordinates on the map in the form of {[[minLat, minLng],[maxLat, maxLng]]}.
|
* @param {[[minLat, minLng],[maxLat, maxLng]]}[opts.bounds] - Describes the minimum and maximum coordinates on the map
|
||||||
* @param {Point}[opts.translate] - Defines a translation, when clipping is not an option (e.g. when the whole world is shown, but translated.)
|
* @param {Point}[opts.translate] - Defines a translation, when clipping is not an option (e.g. when the whole world is shown, but translated.)
|
||||||
*/
|
*/
|
||||||
constructor(projection, opts = {}) {
|
constructor(projection, opts = {}) {
|
||||||
@ -17482,7 +17482,6 @@
|
|||||||
/**
|
/**
|
||||||
* Transforms a pixel point on the map to a geographical coordinate.
|
* Transforms a pixel point on the map to a geographical coordinate.
|
||||||
*
|
*
|
||||||
* @public
|
|
||||||
* @param {{x,y} | PIXI.Point} point - A pixel position on the map.
|
* @param {{x,y} | PIXI.Point} point - A pixel position on the map.
|
||||||
* @returns {{x,y} | PIXI.Point} - A geographical coordinate.
|
* @returns {{x,y} | PIXI.Point} - A geographical coordinate.
|
||||||
* @memberof MapData
|
* @memberof MapData
|
||||||
@ -17515,7 +17514,6 @@
|
|||||||
/**
|
/**
|
||||||
* Transform a geographical coordinate to a pixel point on the map.
|
* Transform a geographical coordinate to a pixel point on the map.
|
||||||
*
|
*
|
||||||
* @public
|
|
||||||
* @param {{x,y} | PIXI.Point} coordinates - A point in the form of {x:lat,y:lng}.
|
* @param {{x,y} | PIXI.Point} coordinates - A point in the form of {x:lat,y:lng}.
|
||||||
* @returns {{x,y} | PIXI.Point} point - A pixel position on the map.
|
* @returns {{x,y} | PIXI.Point} point - A pixel position on the map.
|
||||||
* @memberof MapData
|
* @memberof MapData
|
||||||
@ -17548,18 +17546,6 @@
|
|||||||
return point
|
return point
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get's the clipping of the map data. Clipping describes the
|
|
||||||
* piece of the map that is shown. E.g. if we just show a map of
|
|
||||||
* europe, then we have to set the clipping properly, otherwise
|
|
||||||
* the preojection would produce the wrong results when transforming
|
|
||||||
* from a point to coordinates or the other way around.
|
|
||||||
*
|
|
||||||
* @readonly
|
|
||||||
* @memberof MapData
|
|
||||||
* @returns {object} - Object that contains a min and max value of the clipping in form of: {min: {x,y}, max:{x,y}}. Where x and y are in between 0 and 1.
|
|
||||||
*/
|
|
||||||
get clip() {
|
get clip() {
|
||||||
let unclipped = {
|
let unclipped = {
|
||||||
min: { x: 0, y: 0 },
|
min: { x: 0, y: 0 },
|
||||||
@ -17569,30 +17555,30 @@
|
|||||||
return this.opts.clip ? this.opts.clip : unclipped
|
return this.opts.clip ? this.opts.clip : unclipped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the biggest viewport the mapdata allows.
|
* Bounds to pixel transforms some bounds in form of {min:{x:minLat, y:minLng},max:{x:maxLat, y:maxLng}}
|
||||||
* This is determined by the projecton or the clipping on the mapapp.
|
* to pixel coordinates.
|
||||||
*
|
*
|
||||||
* @readonly
|
|
||||||
* @memberof MapData
|
|
||||||
*/
|
*/
|
||||||
|
getBoundaries() {
|
||||||
|
// let min = this.toPixel(bounds.min)
|
||||||
|
// let max = this.toPixel(bounds.max)
|
||||||
|
|
||||||
|
// Y values needs to be swapped, as PIXI has it's origin
|
||||||
|
// in the top-left corner and a regular map in the bottom-left corner.
|
||||||
|
let boundaries = {
|
||||||
|
min: { x: 0, y: 0 },
|
||||||
|
max: { x: 1, y: 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
return boundaries
|
||||||
|
}
|
||||||
|
|
||||||
get maxViewport() {
|
get maxViewport() {
|
||||||
return this.opts.clip ? this.opts.clip : this.projection.maxViewport
|
return this.opts.clip ? this.opts.clip : this.projection.maxViewport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Special mapdata for DeepZoomMap objects.
|
|
||||||
*
|
|
||||||
* Note: It just transform the clipping parameter of the tiles config
|
|
||||||
* to the clipping of the mapapp.
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class DeepZoomMapData
|
|
||||||
* @extends {MapData}
|
|
||||||
*/
|
|
||||||
class DeepZoomMapData extends MapData {
|
class DeepZoomMapData extends MapData {
|
||||||
constructor(projection, tilesConfig, opts = {}) {
|
constructor(projection, tilesConfig, opts = {}) {
|
||||||
if (tilesConfig.clip) {
|
if (tilesConfig.clip) {
|
||||||
@ -17787,18 +17773,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
flushHandlers() {
|
flushHandlers() {
|
||||||
this.onLoad.empty();
|
// this.onLoaded
|
||||||
this.onTransform.empty();
|
this.onTransform.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Locks all transformations on the map.
|
|
||||||
* Single parameters can be set if necessary. False means the value is locked, true means they can be modified.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @param {object} [{ rotatable = false, translatable = false, movableX = false, movableY = false, scalable = false }={}]
|
|
||||||
* @memberof GeoMap
|
|
||||||
*/
|
|
||||||
lock({ rotatable = false, translatable = false, movableX = false, movableY = false, scalable = false } = {}) {
|
lock({ rotatable = false, translatable = false, movableX = false, movableY = false, scalable = false } = {}) {
|
||||||
if (this.image && this.image.scatter) {
|
if (this.image && this.image.scatter) {
|
||||||
this.image.scatter.translatable = rotatable;
|
this.image.scatter.translatable = rotatable;
|
||||||
@ -17807,26 +17785,30 @@
|
|||||||
this.image.scatter.rotatable = movableY;
|
this.image.scatter.rotatable = movableY;
|
||||||
this.image.scatter.scalable = scalable;
|
this.image.scatter.scalable = scalable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #001: This causes the map to not be displayed at the correct position on
|
||||||
|
// map change.
|
||||||
|
// // Rotation does not yet work with the cover mechanism.
|
||||||
|
// //this.rotatable = false
|
||||||
|
// this.translatable = false
|
||||||
|
// this.scalable = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlocks all transformations on the map.
|
|
||||||
* Single parameters can be set if necessary. False means the value is locked, true means they can be modified.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @param {object} [{ rotatable = false, translatable = false, movableX = false, movableY = false, scalable = false }={}]
|
|
||||||
* @memberof GeoMap
|
|
||||||
*/
|
|
||||||
unlock({ rotatable = true, translatable = true, movableX = true, movableY = true, scalable = true } = {}) {
|
unlock({ rotatable = true, translatable = true, movableX = true, movableY = true, scalable = true } = {}) {
|
||||||
this.lock({ rotatable, translatable, movableX, movableY, scalable });
|
if (this.image && this.image.scatter) {
|
||||||
|
this.image.scatter.translatable = translatable;
|
||||||
|
this.image.scatter.movableX = movableX;
|
||||||
|
this.image.scatter.movableY = movableY;
|
||||||
|
this.image.scatter.rotatable = rotatable;
|
||||||
|
this.image.scatter.scalable = scalable;
|
||||||
|
}
|
||||||
|
// Issue #001
|
||||||
|
// // Rotation does not yet work with the cover mechanism.
|
||||||
|
// //this.rotatable = true
|
||||||
|
// this.translatable = true
|
||||||
|
// this.scalable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unloads the image of the map.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @memberof GeoMap
|
|
||||||
*/
|
|
||||||
unload() {
|
unload() {
|
||||||
if (this.image) {
|
if (this.image) {
|
||||||
if (this.image.parent) {
|
if (this.image.parent) {
|
||||||
@ -17840,12 +17822,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the map, freeing all memory ba flushing handlers and removing the image.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @memberof GeoMap
|
|
||||||
*/
|
|
||||||
remove() {
|
remove() {
|
||||||
if (this.image) this.image.mask = null;
|
if (this.image) this.image.mask = null;
|
||||||
|
|
||||||
@ -17879,6 +17855,8 @@
|
|||||||
this.image = image;
|
this.image = image;
|
||||||
if (frame) this.setFrame(frame);
|
if (frame) this.setFrame(frame);
|
||||||
|
|
||||||
|
let boundaries = this.mapdata.getBoundaries();
|
||||||
|
|
||||||
let scatterOpts = Object.assign({
|
let scatterOpts = Object.assign({
|
||||||
cover: this.cover,
|
cover: this.cover,
|
||||||
scaleable: this.scaleable,
|
scaleable: this.scaleable,
|
||||||
@ -17888,6 +17866,7 @@
|
|||||||
startScale: this.startScale,
|
startScale: this.startScale,
|
||||||
minScale: this.minScale,
|
minScale: this.minScale,
|
||||||
maxScale: this.maxScale,
|
maxScale: this.maxScale,
|
||||||
|
boundaries,
|
||||||
onTransform: this.transformed.bind(this)
|
onTransform: this.transformed.bind(this)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -17943,7 +17922,7 @@
|
|||||||
* to a coordinate with latitude and longitude.
|
* to a coordinate with latitude and longitude.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param {object} point - Point in form of {x, y}.
|
* @param {object} point - Point in form of {x: x_val, y: y_val}.
|
||||||
* @returns {object} - Coordinates on the map in form of {x: latitude, y: longitude}.
|
* @returns {object} - Coordinates on the map in form of {x: latitude, y: longitude}.
|
||||||
*/
|
*/
|
||||||
coordinatesFromPoint(point) {
|
coordinatesFromPoint(point) {
|
||||||
@ -17955,7 +17934,7 @@
|
|||||||
* Transform coordinates in the map into pixel positions on the deep zoom image.
|
* Transform coordinates in the map into pixel positions on the deep zoom image.
|
||||||
*
|
*
|
||||||
* @param {object} coords - Coordinates of a map position in form {x: latitude, y: longitude}.
|
* @param {object} coords - Coordinates of a map position in form {x: latitude, y: longitude}.
|
||||||
* @return {Point} - Returns a image position in form of {x: x, y: y}.
|
* @return - Returns a image position in form of {x: x_val, y: y_val}.
|
||||||
*/
|
*/
|
||||||
coordinatesToPoint(coordinates) {
|
coordinatesToPoint(coordinates) {
|
||||||
return this.toAbsolutePixelCoordinates(this.mapdata.toPixel(coordinates))
|
return this.toAbsolutePixelCoordinates(this.mapdata.toPixel(coordinates))
|
||||||
@ -19115,31 +19094,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PIXIUtils {
|
|
||||||
/*
|
|
||||||
* Transform a pixi text to it's actual screensize,
|
|
||||||
* ignoring it's local transforms
|
|
||||||
*/
|
|
||||||
static toScreenFontSize(pixiText, fontSize = null) {
|
|
||||||
pixiText._recursivePostUpdateTransform();
|
|
||||||
|
|
||||||
let normalizedScale = {
|
|
||||||
x: pixiText.scale.x / pixiText.transform.worldTransform.a,
|
|
||||||
y: pixiText.scale.x / pixiText.transform.worldTransform.d
|
|
||||||
};
|
|
||||||
|
|
||||||
pixiText.scale = { x: normalizedScale.x, y: normalizedScale.y };
|
|
||||||
if (fontSize) pixiText.style.fontSize = fontSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static saveFill(graphics) {
|
|
||||||
return {
|
|
||||||
fill: graphics.fill.color,
|
|
||||||
alpha: graphics.fill.alpha
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GeoGraphics are graphical objects, that does not store the graphics information
|
* GeoGraphics are graphical objects, that does not store the graphics information
|
||||||
* in screen space, but in geographical coordinates. Therefore GeoGraphics must be
|
* in screen space, but in geographical coordinates. Therefore GeoGraphics must be
|
||||||
@ -19578,12 +19532,15 @@
|
|||||||
*/
|
*/
|
||||||
_drawShape(polygon, hole = []) {
|
_drawShape(polygon, hole = []) {
|
||||||
// We save the fill specified in the onDraw event handler.
|
// We save the fill specified in the onDraw event handler.
|
||||||
|
//
|
||||||
|
// Consider: Maybe it would be a good idea to add a 'onHoleDraw'
|
||||||
|
// callback to make the hole customizable. Maybe you want
|
||||||
|
// to fill it with a different color or an mediocre alpha value.
|
||||||
|
// then feel free to implement it.
|
||||||
let { fill, alpha } = PIXIUtils.saveFill(this.graphics);
|
let { fill, alpha } = PIXIUtils.saveFill(this.graphics);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a) Draw the hole with a polygon.
|
* This may seem redundant, but it's required
|
||||||
*
|
|
||||||
* This may seem redundant to (c), but it's required (in this order(!))
|
|
||||||
* to make the hole clickable.
|
* to make the hole clickable.
|
||||||
*
|
*
|
||||||
* It was a bit confusing, so I made a CodePen
|
* It was a bit confusing, so I made a CodePen
|
||||||
@ -19594,15 +19551,9 @@
|
|||||||
this.graphics.drawPolygon(hole);
|
this.graphics.drawPolygon(hole);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* b) Draw the shape.
|
|
||||||
*/
|
|
||||||
this.graphics.beginFill(fill, alpha);
|
this.graphics.beginFill(fill, alpha);
|
||||||
this.graphics.drawPolygon(polygon);
|
this.graphics.drawPolygon(polygon);
|
||||||
|
|
||||||
/**
|
|
||||||
* c) Add the hole.
|
|
||||||
*/
|
|
||||||
if (hole.length > 0) {
|
if (hole.length > 0) {
|
||||||
this.graphics.beginHole();
|
this.graphics.beginHole();
|
||||||
this.graphics.drawPolygon(hole);
|
this.graphics.drawPolygon(hole);
|
||||||
@ -19651,13 +19602,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
class PIXIUtils {
|
||||||
* MapList is a list of maps with one active index.
|
/*
|
||||||
* It contains some utility functions to change the map.
|
* Transform a pixi text to it's actual screensize,
|
||||||
*
|
* ignoring it's local transforms
|
||||||
* @export
|
|
||||||
* @class MapList
|
|
||||||
*/
|
*/
|
||||||
|
static toScreenFontSize(pixiText, fontSize = null) {
|
||||||
|
pixiText._recursivePostUpdateTransform();
|
||||||
|
|
||||||
|
let normalizedScale = {
|
||||||
|
x: pixiText.scale.x / pixiText.transform.worldTransform.a,
|
||||||
|
y: pixiText.scale.x / pixiText.transform.worldTransform.d
|
||||||
|
};
|
||||||
|
|
||||||
|
pixiText.scale = { x: normalizedScale.x, y: normalizedScale.y };
|
||||||
|
if (fontSize) pixiText.style.fontSize = fontSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static saveFill(graphics) {
|
||||||
|
return {
|
||||||
|
fill: graphics.fill.color,
|
||||||
|
alpha: graphics.fill.alpha
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MapList {
|
class MapList {
|
||||||
constructor(active = null, maps = {}) {
|
constructor(active = null, maps = {}) {
|
||||||
this.maps = maps;
|
this.maps = maps;
|
||||||
@ -19669,9 +19638,8 @@
|
|||||||
/**
|
/**
|
||||||
* Selects a map from the map list.
|
* Selects a map from the map list.
|
||||||
*
|
*
|
||||||
* @public
|
|
||||||
* @param {string} active - Name of the map to select.
|
* @param {string} active - Name of the map to select.
|
||||||
* @returns {Map} - Returns the active map. Returns null if no map was added to the MapList.
|
* @returns
|
||||||
* @memberof MapList
|
* @memberof MapList
|
||||||
*/
|
*/
|
||||||
select(active) {
|
select(active) {
|
||||||
@ -19701,13 +19669,6 @@
|
|||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clones the entire maplist.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @returns {MapList} - Returns a cloned instance of this map list.
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
clone() {
|
clone() {
|
||||||
let maps = {};
|
let maps = {};
|
||||||
|
|
||||||
@ -19718,14 +19679,6 @@
|
|||||||
return new MapList(this.active, maps)
|
return new MapList(this.active, maps)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new map to the map list.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @param {string} key - Key to identify the map.
|
|
||||||
* @param {GeoMap} map - The GeoMap to add.
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
add(key, map) {
|
add(key, map) {
|
||||||
if (this.maps[key] != null) consol.warn('Key already in mapList. The existing key was overwritten.');
|
if (this.maps[key] != null) consol.warn('Key already in mapList. The existing key was overwritten.');
|
||||||
if (this.active == null) this.active = key;
|
if (this.active == null) this.active = key;
|
||||||
@ -19733,25 +19686,10 @@
|
|||||||
this.maps[key] = map;
|
this.maps[key] = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the the active map.
|
|
||||||
* If none is set, it returns null.
|
|
||||||
*
|
|
||||||
*@public
|
|
||||||
* @readonly
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
get map() {
|
get map() {
|
||||||
return this.maps && this.maps[this.active] ? this.maps[this.active] : null
|
return this.maps && this.maps[this.active] ? this.maps[this.active] : null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects the next map in the map array.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @returns {GeoMap} - Returns the next map in the list.
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
next() {
|
next() {
|
||||||
let keys = Object.keys(this.maps);
|
let keys = Object.keys(this.maps);
|
||||||
let idx = keys.indexOf(this.active);
|
let idx = keys.indexOf(this.active);
|
||||||
@ -19760,13 +19698,6 @@
|
|||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all maps from the maplist.
|
|
||||||
* And cleans up all maps.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
for (let key in this.maps) {
|
for (let key in this.maps) {
|
||||||
let map = this.maps[key];
|
let map = this.maps[key];
|
||||||
@ -19995,15 +19926,7 @@
|
|||||||
mapList,
|
mapList,
|
||||||
scatterContainer,
|
scatterContainer,
|
||||||
displayObject,
|
displayObject,
|
||||||
{
|
{ onTransform = null, onChange = null, focus = null, zoom = null, viewport = null, name = null } = {}
|
||||||
onTransform = null,
|
|
||||||
onChange = null,
|
|
||||||
focus = null,
|
|
||||||
zoom = null,
|
|
||||||
viewport = null,
|
|
||||||
name = null,
|
|
||||||
mapChangeLocked = false
|
|
||||||
} = {}
|
|
||||||
) {
|
) {
|
||||||
super(displayObject, {
|
super(displayObject, {
|
||||||
name
|
name
|
||||||
@ -20031,7 +19954,6 @@
|
|||||||
// this.maps = maps
|
// this.maps = maps
|
||||||
// if (opts.map) this.placeMap(opts.map)
|
// if (opts.map) this.placeMap(opts.map)
|
||||||
this.dynamicElements = new Map();
|
this.dynamicElements = new Map();
|
||||||
this._mapChangeLocked = mapChangeLocked;
|
|
||||||
|
|
||||||
// Binds the transformed callback beforehand.
|
// Binds the transformed callback beforehand.
|
||||||
this.transformed = this.transformed.bind(this);
|
this.transformed = this.transformed.bind(this);
|
||||||
@ -20039,24 +19961,13 @@
|
|||||||
this.changeMap(mapList.active);
|
this.changeMap(mapList.active);
|
||||||
}
|
}
|
||||||
|
|
||||||
get mapChangeLocked() {
|
|
||||||
return this._mapChangeLocked
|
|
||||||
}
|
|
||||||
|
|
||||||
lockMapChange() {
|
|
||||||
this._mapChangeLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlockMapChange() {
|
|
||||||
this._mapChangeLocked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
adapt() {
|
adapt() {
|
||||||
this.layers.forEach(layer => {
|
this.layers.forEach(layer => {
|
||||||
if (layer.adapt) layer.adapt(this.map);
|
if (layer.adapt) layer.adapt(this.map);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
focus(coordinates, zoom) {
|
focus(coordinates, zoom) {
|
||||||
this.mapview.updateFocusPoint(this.map);
|
this.mapview.updateFocusPoint(this.map);
|
||||||
}
|
}
|
||||||
@ -20106,7 +20017,6 @@
|
|||||||
/* map ,
|
/* map ,
|
||||||
useScatterAsContainer = true // If set to false, the normal container is used. This is necessary when using submaps and the container need to be a RigidContainer.*/
|
useScatterAsContainer = true // If set to false, the normal container is used. This is necessary when using submaps and the container need to be a RigidContainer.*/
|
||||||
) {
|
) {
|
||||||
if (!this.mapChangeLocked) {
|
|
||||||
console.log('🗺️ Change map to: ', name);
|
console.log('🗺️ Change map to: ', name);
|
||||||
let oldMap = this.map;
|
let oldMap = this.map;
|
||||||
|
|
||||||
@ -20138,8 +20048,59 @@
|
|||||||
} else {
|
} else {
|
||||||
console.error(`Could not change map to ${name}.`);
|
console.error(`Could not change map to ${name}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Logging.log(`Map change: ${key}`)
|
||||||
|
|
||||||
|
if (this.active !== key) {
|
||||||
|
if (this.maps.hasOwnProperty(key)) {
|
||||||
|
let old = this.map ? this.map : null
|
||||||
|
this._map = this.maps[key]
|
||||||
|
this._map.name = key
|
||||||
|
this.active = key
|
||||||
|
|
||||||
|
let container = useScatterAsContainer ? this.scatterContainer : this.container
|
||||||
|
|
||||||
|
this.map.load(container)
|
||||||
|
|
||||||
|
// Copies all layers.
|
||||||
|
this.layers.forEach(layer => {
|
||||||
|
if (old) this.map.image.addChild(layer.container)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.placeMap(this.map)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Improve
|
||||||
|
*
|
||||||
|
* I'm quite sure if I made a design mistake here.
|
||||||
|
* In an earlier version I did not need to migrate the
|
||||||
|
* layers manually from the map to the next map.
|
||||||
|
*
|
||||||
|
* I believe the old version was a container next to the
|
||||||
|
* map, which got updated on transform.
|
||||||
|
*
|
||||||
|
* -SO
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if (old) old.unload()
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
let keys = Object.keys(this.maps)
|
||||||
|
|
||||||
|
if (keys.length == 0) console.error('There is no map set for the map layer!')
|
||||||
|
else {
|
||||||
|
let fallbackMap = keys[0]
|
||||||
|
console.error(
|
||||||
|
`A map with the key (${key}) does not exists within the mapapp. Fallback to map: ${fallbackMap}.`
|
||||||
|
)
|
||||||
|
this.changeMap(fallbackMap, {
|
||||||
|
useScatterAsContainer
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
refocus() {
|
refocus() {
|
||||||
this.mapview.apply(this.map);
|
this.mapview.apply(this.map);
|
||||||
@ -20349,9 +20310,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectMap(key) {
|
selectMap(key) {
|
||||||
if (this.debug) console.log('Select map', key, result);
|
|
||||||
let result = this.mapList.select(key);
|
let result = this.mapList.select(key);
|
||||||
|
|
||||||
|
console.log('Select map', key, result);
|
||||||
if (result && this.mapLayer) {
|
if (result && this.mapLayer) {
|
||||||
this.mapLayer.changeMap(this.mapList.map);
|
this.mapLayer.changeMap(this.mapList.map);
|
||||||
}
|
}
|
||||||
@ -20384,14 +20345,6 @@
|
|||||||
this.onTransform.call(this, event);
|
this.onTransform.call(this, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Called when the mapLayer changed the map.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {*} lastMap
|
|
||||||
* @memberof MapApp
|
|
||||||
*/
|
|
||||||
_mapChanged(lastMap) {
|
_mapChanged(lastMap) {
|
||||||
if (lastMap) {
|
if (lastMap) {
|
||||||
lastMap.flushHandlers();
|
lastMap.flushHandlers();
|
||||||
@ -20722,7 +20675,8 @@
|
|||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @export
|
* @export
|
||||||
* @class
|
* @class GeoJsonGraphics
|
||||||
|
* @extends {GeoGraphics}
|
||||||
*/
|
*/
|
||||||
class GeoJson {
|
class GeoJson {
|
||||||
static isLineType(type) {
|
static isLineType(type) {
|
||||||
@ -20774,6 +20728,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
list.push({ type, coordinates });
|
list.push({ type, coordinates });
|
||||||
|
// console.log({type, coordinates})
|
||||||
});
|
});
|
||||||
|
|
||||||
return list
|
return list
|
||||||
@ -20837,7 +20792,7 @@
|
|||||||
* considered valid. A complete list is provided in the GeoUtils.
|
* considered valid. A complete list is provided in the GeoUtils.
|
||||||
*
|
*
|
||||||
* @param {object} point - The point that is tested for validity.
|
* @param {object} point - The point that is tested for validity.
|
||||||
* @returns {boolean}
|
* @returns
|
||||||
* @memberof GeoJson
|
* @memberof GeoJson
|
||||||
*/
|
*/
|
||||||
static validateAndConvertPoint(point) {
|
static validateAndConvertPoint(point) {
|
||||||
@ -21016,7 +20971,7 @@
|
|||||||
* {latitude: lat, longitude: lng}
|
* {latitude: lat, longitude: lng}
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @param {object|array} coordinate - Coordinate to be tested, if it is an valid coordinate.
|
* @param {object / array} coordinate - Coordinate to be tested, if it is an valid coordinate.
|
||||||
* @returns - Returns the coordinate properly transformed. If transformation was not possible, it returns null.
|
* @returns - Returns the coordinate properly transformed. If transformation was not possible, it returns null.
|
||||||
* @memberof GeoGraphics
|
* @memberof GeoGraphics
|
||||||
*/
|
*/
|
||||||
@ -21687,7 +21642,4 @@
|
|||||||
window.Overlay = Overlay;
|
window.Overlay = Overlay;
|
||||||
window.MapList = MapList;
|
window.MapList = MapList;
|
||||||
|
|
||||||
window.GeoJson = GeoJson;
|
|
||||||
window.GeoUtils = GeoUtils;
|
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
@ -145,29 +145,18 @@ export default class Doctest {
|
|||||||
let container = document.createElement('div')
|
let container = document.createElement('div')
|
||||||
container.className = 'doctest-wrapper'
|
container.className = 'doctest-wrapper'
|
||||||
|
|
||||||
if (doctest.hasAttribute('data-title') || doctest.hasAttribute('data-collapsible')) {
|
let titleParent = container
|
||||||
let titlebar = document.createElement('div')
|
|
||||||
titlebar.className = 'doctest-titlebar'
|
|
||||||
titlebar.style = 'min-height: 10px;'
|
|
||||||
container.appendChild(titlebar)
|
|
||||||
|
|
||||||
if (doctest.hasAttribute('data-title')) {
|
|
||||||
let title = document.createElement('h6')
|
|
||||||
title.innerText = doctest.getAttribute('data-title')
|
|
||||||
title.className = 'doctest-section-title'
|
|
||||||
titlebar.appendChild(title)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doctest.hasAttribute('data-collapsible')) {
|
if (doctest.hasAttribute('data-collapsible')) {
|
||||||
|
let collapsibleToggle = document.createElement('div')
|
||||||
|
|
||||||
let icon = document.createElement('i')
|
let icon = document.createElement('i')
|
||||||
icon.className = 'material-icons'
|
icon.className = 'material-icons'
|
||||||
titlebar.classList.add('doctest-collapsible-toggle')
|
collapsibleToggle.appendChild(icon)
|
||||||
|
|
||||||
if (titlebar.childNodes.length > 0) {
|
collapsibleToggle.className = 'doctest-collapsible-toggle'
|
||||||
titlebar.insertBefore(icon, titlebar.childNodes[0])
|
collapsibleToggle.style = 'min-height: 10px;'
|
||||||
} else {
|
titleParent = collapsibleToggle
|
||||||
titlebar.appendChild(icon)
|
container.appendChild(collapsibleToggle)
|
||||||
}
|
|
||||||
|
|
||||||
const collapsedClass = 'collapsed'
|
const collapsedClass = 'collapsed'
|
||||||
|
|
||||||
@ -186,8 +175,13 @@ export default class Doctest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setToggleMode(doctest.hasAttribute('data-collapsed'))
|
setToggleMode(doctest.hasAttribute('data-collapsed'))
|
||||||
titlebar.addEventListener('click', determineToggleMode)
|
collapsibleToggle.addEventListener('click', determineToggleMode)
|
||||||
}
|
}
|
||||||
|
if (doctest.hasAttribute('data-title')) {
|
||||||
|
let title = document.createElement('h6')
|
||||||
|
title.innerText = doctest.getAttribute('data-title')
|
||||||
|
title.className = 'doctest-section-title'
|
||||||
|
titleParent.appendChild(title)
|
||||||
}
|
}
|
||||||
|
|
||||||
let pre = document.createElement('pre')
|
let pre = document.createElement('pre')
|
||||||
|
@ -62,6 +62,7 @@ window.FontInfo = FontInfo
|
|||||||
window.Text = Text
|
window.Text = Text
|
||||||
|
|
||||||
//Maps
|
//Maps
|
||||||
|
import MapView from './maps/mapview.js'
|
||||||
import { GeoMap, ImageMap, DeepZoomMap } from './maps/map.js'
|
import { GeoMap, ImageMap, DeepZoomMap } from './maps/map.js'
|
||||||
import { MapData, DeepZoomMapData } from './maps/mapdata.js'
|
import { MapData, DeepZoomMapData } from './maps/mapdata.js'
|
||||||
|
|
||||||
@ -79,8 +80,7 @@ window.Projection = {
|
|||||||
Robinson
|
Robinson
|
||||||
}
|
}
|
||||||
|
|
||||||
import MapViewport from './maps/mapviewport.js'
|
window.MapView = MapView
|
||||||
window.MapViewport = MapViewport
|
|
||||||
|
|
||||||
import MapApp from './maps/mapapp.js'
|
import MapApp from './maps/mapapp.js'
|
||||||
|
|
||||||
@ -100,6 +100,7 @@ window.CompactScatter = CompactScatter
|
|||||||
window.CoverScatter = CoverScatter
|
window.CoverScatter = CoverScatter
|
||||||
window.MapObjectScatter = MapObjectScatter
|
window.MapObjectScatter = MapObjectScatter
|
||||||
|
|
||||||
|
|
||||||
import { GeoLayer, MapLayer } from './maps/geolayer.js'
|
import { GeoLayer, MapLayer } from './maps/geolayer.js'
|
||||||
window.GeoLayer = GeoLayer
|
window.GeoLayer = GeoLayer
|
||||||
window.MapLayer = MapLayer
|
window.MapLayer = MapLayer
|
||||||
@ -117,8 +118,5 @@ import Overlay from './maps/overlay.js'
|
|||||||
window.Overlay = Overlay
|
window.Overlay = Overlay
|
||||||
|
|
||||||
import { MapList } from './maps/maplist.js'
|
import { MapList } from './maps/maplist.js'
|
||||||
import GeoJson, { GeoUtils } from './maps/geojson.js'
|
|
||||||
window.MapList = MapList
|
window.MapList = MapList
|
||||||
|
|
||||||
window.GeoJson = GeoJson
|
|
||||||
window.GeoUtils = GeoUtils
|
|
||||||
|
@ -37,7 +37,6 @@ const index = new Index(itemTemplate, [
|
|||||||
['Flippable', 'flippable.html'],
|
['Flippable', 'flippable.html'],
|
||||||
['LabeledGraphics', 'labeledgraphics.html'],
|
['LabeledGraphics', 'labeledgraphics.html'],
|
||||||
['List', 'list.html'],
|
['List', 'list.html'],
|
||||||
['Maps', 'maps/index.html'],
|
|
||||||
['Message', 'message.html'],
|
['Message', 'message.html'],
|
||||||
['Modal', 'modal.html'],
|
['Modal', 'modal.html'],
|
||||||
['Tooltip', 'tooltip.html'],
|
['Tooltip', 'tooltip.html'],
|
||||||
|
File diff suppressed because one or more lines are too long
@ -2,7 +2,6 @@ import { Points } from '../../utils.js'
|
|||||||
import { EventHandler } from './utils.js'
|
import { EventHandler } from './utils.js'
|
||||||
import { FlagPolygon } from '../graphics/label.js'
|
import { FlagPolygon } from '../graphics/label.js'
|
||||||
import { DeepZoomMap } from './map.js'
|
import { DeepZoomMap } from './map.js'
|
||||||
import { PIXIUtils } from '../../../../js/pixi/utils.js'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GeoGraphics are graphical objects, that does not store the graphics information
|
* GeoGraphics are graphical objects, that does not store the graphics information
|
||||||
@ -442,12 +441,15 @@ export class GeoShape extends GeoGraphics {
|
|||||||
*/
|
*/
|
||||||
_drawShape(polygon, hole = []) {
|
_drawShape(polygon, hole = []) {
|
||||||
// We save the fill specified in the onDraw event handler.
|
// We save the fill specified in the onDraw event handler.
|
||||||
|
//
|
||||||
|
// Consider: Maybe it would be a good idea to add a 'onHoleDraw'
|
||||||
|
// callback to make the hole customizable. Maybe you want
|
||||||
|
// to fill it with a different color or an mediocre alpha value.
|
||||||
|
// then feel free to implement it.
|
||||||
let { fill, alpha } = PIXIUtils.saveFill(this.graphics)
|
let { fill, alpha } = PIXIUtils.saveFill(this.graphics)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a) Draw the hole with a polygon.
|
* This may seem redundant, but it's required
|
||||||
*
|
|
||||||
* This may seem redundant to (c), but it's required (in this order(!))
|
|
||||||
* to make the hole clickable.
|
* to make the hole clickable.
|
||||||
*
|
*
|
||||||
* It was a bit confusing, so I made a CodePen
|
* It was a bit confusing, so I made a CodePen
|
||||||
@ -458,15 +460,9 @@ export class GeoShape extends GeoGraphics {
|
|||||||
this.graphics.drawPolygon(hole)
|
this.graphics.drawPolygon(hole)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* b) Draw the shape.
|
|
||||||
*/
|
|
||||||
this.graphics.beginFill(fill, alpha)
|
this.graphics.beginFill(fill, alpha)
|
||||||
this.graphics.drawPolygon(polygon)
|
this.graphics.drawPolygon(polygon)
|
||||||
|
|
||||||
/**
|
|
||||||
* c) Add the hole.
|
|
||||||
*/
|
|
||||||
if (hole.length > 0) {
|
if (hole.length > 0) {
|
||||||
this.graphics.beginHole()
|
this.graphics.beginHole()
|
||||||
this.graphics.drawPolygon(hole)
|
this.graphics.drawPolygon(hole)
|
||||||
@ -528,14 +524,6 @@ class GeoMultiGraphics extends GeoGraphics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class GeoText
|
|
||||||
* @extends {GeoPoint}
|
|
||||||
*/
|
|
||||||
export class GeoText extends GeoPoint {
|
export class GeoText extends GeoPoint {
|
||||||
constructor(coordinates, text, opts) {
|
constructor(coordinates, text, opts) {
|
||||||
super(coordinates, opts)
|
super(coordinates, opts)
|
||||||
@ -543,6 +531,14 @@ export class GeoText extends GeoPoint {
|
|||||||
this.textStyle = Object.assign(new PIXI.TextStyle(), opts.textStyle)
|
this.textStyle = Object.assign(new PIXI.TextStyle(), opts.textStyle)
|
||||||
this._text = new PIXI.Text(text, this.textStyle)
|
this._text = new PIXI.Text(text, this.textStyle)
|
||||||
|
|
||||||
|
//TODO: Make this more generic:
|
||||||
|
// We have 8 layers (12-20) for each map so this temporarily works fine.
|
||||||
|
// Outsource it to the map class.
|
||||||
|
//let textScale = Math.pow(2, 7)
|
||||||
|
|
||||||
|
// let textScale = 5
|
||||||
|
// this.text.scale.set(1 / textScale, 1 / textScale)
|
||||||
|
|
||||||
switch (this.align) {
|
switch (this.align) {
|
||||||
case 'left':
|
case 'left':
|
||||||
break
|
break
|
||||||
@ -719,3 +715,27 @@ export class GeoMultiShape extends GeoShape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PIXIUtils {
|
||||||
|
/*
|
||||||
|
* Transform a pixi text to it's actual screensize,
|
||||||
|
* ignoring it's local transforms
|
||||||
|
*/
|
||||||
|
static toScreenFontSize(pixiText, fontSize = null) {
|
||||||
|
pixiText._recursivePostUpdateTransform()
|
||||||
|
|
||||||
|
let normalizedScale = {
|
||||||
|
x: pixiText.scale.x / pixiText.transform.worldTransform.a,
|
||||||
|
y: pixiText.scale.x / pixiText.transform.worldTransform.d
|
||||||
|
}
|
||||||
|
|
||||||
|
pixiText.scale = { x: normalizedScale.x, y: normalizedScale.y }
|
||||||
|
if (fontSize) pixiText.style.fontSize = fontSize
|
||||||
|
}
|
||||||
|
|
||||||
|
static saveFill(graphics) {
|
||||||
|
return {
|
||||||
|
fill: graphics.fill.color,
|
||||||
|
alpha: graphics.fill.alpha
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,7 +6,8 @@ import { GeoGraphics, GeoShape, GeoMultiShape, GeoLine, GeoPoint } from './geogr
|
|||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @export
|
* @export
|
||||||
* @class
|
* @class GeoJsonGraphics
|
||||||
|
* @extends {GeoGraphics}
|
||||||
*/
|
*/
|
||||||
export default class GeoJson {
|
export default class GeoJson {
|
||||||
static isLineType(type) {
|
static isLineType(type) {
|
||||||
@ -58,6 +59,7 @@ export default class GeoJson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
list.push({ type, coordinates })
|
list.push({ type, coordinates })
|
||||||
|
// console.log({type, coordinates})
|
||||||
})
|
})
|
||||||
|
|
||||||
return list
|
return list
|
||||||
@ -121,7 +123,7 @@ export default class GeoJson {
|
|||||||
* considered valid. A complete list is provided in the GeoUtils.
|
* considered valid. A complete list is provided in the GeoUtils.
|
||||||
*
|
*
|
||||||
* @param {object} point - The point that is tested for validity.
|
* @param {object} point - The point that is tested for validity.
|
||||||
* @returns {boolean}
|
* @returns
|
||||||
* @memberof GeoJson
|
* @memberof GeoJson
|
||||||
*/
|
*/
|
||||||
static validateAndConvertPoint(point) {
|
static validateAndConvertPoint(point) {
|
||||||
@ -300,7 +302,7 @@ export class GeoUtils {
|
|||||||
* {latitude: lat, longitude: lng}
|
* {latitude: lat, longitude: lng}
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @param {object|array} coordinate - Coordinate to be tested, if it is an valid coordinate.
|
* @param {object / array} coordinate - Coordinate to be tested, if it is an valid coordinate.
|
||||||
* @returns - Returns the coordinate properly transformed. If transformation was not possible, it returns null.
|
* @returns - Returns the coordinate properly transformed. If transformation was not possible, it returns null.
|
||||||
* @memberof GeoGraphics
|
* @memberof GeoGraphics
|
||||||
*/
|
*/
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { GeoMap } from './map.js'
|
import { GeoMap } from './map.js'
|
||||||
|
import MapView from './mapview.js'
|
||||||
import { EventHandler } from './utils.js'
|
import { EventHandler } from './utils.js'
|
||||||
import { GeoGraphics } from './geographics.js'
|
import { GeoGraphics } from './geographics.js'
|
||||||
import { MapList } from './maplist.js'
|
import { MapList } from './maplist.js'
|
||||||
import MapViewport from './mapviewport.js'
|
//import { GeoGraphics } from "../pixi/geographics.js"
|
||||||
import { ScatterContainer } from '../scatter.js'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GeoLayer is a special PIXILayer, that recognizes other GeoLayers and
|
* The GeoLayer is a special PIXILayer, that recognizes other GeoLayers and
|
||||||
@ -93,13 +93,6 @@ export class GeoLayer {
|
|||||||
return this._visibility
|
return this._visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Alias for geoLayer.displayObject.addChild.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @param {GeoGraphics | PIXI.DisplayObject} element - Element to add to the displayObject.
|
|
||||||
* @memberof GeoLayer
|
|
||||||
*/
|
|
||||||
addChild(element) {
|
addChild(element) {
|
||||||
this.displayObject.addChild(element)
|
this.displayObject.addChild(element)
|
||||||
}
|
}
|
||||||
@ -124,6 +117,15 @@ export class GeoLayer {
|
|||||||
} else console.error('There was no map specified.', this)
|
} else console.error('There was no map specified.', this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// place(geographic) {
|
||||||
|
// if (geographic.constructor.name.startsWith('Geo') && geographic.graphics) {
|
||||||
|
// // Fix to remove the rollupjs circular dependency
|
||||||
|
// //if (geographic instanceof GeoGraphics) {
|
||||||
|
// this.geographics.push(geographic)
|
||||||
|
// super.place(geographic.graphics)
|
||||||
|
// } else super.place(geographic)
|
||||||
|
// }
|
||||||
|
|
||||||
removeFromParent() {
|
removeFromParent() {
|
||||||
if (this.parent) {
|
if (this.parent) {
|
||||||
this.parent.removeLayer(this)
|
this.parent.removeLayer(this)
|
||||||
@ -163,15 +165,8 @@ export class GeoLayer {
|
|||||||
return this._parent
|
return this._parent
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a GeoLayer as child to the GeoLayer.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @param {GeoLayer} layer - GeoLayer to add.
|
|
||||||
* @memberof GeoLayer
|
|
||||||
*/
|
|
||||||
addLayer(layer) {
|
addLayer(layer) {
|
||||||
if (layer instanceof GeoLayer) {
|
if (layer instanceof GeoLayer || layer instanceof MapLayer) {
|
||||||
layer.removeFromParent()
|
layer.removeFromParent()
|
||||||
|
|
||||||
this.layers.push(layer)
|
this.layers.push(layer)
|
||||||
@ -223,18 +218,6 @@ export class GeoLayer {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The map layer is responsible for showing certain maps, at a specific position It contains
|
|
||||||
* a list of available maps and can switch between them seamlessly. GeoGraphics placed on the MapLayer itself
|
|
||||||
* or child Geolayers will be adapted to maps and adjusted on map change automatically.
|
|
||||||
*
|
|
||||||
* The map layer is the 'king' of the geo layers. Every geolayer
|
|
||||||
* needs a map layer at it's root. Otherwise they won't work-
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class MapLayer
|
|
||||||
* @extends {GeoLayer}
|
|
||||||
*/
|
|
||||||
export class MapLayer extends GeoLayer {
|
export class MapLayer extends GeoLayer {
|
||||||
constructor(
|
constructor(
|
||||||
mapList,
|
mapList,
|
||||||
@ -264,7 +247,7 @@ export class MapLayer extends GeoLayer {
|
|||||||
listeners: onChange
|
listeners: onChange
|
||||||
})
|
})
|
||||||
|
|
||||||
this.mapview = new MapViewport({
|
this.mapview = new MapView({
|
||||||
zoom,
|
zoom,
|
||||||
focus,
|
focus,
|
||||||
viewport
|
viewport
|
||||||
@ -296,34 +279,22 @@ export class MapLayer extends GeoLayer {
|
|||||||
this._mapChangeLocked = false
|
this._mapChangeLocked = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapts all child layers and their GeoGraphics.
|
|
||||||
*
|
|
||||||
* This is called primarily on a map change.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @memberof MapLayer
|
|
||||||
*/
|
|
||||||
adapt() {
|
adapt() {
|
||||||
this.layers.forEach(layer => {
|
this.layers.forEach(layer => {
|
||||||
if (layer.adapt) layer.adapt(this.map)
|
if (layer.adapt) layer.adapt(this.map)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focus(coordinates, zoom) {
|
||||||
|
this.mapview.updateFocusPoint(this.map)
|
||||||
|
}
|
||||||
|
|
||||||
transformed(e) {
|
transformed(e) {
|
||||||
this.mapview.transformed(this.map)
|
this.mapview.transformed(this.map)
|
||||||
this.layers.forEach(layer => layer.parentMapLayerTransformed(this))
|
this.layers.forEach(layer => layer.parentMapLayerTransformed(this))
|
||||||
this.transformHandler.call(this)
|
this.transformHandler.call(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clones the map layer-
|
|
||||||
*
|
|
||||||
* @param {ScatterContainer} scatterContainer - ScatterContainer of the app.
|
|
||||||
* @param {PIXI.DisplayObject} [container=null] - Container of the newly created MapLayer. If null, an empty PIXI.Container will be created.
|
|
||||||
* @returns
|
|
||||||
* @memberof MapLayer
|
|
||||||
*/
|
|
||||||
clone(scatterContainer, container = null) {
|
clone(scatterContainer, container = null) {
|
||||||
let mapList = this.mapList.clone()
|
let mapList = this.mapList.clone()
|
||||||
container = container == null ? new PIXI.Container() : container
|
container = container == null ? new PIXI.Container() : container
|
||||||
@ -398,46 +369,23 @@ export class MapLayer extends GeoLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the mapviews focus to the map.
|
|
||||||
* This may be useful, if the container was modified.
|
|
||||||
*
|
|
||||||
* @memberof MapLayer
|
|
||||||
*/
|
|
||||||
refocus() {
|
refocus() {
|
||||||
this.mapview.apply(this.map)
|
this.mapview.apply(this.map)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
* @returns {GeoMap} - Returns the active map.
|
|
||||||
* @readonly
|
|
||||||
* @memberof MapLayer
|
|
||||||
*/
|
|
||||||
get map() {
|
get map() {
|
||||||
return this.mapList.map
|
return this.mapList.map
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* This is required for the consistency of georelated layers.
|
||||||
* This is required for the geo layers.
|
* The request traverses up to the mapLayer where it then returns
|
||||||
* MapLayer requests from the geoLayers traverse up to the next MapLayer.
|
* the responsible map layer.
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @returns {MapLayer} - Returns this MapLayer.
|
|
||||||
* @readonly
|
|
||||||
* @memberof MapLayer
|
|
||||||
*/
|
*/
|
||||||
get mapLayer() {
|
get mapLayer() {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleans up the MapLayer.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @memberof MapLayer
|
|
||||||
*/
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
this.mapList.cleanup()
|
this.mapList.cleanup()
|
||||||
}
|
}
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>PIXI Maps Doctests</title>
|
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
||||||
<meta name="viewport"
|
|
||||||
content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0" />
|
|
||||||
<link rel="stylesheet" href="../../../css/index.css">
|
|
||||||
|
|
||||||
<script src="../../../dist/iwmlib.js"></script>
|
|
||||||
|
|
||||||
<template id="itemTemplate">
|
|
||||||
<a class="wrapper" href="">
|
|
||||||
<div class="preview">
|
|
||||||
<div class="thumbnail-container">
|
|
||||||
<div class="thumbnail">
|
|
||||||
<img class="icon" src="thumbnails/notfound.png">
|
|
||||||
<!-- <iframe src="" frameborder="0"></iframe> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="title"></div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-size: 20px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#logo {
|
|
||||||
left: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#logo>img {
|
|
||||||
width: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header>h1 {
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.05em;
|
|
||||||
word-spacing: 0.25em;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
header>p {
|
|
||||||
max-width: 720px;
|
|
||||||
line-height: 1.5em;
|
|
||||||
color: rgb(207, 207, 207);
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
font-family: "Open Sans", sans-serif;
|
|
||||||
background-color: #4c4f4f;
|
|
||||||
color: whitesmoke;
|
|
||||||
|
|
||||||
padding: 68px 50px 10px 150px;
|
|
||||||
|
|
||||||
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
flex: 1;
|
|
||||||
height: auto;
|
|
||||||
min-height: auto;
|
|
||||||
width: auto;
|
|
||||||
min-width: auto;
|
|
||||||
|
|
||||||
margin: 0 60px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<a id="logo" target="_blank" href="http://www.iwm-tuebingen.de">
|
|
||||||
<img src="../../../assets/logos/iwm_logo_2015_twitter.png">
|
|
||||||
</a>
|
|
||||||
<h1>Maps Module</h1>
|
|
||||||
<p>The maps module provides a handy toolkit to easily integrate maps in an application. Create a full screen map
|
|
||||||
application by using the mapapp. Utilize the GeoLayer-system to integrate maps in an existing application.
|
|
||||||
Draw graphics onto the map using geographical positions instead of pixel positions with the GeoGraphics.
|
|
||||||
Or just use an Overlay to quickly draw icons for each point on a map.
|
|
||||||
</p>
|
|
||||||
</header>
|
|
||||||
<div id="container" class="container">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
const index = new Index(itemTemplate, [
|
|
||||||
["GeoGraphics", "geographics.html"],
|
|
||||||
["GeoJson", "geojson.html"],
|
|
||||||
["GeoMap", "map.html"],
|
|
||||||
["MapApp", "mapapp.html"],
|
|
||||||
["MapData", "mapdata.html"],
|
|
||||||
["MapViewport", "mapviewport.html"],
|
|
||||||
["Overlay", "overlay.html"],
|
|
||||||
["Scatter", "scatter.html"]
|
|
||||||
],
|
|
||||||
null)
|
|
||||||
index.load()
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -93,18 +93,10 @@ export class GeoMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
flushHandlers() {
|
flushHandlers() {
|
||||||
this.onLoad.empty()
|
// this.onLoaded
|
||||||
this.onTransform.empty()
|
this.onTransform.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Locks all transformations on the map.
|
|
||||||
* Single parameters can be set if necessary. False means the value is locked, true means they can be modified.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @param {object} [{ rotatable = false, translatable = false, movableX = false, movableY = false, scalable = false }={}]
|
|
||||||
* @memberof GeoMap
|
|
||||||
*/
|
|
||||||
lock({ rotatable = false, translatable = false, movableX = false, movableY = false, scalable = false } = {}) {
|
lock({ rotatable = false, translatable = false, movableX = false, movableY = false, scalable = false } = {}) {
|
||||||
if (this.image && this.image.scatter) {
|
if (this.image && this.image.scatter) {
|
||||||
this.image.scatter.translatable = rotatable
|
this.image.scatter.translatable = rotatable
|
||||||
@ -113,26 +105,30 @@ export class GeoMap {
|
|||||||
this.image.scatter.rotatable = movableY
|
this.image.scatter.rotatable = movableY
|
||||||
this.image.scatter.scalable = scalable
|
this.image.scatter.scalable = scalable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #001: This causes the map to not be displayed at the correct position on
|
||||||
|
// map change.
|
||||||
|
// // Rotation does not yet work with the cover mechanism.
|
||||||
|
// //this.rotatable = false
|
||||||
|
// this.translatable = false
|
||||||
|
// this.scalable = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlocks all transformations on the map.
|
|
||||||
* Single parameters can be set if necessary. False means the value is locked, true means they can be modified.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @param {object} [{ rotatable = false, translatable = false, movableX = false, movableY = false, scalable = false }={}]
|
|
||||||
* @memberof GeoMap
|
|
||||||
*/
|
|
||||||
unlock({ rotatable = true, translatable = true, movableX = true, movableY = true, scalable = true } = {}) {
|
unlock({ rotatable = true, translatable = true, movableX = true, movableY = true, scalable = true } = {}) {
|
||||||
this.lock({ rotatable, translatable, movableX, movableY, scalable })
|
if (this.image && this.image.scatter) {
|
||||||
|
this.image.scatter.translatable = translatable
|
||||||
|
this.image.scatter.movableX = movableX
|
||||||
|
this.image.scatter.movableY = movableY
|
||||||
|
this.image.scatter.rotatable = rotatable
|
||||||
|
this.image.scatter.scalable = scalable
|
||||||
|
}
|
||||||
|
// Issue #001
|
||||||
|
// // Rotation does not yet work with the cover mechanism.
|
||||||
|
// //this.rotatable = true
|
||||||
|
// this.translatable = true
|
||||||
|
// this.scalable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unloads the image of the map.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @memberof GeoMap
|
|
||||||
*/
|
|
||||||
unload() {
|
unload() {
|
||||||
if (this.image) {
|
if (this.image) {
|
||||||
if (this.image.parent) {
|
if (this.image.parent) {
|
||||||
@ -146,12 +142,6 @@ export class GeoMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the map, freeing all memory ba flushing handlers and removing the image.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @memberof GeoMap
|
|
||||||
*/
|
|
||||||
remove() {
|
remove() {
|
||||||
if (this.image) this.image.mask = null
|
if (this.image) this.image.mask = null
|
||||||
|
|
||||||
@ -185,6 +175,8 @@ export class GeoMap {
|
|||||||
this.image = image
|
this.image = image
|
||||||
if (frame) this.setFrame(frame)
|
if (frame) this.setFrame(frame)
|
||||||
|
|
||||||
|
let boundaries = this.mapdata.getBoundaries()
|
||||||
|
|
||||||
let scatterOpts = Object.assign({
|
let scatterOpts = Object.assign({
|
||||||
cover: this.cover,
|
cover: this.cover,
|
||||||
scaleable: this.scaleable,
|
scaleable: this.scaleable,
|
||||||
@ -194,6 +186,7 @@ export class GeoMap {
|
|||||||
startScale: this.startScale,
|
startScale: this.startScale,
|
||||||
minScale: this.minScale,
|
minScale: this.minScale,
|
||||||
maxScale: this.maxScale,
|
maxScale: this.maxScale,
|
||||||
|
boundaries,
|
||||||
onTransform: this.transformed.bind(this)
|
onTransform: this.transformed.bind(this)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -249,7 +242,7 @@ export class GeoMap {
|
|||||||
* to a coordinate with latitude and longitude.
|
* to a coordinate with latitude and longitude.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param {object} point - Point in form of {x, y}.
|
* @param {object} point - Point in form of {x: x_val, y: y_val}.
|
||||||
* @returns {object} - Coordinates on the map in form of {x: latitude, y: longitude}.
|
* @returns {object} - Coordinates on the map in form of {x: latitude, y: longitude}.
|
||||||
*/
|
*/
|
||||||
coordinatesFromPoint(point) {
|
coordinatesFromPoint(point) {
|
||||||
@ -261,7 +254,7 @@ export class GeoMap {
|
|||||||
* Transform coordinates in the map into pixel positions on the deep zoom image.
|
* Transform coordinates in the map into pixel positions on the deep zoom image.
|
||||||
*
|
*
|
||||||
* @param {object} coords - Coordinates of a map position in form {x: latitude, y: longitude}.
|
* @param {object} coords - Coordinates of a map position in form {x: latitude, y: longitude}.
|
||||||
* @return {Point} - Returns a image position in form of {x: x, y: y}.
|
* @return - Returns a image position in form of {x: x_val, y: y_val}.
|
||||||
*/
|
*/
|
||||||
coordinatesToPoint(coordinates) {
|
coordinatesToPoint(coordinates) {
|
||||||
return this.toAbsolutePixelCoordinates(this.mapdata.toPixel(coordinates))
|
return this.toAbsolutePixelCoordinates(this.mapdata.toPixel(coordinates))
|
||||||
|
@ -11,9 +11,6 @@ import { MapList } from './maplist.js'
|
|||||||
* MapApp is responsible for showing fullscreen
|
* MapApp is responsible for showing fullscreen
|
||||||
* map applications.
|
* map applications.
|
||||||
*
|
*
|
||||||
* @export
|
|
||||||
* @class MapApp
|
|
||||||
* @extends {PIXIApp}
|
|
||||||
*/
|
*/
|
||||||
export default class MapApp extends PIXIApp {
|
export default class MapApp extends PIXIApp {
|
||||||
constructor(opts = {}) {
|
constructor(opts = {}) {
|
||||||
@ -194,9 +191,9 @@ export default class MapApp extends PIXIApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectMap(key) {
|
selectMap(key) {
|
||||||
if (this.debug) console.log('Select map', key, result)
|
|
||||||
let result = this.mapList.select(key)
|
let result = this.mapList.select(key)
|
||||||
|
|
||||||
|
console.log('Select map', key, result)
|
||||||
if (result && this.mapLayer) {
|
if (result && this.mapLayer) {
|
||||||
this.mapLayer.changeMap(this.mapList.map)
|
this.mapLayer.changeMap(this.mapList.map)
|
||||||
}
|
}
|
||||||
@ -229,14 +226,6 @@ export default class MapApp extends PIXIApp {
|
|||||||
this.onTransform.call(this, event)
|
this.onTransform.call(this, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Called when the mapLayer changed the map.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {*} lastMap
|
|
||||||
* @memberof MapApp
|
|
||||||
*/
|
|
||||||
_mapChanged(lastMap) {
|
_mapChanged(lastMap) {
|
||||||
if (lastMap) {
|
if (lastMap) {
|
||||||
lastMap.flushHandlers()
|
lastMap.flushHandlers()
|
||||||
|
@ -14,7 +14,7 @@ export class MapData {
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @param {Projection}[projection] - Specifies the projection of the map (e.g. Mercator Projection).
|
* @param {Projection}[projection] - Specifies the projection of the map (e.g. Mercator Projection).
|
||||||
* @param {object}[opts] - Addiditonal options.
|
* @param {object}[opts] - Addiditonal options.
|
||||||
* @param {array}[opts.bounds] - Describes the minimum and maximum coordinates on the map in the form of {[[minLat, minLng],[maxLat, maxLng]]}.
|
* @param {[[minLat, minLng],[maxLat, maxLng]]}[opts.bounds] - Describes the minimum and maximum coordinates on the map
|
||||||
* @param {Point}[opts.translate] - Defines a translation, when clipping is not an option (e.g. when the whole world is shown, but translated.)
|
* @param {Point}[opts.translate] - Defines a translation, when clipping is not an option (e.g. when the whole world is shown, but translated.)
|
||||||
*/
|
*/
|
||||||
constructor(projection, opts = {}) {
|
constructor(projection, opts = {}) {
|
||||||
@ -52,7 +52,6 @@ export class MapData {
|
|||||||
/**
|
/**
|
||||||
* Transforms a pixel point on the map to a geographical coordinate.
|
* Transforms a pixel point on the map to a geographical coordinate.
|
||||||
*
|
*
|
||||||
* @public
|
|
||||||
* @param {{x,y} | PIXI.Point} point - A pixel position on the map.
|
* @param {{x,y} | PIXI.Point} point - A pixel position on the map.
|
||||||
* @returns {{x,y} | PIXI.Point} - A geographical coordinate.
|
* @returns {{x,y} | PIXI.Point} - A geographical coordinate.
|
||||||
* @memberof MapData
|
* @memberof MapData
|
||||||
@ -85,7 +84,6 @@ export class MapData {
|
|||||||
/**
|
/**
|
||||||
* Transform a geographical coordinate to a pixel point on the map.
|
* Transform a geographical coordinate to a pixel point on the map.
|
||||||
*
|
*
|
||||||
* @public
|
|
||||||
* @param {{x,y} | PIXI.Point} coordinates - A point in the form of {x:lat,y:lng}.
|
* @param {{x,y} | PIXI.Point} coordinates - A point in the form of {x:lat,y:lng}.
|
||||||
* @returns {{x,y} | PIXI.Point} point - A pixel position on the map.
|
* @returns {{x,y} | PIXI.Point} point - A pixel position on the map.
|
||||||
* @memberof MapData
|
* @memberof MapData
|
||||||
@ -118,18 +116,6 @@ export class MapData {
|
|||||||
return point
|
return point
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get's the clipping of the map data. Clipping describes the
|
|
||||||
* piece of the map that is shown. E.g. if we just show a map of
|
|
||||||
* europe, then we have to set the clipping properly, otherwise
|
|
||||||
* the preojection would produce the wrong results when transforming
|
|
||||||
* from a point to coordinates or the other way around.
|
|
||||||
*
|
|
||||||
* @readonly
|
|
||||||
* @memberof MapData
|
|
||||||
* @returns {object} - Object that contains a min and max value of the clipping in form of: {min: {x,y}, max:{x,y}}. Where x and y are in between 0 and 1.
|
|
||||||
*/
|
|
||||||
get clip() {
|
get clip() {
|
||||||
let unclipped = {
|
let unclipped = {
|
||||||
min: { x: 0, y: 0 },
|
min: { x: 0, y: 0 },
|
||||||
@ -139,30 +125,30 @@ export class MapData {
|
|||||||
return this.opts.clip ? this.opts.clip : unclipped
|
return this.opts.clip ? this.opts.clip : unclipped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the biggest viewport the mapdata allows.
|
* Bounds to pixel transforms some bounds in form of {min:{x:minLat, y:minLng},max:{x:maxLat, y:maxLng}}
|
||||||
* This is determined by the projecton or the clipping on the mapapp.
|
* to pixel coordinates.
|
||||||
*
|
*
|
||||||
* @readonly
|
|
||||||
* @memberof MapData
|
|
||||||
*/
|
*/
|
||||||
|
getBoundaries() {
|
||||||
|
// let min = this.toPixel(bounds.min)
|
||||||
|
// let max = this.toPixel(bounds.max)
|
||||||
|
|
||||||
|
// Y values needs to be swapped, as PIXI has it's origin
|
||||||
|
// in the top-left corner and a regular map in the bottom-left corner.
|
||||||
|
let boundaries = {
|
||||||
|
min: { x: 0, y: 0 },
|
||||||
|
max: { x: 1, y: 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
return boundaries
|
||||||
|
}
|
||||||
|
|
||||||
get maxViewport() {
|
get maxViewport() {
|
||||||
return this.opts.clip ? this.opts.clip : this.projection.maxViewport
|
return this.opts.clip ? this.opts.clip : this.projection.maxViewport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Special mapdata for DeepZoomMap objects.
|
|
||||||
*
|
|
||||||
* Note: It just transform the clipping parameter of the tiles config
|
|
||||||
* to the clipping of the mapapp.
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class DeepZoomMapData
|
|
||||||
* @extends {MapData}
|
|
||||||
*/
|
|
||||||
export class DeepZoomMapData extends MapData {
|
export class DeepZoomMapData extends MapData {
|
||||||
constructor(projection, tilesConfig, opts = {}) {
|
constructor(projection, tilesConfig, opts = {}) {
|
||||||
if (tilesConfig.clip) {
|
if (tilesConfig.clip) {
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
/**
|
|
||||||
* MapList is a list of maps with one active index.
|
|
||||||
* It contains some utility functions to change the map.
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class MapList
|
|
||||||
*/
|
|
||||||
export class MapList {
|
export class MapList {
|
||||||
constructor(active = null, maps = {}) {
|
constructor(active = null, maps = {}) {
|
||||||
this.maps = maps
|
this.maps = maps
|
||||||
@ -16,9 +9,8 @@ export class MapList {
|
|||||||
/**
|
/**
|
||||||
* Selects a map from the map list.
|
* Selects a map from the map list.
|
||||||
*
|
*
|
||||||
* @public
|
|
||||||
* @param {string} active - Name of the map to select.
|
* @param {string} active - Name of the map to select.
|
||||||
* @returns {Map} - Returns the active map. Returns null if no map was added to the MapList.
|
* @returns
|
||||||
* @memberof MapList
|
* @memberof MapList
|
||||||
*/
|
*/
|
||||||
select(active) {
|
select(active) {
|
||||||
@ -48,13 +40,6 @@ export class MapList {
|
|||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clones the entire maplist.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @returns {MapList} - Returns a cloned instance of this map list.
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
clone() {
|
clone() {
|
||||||
let maps = {}
|
let maps = {}
|
||||||
|
|
||||||
@ -65,14 +50,6 @@ export class MapList {
|
|||||||
return new MapList(this.active, maps)
|
return new MapList(this.active, maps)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new map to the map list.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @param {string} key - Key to identify the map.
|
|
||||||
* @param {GeoMap} map - The GeoMap to add.
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
add(key, map) {
|
add(key, map) {
|
||||||
if (this.maps[key] != null) consol.warn('Key already in mapList. The existing key was overwritten.')
|
if (this.maps[key] != null) consol.warn('Key already in mapList. The existing key was overwritten.')
|
||||||
if (this.active == null) this.active = key
|
if (this.active == null) this.active = key
|
||||||
@ -80,25 +57,10 @@ export class MapList {
|
|||||||
this.maps[key] = map
|
this.maps[key] = map
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the the active map.
|
|
||||||
* If none is set, it returns null.
|
|
||||||
*
|
|
||||||
*@public
|
|
||||||
* @readonly
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
get map() {
|
get map() {
|
||||||
return this.maps && this.maps[this.active] ? this.maps[this.active] : null
|
return this.maps && this.maps[this.active] ? this.maps[this.active] : null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects the next map in the map array.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @returns {GeoMap} - Returns the next map in the list.
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
next() {
|
next() {
|
||||||
let keys = Object.keys(this.maps)
|
let keys = Object.keys(this.maps)
|
||||||
let idx = keys.indexOf(this.active)
|
let idx = keys.indexOf(this.active)
|
||||||
@ -107,13 +69,6 @@ export class MapList {
|
|||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all maps from the maplist.
|
|
||||||
* And cleans up all maps.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
* @memberof MapList
|
|
||||||
*/
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
for (let key in this.maps) {
|
for (let key in this.maps) {
|
||||||
let map = this.maps[key]
|
let map = this.maps[key]
|
||||||
|
@ -6,7 +6,7 @@ import { DeepZoomMap } from './map.js'
|
|||||||
* It ensures, that maps can be changed, without the user noticing it.
|
* It ensures, that maps can be changed, without the user noticing it.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export default class MapViewport {
|
export default class MapView {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {object} [focus = {x:0, y:0}] - Defines the startup focuspoint of the app.
|
* @param {object} [focus = {x:0, y:0}] - Defines the startup focuspoint of the app.
|
@ -1,163 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" class="dark-mode">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>MapViewport</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>
|
|
||||||
.controls {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body onload="Doctest.run()">
|
|
||||||
<h1>MapViewport</h1>
|
|
||||||
<p>
|
|
||||||
The MapViewport works under the hood of a map layer to track the informations about the current focus point and
|
|
||||||
zoom position.
|
|
||||||
This is important to maintain the same view when maps are changed.
|
|
||||||
</p>
|
|
||||||
<canvas id="canvas"></canvas>
|
|
||||||
<div id="mapControl"></div>
|
|
||||||
<div id="cityControl" class="controls"></div>
|
|
||||||
<p><strong>WHAT TO SEE:</strong> The map should focus Paris.</p>
|
|
||||||
<script>
|
|
||||||
let osmConfig = {
|
|
||||||
"projection": "mercator",
|
|
||||||
"type": "deepzoom",
|
|
||||||
"tiles": {
|
|
||||||
"tileSize": 256,
|
|
||||||
"format": "png",
|
|
||||||
"overlap": 0,
|
|
||||||
"type": "map",
|
|
||||||
"height": 1024,
|
|
||||||
"width": 1024,
|
|
||||||
"path": "../assets/maps/osm",
|
|
||||||
"urlTileTemplate": "{path}/{level}/{row}/{column}.{format}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let testConfig = {
|
|
||||||
"projection": "mercator",
|
|
||||||
"type": "deepzoom",
|
|
||||||
"tiles": {
|
|
||||||
"tileSize": 128,
|
|
||||||
"format": "jpg",
|
|
||||||
"overlap": 0,
|
|
||||||
"type": "map",
|
|
||||||
"height": 4096,
|
|
||||||
"width": 4096,
|
|
||||||
"path": "../assets/maps/test",
|
|
||||||
"urlTileTemplate": "{path}/{level}/{row}/{column}.{format}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<script class="doctest">
|
|
||||||
let capitals = {
|
|
||||||
london: { x: 51.5, y: -0.083333 },
|
|
||||||
rome: { x: 41.9, y: 12.483333 },
|
|
||||||
madrid: { x: 40.4, y: -3.683333 },
|
|
||||||
paris: { x: 48.833986, y: 2.346989 }
|
|
||||||
}
|
|
||||||
|
|
||||||
// You may define a focus point ...
|
|
||||||
let focus = capitals.paris
|
|
||||||
|
|
||||||
// ... and a zoom level.
|
|
||||||
let zoom = 1
|
|
||||||
|
|
||||||
// Name has to be app (like all other PIXIApps).
|
|
||||||
const app = (window.app = new MapApp({
|
|
||||||
focus,
|
|
||||||
zoom,
|
|
||||||
view: canvas,
|
|
||||||
coordsLogging: true,
|
|
||||||
width: 512,
|
|
||||||
height: 512
|
|
||||||
}))
|
|
||||||
|
|
||||||
// As map an image of europe is used.
|
|
||||||
let europe = '../assets/maps/pixabay/europe.jpg'
|
|
||||||
|
|
||||||
//Preload all required sprites for the image map.
|
|
||||||
app.loadSprites([europe], sprites => ready(sprites), {
|
|
||||||
resolutionDependent: false
|
|
||||||
})
|
|
||||||
|
|
||||||
// The mapdata object contains informations,
|
|
||||||
// how the displayed map has to be interpreted.
|
|
||||||
// e.g. which projection is used or how the
|
|
||||||
// image is clipped.
|
|
||||||
let europeData = new MapData(new Projection.Mercator(), {
|
|
||||||
clip: {
|
|
||||||
min: { x: 32.863294, y: -18.58 },
|
|
||||||
max: { x: 57.467973, y: 44.277158 }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
function ready(sprites) {
|
|
||||||
|
|
||||||
const cover = true
|
|
||||||
|
|
||||||
// When resources are loaded, the ImageMap can be instantiated.
|
|
||||||
let imageMap = new ImageMap(sprites.get(europe), europeData, {
|
|
||||||
coordsLogging: true,
|
|
||||||
maxScale: 1,
|
|
||||||
cover
|
|
||||||
})
|
|
||||||
|
|
||||||
let testMapData = new DeepZoomMapData(new Projection.Mercator(), testConfig.tiles, {
|
|
||||||
app
|
|
||||||
})
|
|
||||||
let testMap = new DeepZoomMap(testMapData, Object.assign({}, testConfig.tiles, { app }), { cover })
|
|
||||||
app.addMap("test", testMap)
|
|
||||||
|
|
||||||
let osmMapData = new DeepZoomMapData(new Projection.Mercator(), osmConfig.tiles, {
|
|
||||||
app
|
|
||||||
})
|
|
||||||
let deepZoomMap = new DeepZoomMap(osmMapData, Object.assign({}, osmConfig.tiles, { app }), { cover })
|
|
||||||
app.addMap("osm", deepZoomMap)
|
|
||||||
|
|
||||||
// Finally apply the map to the MapApp
|
|
||||||
app.setMap('europe', imageMap)
|
|
||||||
|
|
||||||
// The app requires a map before beeing able to run.
|
|
||||||
// So start the app here.
|
|
||||||
app.setup().run()
|
|
||||||
|
|
||||||
for (let [key, val] of Object.entries(app.mapList.maps)) {
|
|
||||||
let mapBtn = document.createElement("button")
|
|
||||||
mapBtn.innerText = key
|
|
||||||
mapBtn.addEventListener("click", () => {
|
|
||||||
app.mapLayer.changeMap(val)
|
|
||||||
})
|
|
||||||
mapControl.appendChild(mapBtn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let [key, val] of Object.entries(capitals)) {
|
|
||||||
let cityBtn = document.createElement("button")
|
|
||||||
cityBtn.innerText = key
|
|
||||||
cityBtn.addEventListener("click", () => {
|
|
||||||
app.mapLayer.map.moveTo(val)
|
|
||||||
})
|
|
||||||
cityControl.appendChild(cityBtn)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
Binary file not shown.
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 184 KiB |
Loading…
x
Reference in New Issue
Block a user