infusion-code/angular-maps

View on GitHub
src/models/google/google-label.ts

Summary

Maintainability
A
2 hrs
Test Coverage
import * as GoogleMapTypes from '../../services/google/google-map-types';
import { MapLabel } from '../map-label';
import { ILabelOptions } from '../../interfaces/ilabel-options';
import { Extender } from '../extender';


declare var google: any;

/**
 * Implements map a labled to be placed on the map.
 *
 * @export
 */
export class GoogleMapLabel extends MapLabel {

    /**
     * Returns the default label style for the platform
     *
     * @readonly
     * @abstract
     * @memberof GoogleMapLabel
     */
    public get DefaultLabelStyle(): ILabelOptions {
        return {
            fontSize: 12,
            fontFamily: 'sans-serif',
            fontColor: '#ffffff',
            strokeWeight: 3,
            strokeColor: '#000000'
        };
    }

    ///
    /// Constructor
    ///

    /**
     * Creates a new MapLabel
     * @param options Optional properties to set.
     */
    constructor(options: { [key: string]: any }) {
        options.fontSize = options.fontSize || 12;
        options.fontColor = options.fontColor || '#ffffff';
        options.strokeWeight = options.strokeWeight || 3;
        options.strokeColor = options.strokeColor || '#000000';
        super(options);
    }

    ///
    /// Public methods
    ///

    /**
     * Gets the value of a setting.
     *
     * @param key - Key specifying the setting.
     * @returns - The value of the setting.
     * @memberof MapLabel
     * @method
     */
    public Get(key: string): any {
        return (<any>this).get(key);
    }

    /**
     * Gets the map associted with the label.
     *
     * @memberof GoogleMapLabel
     * @method
     */
    public GetMap(): GoogleMapTypes.GoogleMap {
        return (<any>this).getMap();
    }

    /**
     * Set the value for a setting.
     *
     * @param key - Key specifying the setting.
     * @param val - The value to set.
     * @memberof MapLabel
     * @method
     */
    public Set(key: string, val: any): void {
        if (key === 'position' && val.hasOwnProperty('latitude') && val.hasOwnProperty('longitude')) {
            val = new google.maps.LatLng(val.latitude, val.longitude);
        }
        if (this.Get(key) !== val) {
            (<any>this).set(key, val);
        }
    }

    /**
     * Sets the map for the label. Settings this to null remove the label from hte map.
     *
     * @param map - Map to associated with the label.
     * @memberof GoogleMapLabel
     * @method
     */
    public SetMap(map: GoogleMapTypes.GoogleMap): void {
        (<any>this).setMap(map);
    }

    /**
     * Applies settings to the object
     *
     * @param options - An object containing the settings key value pairs.
     * @memberof MapLabel
     * @method
     */
    public SetValues(options: { [key: string]: any }): void {
        for (const key in options) {
            if (key !== '') {
                if (key === 'position' &&  options[key].hasOwnProperty('latitude') &&  options[key].hasOwnProperty('longitude')) {
                    options[key] = new google.maps.LatLng( options[key].latitude,  options[key].longitude);
                }
                if (this.Get(key) === options[key]) { delete options[key]; }
            }
        }
        (<any>this).setValues(options);
    }

    ///
    /// Protected methods
    ///

    /**
     * Draws the label on the map.
     * @memberof GoogleMapLabel
     * @method
     * @protected
     */
    protected Draw(): void {
        const projection = (<any>this).getProjection();
        const visibility: string = this.GetVisible();
        if (!projection) {
            // The map projection is not ready yet so do nothing
            return;
        }
        if (!this._canvas) {
            // onAdd has not been called yet.
            return;
        }
        const style: CSSStyleDeclaration = this._canvas.style;
        if (visibility !== '') {
            // label is not visible, don't calculate positions etc.
            style['visibility'] = visibility;
            return;
        }

        let offset: GoogleMapTypes.Point = this.Get('offset');
        let latLng: GoogleMapTypes.LatLng|GoogleMapTypes.LatLngLiteral = this.Get('position');
        if (!latLng) { return; }
        if (!(latLng instanceof google.maps.LatLng)) { latLng = new google.maps.LatLng(latLng.lat, latLng.lng); }
        if (!offset) { offset = new google.maps.Point(0, 0); }

        const pos = projection.fromLatLngToDivPixel(latLng);
        style['top'] = (pos.y + offset.y) + 'px';
        style['left'] = (pos.x + offset.x) + 'px';
        style['visibility'] = visibility;
    }

    /**
     * Delegate called when the label is added to the map. Generates and configures
     * the canvas.
     *
     * @memberof GoogleMapLabel
     * @method
     * @protected
     */
    protected OnAdd() {
        this._canvas = document.createElement('canvas');
        const style: CSSStyleDeclaration = this._canvas.style;
        style.position = 'absolute';

        const ctx: CanvasRenderingContext2D = this._canvas.getContext('2d');
        ctx.lineJoin = 'round';
        ctx.textBaseline = 'top';

        this.DrawCanvas();
        const panes = (<any>this).getPanes();
        if (panes) {
            panes.overlayLayer.appendChild(this._canvas);
                // 4: floatPane (infowindow)
                // 3: overlayMouseTarget (mouse events)
                // 2: markerLayer (marker images)
                // 1: overlayLayer (polygons, polylines, ground overlays, tile layer overlays)
                // 0: mapPane (lowest pane above the map tiles)
        }
    }
}

/**
 * Helper function to extend the OverlayView into the MapLabel
 *
 * @export
 * @method
 */


export function MixinMapLabelWithOverlayView() {

    new Extender(GoogleMapLabel)
        .Extend(new google.maps.OverlayView)
        .Map('changed', 'Changed')
        .Map('onAdd', 'OnAdd')
        .Map('draw', 'Draw')
        .Map('onRemove', 'OnRemove');
}