components/layer/queryLayer.js

/*``
 * @Author: tjc
 * @Date:   2017-04-20 17:03:05
 * @Last Modified by:   hydata
 * @Last Modified time: 2018-05-10 17:11:35
 * @Email: 304861063@qq.com
 * @File Path: F:\work\hyMap\src\components\layer\buildingLayer.js
 * @File Name: clustersLayer.js
 * @Descript:雷达图查询图层
 */
import mapboxgl from 'mapbox-gl';
import baseLayer from './baseLayer';
import baseUtil from '../../util/baseUtil';
import radarLayer from './radarLayer';

const turf = require('../../tools/turf');

class QueryLayer extends baseLayer {
    /**
     * 初始化
     * @param options
     * @extends baseLayer
     */
    constructor(options) {

        super(options);
        this.id = 'hy-queryLayer-' + baseUtil.guid();
        this.center = [0, 0];

        this.minRadius = 0.05;
        this.maxRadius = 10;
        this.radius = this.minRadius;
        this.queryLayers = [];
        this.marker;
        this.threebox = options.threebox;
        this.init();

        this.isLoad = false;

    }

    init() {


    }

    /**
     * 初始化数据
     */
    initData() {

        return {
            'id': this.id,
            'type': 'fill',
            'source': {
                'type': 'geojson',
                'data': {}
            },
            'layout': {},
            'paint': {
                'fill-color': 'rgb(14,139,225)',
                'fill-opacity': 0.2,
                'fill-outline-color': '#059639'

            }
        };


    }

    /**
     * 加载雷达
     * @param {*} center 
     * @param {*} radius 
     */
    initRadar(center, radius) {

        if (this.radar) {

            this.radar.showRadarLayer();

        } else {

            this.radar = new radarLayer({
                threebox: this.threebox,
                map: this.map,
                center: center,
                radius: radius,
                color: '#ff0000'
            });

        }


    }

    /**
     * 设置雷达半径
     * @param {*} newRadius 
     */
    setRadarRadius(newRadius) {

        // this.radar && this.radar.changeRadius(this.center, newRadius);
        this.radar && this.radar.setRadarOptions(this.center, newRadius);

    }

    /**
     * 设置空间查询半径
     * @param {*} radius 
     */
    setCoords(radius) {

        this.radius = radius;
        this.setMarker(radius);


        const circle = turf.circle(this.center, radius,
            {
                steps: 72,
                units: 'kilometers',
                properties: { id: 'circlePolygon', value: 'circle' }
            });

        if (this.showRadar) {

            this.setRadarRadius(radius);

        } else {

            if (this.isLoad) {

                this.map.getSource(this.id).setData(circle);

            } else {

                this.geojson = this.initData();
                this.geojson.source.data = circle;
                this.addLayer(this.geojson);
                this.isLoad = true;

            }

        }

        return circle;

    }

    /**
     * 设置半径
     * @param {*} radius 
     * @param {*} relative 
     */
    setRadius(radius, relative = false) {

        this.map.fire('drawStart', {
            radius,
            center: this.center
        });
        if (relative) {

            radius = this.radius + radius;

        }
        if (radius < this.minRadius) {

            radius = this.minRadius;
            console.error('半径不能小于' + this.minRadius);

        }

        const circle = this.setCoords(radius);

        this.query(circle);

    }

