如何使用mapbox选择拾取地图要素

前言

你好! 最近在研究地图元素和客户端交互的方法,我将项目中的应用技能分享给大家!这是关于使用mapbox(点、线、多边形)选择或者称作拾取地图界面要素信息的一篇文章!

需要引入的js、css

我们除了最基本的jquery和mapbox之外,还需要引入turf.min.js,这是一个mapbox多边形和点、线选的插件。

<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="mapbox-gl-draw.js"></script>
<script type="text/javascript" src="mapbox-gl.min.js"></script>
<script src='turf.min.js'></script>
<link type="text/css" rel="stylesheet" href="mapbox-gl.min.css"/>
<link type="text/css" rel="stylesheet" href="mapbox-gl-draw.css"/>

如何加载地图

页面内容如下,需要三个div;一个存放地图需要的展示信息、一个存放地图控件、一个存放地图。

<body>
    <div id="draw_area" style="color: chocolate; font-weight: bold;"></div>
    <div id="draws"></div>
    <div id='map'></div>
</body>

我们需要定义一个demo.js;用来编写如何加载地图和如何拾取要素,页面上引用它,并在demo.js里先加载地图和地图控件,我们用iclient官网上的地图和要素数据。


var host = window.isLocal ? window.server : "https://iserver.supermap.io";
var drawHandleModel;
var attribution = "我的mapbox要素拾取demo";

var map = new mapboxgl.Map({
    container: 'map', // container id
    style: {
        "version": 8,
        "sources": {
            "vector-tiles": {
                "attribution": attribution,
                "type": "vector",
                "tiles": [host + "/iserver/services/map-beijing/rest/maps/beijingMap/tileFeature.mvt?"+
                "returnAttributes=true&compressTolerance=-1&width=512&height=512&viewBounds={bbox-epsg-3857}"+
                "&expands=0:0_2,132_128,138_64,141_32,143_16,145_8,147_4"
                ]
            },
        },
        "sprite": "https://iclient.supermap.io/web/styles/street/sprite",
        "glyphs": host + "/iserver/services/map-beijing/rest/maps/beijingMap/tileFeature/sdffonts/{fontstack}/{range}.pbf",
        "layers": []
    },
    center: [116.4, 39.9],
    minZoom: 10,
    zoom: 11
});

	map.addControl(new mapboxgl.NavigationControl(), 'top-left');

 	var map = getMap();    

        var draw = new MapboxDraw({
            displayControlsDefault: false,
            controls: {
                point: true,
                line_string: true,
                polygon: true,
                trash: true
            }

        });
        window.Draw = draw;
        map.addControl(draw, "top-right");
        map.on("draw.create", this.updateArea);
        map.on("draw.update", this.updateArea);
        map.on("draw.delete", this.delArea);

然后加载地图要素

map.on('load', function() {

    map.addLayer({
        "id": "background",
        "type": "background",
        "layout": {},
        "paint": {
            "background-color": "#75CFF0"
        }
    });
    map.addLayer({
        "id": "面区界R@北京",
        "type": "fill",
        "source": "vector-tiles",
        "source-layer": "面区界R@北京",
        "paint": {
            "fill-color": "#EFE9E1",
        }
    });
    map.addLayer({
        "id": "界线@北京",
        "type": "line",
        "source": "vector-tiles",
        "source-layer": "界线@北京",
        "paint": {
            "line-color": "hsl(240, 8%, 51%)",
            "line-width": 0.5
        }
    });
    map.addLayer({
        "id": "立交桥绿地R@北京",
        "type": "fill",
        "source": "vector-tiles",
        "source-layer": "立交桥绿地R@北京",
        "paint": {
            "fill-color": "hsl(100, 58%, 76%)",
            "fill-opacity": {
                "base": 1,
                "stops": [
                    [
                        5,
                        0
                    ],
                    [
                        6,
                        0.5
                    ]
                ]
            }
        },
    });
    map.addLayer({
        "id": "绿地R@北京",
        "type": "fill",
        "source": "vector-tiles",
        "source-layer": "绿地R@北京",
        "paint": {
            "fill-color": "hsl(100, 58%, 76%)",
            "fill-opacity": {
                "base": 1,
                "stops": [
                    [
                        5,
                        0
                    ],
                    [
                        6,
                        0.5
                    ]
                ]
            }
        },
    });
    map.addLayer({
        "id": "	双线河R@北京",
        "type": "fill",
        "source": "vector-tiles",
        "source-layer": "双线河R@北京",
        "paint": {
            "fill-color": "hsl(196, 80%, 70%)"
        }
    });
    map.addLayer({
        "id": "湖泊、水库R@北京",
        "type": "fill",
        "source": "vector-tiles",
        "source-layer": "湖泊、水库R@北京",
        "paint": {
            "fill-color": "hsl(196, 80%, 70%)"
        }
    });

    map.addLayer({
        "id": "	四级道路L@北京",
        "type": "line",
        "source": "vector-tiles",
        "source-layer": "四级道路L@北京",
        "paint": {
            "line-width": {
                "base": 1.5,
                "stops": [
                    [
                        11,
                        1
                    ],
                    [
                        18,
                        10
                    ]
                ]
            },
            "line-color": "hsl(0, 0%, 100%)",
        }
    });
});

