[Webgis][地图加载]Openlayer添加点线面

描述在前

本文继续以项目需求为方向,进行学习记录,在Web地图应用中,常见的需求就是在地图上添加点Point(图片或点),添加多段线Polyline,以及添加多边形Polygon,下面上代码,方便理解。

代码在后

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/ol@v8.2.0/dist/ol.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v8.2.0/ol.css">
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>

    <style>
        html { height: 100% }
        body { height: 100%;margin: 0px;padding: 0px }

        ul,li{
            margin:0;
            padding:0;
            list-style:none;
        }
        p{font-size:12px;}
        li{
            line-height:28px;
        }
        #container{
            width: 100%;
            height: 100%;
            overflow: hidden;
            position: absolute;
        }
        .unselectMap{
            float: left;
            box-shadow: rgba(0, 0, 0, 0.35) 2px 2px 3px; 
            border-left: 1px solid rgb(139, 164, 220); 
            border-top: 1px solid rgb(139, 164, 220); 
            border-bottom: 1px solid rgb(139, 164, 220); 
            background: rgb(255, 255, 255); 
            padding: 2px 6px; 
            font-style: normal; 
            font-variant: normal; 
            font-kerning: auto; 
            font-optical-sizing: auto; 
            font-feature-settings: normal; 
            font-variation-settings: normal; 
            font-stretch: normal; 
            font-size: 12px; 
            line-height: 1.3em; 
            font-family: arial, sans-serif; 
            text-align: center; 
            white-space: nowrap; 
            border-radius: 3px 0px 0px 3px; 
            color: rgb(0, 0, 0);
        }
        .selectMap{
            float: left;
            box-shadow: rgba(0, 0, 0, 0.35) 2px 2px 3px; 
            border-width: 1px; 
            border-style: solid; 
            border-color: rgb(139, 164, 220); 
            background: rgb(142, 168, 224); 
            padding: 2px 6px; 
            font: bold 12px / 1.3em arial, sans-serif; 
            text-align: center; 
            white-space: nowrap; 
            border-radius: 0px 3px 3px 0px; 
            color: rgb(255, 255, 255);
        }
        .mapChange{
            margin-left: 4rem;
            padding-left: 40px;
            padding-top: 10px;
            white-space: nowrap; 
            cursor: pointer; 
            position: absolute; 
            z-index: 1; 
            text-size-adjust: none;
        }
        .drawing-panel {
            z-index: 999;
            position: fixed;
            bottom: 1rem;
            right: 0.2rem;
            margin-left: 0.2rem;
            padding: 0.1rem 0.1rem;
            border-radius: .25rem;
            background-color: transparent;
            /* 设置阴影 */
            box-shadow: 0 0px 0px 0 rgba(27, 142, 236, 0.5); 
        }
        .pos {
	        width: 150px;
            height: 30px;
            float: left;
            background-color: #fff;
            color: rgba(27, 142, 236, 1);
            font-size: 13px;
            border:1px solid rgba(27, 142, 236, 1);
            border-radius: 5px;
            margin: 0 5px;
            text-align: center;
            line-height: 30px;
        }
        .pos2 {
            width: 180px;
            height: 30px;
            float: left;
            background-color: #fff;
            color: red;
            font-size: 13px;
            border:1px solid rgba(27, 142, 236, 1);
            border-radius: 5px;
            margin: 0 5px;
            text-align: center;
            line-height: 30px;
        }

        /* 比例尺的样式 */
        .my-scale-line {
            position: absolute;
            right: 75px;
            font-weight: 700;
            font-size: 12px;
            color: white;
            bottom: 60px;
            left: auto;
            border: 2px solid white;
            border-top: none;
            text-align: center;
            background-color: hsla(0, 0%, 100%, 0);
            height: 8px;
            line-height: 0;
        }

        /* 设置缩放按钮与滑块的样式 */
        .ol-zoom .ol-zoom-out {
            margin-top: 200px;
        }
        .ol-zoomslider {
            background-color: transparent;
            top: calc(0.5em + 2px + 1px + 1.14 * 1.375em);
        }

        .ol-touch .ol-zoom .ol-zoom-out {
            margin-top: 212px;
        }
        .ol-touch .ol-zoomslider {
            top: 2.75em;
        }

        .ol-zoom-in.ol-has-tooltip:hover [role=tooltip],
        .ol-zoom-in.ol-has-tooltip:focus [role=tooltip] {
            top: 3px;
        }

        .ol-zoom-out.ol-has-tooltip:hover [role=tooltip],
        .ol-zoom-out.ol-has-tooltip:focus [role=tooltip] {
            top: 232px;
        }
    </style>

    <title>Tool</title>