    /**
     * 增加拖拽标记
     */
    addMarker() {

        //获取图标容器
        let el = document.createElement('div');
        el.className = 'queryBtn';
        //显示雷达半径
        this.label = document.createElement('span');
        this.label.className = 'text';
        this.label.innerHTML = this.radius * 1000 + 'm';
        let btn = document.createElement('span');
        btn.className = 'btn';
        let close = document.createElement('span');
        close.innerHTML = '&times';
        close.className = 'close';

        el.appendChild(btn);
        el.appendChild(this.label);
        el.appendChild(close);
        close.addEventListener('mousedown', (event) => {

            this.clear();
            event.stopPropagation();

        });
        let mouseMove = false;
        //对图标添加拖拽监听,放大缩小雷达
        el.addEventListener('mousedown', (event) => {


            mouseMove = true;

            event.stopPropagation();

        });

        // 将图标放置至地图上
        let markerPosition = turf.transformTranslate(this.centerPoint, this.radius, 90);
        this.marker = new mapboxgl.Marker(el).setLngLat(markerPosition.geometry.coordinates).addTo(this.map);

        //注册事件
        this.map.on('mousemove', (ev) => {

            if (mouseMove) {

                const to = turf.point([ev.lngLat.lng, this.center[1]]);
                let distance = turf.distance(this.centerPoint, to, { units: 'kilometers' });
                if (distance >= this.minRadius && distance <= this.maxRadius) {

                    this.setCoords(distance);

                }

            }

        });
        this.map.on('mouseup', () => {

            if (mouseMove) {

                this.setRadius(this.radius);
                mouseMove = false;

            }

        });

    }

    /**
     * 设置标注位置
     * @param distance
     */
    setMarker(distance) {

        let position = turf.transformTranslate(this.centerPoint, distance, 90);
        this.label.innerHTML = distance * 1000 > 3000 ? distance.toFixed(2) + 'km' : (distance * 1000).toFixed(0) + 'm';
        this.marker.setLngLat(position.geometry.coordinates);

    }

    /**
     * 查询
     * @param geometry
     */
    query(geometry) {

        if (this.map.realReady) {

            let style = this.map.getStyle();
            let sources = style.sources;
            let result = {};
            for (let i in sources) {

                let source = sources[i];
                // if (layers[i].type !== 'line' && layers[i].metadata && layers[i].metadata['hy_key'] === 'hyLayer') {
                if (source.type === 'geojson' && source.data['_LKey'] === 'hyLayer') {

                    //空间过滤
                    if (source.data.features.length > 0 && source.data.features[0].geometry.type === 'Point') {

                        let features = turf.pointsWithinPolygon(source.data, geometry);
                        if (features.features.length > 0) {

                            result[i] = features.features;

                        }

                    }

                }

            }
            this.queryResult = result;
            this.queryFun && this.queryFun({ result, geometry });

        } else {

            setTimeout((geometry) => {

                this.query(geometry);

            }, 100);

        }

    }

    /**
     * 设置空间查询回调
     * @param  {Function}   fun function
     */
    setQueryFun(fun) {

        if (fun) {

            this.queryFun = fun;

        }

    }

    /**
     *获取查询结果
     * @returns {{}|*}
     */
    getQueryResult() {

        return this.queryResult;

    }



    /**
   *空间查询
   * @param {Array} center 中心点
   * @param {Number} radius 半径
   * @param {Boolean} radar 展示动画
   * @param {Number} maxRadius 最小半径
   * @param {Number} minRadius 最大半径
   * @param {Boolean} showMoveSign 显示拖动标记
   * @param {Array} layers 查询图层
   * @param {requestCallback} result 查询结果回调
   */
    spatialQuery({
        center = [0, 0],
        radius = 100,
        radar = false,
        maxRadius = 20,
        minRadius = 0.05,
        showMoveSign = true,layers, result
    } = {}) {

        this.maxRadius = maxRadius;
        this.minRadius = minRadius;
        radius /= 1000;
        radius = radius < this.minRadius ? this.minRadius : radius;
        radius = radius > this.maxRadius ? this.maxRadius : radius;
        this.radius = radius;

        this.center = center;
        this.centerPoint = turf.point(center);


        if (!this.marker && showMoveSign) {

            this.addMarker(center, radius);

        }
        if (radar) {

            this.showRadar = true;
            this.initRadar(center, radius);

        }
        this.setQueryFun(result);
        this.setRadius(radius);

    }

    /**
     * 清空查询结果
     */
    clear() {

        this.isLoad = false;
        this.marker && this.marker.remove();
        this.marker = null;

        if (this.radar) {

            this.radar.clear();

        } else {

            this.dispose();

        }

        this.map.fire('drawClear');

    }
}

export default QueryLayer;