地图上就是这样的效果
地图效果

如何使用地图空间选择要素

先做地图点击事件

 /**
         *  mapBox 提供强大的地图可视化功能
         * */
        map.on('click', function(e) {
            // 以此点*px范围内的正方形算为点击反应区
            var bbox = [
                [e.point.x - 1, e.point.y - 1],
                [e.point.x + 1, e.point.y + 1]
            ];
            // mapbox 返回查询要素的图层属性
            var features = map.queryRenderedFeatures(bbox, {
                layers: ['湖泊、水库R@北京','一级道路L@北京','绿地R@北京']
            });
            
            // 返回查询图层属性feature合集

            var filter_hp = features.reduce(
                function(memo, feature) {
                    //console.log(feature);
                    if (feature.sourceLayer == '湖泊、水库R@北京') {
                        memo.push(feature.properties.SmID);
                        //alert(feature.properties.NAME);
                    } else {
                        console.log(feature.properties);
                    }
                    return memo;
                },['in', 'SmID']
            );
            //返回符合查询要素集合后设置符合这些图层要素的属性
            //map.setFilter('counties-highlighted-hp', filter_hp);

            var filter_dl1 = features.reduce(
                function(memo, feature) {
                    //console.log(feature);
                    if (feature.sourceLayer == '一级道路L@北京') {
                        memo.push(feature.properties.SmID);
                        alert(feature.properties.道路所属区域 + "——" +feature.properties.道路名称);
                    } else {
                        console.log(feature.properties);
                    }
                    return memo;
                },
                ['in', 'SmID']
            );
            //map.setFilter('counties-highlighted-dl1', filter_dl1);

            var filter_ld = features.reduce(
                function(memo, feature) {
                    //console.log(feature);
                    if (feature.sourceLayer == '绿地R@北京') {
                        memo.push(feature.properties.SmID);
                        //alert(feature.properties.NAME);
                    } else {
                        console.log(feature.properties);
                    }
                    return memo;
                },
                ['in', 'SmID']
            );
            //map.setFilter('counties-highlighted-ld', filter_ld);
            
        });

还记的加载地图时的控件方法吗?我们需要定义控件方法的实现!