</head>
<body>

    <div id="container"></div>
    <script>

        // 核心图层layer 为三种地图形式创建各自的 Layer,其中混合地图需要 路网地图AMapLayerRoadNet 与 卫星地图AMapLayerSatellite 叠加
        // AMapLayer 为普通地图的 Layer
        AMapLayer = new ol.layer.Tile({
            // 每个图层有对应的数据源(Source)
            source: new ol.source.XYZ({
                // 该url为高德瓦片地图地址
                url:'https://wprd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'
            })
        });
        // AMapLayerRoadNet 为路网地图的 Layer
        AMapLayerRoadNet = new ol.layer.Tile({
            // 每个图层有对应的数据源(Source)
            source: new ol.source.XYZ({
                // 该url为高德瓦片地图地址
                url:'https://wprd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
            })
        });
        // AMapLayerSatellite 为卫星地图的 Layer
        AMapLayerSatellite = new ol.layer.Tile({
            // 每个图层有对应的数据源(Source)
            source: new ol.source.XYZ({
                // 该url为高德瓦片地图地址
                url:'https://wprd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=6&x={x}&y={y}&z={z}'
            })
        });
        // 把整个地图看作一个容器(Map)
        var map = new ol.Map({
            target: 'container',
            // 核心为地图图层(Layer),若想实现路网与卫星地图混合,AMapLayerSatellite 需要在 AMapLayerRoadNet 之前
            layers: [AMapLayer,AMapLayerSatellite,AMapLayerRoadNet], 
            // 并由地图视图(View)进行地图表现
            view: new ol.View({
                //设定默认坐标系
                projection: 'EPSG:3857', 
                //设定中心点,因为默认坐标系为 3587,所以要将我们常用的经纬度坐标系4326 转换为 3587坐标系
                center: ol.proj.transform([120.266053,31.550228], 'EPSG:4326', 'EPSG:3857'), 
                // 默认显示级别,相当于瓦片地图的 Z 级别
                zoom: 5,
                // 最小显示级别
                minZoom:3, 
                // 最大显示级别
                maxZoom:19
            })
        });
        // 默认显示普通地图,所以将 AMapLayer 的 Visible 设定为true,其他设定为fasle
        AMapLayer.setVisible(true);
		AMapLayerRoadNet.setVisible(false);
		AMapLayerSatellite.setVisible(false);

        // 创建坐标显示框
        function createMapShowBar(){
            let htmlBottomShow = "";
            htmlBottomShow += "<li id=\"position0\" class=\"pos\">0.0,0.0</li>";
            let htmlBottomUl = document.createElement("ul");
            htmlBottomUl.className = "drawing-panel";
            htmlBottomUl.innerHTML = htmlBottomShow;
            document.body.appendChild(htmlBottomUl);
        }
        // 创建地图形式切换按钮
        function createMapChangeBar(){
            let htmllet = "";
            htmllet += "<div title=\"显示普通地图\" id=\"usualMap\" class=\"selectMap\">地图</div>";
            htmllet += "<div title=\"显示卫星地图\" id=\"satelliteMap\" class=\"unselectMap\">卫星</div>";
            htmllet += "<div title=\"显示混合地图\" id=\"hybridMap\" class=\"unselectMap\">混合</div>";
            let p = document.createElement("div");
            p.className = "mapChange";
            p.innerHTML = htmllet;
            document.body.appendChild(p);
        }
        // 设定地图形式切换按钮的响应函数
        function mapTypeChangeMap() {
            createMapShowBar();
            createMapChangeBar();
            var usualMap=document.getElementById("usualMap");
            var satelliteMap=document.getElementById("satelliteMap");
            var hybridMap=document.getElementById("hybridMap");
            usualMap.addEventListener('click',function(){
                usualMap.className="selectMap";
                satelliteMap.className="unselectMap";
                hybridMap.className="unselectMap";
                AMapLayer.setVisible(true);
                AMapLayerRoadNet.setVisible(false);
                AMapLayerSatellite.setVisible(false);
            })
            satelliteMap.addEventListener('click',function(){
                usualMap.className="unselectMap";
                satelliteMap.className="selectMap";
                hybridMap.className="unselectMap";
                AMapLayer.setVisible(false);
                AMapLayerRoadNet.setVisible(false);
                AMapLayerSatellite.setVisible(true);
            })
            hybridMap.addEventListener('click',function(){
                usualMap.className="unselectMap";Polygon
                satelliteMap.className="unselectMap";
                hybridMap.className="selectMap";

                AMapLayer.setVisible(false);
                AMapLayerRoadNet.setVisible(true);
                AMapLayerSatellite.setVisible(true);
            })
        }
        mapTypeChangeMap();

        // 添加比例尺
        map.addControl(new ol.control.ScaleLine({
            units: 'metric', // 设置单位
            className: 'my-scale-line'
        }));
        // 添加缩放滑块
        map.addControl(new ol.control.ZoomSlider());
        // 添加全局视图小控件
        map.addControl(new ol.control.OverviewMap({
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.XYZ({
                        // 该url为高德瓦片地图地址
                        url:'https://wprd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'
                    })
                })
            ],
        }));
        
        // 监听鼠标移动,显示实时坐标
        var moveSignal = map.on('pointermove',(evt)=>{
            let movePoint = ol.proj.transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326')
            document.getElementById('position0').innerText = movePoint[0].toFixed(7) + "," + movePoint[1].toFixed(7);
        });


        //============ 本文实现功能从此处开始 ================//
        
        // 定义一个保存添加点的数组
        var addPoints = [];
        // 定义一个 线LineString
        var wayPolyline;
        // 定义一个 多边形Polygon
        var wayPolygon;
        // 定义一个画图的图层,后面添加的 点线面 都是在此图层上添加
        var drawLayer = new ol.layer.Vector({
            // 定义图层数据源,给图层数据源添加数据
            source: new ol.source.Vector()
        });
        // 将画图的图层添加给地图
        map.addLayer(drawLayer);  

        // 定义一个函数,功能为创建 Point 图形的样式,path为图片的路径,name为图片上显示的信息
        function createPointStyle(path,name) {
            return new ol.style.Style({
                image: new ol.style.Icon({
                    anchor: [0.5, 1], //中心改到图片下面
                    src:path
                }),
                text: new ol.style.Text({
                    textAlign: 'center',            //位置
                    textBaseline: 'middle',         //基准线
                    font: 'normal 14px 微软雅黑',    //文字样式
                    text: name,                     //文本内容
                    offsetY:-19,                    //Y偏移值,目的是使文字居中
                    fill: new ol.style.Fill({       //文本填充样式(即文字颜色)
                        color: '#fff'
                    }),
                })
            });
        }
        //定义一个函数,功能为增加点
        function pointAdd(point) {
            // 创建 Point 
            let pointGeom = new ol.geom.Point(point);
            // 创建 Feature
            let addMarker = new ol.Feature(pointGeom);
            // 设置样式
            addMarker.setStyle(createPointStyle('image/marker.png',String(addPoints.length)));
            // 将 Feature 添加到图层
            drawLayer.getSource().addFeature(addMarker);
        }
        // 定义一个函数,功能为增加线段
        function polylineAdd(points){
            wayPolyline = new ol.geom.LineString(points);
            // 创建 Feature
            let wayPolylineF = new ol.Feature(wayPolyline);
            wayPolylineF.setStyle(
                new ol.style.Style({
                    // 点断颜色
                    stroke: new ol.style.Stroke({
                        color: 'red',
                        width: 2,
                        // 虚线 20 为虚线小线段长度
                        lineDash: [20], 
                    }),
                })
            )
            drawLayer.getSource().addFeature(wayPolylineF);
            // 定位到画图位置
            // map.getView().fit(wayPolyline, { duration: 500, padding: [150, 150, 150, 150] });
        }
        polylineAdd([]);
        // 定义一个函数,功能为增加多边形
        function polygonAdd(points){
            wayPolygon = new ol.geom.Polygon([points]);	
            // 创建 Feature
            let addPolyon = new ol.Feature(wayPolygon);
            addPolyon.setStyle(
                new ol.style.Style({
                    // 多边形填充颜色
                    fill: new ol.style.Fill({
                        color: 'rgba(0, 255, 0, 0.5)',
                    }),
                    // 多边形边框颜色
                    stroke: new ol.style.Stroke({
                        color: 'white',
                        width: 2,
                    }),
                })
            )
            drawLayer.getSource().addFeature(addPolyon);
        }
        polygonAdd([]);

        // 监听鼠标点击
        var clickSignal = map.on('click',(evt)=>{
            // 添加点
            pointAdd(evt.coordinate);
            // 保存点到数组
            addPoints.push(evt.coordinate);
            // 大于一个点时,可画线段
            if(addPoints.length>1) {
                console.log("add polyline");
                wayPolyline.setCoordinates(addPoints);
               
            } 
            // 大于两个点时可画多边形
            if(addPoints.length>2) {
                console.log("add polygon");
                wayPolygon.setCoordinates([addPoints]);
            }
        })

    </script>
