From 87727d28b9927fb4a2dda9c87b93b98f260a59b9 Mon Sep 17 00:00:00 2001 From: Severin Opel Date: Tue, 5 Nov 2019 11:07:36 +0100 Subject: [PATCH] Geographics placements working again. --- dist/iwmlib.pixi.js | 253 +++++++++++++++++++-------------- lib/pixi/bundle.js | 6 +- lib/pixi/maps/geographics.html | 7 +- lib/pixi/maps/geolayer.js | 121 +++++----------- lib/pixi/maps/map.js | 10 +- lib/pixi/maps/mapapp.js | 59 +++++--- lib/pixi/maps/maplist.js | 62 ++++++++ lib/pixi/maps/mapview.js | 1 + 8 files changed, 297 insertions(+), 222 deletions(-) create mode 100644 lib/pixi/maps/maplist.js diff --git a/dist/iwmlib.pixi.js b/dist/iwmlib.pixi.js index 35b0415..46847f5 100644 --- a/dist/iwmlib.pixi.js +++ b/dist/iwmlib.pixi.js @@ -17791,8 +17791,13 @@ } unload() { + console.log('unload', this, this.image); if (this.image) { - if (this.image.parent) this.image.parent.removeChild(this.image); + console.log('removeScatter'); + if (this.image.parent) { + console.log('Remove from parent'); + this.image.parent.removeChild(this.image); + } this.image.scatter = null; } } @@ -17804,6 +17809,7 @@ * @param {ScatterEvent}[e] - Contains informations on how the element was transformed. */ transformed(e) { + console.log(this.name); this.onTransform.call(this, e); } @@ -18157,8 +18163,6 @@ return null } } - - } GeoMap.counter = 0; @@ -18607,6 +18611,7 @@ } transformed(map) { + console.log('MAPVIEW RECEIVED TRANSFORM'); this.updateZoom(map); this.updateFocusPoint(map); } @@ -19656,20 +19661,20 @@ ); return null } else { + this.geographics = []; displayObject.map = this; this.displayObject = displayObject; this.layers = []; - this.geographics = []; - let pixiAddChild = displayObject.addChild.bind(displayObject); + this.pixiAddChild = displayObject.addChild.bind(displayObject); displayObject.addChild = (...elements) => { elements.forEach(element => { if (element instanceof GeoGraphics) { this.geographics.push(element); - pixiAddChild(element.graphics); + this.pixiAddChild(element.graphics); } else { - pixiAddChild(element); + this.pixiAddChild(element); } }); }; @@ -19747,59 +19752,6 @@ // } } - class MapList { - constructor(active, maps) { - this.maps = maps; - this.active = active; - - if (Object.keys(maps).length > 0) this.select(active); - } - - /** - * Selects a map from the map list. - * - * @param {string} active - Name of the map to select. - * @returns - * @memberof MapList - */ - select(active) { - let map = null; - - if (active !== this.active) { - let keys = Object.keys(this.maps); - if (keys.length > 0) { - if (this.maps[active] == null) { - let altActive = keys[0]; - console.warn( - `The MapList does not contain the provided active key '${active}'. Used '${altActive}' as fallback.` - ); - - active = altActive; - } - - if (this.active !== active) { - this.active = active; - map = this.maps[active]; - } - } else { - console.error(`Could not provide a fallback map! The map object is empty.`); - } - } - - return map - } - - add(key, map) { - if (this.maps[key] != null) consol.warn('Key already in mapList. The existing key was overwritten.'); - this.maps[key] = map; - } - - get map() { - console.log(this.maps, this.active); - return this.maps[this.active] - } - } - class MapLayer extends GeoLayer { constructor( scatterContainer, @@ -19884,27 +19836,6 @@ // } // } - placeMap(map) { - if (map instanceof GeoMap) { - this.scatterContainer.addChild(map.image); - this.map.onTransform.add(this.transformed.bind(this)); - this.mapview.update(this.map); - - this.adapt(); - } else { - console.error("Could not set map, it's not of type GeoMap.", map); - } - } - - placeElement(elem) { - if (elem instanceof PIXI.DisplayObject) { - this.map.image.addChild(elem); - this.elements.push(elem); - } else { - console.error('Element need to be of type PIXI.DisplayObject.', elem); - } - } - transformed(e) { this.mapview.transformed(this.map); this.transformHandler.call(this); @@ -19929,18 +19860,39 @@ return mapLayerClone } + /** + * Changes the map to the specified one, keeping the position and the zoom of the old map. + * + * @public + * @param {GeoMap} map + * @memberof MapLayer + */ changeMap( - 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. + 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.*/ ) { - let oldMap = map; - this._map = map; + if (map instanceof GeoMap) { + let oldMap = this.map; + if (oldMap) oldMap.unload(); - if (oldMap) oldMap.unload(); - map.load(); + this._map = map; - this.changeHandler.call(this, map, oldMap); - this.placeMap(map); + this.map.load(); + this.scatterContainer.addChild(this.map.image); + + map.image.addChild(this.displayObject); + this.mapview.update(this.map); + + // A geolayer's displayObject is on the parent layer. + // A maplayer's displayobject is always the child of the map. + this.adapt(); + + this.changeHandler.call(this, map, oldMap); + this.map.onTransform.add(this.transformed.bind(this)); + + } else { + console.error("Could not set map, it's not of type GeoMap.", map); + } /*Logging.log(`Map change: ${key}`) @@ -20007,8 +19959,6 @@ get mapLayer() { return this } - - } MapLayer.idx = 0; @@ -20667,6 +20617,69 @@ } } + class MapList { + constructor(active, maps) { + this.maps = maps; + this.active = active; + + if (Object.keys(maps).length > 0) this.select(active); + } + + /** + * Selects a map from the map list. + * + * @param {string} active - Name of the map to select. + * @returns + * @memberof MapList + */ + select(active) { + let map = null; + + if (active !== this.active) { + let keys = Object.keys(this.maps); + if (keys.length > 0) { + if (this.maps[active] == null) { + let altActive = keys[0]; + console.warn( + `The MapList does not contain the provided active key '${active}'. Used '${altActive}' as fallback.` + ); + + active = altActive; + } + + if (this.active !== active) { + this.active = active; + map = this.maps[active]; + } + } else { + console.error(`Could not provide a fallback map! The map object is empty.`); + } + } + + return map + } + + add(key, map) { + if (this.maps[key] != null) consol.warn('Key already in mapList. The existing key was overwritten.'); + map.name = key; + this.maps[key] = map; + } + + get map() { + console.log(this.maps, this.active); + return this.maps[this.active] + } + + next() { + let keys = Object.keys(this.maps); + let idx = keys.indexOf(this.active); + + let next = idx + 1 < key.length ? keys[idx + 1] : keys[0]; + console.log(keys, idx, next); + return next + } + } + /** * MapApp is responsible for showing fullscreen * map applications. @@ -20681,7 +20694,8 @@ { debug: false, maps: {}, //required - view: null, + view: null, //required + wrapper: null, // Required if you want to use DOM Overlays. startmap: null, coordsLogging: false, overlays: {}, @@ -20709,6 +20723,7 @@ this.overlays = opts.overlays; this.focus = opts.focus; this.zoom = opts.zoom; + this.wrapper = opts.wrapper; this.onMapChanged = new EventHandler('mapChanged', { listeners: opts.onMapChanged @@ -20774,25 +20789,16 @@ container: this.scene }); - this.domLayer = new DOMLayer({ - name: 'DOM Root', - container: document.body - }); - this._setupMapLayer(); - this.pixiLayer.place(this.mapContainer); - this.pixiUiLayer = new PIXILayer({ name: 'Pixi UI' }); - this.pixiLayer.placeLayer(this.pixiUiLayer); + this.ui = new PIXI.Container(); + this.scene.addChild(this.ui); - this.domUiLayer = new DOMLayer({ name: 'DOM UI' }); - this.domLayer.placeLayer(this.domUiLayer); - - if (this.fpsLogging && fpsDisplay) this.pixiUiLayer.place(fpsDisplay); + if (this.fpsLogging && fpsDisplay) this.ui.addChild(fpsDisplay); if (this.coordsLogging) { this.coordsDisplay = new CoordinateDisplay(this); - this.pixiUiLayer.place(this.coordsDisplay); + this.ui.addChild(this.coordsDisplay); } this.__dragging = false; @@ -20810,6 +20816,29 @@ return this } + /** + * You can add Dom elements directly to the app's DomLayer by calling + * appendChild(). The elements will be forced to use an absolute positioning. + * This shall prevent unwanted sideeffects with the app. + * + * @param {HTMLElement} element - Element to add to DOMRoot. + * @memberof MapApp + */ + appendChild(element) { + if (!this.wrapper) + console.error( + `When using DOMElements on ${this.constructor.name} you must specify a wrapper in the constructor.` + ); + if (!(element instanceof HTMLElement)) + console.error( + 'You can only append HTMLElements to DOM. If you want to add PIXI elements to the scene call app.scene.addChild(element).' + ); + else { + Object.assign(element.style, { position: 'absolute' }); + this.wrapper.appendChild(element); + } + } + layout(width, height) { this.scene.resize(width, height); this.mapLayer.mapview.update(); @@ -20827,8 +20856,9 @@ } selectMap(key) { - this.mapList.select(key); - if (this.mapLayer) { + let result = this.mapList.select(key); + console.log('Select map', key, result); + if (result && this.mapLayer) { this.mapLayer.changeMap(this.mapList.map); } } @@ -20885,6 +20915,13 @@ this.transformed(); this.onMapChanged.call(this, this.map); + + if (this.ui && this.ui.parent) { + const parent = this.ui.parent; + parent.removeChild(this.ui); + parent.addChild(this.ui); + console.log('BRING TO FRONT!'); + } } _doesOverlayElementExist(layer, type, name) { @@ -22159,7 +22196,6 @@ window.CoverScatter = CoverScatter; window.GeoLayer = GeoLayer; window.MapLayer = MapLayer; - window.MapList = MapList; window.GeoGraphics = GeoGraphics; window.GeoPoint = GeoPoint; @@ -22168,5 +22204,6 @@ window.GeoMultiShape = GeoMultiShape; window.Overlay = Overlay; + window.MapList = MapList; }()); diff --git a/lib/pixi/bundle.js b/lib/pixi/bundle.js index ad2861f..5e331c1 100755 --- a/lib/pixi/bundle.js +++ b/lib/pixi/bundle.js @@ -93,10 +93,9 @@ window.RigidContainer = RigidContainer window.CompactScatter = CompactScatter window.CoverScatter = CoverScatter -import { GeoLayer, MapLayer, MapList } from './maps/geolayer.js' +import { GeoLayer, MapLayer } from './maps/geolayer.js' window.GeoLayer = GeoLayer window.MapLayer = MapLayer -window.MapList = MapList import { GeoGraphics, GeoPoint, GeoLine, GeoShape, GeoMultiShape } from './maps/geographics.js' @@ -109,3 +108,6 @@ window.GeoMultiShape = GeoMultiShape import Overlay from './maps/overlay.js' window.Overlay = Overlay + +import { MapList } from './maps/maplist.js' +window.MapList = MapList \ No newline at end of file diff --git a/lib/pixi/maps/geographics.html b/lib/pixi/maps/geographics.html index 5c44ebf..2cc9a28 100644 --- a/lib/pixi/maps/geographics.html +++ b/lib/pixi/maps/geographics.html @@ -88,9 +88,8 @@ function enableSwitch(button, app) { button.addEventListener("click", () => { - let next = (app.activeMapKey == "osm") ? "wiki" : "osm" - console.log("CLICKED") - + let next = app.mapList.next() + console.log(app.mapList) app.selectMap(next) }) } @@ -292,4 +291,4 @@ --> - \ No newline at end of file + \ No newline at end of file diff --git a/lib/pixi/maps/geolayer.js b/lib/pixi/maps/geolayer.js index c4a3d35..51397b1 100644 --- a/lib/pixi/maps/geolayer.js +++ b/lib/pixi/maps/geolayer.js @@ -21,20 +21,20 @@ export class GeoLayer { ) return null } else { + this.geographics = [] displayObject.map = this this.displayObject = displayObject this.layers = [] - this.geographics = [] - let pixiAddChild = displayObject.addChild.bind(displayObject) + this.pixiAddChild = displayObject.addChild.bind(displayObject) displayObject.addChild = (...elements) => { elements.forEach(element => { if (element instanceof GeoGraphics) { this.geographics.push(element) - pixiAddChild(element.graphics) + this.pixiAddChild(element.graphics) } else { - pixiAddChild(element) + this.pixiAddChild(element) } }) } @@ -112,59 +112,6 @@ export class GeoLayer { // } } -export class MapList { - constructor(active, maps) { - this.maps = maps - this.active = active - - if (Object.keys(maps).length > 0) this.select(active) - } - - /** - * Selects a map from the map list. - * - * @param {string} active - Name of the map to select. - * @returns - * @memberof MapList - */ - select(active) { - let map = null - - if (active !== this.active) { - let keys = Object.keys(this.maps) - if (keys.length > 0) { - if (this.maps[active] == null) { - let altActive = keys[0] - console.warn( - `The MapList does not contain the provided active key '${active}'. Used '${altActive}' as fallback.` - ) - - active = altActive - } - - if (this.active !== active) { - this.active = active - map = this.maps[active] - } - } else { - console.error(`Could not provide a fallback map! The map object is empty.`) - } - } - - return map - } - - add(key, map) { - if (this.maps[key] != null) consol.warn('Key already in mapList. The existing key was overwritten.') - this.maps[key] = map - } - - get map() { - console.log(this.maps, this.active) - return this.maps[this.active] - } -} - export class MapLayer extends GeoLayer { constructor( scatterContainer, @@ -249,27 +196,6 @@ export class MapLayer extends GeoLayer { // } // } - placeMap(map) { - if (map instanceof GeoMap) { - this.scatterContainer.addChild(map.image) - this.map.onTransform.add(this.transformed.bind(this)) - this.mapview.update(this.map) - - this.adapt() - } else { - console.error("Could not set map, it's not of type GeoMap.", map) - } - } - - placeElement(elem) { - if (elem instanceof PIXI.DisplayObject) { - this.map.image.addChild(elem) - this.elements.push(elem) - } else { - console.error('Element need to be of type PIXI.DisplayObject.', elem) - } - } - transformed(e) { this.mapview.transformed(this.map) this.transformHandler.call(this) @@ -294,18 +220,39 @@ export class MapLayer extends GeoLayer { return mapLayerClone } + /** + * Changes the map to the specified one, keeping the position and the zoom of the old map. + * + * @public + * @param {GeoMap} map + * @memberof MapLayer + */ changeMap( - 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. + 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.*/ ) { - let oldMap = map - this._map = map + if (map instanceof GeoMap) { + let oldMap = this.map + if (oldMap) oldMap.unload() - if (oldMap) oldMap.unload() - map.load() + this._map = map - this.changeHandler.call(this, map, oldMap) - this.placeMap(map) + this.map.load() + this.scatterContainer.addChild(this.map.image) + + map.image.addChild(this.displayObject) + this.mapview.update(this.map) + + // A geolayer's displayObject is on the parent layer. + // A maplayer's displayobject is always the child of the map. + this.adapt() + + this.changeHandler.call(this, map, oldMap) + this.map.onTransform.add(this.transformed.bind(this)) + + } else { + console.error("Could not set map, it's not of type GeoMap.", map) + } /*Logging.log(`Map change: ${key}`) @@ -372,8 +319,6 @@ export class MapLayer extends GeoLayer { get mapLayer() { return this } - - } MapLayer.idx = 0 diff --git a/lib/pixi/maps/map.js b/lib/pixi/maps/map.js index 29d5b07..333cf37 100644 --- a/lib/pixi/maps/map.js +++ b/lib/pixi/maps/map.js @@ -130,8 +130,13 @@ export class GeoMap { } unload() { + console.log('unload', this, this.image) if (this.image) { - if (this.image.parent) this.image.parent.removeChild(this.image) + console.log('removeScatter') + if (this.image.parent) { + console.log('Remove from parent') + this.image.parent.removeChild(this.image) + } this.image.scatter = null } } @@ -143,6 +148,7 @@ export class GeoMap { * @param {ScatterEvent}[e] - Contains informations on how the element was transformed. */ transformed(e) { + console.log(this.name) this.onTransform.call(this, e) } @@ -496,8 +502,6 @@ export class GeoMap { return null } } - - } GeoMap.counter = 0 diff --git a/lib/pixi/maps/mapapp.js b/lib/pixi/maps/mapapp.js index 9186f9b..983d82c 100644 --- a/lib/pixi/maps/mapapp.js +++ b/lib/pixi/maps/mapapp.js @@ -1,11 +1,12 @@ import PIXIApp from '../app.js' import { CoordinateDisplay } from '../../../../js/display.js' import { DOMLayer, PIXILayer } from '../../../../src/layers/js/layer.js' -import { MapLayer, MapList } from './geolayer.js' +import { MapLayer } from './geolayer.js' import { RigidScatterContainer } from './scatter.js' import { EventHandler } from './utils.js' import { Points } from '../../utils.js' import Logging from '../../logging.js' +import { MapList } from './maplist.js' /** * MapApp is responsible for showing fullscreen @@ -21,7 +22,8 @@ export default class MapApp extends PIXIApp { { debug: false, maps: {}, //required - view: null, + view: null, //required + wrapper: null, // Required if you want to use DOM Overlays. startmap: null, coordsLogging: false, overlays: {}, @@ -49,6 +51,7 @@ export default class MapApp extends PIXIApp { this.overlays = opts.overlays this.focus = opts.focus this.zoom = opts.zoom + this.wrapper = opts.wrapper this.onMapChanged = new EventHandler('mapChanged', { listeners: opts.onMapChanged @@ -114,25 +117,16 @@ export default class MapApp extends PIXIApp { container: this.scene }) - this.domLayer = new DOMLayer({ - name: 'DOM Root', - container: document.body - }) - this._setupMapLayer() - this.pixiLayer.place(this.mapContainer) - this.pixiUiLayer = new PIXILayer({ name: 'Pixi UI' }) - this.pixiLayer.placeLayer(this.pixiUiLayer) + this.ui = new PIXI.Container() + this.scene.addChild(this.ui) - this.domUiLayer = new DOMLayer({ name: 'DOM UI' }) - this.domLayer.placeLayer(this.domUiLayer) - - if (this.fpsLogging && fpsDisplay) this.pixiUiLayer.place(fpsDisplay) + if (this.fpsLogging && fpsDisplay) this.ui.addChild(fpsDisplay) if (this.coordsLogging) { this.coordsDisplay = new CoordinateDisplay(this) - this.pixiUiLayer.place(this.coordsDisplay) + this.ui.addChild(this.coordsDisplay) } this.__dragging = false @@ -150,6 +144,29 @@ export default class MapApp extends PIXIApp { return this } + /** + * You can add Dom elements directly to the app's DomLayer by calling + * appendChild(). The elements will be forced to use an absolute positioning. + * This shall prevent unwanted sideeffects with the app. + * + * @param {HTMLElement} element - Element to add to DOMRoot. + * @memberof MapApp + */ + appendChild(element) { + if (!this.wrapper) + console.error( + `When using DOMElements on ${this.constructor.name} you must specify a wrapper in the constructor.` + ) + if (!(element instanceof HTMLElement)) + console.error( + 'You can only append HTMLElements to DOM. If you want to add PIXI elements to the scene call app.scene.addChild(element).' + ) + else { + Object.assign(element.style, { position: 'absolute' }) + this.wrapper.appendChild(element) + } + } + layout(width, height) { this.scene.resize(width, height) this.mapLayer.mapview.update() @@ -167,8 +184,9 @@ export default class MapApp extends PIXIApp { } selectMap(key) { - this.mapList.select(key) - if (this.mapLayer) { + let result = this.mapList.select(key) + console.log('Select map', key, result) + if (result && this.mapLayer) { this.mapLayer.changeMap(this.mapList.map) } } @@ -225,6 +243,13 @@ export default class MapApp extends PIXIApp { this.transformed() this.onMapChanged.call(this, this.map) + + if (this.ui && this.ui.parent) { + const parent = this.ui.parent + parent.removeChild(this.ui) + parent.addChild(this.ui) + console.log('BRING TO FRONT!') + } } _doesOverlayElementExist(layer, type, name) { diff --git a/lib/pixi/maps/maplist.js b/lib/pixi/maps/maplist.js new file mode 100644 index 0000000..afd2df2 --- /dev/null +++ b/lib/pixi/maps/maplist.js @@ -0,0 +1,62 @@ +export class MapList { + constructor(active, maps) { + this.maps = maps + this.active = active + + if (Object.keys(maps).length > 0) this.select(active) + } + + /** + * Selects a map from the map list. + * + * @param {string} active - Name of the map to select. + * @returns + * @memberof MapList + */ + select(active) { + let map = null + + if (active !== this.active) { + let keys = Object.keys(this.maps) + if (keys.length > 0) { + if (this.maps[active] == null) { + let altActive = keys[0] + console.warn( + `The MapList does not contain the provided active key '${active}'. Used '${altActive}' as fallback.` + ) + + active = altActive + } + + if (this.active !== active) { + this.active = active + map = this.maps[active] + } + } else { + console.error(`Could not provide a fallback map! The map object is empty.`) + } + } + + return map + } + + add(key, map) { + if (this.maps[key] != null) consol.warn('Key already in mapList. The existing key was overwritten.') + map.name = key + this.maps[key] = map + } + + get map() { + console.log(this.maps, this.active) + return this.maps[this.active] + } + + next() { + let keys = Object.keys(this.maps) + let idx = keys.indexOf(this.active) + + let next = idx + 1 < key.length ? keys[idx + 1] : keys[0] + console.log(keys, idx, next) + return next + } +} diff --git a/lib/pixi/maps/mapview.js b/lib/pixi/maps/mapview.js index 3ebd9f4..90379a3 100644 --- a/lib/pixi/maps/mapview.js +++ b/lib/pixi/maps/mapview.js @@ -32,6 +32,7 @@ export default class MapView { } transformed(map) { + console.log('MAPVIEW RECEIVED TRANSFORM') this.updateZoom(map) this.updateFocusPoint(map) }