import { DeepZoomMap } from './map.js' /** * The MapView class is responsible for a consistent map view. * It is aware of the current viewposition, the scale and viewport. * It ensures, that maps can be changed, without the user noticing it. * */ export default class MapViewport { /** * * @param {object} [focus = {x:0, y:0}] - Defines the startup focuspoint of the app. * @param {number} [zoom = 0] - Defines the startup zoom of the app. Note that this is just a request. * The MapView will prioritize a full scale app, than displaying the demanded zoom factor */ constructor({ focus = null, zoom = null, viewport = { min: { x: -85, y: -180 }, max: { x: 85, y: 180 } } } = {}) { this.viewport = viewport this._focus = focus this._zoom = zoom this.referenceHeight = 256 } get focus() { return this._focus } get zoom() { return this._zoom } apply(map) { map.moveTo(this._focus, this._zoom) } transformed(map) { this.updateZoom(map) this.updateFocusPoint(map) } updatePosition(map) { this.updateFocusPoint(map) this.updateZoom(map) } updateFocusPoint(map) { const frame = map.getFrame() this._focus = this.coordinatesFromWindowPoint(map, frame.localCenter) } updateZoom(map) { /** * TODO: This relies on the fact, that all maps have the same tileSize, * if a set would have a smaller tileSize. Improve that. */ if (map instanceof DeepZoomMap) this._zoom = map.floatingLevelForScale(map.image.scatter.scale) else { this._zoom = map.zoom } } mapPointToWindowPoint(map, point) { let windowPoint = { x: 0, y: 0 } if (map['image'] && map.image['parent']) { let container = map.image.parent windowPoint = new PIXI.Point( map.scatter.position.x + map.scatter.scale * point.x, map.scatter.position.y + map.scatter.scale * point.y ) windowPoint = container.toGlobal(windowPoint) } else { console.error(this._noParentError) } return windowPoint } windowPointToMapPoint(map, point) { let pointOnMap = { x: 0, y: 0 } if (map['image'] && map.image['parent']) { let offset = map.image.parent.toGlobal({ x: 0, y: 0 }) pointOnMap = new PIXI.Point( (point.x - map.scatter.position.x - offset.x) / map.scatter.scale, (point.y - map.scatter.position.y - offset.y) / map.scatter.scale ) } else console.error(this._noParentError) return pointOnMap } get _noParentError() { return 'Cannot compute map point when map has no parent.' } /** * Gets the coordinates of a specific point in the viewport. * * @param {PIXI.Point | {x,y}} point - Pixel position in the viewport. * @returns {{x,y}} Coordinates on the map of the provided position. * @memberof MapView */ coordinatesFromWindowPoint(map, point) { let position = { x: point.x - map.scatter.position.x, y: point.y - map.scatter.position.y } let normalized = { x: position.x / (map.width * map.scatter.scale), y: position.y / (map.height * map.scatter.scale) } let coordinates = map.mapdata.toCoordinates(normalized) return coordinates } }