</body>
</html>

显示效果如下
在这里插入图片描述

最后总结

以上代码添加的时候是响应Map的点击信号,实际应用中,可能是某个实时轨迹,或者某个实时位置,道理相同,调用对应的add功能块,即可添加图形。下一章,让我们记录一下,如何让添加的图片旋转起来。

  • 19
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenLayers中,可以通过创建要素(Feature)并将其添加到矢量图层(VectorLayer)中来创建点线面。对于数据量不大的场景,可以直接从数据库读取数据,并将其转换为要素,然后添加到矢量图层中以在地图上展示。可以封装一个方法来方便地添加点线面。 例如,在WebGIS开发中,可以使用以下代码创建点线面图层: ```javascript // 创建点线面图层 addDrawLayer() { // 创建矢量数据源 const draw_source = new ol.source.Vector(); // 创建点线面图层 const draw_vector = new ol.layer.Vector({ source: draw_source, title: '自由图层绘制点线面', name: 'operateTu', visible: true, zIndex: 99999, style: new ol.style.Style({ fill: new ol.style.Fill({ color: "rgba(255, 255, 255, 0.2)", }), stroke: new ol.style.Stroke({ color: "#ffcc33", width: 3, }), image: new ol.style.Icon({ src: require('@/assets/index/dingwei-tu.png'), scale: 1, }), }), }); // 将图层添加地图中 this.map.addLayer(draw_vector); } ``` 这段代码创建了一个名为`draw_vector`的矢量图层,并设置了图层的样式。可以根据需要自定义样式。然后,将该图层添加地图中即可。 请注意,这只是一个示例代码,具体的实现可能会根据项目的需求有所不同。 #### 引用[.reference_title] - *1* [Openlayers 添加 WKT WKB GeoJson 格式点线面数据](https://blog.csdn.net/linzi19900517/article/details/123210537)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [openlayers6 第一篇绘制点线面](https://blog.csdn.net/m0_65607651/article/details/130517064)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [openlayers3基础点线面添加](https://blog.csdn.net/qq_35091287/article/details/109112342)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值