定义地图时的控件方法

 		function newArea(){
			//画新区域的方法
        }

        function delArea(){
        	//清除区域时
            var answer = document.getElementById('draw_area');
            answer.innerHTML = '';
        }

        function updateArea(e){
        	//更新区域时
            var data = draw.getAll();
            var answer = document.getElementById('draw_area');
            if (data.features.length > 0) {

                // 计算面积
                var area = turf.area(data);
                // restrict to area to 2 decimal points
                var rounded_area = Math.round(area*100)/100;
                answer.innerHTML = '<p><strong>' + rounded_area + '</strong> ㎡</p>';

                //查询选中要素
                var draw_polygon = turf.bbox(e.features[0]);
                var southWest = [draw_polygon[0], draw_polygon[1]];
                var northEast = [draw_polygon[2], draw_polygon[3]];
        
                var northEastPointPixel = map.project(northEast);
                var southWestPointPixel = map.project(southWest);

                var features = map.queryRenderedFeatures([southWestPointPixel, northEastPointPixel], { layers: ['湖泊、水库R@北京','一级道路L@北京','绿地R@北京'] });
 
                //框选结果
                var filter_hp = features.reduce(
                function(memo, feature) {
                    //console.log(feature);
                    if (feature.sourceLayer == '湖泊、水库R@北京') {
                        memo.push(feature.properties.SmID);
                        //alert(feature.properties.NAME);
                    } else {
                        console.log(feature.properties);
                    }
                    return memo;
                },['in', 'SmID']
            );
            //返回符合查询要素集合后设置符合这些图层要素的属性
            map.setFilter('counties-highlighted-hp', filter_hp);

            var filter_dl1 = features.reduce(
                function(memo, feature) {
                    //console.log(feature);
                    if (feature.sourceLayer == '一级道路L@北京') {
                        memo.push(feature.properties.SmID);
                        //alert(feature.properties.道路所属区域 + "——" +feature.properties.道路名称);
                    } else {
                        console.log(feature.properties);
                    }
                    return memo;
                },
                ['in', 'SmID']
            );
            map.setFilter('counties-highlighted-dl1', filter_dl1);

            var filter_ld = features.reduce(
                function(memo, feature) {
                    //console.log(feature);
                    if (feature.sourceLayer == '绿地R@北京') {
                        memo.push(feature.properties.SmID);
                        //alert(feature.properties.NAME);
                    } else {
                        console.log(feature.properties);
                    }
                    return memo;
                },
                ['in', 'SmID']
            );
            map.setFilter('counties-highlighted-ld', filter_ld);


                // var filter_polygon = features.reduce(function(memo, feature) {

                //     if (! (undefined === turf.intersect(feature, e.features[0]))) {
                //         memo.push(feature.properties.SmID);
                //         //alert(feature.properties.NAME);
                //     }
                //     return memo;
                //     // memo.push(feature.properties.SmID);
                //     // //alert(feature.properties.NAME);
                //     // return memo;
                    
                    
                // }, ['in', 'SmID']);

                // map.setFilter("counties-highlighted-hp", filter_polygon);

            } else {
                answer.innerHTML = '';
                if (e.type !== 'draw.delete') alert("请用绘制工具绘制图形后再试!");
            }
        }

这里我们高亮了选中图层的区域
高亮layer
我们需要定义这些layer

    /**
     * 下面添加选中变色layer
     */

    map.addLayer({
        'id': 'counties-highlighted-hp',
        'type': 'fill',
        'source': 'vector-tiles',
        'source-layer': '湖泊、水库R@北京',
        'paint': {
            'fill-outline-color': '#484896',
            'fill-color': '#6e599f',
            'fill-opacity': 0.75
        },
        'filter': ['in', 'SmID', '']
        }
    ); // Place polygon under these labels.

    map.addLayer({
        'id': 'counties-highlighted-dl1',
        'type': 'fill',
        'source': 'vector-tiles',
        'source-layer': '一级道路L@北京',
        'paint': {
            'fill-outline-color': '#484896',
            'fill-color': '#6e599f',
            'fill-opacity': 0.75
        },
        'filter': ['in', 'SmID', '']
        }
    ); // Place polygon under these labels.
    map.addLayer({
        'id': 'counties-highlighted-ld',
        'type': 'fill',
        'source': 'vector-tiles',
        'source-layer': '绿地R@北京',
        'paint': {
            'fill-outline-color': '#484896',
            'fill-color': '#6e599f',
            'fill-opacity': 0.75
        },
        'filter': ['in', 'SmID', '']
        }
    ); // Place polygon under these labels.

});

最后返回一个提供外部js访问的方法


var getMap = function (){
    if (map) {
        return map;
    }
};

效果

效果
输出信息

demo下载地址

demo下载地址

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sun_falls

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值