control/styletoggleControl/index.js

'use strict';

import onlineMapUrlModel from '../../model/baseMap/onlineMapUrlModel';


/**
 *@添加自定义地图控件(地图样式集切换控件)
 *@author lc
 *@date 2018-03-28 15:46:31
 */
 class StyleToggleControl {
    constructor(options) {

        // this.options = options;
        this._map = null;
        this.host = options.host;
        this.types = options.types;
        this.baseMapType = this.host.split('/');
        this.baseMapType = this.baseMapType[this.baseMapType.length - 1];
        this.styleToggleContainer = null;
        this.LAYERKEY = 'hyLayer';

    }

    onAdd(map) {

        this._map = map;
        this._container = document.createElement('div');
        this._container.className = 'mapboxgl-ctrl';
        let style_toggle = document.createElement('div');
        style_toggle.className = 'style-toggle-container';
        let hymap_style_container = document.createElement('div');
        hymap_style_container.className = 'hymap-style-container';
        style_toggle.appendChild(hymap_style_container);
        this._container.appendChild(style_toggle);

        this.addStyleToMap();
        return this._container;

    }

    onRemove() {

        this._container.parentNode.removeChild(this._container);
        this._map = undefined;

    }

    /**
     *@地图加载完毕后添加控件样式
     *@author lc
     *@date 2018-04-27 10:16:08
     */
    addStyleToMap() {

        this._map.on('load', () => {

            this.styleToggleContainer = document.querySelector('.style-toggle-container');
            this.types.map((value) => {

                let div = document.createElement('div');
                div.className = 'child-style-container';
                div.style.backgroundImage = `url(${this.host}/images/${value}.png)`;
                div.style.display = 'none';
                div.onclick = this.toogleMapStyle;
                div.setAttribute('typeName', value);
                this.styleToggleContainer.appendChild(div);

            });
            this.styleToggleContainer.style.backgroundImage = `url(${this.host}/images/black.png)`;
            this.stylesContainerChilds = this.styleToggleContainer.childNodes;
            let firstChild = this.stylesContainerChilds[1];
            firstChild.style.display = 'block';
            firstChild.className = firstChild.className + ' container-border';
            this.styleToggleContainer.onmouseover = this.showStyleContainer;
            this.styleToggleContainer.onmouseleave = this.hideStyleContainer;

        });

    }

    /**
     *@显示地图样式选择容器
     *@author lc
     *@date 2018-03-27 11:17:43
     */
    showStyleContainer = () => {

        for (let i = 1; i < this.stylesContainerChilds.length; i++) {

            this.stylesContainerChilds[i].style.display = 'block';

        }

    };

    /**
     *@隐藏地图样式选择容器
     *@author lc
     *@date 2018-03-27 11:18:14
     */
    hideStyleContainer = () => {

        this.styleToggleContainer.childNodes.forEach(div => {

            if (div.className.indexOf('container-border') < 0) {

                div.style.display = 'none';

            }

        });
        this.styleToggleContainer.style.cursor = '';

    };

    /**
     *@点击改变容器样式以及切换地图样式
     *@author lc
     *@date 2018-03-27 11:18:33
     */
    toogleMapStyle = e => {

        let targetDiv = e.target;
        //改变容器样式
        if (targetDiv.className.indexOf('container-border') < 0) {

            this.styleToggleContainer.childNodes.forEach(div => {

                div.className = div.className.replace(' container-border', '');

            });
            targetDiv.className = targetDiv.className + ' container-border';

            //切换地图
            let type = targetDiv.getAttribute('typeName');
            if (this.baseMapType === 'customMap') {

                this.setMapStyleByUrl(`${this.host}/${type}/style.json`);

            } else {

                this.setMapStyleByUrl(onlineMapUrlModel[this.baseMapType][type]);

            }

        }

    };

    /**
     *@切换地图
     *@author lc
     *@date 2018-03-28 15:52:43
     */
    setMapStyleByUrl(url) {

        if (this.baseMapType !== 'customMap') {

            this._map.removeLayer(this.baseMapType + '-base-layer');
            this._map.removeSource(this.baseMapType + '-base-layer');
            this._map.addSource(this.baseMapType + '-base-layer', {
                'type': 'onlineraster',
                'url': url,
                'tileSize': 256
            });
            this._map.addLayer({
                'id': this.baseMapType + '-base-layer',
                'type': 'raster',
                'source': this.baseMapType + '-base-layer',
                'minzoom': 0,
                'maxzoom': 19,
                'paint': {
                    'raster-opacity': 1
                }
            });
            this._map.moveLayer(this.baseMapType + '-base-layer', this._map.getStyle().layers[0].id);

        }
        else {

            const oldStyle = this._map.getStyle();
            const oldStyleObj = this._map.style;
            this._map.setStyle(url);
            this._map.once('styledata', () => {

                //保留原有图层
                if (oldStyle) {

                    let style = this._map.getStyle();
                    let source = oldStyle.sources;
                    for (let j in source) {

                        if (source[j].type === 'geojson' && source[j].data['_LKey'] && source[j].data['_LKey'] === this.LAYERKEY) {

                            style.sources[j] = source[j];

                        }

                    }
                    let layers = oldStyle.layers;

                    for (let i = 0; i < layers.length; i++) {

                        if (layers[i].metadata && layers[i].metadata['_LKey'] && layers[i].metadata['_LKey'].indexOf(this.LAYERKEY) > -1) {

                            const layer = layers[i];
                            if (layer.type === 'symbol') {

                                const icon = layer.layout['icon-image'];
                                const image = oldStyleObj.getImage(icon);
                                if (image) {

                                    this._map.addImage(icon, image.data);

                                }

                            }
                            style.layers.push(layers[i]);

                        }

                    }
                    this._map.setStyle(style);

                }

            });

        }

    }
}

export default StyleToggleControl;