775 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			775 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { Points } from '../../utils.js'
 | 
						|
import { EventHandler } from './utils.js'
 | 
						|
import { FlagPolygon } from '../graphics/label.js'
 | 
						|
import { DeepZoomMap } from './map.js'
 | 
						|
import { PIXIUtils } from './utils.js'
 | 
						|
 | 
						|
/**
 | 
						|
 * * GeoGraphics are graphical objects, that does not store the graphics information
 | 
						|
 * in screen space, but in geographical coordinates. Therefore GeoGraphics must be
 | 
						|
 * placed on GeoLayers to work properly.
 | 
						|
 *
 | 
						|
 * (Note: As GeoLayers are always children of a map layer. When the map is changed
 | 
						|
 * all GeoLayers are notified via the 'adaptTo(map)' method.)
 | 
						|
 *
 | 
						|
 * The geolayers forward this 'adaptTo' to all children that are GeoGraphics.
 | 
						|
 * Which adjust their so called 'point' data to the new map.
 | 
						|
 *
 | 
						|
 * @export
 | 
						|
 * @class GeoGraphics
 | 
						|
 */
 | 
						|
export class GeoGraphics {
 | 
						|
    constructor(coordinates, { scale = 1, onDraw = null, onDrawEnd = null, debug = false } = {}) {
 | 
						|
        this._coordinates = coordinates
 | 
						|
        this.debug = debug
 | 
						|
        this.graphics = new PIXI.Graphics()
 | 
						|
        this.scale = scale
 | 
						|
        this.drawHandler = new EventHandler('onDraw', { listeners: onDraw })
 | 
						|
        this.drawEndHandler = new EventHandler('onDrawEnd', { listeners: onDrawEnd })
 | 
						|
        this._points = null
 | 
						|
        this._position = null
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The coordinates of the geographics.
 | 
						|
     *
 | 
						|
     * @member {array}
 | 
						|
     * @readonly
 | 
						|
     * @memberof GeoGraphics
 | 
						|
     */
 | 
						|
    get coordinates() {
 | 
						|
        return this._coordinates
 | 
						|
    }
 | 
						|
 | 
						|
    clone() {
 | 
						|
        console.error(`Call of abstract method clone(). Overwrite in subclass.`, this)
 | 
						|
    }
 | 
						|
 | 
						|
    _cloneOptions() {
 | 
						|
        return {
 | 
						|
            debug: this.debug,
 | 
						|
            scale: this.scale
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The _adaptCoordinates is called first by the adaptTo Method.
 | 
						|
     * Here all coordinates are transformed into point coordinates.
 | 
						|
     * This must be overloaded in subclass.
 | 
						|
     *
 | 
						|
     * @abstract
 | 
						|
     */
 | 
						|
    _adaptCoordinates(map) {
 | 
						|
        console.error(`Call of abstract method _adaptCoordinates(map). Overwrite in subclass.`, this)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Gets all screen points in a single array.
 | 
						|
     *
 | 
						|
     * @abstract
 | 
						|
     * @returns {array} - Array of all points in the GeoGraphic.
 | 
						|
     */
 | 
						|
    _getPoints() {
 | 
						|
        console.error(`Call of abstract method _getPoints(func). Overwrite in subclass.`, this)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Manipulates all points depending on a function.
 | 
						|
     * Mainly used to transform points to local space.
 | 
						|
     *
 | 
						|
     * @abstract
 | 
						|
     * @param {function} func
 | 
						|
     * @memberof GeoGraphics
 | 
						|
     */
 | 
						|
    _manipulatePoints(func) {
 | 
						|
        console.error(`Call of abstract method _manipulatePoints(func). Overwrite in subclass.`, this)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The _draw method is called last on adaptation. It creates the GraphicData
 | 
						|
     * of the specified subclass. To manipulate the style of the graphic, hook an onDraw listener
 | 
						|
     * to the GeoGraphics object. It is called before the _draw and lets the user modify color and
 | 
						|
     * lineStyle of the drawn object.
 | 
						|
     *
 | 
						|
     * Note: It could also be used for more radical manipulations on the graphics object.
 | 
						|
     * But this should be used with care.
 | 
						|
     *
 | 
						|
     * @abstract
 | 
						|
     */
 | 
						|
    _draw() {
 | 
						|
        console.error(`Call of abstract method _draw(). Overwrite in subclass.`, this)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Called by the containing geo layer, when the map changes.
 | 
						|
     */
 | 
						|
    adaptTo(map) {
 | 
						|
        this._points = this._adaptCoordinates(map)
 | 
						|
        this._updatePosition()
 | 
						|
        this.draw()
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Redraws the graphics.
 | 
						|
     *
 | 
						|
     * This should be only called if you require an redraw independent of an adapt.
 | 
						|
     *
 | 
						|
     * @memberof GeoGraphics
 | 
						|
     */
 | 
						|
    draw() {
 | 
						|
        this._prepareDraw()
 | 
						|
        this.drawHandler.call(this, this.graphics)
 | 
						|
        this._draw()
 | 
						|
        this.drawEndHandler.call(this, this.graphics)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Retrieves the point data.
 | 
						|
     * Note: This data changes on adaptation.
 | 
						|
     */
 | 
						|
    get points() {
 | 
						|
        return this._points
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the screen position of the GeoGraphics.
 | 
						|
     */
 | 
						|
    get position() {
 | 
						|
        return this._position
 | 
						|
    }
 | 
						|
 | 
						|
    get layer() {
 | 
						|
        return this._layer ? this._layer : null
 | 
						|
    }
 | 
						|
 | 
						|
    setLayer(layer) {
 | 
						|
        this._layer = layer
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Map of the containing layer. Null if on no layer.
 | 
						|
     *
 | 
						|
     * @readonly
 | 
						|
     * @memberof GeoGraphics
 | 
						|
     */
 | 
						|
    get map() {
 | 
						|
        let map = null
 | 
						|
        if (this.mapLayer) {
 | 
						|
            map = this.mapLayer.map
 | 
						|
        }
 | 
						|
        return map
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * MapLayer of the containing layer. Null if on no layer.
 | 
						|
     *
 | 
						|
     * @member {MapLayer}
 | 
						|
     * @readonly
 | 
						|
     * @memberof GeoGraphics
 | 
						|
     */
 | 
						|
    get mapLayer() {
 | 
						|
        let mapLayer = null
 | 
						|
        if (this.layer) {
 | 
						|
            mapLayer = this.layer.mapLayer
 | 
						|
        }
 | 
						|
        return mapLayer
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *  Prepare draw is a private function, that prepares the graphics
 | 
						|
     * for the next draw call. It also fires the drawHandler.
 | 
						|
     *
 | 
						|
     * @private
 | 
						|
     * @memberof GeoGraphics
 | 
						|
     */
 | 
						|
    _prepareDraw() {
 | 
						|
        this.graphics.clear()
 | 
						|
        /*
 | 
						|
           Set a fillcolor and a stroke style for
 | 
						|
           debugging. Can be overloaded using the onDraw 
 | 
						|
           event function.
 | 
						|
       */
 | 
						|
        if (this.debug) this.graphics.beginFill(0xff00ff)
 | 
						|
    }
 | 
						|
 | 
						|
    _updatePosition() {
 | 
						|
        let points = this._getPoints()
 | 
						|
        this._position = GeoGraphics.calculateCenterOfMass(points)
 | 
						|
        this._manipulatePoints(point => {
 | 
						|
            point = Points.subtract(point, this._position)
 | 
						|
            return point
 | 
						|
        })
 | 
						|
        this.graphics.position = this._position
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Calculates the center of Mass for a set of points.
 | 
						|
     *
 | 
						|
     * @static
 | 
						|
     * @param {Array} points - Array of points in the format {x: a, y:b}
 | 
						|
     * @returns {object} - Returns a point containing the center of mass of the polygon.
 | 
						|
     * @memberof GeoGraphics
 | 
						|
     */
 | 
						|
    static calculateCenterOfMass(points) {
 | 
						|
        let com = new PIXI.Point()
 | 
						|
        points.forEach(p => {
 | 
						|
            let point = new PIXI.Point(p.x, p.y)
 | 
						|
            com = Points.add(com, point)
 | 
						|
        })
 | 
						|
        return Points.multiplyScalar(com, 1 / points.length)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Represents a single point on the Map.
 | 
						|
 *
 | 
						|
 * This GeoGraphics does not provide any visual representation.
 | 
						|
 * Draw the desired shape in the onDraw callback.
 | 
						|
 *
 | 
						|
 * @export
 | 
						|
 * @class GeoPoint
 | 
						|
 * @extends {GeoGraphics}
 | 
						|
 */
 | 
						|
export class GeoPoint extends GeoGraphics {
 | 
						|
    clone() {
 | 
						|
        return new GeoPoint(this.coordinates, this._cloneOptions())
 | 
						|
    }
 | 
						|
 | 
						|
    _adaptCoordinates(map) {
 | 
						|
        let scale = 1
 | 
						|
 | 
						|
        if (map instanceof DeepZoomMap) {
 | 
						|
            scale = map.image.scale.x
 | 
						|
        }
 | 
						|
 | 
						|
        scale = scale / 4
 | 
						|
 | 
						|
        return map.coordinatesToPoint(this.coordinates)
 | 
						|
    }
 | 
						|
 | 
						|
    _getPoints() {
 | 
						|
        return [this.points]
 | 
						|
    }
 | 
						|
 | 
						|
    _manipulatePoints(func) {
 | 
						|
        this._points = func(this._points)
 | 
						|
    }
 | 
						|
 | 
						|
    _draw() {}
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Represensts a line between two locations.
 | 
						|
 *
 | 
						|
 * @export
 | 
						|
 * @class GeoLine
 | 
						|
 * @extends {GeoGraphics}
 | 
						|
 */
 | 
						|
export class GeoLine extends GeoGraphics {
 | 
						|
    /**
 | 
						|
     * @param {object} opts - Optional values
 | 
						|
     * @param {array} [opts.points=[]] - Initial points of the geo shape.
 | 
						|
     * @param {boolean} [closed=false] - Defines if the
 | 
						|
     */
 | 
						|
    constructor(coordinates, { closed = false, size = 1, onDraw = null } = {}) {
 | 
						|
        super(coordinates, {
 | 
						|
            size,
 | 
						|
            onDraw
 | 
						|
        })
 | 
						|
 | 
						|
        this._closed = closed
 | 
						|
    }
 | 
						|
 | 
						|
    clone() {
 | 
						|
        return new GeoLine(this.coordinates, this._cloneOptions)
 | 
						|
    }
 | 
						|
 | 
						|
    _cloneOptions() {
 | 
						|
        let options = super._cloneOptions()
 | 
						|
        Object.assign(options, {
 | 
						|
            closed: this.closed
 | 
						|
        })
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Adds a point to the geo line.
 | 
						|
     */
 | 
						|
    addPoint(coordinate) {
 | 
						|
        this.coordinates.push(coordinate)
 | 
						|
    }
 | 
						|
 | 
						|
    _manipulatePoints(func) {
 | 
						|
        this.points.forEach((point, idx, array) => {
 | 
						|
            array[idx] = func(point)
 | 
						|
        })
 | 
						|
    }
 | 
						|
 | 
						|
    _getPoints() {
 | 
						|
        return this.points
 | 
						|
    }
 | 
						|
 | 
						|
    _adaptCoordinates(map) {
 | 
						|
        let points = []
 | 
						|
        this.coordinates.forEach(point => {
 | 
						|
            points.push(map.coordinatesToPoint(point))
 | 
						|
        })
 | 
						|
        return points
 | 
						|
    }
 | 
						|
 | 
						|
    _prepareDraw() {
 | 
						|
        this.graphics.clear()
 | 
						|
        if (this.debug) this.graphics.lineStyle(0.5, 0xff00ff)
 | 
						|
        this.drawHandler.call(this)
 | 
						|
    }
 | 
						|
 | 
						|
    _draw() {
 | 
						|
        /**
 | 
						|
         * This resets the fill.
 | 
						|
         *
 | 
						|
         *  DISCUSS:    SO: "I'm not sure how the line should be defined.
 | 
						|
         *              On the one hand. The line is clearly intended to
 | 
						|
         *              represent a line and not an area. On the other hand,
 | 
						|
         *              why should the user be prevented from using a fill for the
 | 
						|
         *              area within the line. But if he want's a fill, why don't take
 | 
						|
         *              a Polygon in the first place?
 | 
						|
         *
 | 
						|
         *              (But if it's a predefined GeoJSON object obtained through e.g. elasticsearch,
 | 
						|
         *              then the user is not in full control of the object type and it may be a good
 | 
						|
         *              addition to grant the user this additional design choice.)
 | 
						|
         *
 | 
						|
         *              The opportunity to do so would result in additional conditions, when creating the
 | 
						|
         *              GeoGraphics of an overlay."
 | 
						|
         * */
 | 
						|
        this.graphics.beginFill(0, 0)
 | 
						|
 | 
						|
        if (this.points.length > 0) {
 | 
						|
            this.graphics.moveTo(this.points[0].x, this.points[0].y)
 | 
						|
 | 
						|
            for (let i = 1; i < this.points.length; i++) {
 | 
						|
                this.graphics.lineTo(this.points[i].x, this.points[i].y)
 | 
						|
            }
 | 
						|
 | 
						|
            if (this.closed) {
 | 
						|
                this.graphics.lineTo(this.points[0].x, this.points[0].y)
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    get closed() {
 | 
						|
        return this._closed
 | 
						|
    }
 | 
						|
 | 
						|
    set closed(val) {
 | 
						|
        if (val != this._closed) {
 | 
						|
            this._closed = val
 | 
						|
            this.draw()
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Represents a shape on a map.
 | 
						|
 *
 | 
						|
 * @export
 | 
						|
 * @class GeoShape
 | 
						|
 * @extends {GeoGraphics}
 | 
						|
 */
 | 
						|
export class GeoShape extends GeoGraphics {
 | 
						|
    clone() {
 | 
						|
        return new GeoShape(this.coordinates, this._cloneOptions)
 | 
						|
    }
 | 
						|
 | 
						|
    _manipulatePoints(func) {
 | 
						|
        this.constructor._manipulatePoints(this.points, func)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Mets the requirements for the _manipulatePointsMethod().
 | 
						|
     * Primarily used in subclasses to get the processing steps from
 | 
						|
     * their superclass.
 | 
						|
     *
 | 
						|
     * @static
 | 
						|
     * @protected
 | 
						|
     * @param {Array.<PIXI.Points>} points - The points array that shold be manipulated.
 | 
						|
     * @param {function} func   - The function that changes the single point value. Has to return a new point.
 | 
						|
     * @memberof GeoShape
 | 
						|
     */
 | 
						|
    static _manipulatePoints(points, func) {
 | 
						|
        points.forEach((pointArray, arrIdx) => {
 | 
						|
            pointArray.forEach((point, idx) => {
 | 
						|
                points[arrIdx][idx] = func(point)
 | 
						|
            })
 | 
						|
        })
 | 
						|
    }
 | 
						|
 | 
						|
    _getPoints() {
 | 
						|
        return this.constructor._getPointsFrom(this.points)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns all points of a polygon array.
 | 
						|
     * Useful for when getting sub polygons in child class.
 | 
						|
     */
 | 
						|
    static _getPointsFrom(shape) {
 | 
						|
        let concatArray = []
 | 
						|
        shape.forEach(array => {
 | 
						|
            concatArray = concatArray.concat(array)
 | 
						|
        })
 | 
						|
 | 
						|
        return concatArray
 | 
						|
    }
 | 
						|
 | 
						|
    _adaptCoordinates(map) {
 | 
						|
        let val = this.constructor._adaptPoint(this.coordinates, map)
 | 
						|
        return val
 | 
						|
    }
 | 
						|
 | 
						|
    static _adaptPoint(coordinates, map) {
 | 
						|
        return coordinates.map(array => {
 | 
						|
            return array.map(point => {
 | 
						|
                return map.coordinatesToPoint(point)
 | 
						|
            })
 | 
						|
        })
 | 
						|
    }
 | 
						|
 | 
						|
    _draw() {
 | 
						|
        this._drawFrom(this.points)
 | 
						|
        this.graphics.position = this.position
 | 
						|
    }
 | 
						|
 | 
						|
    _drawFrom(shape) {
 | 
						|
        const { polygon, hole } = this.constructor._pointsToShape(shape)
 | 
						|
        this._drawShape(polygon, hole)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Separates the points array into it's two parts:
 | 
						|
     *      - the solid polygon
 | 
						|
     *      - a hole that is cut into the polygon (optional)
 | 
						|
     *
 | 
						|
     * @private
 | 
						|
     * @returns {object} - Returns an object containing the polygon and the hole in the form of {polygon: [...PIXI.Point], hole: [...PIXI.Point]}
 | 
						|
     */
 | 
						|
    static _pointsToShape(points) {
 | 
						|
        let polygon = GeoShape._transformToPIXI(points[0])
 | 
						|
        let hole = points[1] ? GeoShape._transformToPIXI(points[1]) : []
 | 
						|
        return { polygon, hole }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Transform an array of poins into an array of PIXI.Points.
 | 
						|
     * Note:    When creating PIXI.Polygons, for some reason the points
 | 
						|
     *          need to be a PIXI.Points object (at least the first one).
 | 
						|
     *
 | 
						|
     * @param {array} points - Points in the form of {x:a,y:b}
 | 
						|
     * @returns An array of PIXI.Points
 | 
						|
     * @memberof GeoPolygon
 | 
						|
     */
 | 
						|
    static _transformToPIXI(points = []) {
 | 
						|
        let polygon = []
 | 
						|
        points.forEach(point => {
 | 
						|
            polygon.push(new PIXI.Point(point.x, point.y))
 | 
						|
        })
 | 
						|
 | 
						|
        return polygon
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Draws a single shape onto the graphics object.
 | 
						|
     * Useful when being called from subclass.
 | 
						|
     *
 | 
						|
     * @protected
 | 
						|
     * @param {Array.<PIXI.Point>} polygon - An array of PIXI.Points for drawing a polygon.
 | 
						|
     * @param {Array.<PIXI.Point>} [hole=[]] - An Array of PIXI.Points for cutting a hole into the polygon
 | 
						|
     * @memberof GeoShape
 | 
						|
     */
 | 
						|
    _drawShape(polygon, hole = []) {
 | 
						|
        // We save the fill specified in the onDraw event handler.
 | 
						|
        let { fill, alpha } = PIXIUtils.saveFill(this.graphics)
 | 
						|
 | 
						|
        /**
 | 
						|
         * a) Draw the hole with a polygon.
 | 
						|
         *
 | 
						|
         * This may seem redundant to (c), but it's required (in this order(!))
 | 
						|
         * to make the hole clickable.
 | 
						|
         *
 | 
						|
         * It was a bit confusing, so I made a CodePen
 | 
						|
         * for it: https://codepen.io/Ukmasmu/pen/WJEaoK
 | 
						|
         */
 | 
						|
        if (hole.length > 0) {
 | 
						|
            this.graphics.beginFill(0x0000ff, 0.0000001)
 | 
						|
            this.graphics.drawPolygon(hole)
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * b) Draw the shape.
 | 
						|
         */
 | 
						|
        this.graphics.beginFill(fill, alpha)
 | 
						|
        this.graphics.drawPolygon(polygon)
 | 
						|
 | 
						|
        /**
 | 
						|
         * c) Add the hole.
 | 
						|
         */
 | 
						|
        if (hole.length > 0) {
 | 
						|
            this.graphics.beginHole()
 | 
						|
            this.graphics.drawPolygon(hole)
 | 
						|
            this.graphics.endHole()
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * The MultiGraphics makes use of the other GeoGraphics to
 | 
						|
 * create a single graphics element out of multiple different
 | 
						|
 * GeoGraphics.
 | 
						|
 *
 | 
						|
 * @class GeoMultiGraphics
 | 
						|
 * @extends {GeoGraphics}
 | 
						|
 */
 | 
						|
class GeoMultiGraphics extends GeoGraphics {
 | 
						|
    /**
 | 
						|
     * The _adaptCoordinates is called first by the adaptTo Method.
 | 
						|
     * Here all coordinates are transformed into point coordinates.
 | 
						|
     * This must be overloaded in subclass.
 | 
						|
     *
 | 
						|
     * @abstract
 | 
						|
     */
 | 
						|
    _adaptCoordinates(map) {}
 | 
						|
 | 
						|
    /**
 | 
						|
     * Gets all screen points in a single array.
 | 
						|
     *
 | 
						|
     * @abstract
 | 
						|
     * @returns {array} - Array of all points in the GeoGraphic.
 | 
						|
     */
 | 
						|
    _getPoints() {
 | 
						|
        console.error(`Call of abstract method _getPoints(func). Overwrite in subclass.`, this)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Manipulates all points depending on a function.
 | 
						|
     * Mainly used to transform points to local space.
 | 
						|
     *
 | 
						|
     * @abstract
 | 
						|
     * @param {function} func
 | 
						|
     * @memberof GeoGraphics
 | 
						|
     */
 | 
						|
    _manipulatePoints(func) {
 | 
						|
        console.error(`Call of abstract method _manipulatePoints(func). Overwrite in subclass.`, this)
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The _draw method is called last on adaptation. It creates the GraphicData
 | 
						|
     * of the specified subclass. To manipulate the style of the graphic, hook an onDraw listener
 | 
						|
     * to the GeoGraphics object. It is called before the _draw and lets the user modify color and
 | 
						|
     * lineStyle of the drawn object.
 | 
						|
     *
 | 
						|
     * Note: It could also be used for more radical manipulations on the graphics object.
 | 
						|
     * But this should be used with care.
 | 
						|
     *
 | 
						|
     * @abstract
 | 
						|
     */
 | 
						|
    _draw() {
 | 
						|
        console.error(`Call of abstract method _draw(). Overwrite in subclass.`, this)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Text that is attatched to a GeoPoint.
 | 
						|
 *
 | 
						|
 * @export
 | 
						|
 * @class GeoText
 | 
						|
 * @extends {GeoPoint}
 | 
						|
 */
 | 
						|
export class GeoText extends GeoPoint {
 | 
						|
    constructor(coordinates, text, opts) {
 | 
						|
        super(coordinates, opts)
 | 
						|
        this.align = opts.align
 | 
						|
        this.textStyle = Object.assign(new PIXI.TextStyle(), opts.textStyle)
 | 
						|
        this._text = new PIXI.Text(text, this.textStyle)
 | 
						|
 | 
						|
        switch (this.align) {
 | 
						|
            case 'left':
 | 
						|
                break
 | 
						|
            case 'center':
 | 
						|
                this.text.position.x -= this.text.width / 2
 | 
						|
                break
 | 
						|
            case 'right':
 | 
						|
                this.text.position.x -= this.text.width
 | 
						|
                break
 | 
						|
            default:
 | 
						|
                console.error('Align type is not implemented: ' + this.align + ". Use 'left', 'right' or 'center'.")
 | 
						|
        }
 | 
						|
        this.text.position.y -= this.text.height / 2
 | 
						|
        this.graphics.addChild(this.text)
 | 
						|
    }
 | 
						|
 | 
						|
    get text() {
 | 
						|
        return this._text
 | 
						|
    }
 | 
						|
 | 
						|
    _draw() {
 | 
						|
        super._draw()
 | 
						|
    }
 | 
						|
 | 
						|
    adaptTo(map) {
 | 
						|
        super.adaptTo(map)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * A geotext with a notch at a certain Position.
 | 
						|
 *
 | 
						|
 * TODO: This is a specialization for the Tüsch. This should be inside the Tüsch project.
 | 
						|
 */
 | 
						|
export class GeoFlagLabel extends GeoText {
 | 
						|
    constructor(coordinates, text, opts) {
 | 
						|
        super(
 | 
						|
            coordinates,
 | 
						|
            text,
 | 
						|
            Object.assign(opts, {
 | 
						|
                align: 'left'
 | 
						|
            })
 | 
						|
        )
 | 
						|
 | 
						|
        if (!opts.flag) {
 | 
						|
            opts.flag = {}
 | 
						|
        }
 | 
						|
 | 
						|
        const {
 | 
						|
            alpha = 1,
 | 
						|
            color = 0xffffff,
 | 
						|
            borderAlpha = 1,
 | 
						|
            borderColor = 0x000000,
 | 
						|
            borderThickness = 0,
 | 
						|
            fillNotch = false
 | 
						|
        } = opts
 | 
						|
 | 
						|
        Object.assign(this, {
 | 
						|
            alpha,
 | 
						|
            color,
 | 
						|
            fillNotch,
 | 
						|
            borderAlpha,
 | 
						|
            borderColor,
 | 
						|
            borderThickness
 | 
						|
        })
 | 
						|
 | 
						|
        this.flagOptions = Object.assign(
 | 
						|
            {
 | 
						|
                notchSize: 10,
 | 
						|
                notchWidth: null,
 | 
						|
                notchHeight: null,
 | 
						|
                padding: { x: 0, y: 0 },
 | 
						|
                originOffset: { x: 0, y: 0 }
 | 
						|
            },
 | 
						|
            opts.flag
 | 
						|
        )
 | 
						|
 | 
						|
        this.border = this.borderThickness > 0
 | 
						|
 | 
						|
        Object.assign(this.flagOptions, {
 | 
						|
            width: this.text.width + this.flagOptions.padding.x * 2,
 | 
						|
            height: this.text.height + this.flagOptions.padding.y * 2
 | 
						|
        })
 | 
						|
 | 
						|
        this.flagPolygon = new FlagPolygon(this.flagOptions)
 | 
						|
 | 
						|
        // hover effect
 | 
						|
        //--------------------
 | 
						|
        const duration = 0.2
 | 
						|
        this.graphics.interactive = true
 | 
						|
        this.graphics.on('pointerover', event => {
 | 
						|
            TweenLite.to(this.graphics, duration, { alpha: 0.6 })
 | 
						|
        })
 | 
						|
        this.graphics.on('pointerout', event => {
 | 
						|
            TweenLite.to(this.graphics, duration, { alpha: 1 })
 | 
						|
        })
 | 
						|
        this.graphics.on('pointerupoutside', event => {
 | 
						|
            TweenLite.to(this.graphics, duration, { alpha: 1 })
 | 
						|
        })
 | 
						|
        this.graphics.on('pointercancel', event => {
 | 
						|
            TweenLite.to(this.graphics, duration, { alpha: 1 })
 | 
						|
        })
 | 
						|
        this.graphics.on('pointertap', event => {
 | 
						|
            TweenLite.to(this.graphics, duration, { alpha: 1 })
 | 
						|
        })
 | 
						|
        // this.graphics.on('pointerdown', event => {
 | 
						|
        //     TweenLite.to(this.graphics, duration, { alpha: 0.45 })
 | 
						|
        // })
 | 
						|
        // this.graphics.on('pointerup', event => {
 | 
						|
        //     TweenLite.to(this.graphics, duration, { alpha: 0.6 })
 | 
						|
        // })
 | 
						|
    }
 | 
						|
 | 
						|
    _draw() {
 | 
						|
        super._draw()
 | 
						|
 | 
						|
        this.graphics.beginFill(this.color, this.alpha)
 | 
						|
        this.graphics.drawPolygon(this.flagPolygon)
 | 
						|
        this.flagPolygon.placeText(this.text, this.flagOptions.padding)
 | 
						|
 | 
						|
        if (this.border) {
 | 
						|
            const lineStyle = [this.borderThickness, this.borderColor, this.borderAlpha]
 | 
						|
            if (this.fillNotch) {
 | 
						|
                this.graphics.beginFill(this.borderColor)
 | 
						|
                this.graphics.drawPolygon(this.flagPolygon.notch)
 | 
						|
                this.graphics.endFill()
 | 
						|
 | 
						|
                this.graphics.lineStyle(...lineStyle)
 | 
						|
                this.graphics.drawPolygon(this.flagPolygon.rect)
 | 
						|
                this.graphics.drawPolygon(this.flagPolygon.notch)
 | 
						|
            } else {
 | 
						|
                this.graphics.lineStyle(...lineStyle)
 | 
						|
                this.graphics.drawPolygon(this.flagPolygon)
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * The GeoMultiShape displays multiple forms.
 | 
						|
 *
 | 
						|
 * @export
 | 
						|
 * @class GeoMultiShape
 | 
						|
 * @extends {GeoShape}
 | 
						|
 */
 | 
						|
export class GeoMultiShape extends GeoShape {
 | 
						|
    static _manipulatePoints(points, func) {
 | 
						|
        points.forEach(shape => {
 | 
						|
            GeoShape._manipulatePoints(shape, func)
 | 
						|
        })
 | 
						|
    }
 | 
						|
 | 
						|
    static _getPointsFrom(multiShapeArray) {
 | 
						|
        let points = []
 | 
						|
        multiShapeArray.forEach(shape => {
 | 
						|
            points = points.concat(GeoShape._getPointsFrom(shape))
 | 
						|
        })
 | 
						|
        return points
 | 
						|
    }
 | 
						|
 | 
						|
    static _adaptPoint(coordinates, map) {
 | 
						|
        let points = []
 | 
						|
        coordinates.forEach(shape => {
 | 
						|
            let adaptedPoint = GeoShape._adaptPoint(shape, map)
 | 
						|
            points.push(adaptedPoint)
 | 
						|
        })
 | 
						|
        return points
 | 
						|
    }
 | 
						|
 | 
						|
    calculateLocation() {
 | 
						|
        let coms = []
 | 
						|
        this.coordinates.forEach(polygon => {
 | 
						|
            coms.push(GeoGraphics.calculateCenterOfMass(polygon))
 | 
						|
        })
 | 
						|
 | 
						|
        return GeoGraphics.calculateCenterOfMass(coms)
 | 
						|
    }
 | 
						|
 | 
						|
    _drawFrom(multiShape) {
 | 
						|
        multiShape.forEach(shape => {
 | 
						|
            super._drawFrom(shape)
 | 
						|
        })
 | 
						|
    }
 | 
						|
}
 |