components/layer/baseMap.js

/*
 * @Author: wxq
 * @Date:   2017-04-20 17:03:05
 * @Last Modified by:   hydata
 * @Last Modified time: 2018-05-10 17:09:54
 * @Email: 304861063@qq.com
 * @File Path: F:\work\hyMap\src\components\layer\baseMap.js
 * @File Name: baseMap.js
 * @Descript:地理底图
 */
'use strict';
import baseLayer from './baseLayer';
import OnlineMapUrlModel from '../../model/baseMap/onlineMapUrlModel';

const OnlineRasterTileSource = require('../../model/baseMap/mapbox-gl-online-tiled-map-service-dev.js');

/**
 * 底图
 * @extends baseLayer
 */
class BaseMap extends baseLayer {
    /**
     * 初始化
     * @param  {Object}  options 参数{url:gis后台服务地址}
     * @extends  base
     */
    constructor(options) {

        super(options);

        /**
         * 主题
         * @type {String}
         */
        // this.theme = options && options.theme || 'dark';
        this.map = options.map;

        /**
         * 底图
         * @type {layer}
         */
        this.layer = this.init();


    }

    /**
     * 初始化layer
     * @return {Object}  layer 地图
     */
    init() {

        return this.map.getStyle();

    }

    /**
     * 获取layer
     */
    getLayer() {

        return this.layerGroup;

    }

    /**
     * 创建tile
     */
    createTile(source, label = '地图', opacity = 1) {

        return {
            'type': 'raster',
            'source': source,
            'maxZoom': 24,
            'id': source
        };

    }

    /**
     * 创建layerJson
     * @param {*} layer 
     * @param {*} layers 
     */
    buildLayers(layer, layers = {version: 8, sources: {}, layers: []}) {

        Object.assign(layers.sources, layer.sources);
        layers.layers = layers.layers.concat(layer.layers);
        return layers;

    }

    /**
     * 创建数据源source
     * @param {*} theme 
     */
    initSource(theme) {

        let layers;

        if (Array.isArray(theme)) {

            theme.forEach(themeObj => {

                const layer = this._initSource(themeObj);
                layers = this.buildLayers(layer, layers);

            });

        } else {

            layers = this._initSource(theme);

        }
        // layers=require('../../../../test/data/2017-11-20-重庆-黑色系.json');

        return layers;

    }

    /**
     * 初始化数据源
     * @private
     * @param  {string|object}  theme 主题类型
     * @return {source}        source 数据源
     */
    _initSource(theme) {

        let layers = OnlineMapUrlModel.modelStyle;
        // let source = undefined;
        let baseMapType = theme.host.split('/');
        baseMapType = baseMapType[baseMapType.length - 1];
        layers.id = `${baseMapType}-base-layer`;
        if (baseMapType === 'customMap') {

            layers.url = `${theme.host}/${theme.types[0]}/style.json`;

        } else {

            layers.url = OnlineMapUrlModel[baseMapType][theme.types[0]];

        }
        return layers;

    }

    /**
     * 设置数据源
     * @param  {(string|Object)}   type 设置数据源
     * @default blue
     * @example
     *
     *  setTheme({
     *     mapId: your mapboxID
     *     key: your mapboxkey
     *  })
     *  or:
     *  setTheme('')
     */
    setTheme(type) {

        this.theme = type;

        let layers = this.initSource(type);

        this.setLayer(layers);

    }

    /**
     * 获取主题
     * @return {string} theme 获取主题
     */
    getTheme() {

        return this.theme;

    }

    /**
     * 设置图层
     * @private
     * @param {Array} layers
     */
    setLayer(layers) {

        const oldStyle = this.map.getStyle();
        const oldStyleObj = this.map.style;


        //区分主题类型,hymap类型和在线地图类型采用不同的加载方式
        if (layers.id === 'customMap-base-layer') {

            this.map.setStyle(layers.url);

        } else {

            this.map.setStyle(layers);
            //注册在线地图数据源
            this.map.addSourceType('onlineraster', OnlineRasterTileSource, function (err) {
            });

        }


        this.map.once('styledata', () => {

            //根据主题的id加载不同的地图图层
            if (layers.id !== 'customMap-base-layer') {

                this.map.addSource(layers.id, {
                    'type': 'onlineraster',
                    'url': layers.url,
                    'tileSize': 256
                });
                this.map.addLayer({
                    'id': layers.id,
                    'type': 'raster',
                    'source': layers.id,
                    'minzoom': 0,
                    'maxzoom': 19,
                    'paint': {
                        'raster-opacity': 1
                    }
                });
                if (layers.id === 'tianditu-base-layer') {

                    this.map.addSource('tianditu-font-layer', {
                        'type': 'onlineraster',
                        'url': OnlineMapUrlModel.tianditu.font,
                        'tileSize': 256
                    });
                    this.map.addLayer({
                        'id': 'tianditu-font-layer',
                        'type': 'raster',
                        'source': 'tianditu-font-layer',
                        'minzoom': 0,
                        'maxzoom': 19,
                        'paint': {
                            'raster-opacity': 1
                        }
                    });

                }

            }

            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 BaseMap;