PMA.UI Documentation by Pathomation

view/controls/magnifier.js

import { Control } from 'ol/control';
import View from 'ol/View';
import Map from 'ol/Map';
import Collection from 'ol/Collection';
import TileLayer from 'ol/layer/Tile';

/**
* Displays an interface that shows slide at max zoom level under pointer's position
* @param {object} opt_options Options to initialize the magnifier control
* @param {string} [opt_options.target] Target DOM element to add magnifier control
* @param {boolean} [opt_options.collapsed] Whether the control starts collapsed
*/
export class Magnifier extends Control {
    constructor(opt_options) {
        var options = opt_options || {};
        var element = document.createElement('div');
        super({
            element: element,
            target: options.target
        });

        this.collapsed_ = false;

        if (options.collapsed === true) {
            this.collapsed_ = true;
        }


        element.className = "ol-control ";
        if (!options.target) {
            // create inside the viewport
            element.className += " ol-magnifier";

            this.magnifierDiv = document.createElement('div');
            this.magnifierDiv.className = "magnifier-map-container";

            element.appendChild(this.magnifierDiv);
            // also create grow shrink buttons

            var enlargeButton = document.createElement('button');
            enlargeButton.type = 'button';
            enlargeButton.title = "Enlarge";
            enlargeButton.className = "size";
            enlargeButton.innerHTML = "+";
            if ('ontouchstart' in document.documentElement) {
                enlargeButton.addEventListener('touchstart', this.enlargeButtonClick.bind(this), false);
            }
            else {
                enlargeButton.addEventListener('click', this.enlargeButtonClick.bind(this), false);
            }

            element.appendChild(enlargeButton);

            var shrinkButton = document.createElement('button');
            shrinkButton.type = 'button';
            shrinkButton.title = "Shrink";
            shrinkButton.className = "size";
            shrinkButton.innerHTML = "-";
            if ('ontouchstart' in document.documentElement) {
                shrinkButton.addEventListener('touchstart', this.shrinkButtonClick.bind(this), false);
            }
            else {
                shrinkButton.addEventListener('click', this.shrinkButtonClick.bind(this), false);
            }

            element.appendChild(shrinkButton);
        }
        else {
            this.magnifierDiv = element;
        }

        this.magnifierMap = null;
        this.mouseMoveFunc = null;
    }

    handleMouseMove(event) {
        if (this.getCollapsed() === true) {
            return;
        }

        var map = this.getMap();
        var mousePosition = map.getEventPixel(event);
        var coordinate = map.getCoordinateFromPixel(mousePosition);
        if (coordinate) {
            this.magnifierMap.getView().setCenter(coordinate);
        }
    }

    /** 
     * Gets the collapsed state of the control
     * @return {boolean} True if the control is currently collapsed
    */
    getCollapsed() {
        return (" " + this.element.className + " ").indexOf(' ol-collapsed ') > -1;
    }

    /** 
     * Sets the collapsed state of the control
     * @param {boolean} collapsed - True to collapse the control, otherwise false
    */
    setCollapsed(collapsed) {
        if (this.getCollapsed() != collapsed) {
            if ((" " + this.element.className + " ").indexOf(' ol-collapsed ') > -1) {
                this.element.className = this.element.className.replace(/ol-collapsed/g, '');
                if (this.magnifierMap) {
                    this.magnifierMap.updateSize();
                }
            }
            else {
                this.element.className += ' ol-collapsed';
            }
        }

        this.collapsed_ = collapsed;
    }

    /**
     * Changes magnifier control size by factor
     * @param {number} factor Factor to change magnifier's size
     */
    changeMagnifierSize(factor) {
        if (this.element) {
            var diagonalSize = Math.sqrt(this.element.clientHeight * this.element.clientHeight + this.element.clientWidth * this.element.clientWidth);
            if (diagonalSize < 60 || diagonalSize > 600) {
                return;
            }

            this.element.style.width = this.element.clientWidth * factor + "px";
            this.element.style.height = this.element.clientHeight * factor + "px";
        }
        if (this.magnifierMap) {
            this.magnifierMap.updateSize();
        }
    }

    /**
     * Sets the OpenLayers map this control handles. This is automatically called by OpenLayers
     * @param {ol.Map} map 
     */
    setMap(map) {
        if (!map) {
            if (this.magnifierMap) {
                var el = this.element;
                if (el) {
                    el.parentElement.removeChild(el);
                }
            }

            if (this.getMap() && this.mouseMoveFunc) {
                this.getMap().getViewport().removeEventListener('mousemove', this.mouseMoveFunc);
            }

            return;
        }

        var oldMap = this.getMap();
        if (map === oldMap) {
            return;
        }

        super.setMap(map);

        var mapView = map.getView();

        var newView = new View({
            projection: mapView.getProjection(),
            center: mapView.getCenter(),
            extent: mapView.getProjection().getExtent(),
            maxResolution: 1,
            minResolution: 1,
            zoom: 0
        });

        var firstLayer = map.getLayers().item(0);

        // Magnifier map
        this.magnifierMap = new Map({
            controls: new Collection(),
            interactions: new Collection(),
            target: this.magnifierDiv,
            view: newView,
            layers: [new TileLayer({ source: firstLayer.getSource() })]
        });

        var changing = false;
        this.magnifierMap.on("change:size", (function () {
            if (!changing) {
                changing = true;
                this.magnifierMap.updateSize();
                changing = false;
            }
        }).bind(this));

        this.mouseMoveFunc = this.handleMouseMove.bind(this);
        map.getViewport().addEventListener('mousemove', this.mouseMoveFunc);
        if (this.collapsed_ !== this.getCollapsed()) {
            this.setCollapsed(this.collapsed_);
        }
    }

    enlargeButtonClick(event) {
        if (event) {
            event.preventDefault();
            event.stopPropagation();
        }

        this.changeMagnifierSize(1.25);
    }

    shrinkButtonClick(event) {
        if (event) {
            event.preventDefault();
            event.stopPropagation();
        }

        this.changeMagnifierSize(0.75);
    }
}