OpenLayers实操Vue3(点线面文字标注热力图聚合点地图打印等等...)

1.OpenLayers简介

OpenLayers是一个用于开发WebGIS客户端的JavaScript包,为互联网客户端提供强大的地图展示功能,包括地图数据显示与相关操作,主要还是以面向对象进行开发的。

2.初始化地图

(1)安装
npm install ol
(2)实例化地图

要显示一个基本的地图首先需要提供一个容器,设置好宽高,然后引入OpenLayers,添加一个地图图层,地图服务可以使用内置的一个开源地图OSM,也可以使用其他的在线瓦片服务,比如:百度、高德、天地图、必应、谷歌等,具体服务地址可以自行百度,本文使用的是高德的服务

<template>
    <div class="ol-map" id="olMap"></div>
</template>

引入这模块和组件

        import { ref, reactive, toRefs, onMounted, nextTick } from 'vue'   
        import Map from 'ol/Map'  // OpenLayers的主要类,用于创建和管理地图  
        import View from 'ol/View'  // OpenLayers的视图类,定义地图的视图属性     
        import { Tile as TileLayer } from 'ol/layer'  // OpenLayers的瓦片图层类         
        import { XYZ, OSM } from 'ol/source'  // OpenLayers的瓦片数据源,包括XYZ格式和OpenStreetMap专用的数据源         
        import { fromLonLat, toLonLat } from 'ol/proj'  // OpenLayers的投影转换函数,用于经纬度坐标和投影坐标之间的转换         

初始化地图函数

       onMounted(() => {
                // 地图初始化
                initOLMap()
        })

        let map: any = null
        /**
        * Date:2024/3/26
        * Author:zx
        * Function:【初始化地图】
        * @param 无
        */
        function initOLMap() {
            // 创造地图实例
            map = new Map({
                // 设置地图容器的ID
                target: 'olMap',
                // 定义地图的图层列表,用于显示特定的地理信息。
                layers: [
                    // 高德地图
                    // TileLayer表示一个瓦片图层,它由一系列瓦片(通常是图片)组成,用于在地图上显示地理数据。
                    new TileLayer({
                        // 设置图层的数据源为XYZ类型。XYZ是一个通用的瓦片图层源,它允许你通过URL模板来获取瓦片
                        source: new XYZ({
                            url: 'https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
                        })
                    })
                ],
                // 设置地图的视图参数
                // View表示地图的视图,它定义了地图的中心点、缩放级别、旋转角度等参数。
                view: new View({
                    // fromLonLat是一个函数,用于将经纬度坐标转换为地图的坐标系统。
                    center: fromLonLat([108.924652, 34.208527]),//地图中心点
                    zoom: 15,// 缩放级别
                    minZoom: 0,// 最小缩放级别
                    maxZoom: 18,// 最大缩放级别
                    constrainResolution: true// 因为存在非整数的缩放级别,所以设置该参数为true来让每次缩放结束后自动缩放到距离最近的一个整数级别,这个必须要设置,当缩放在非整数级别时地图会糊
                })
 })
}

 一个基本地图就出来了

添加了地图的旋转效果,包括一些控件以及一些常用的事件,完整代码如下

<template>
    <div class="ol-map" id="olMap"></div>
</template>

<script lang='ts' setup>
        import { ref, reactive, toRefs, onMounted, nextTick } from 'vue'   
        import Map from 'ol/Map'  // OpenLayers的主要类,用于创建和管理地图  
        import View from 'ol/View'  // OpenLayers的视图类,定义地图的视图属性     
        import { Tile as TileLayer } from 'ol/layer'  // OpenLayers的瓦片图层类         
        import { XYZ, OSM } from 'ol/source'  // OpenLayers的瓦片数据源,包括XYZ格式和OpenStreetMap专用的数据源         
        import { fromLonLat, toLonLat } from 'ol/proj'  // OpenLayers的投影转换函数,用于经纬度坐标和投影坐标之间的转换         
        import {  
            defaults as defaultInteractions,  
            DragRotateAndZoom,  
        } from 'ol/interaction'  // OpenLayers的交互类,包括默认的交互集合和特定的旋转缩放交互         
        import { defaults, FullScreen, MousePosition, ScaleLine } from 'ol/control'  // OpenLayers的控件类,包括默认的控件集合和特定的全屏、鼠标位置、比例尺控件         
        import Feature from 'ol/Feature'  // OpenLayers的要素类,表示地图上的一个对象或实体          
        import Point from 'ol/geom/Point'  // OpenLayers的点几何类,用于表示点状的地理数据        
        import { Vector as VectorLayer } from 'ol/layer'  // OpenLayers的矢量图层类,用于显示矢量数据        
        import { Vector as VectorSource } from 'ol/source'  // OpenLayers的矢量数据源类,用于管理和提供矢量数据       
        import { Circle as CircleStyle, Style, Stroke, Fill, Icon } from "ol/style"  // OpenLayers的样式类,用于定义图层的样式,包括圆形样式、基本样式、边框、填充和图标       
        import LineString from 'ol/geom/LineString'  // OpenLayers的线几何类,用于表示线状的地理数据       
        import tb from '@/assets/image/hyfw.png'  // 导入一个图片资源        
        import Polygon from "ol/geom/Polygon"  // OpenLayers的多边形几何类,用于表示面状的地理数据
        onMounted(() => {
                // 地图初始化
                initOLMap()
        })
        let map: any = null
        /**
        * Date:2024/3/26
        * Author:zx
        * Function:【初始化地图】
        * @param 无
        */
        function initOLMap() {
            // 创造地图实例
            map = new Map({
                // 设置地图容器的ID
                target: 'olMap',
                // 定义地图的图层列表,用于显示特定的地理信息。
                layers: [
                    // 高德地图
                    // TileLayer表示一个瓦片图层,它由一系列瓦片(通常是图片)组成,用于在地图上显示地理数据。
                    new TileLayer({
                        // 设置图层的数据源为XYZ类型。XYZ是一个通用的瓦片图层源,它允许你通过URL模板来获取瓦片
                        source: new XYZ({
                            url: 'https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
                        })
                    })
                ],
                // 设置地图的视图参数
                // View表示地图的视图,它定义了地图的中心点、缩放级别、旋转角度等参数。
                view: new View({
                    // fromLonLat是一个函数,用于将经纬度坐标转换为地图的坐标系统。
                    center: fromLonLat([108.924652, 34.208527]),//地图中心点
                    zoom: 15,// 缩放级别
                    minZoom: 0,// 最小缩放级别
                    maxZoom: 18,// 最大缩放级别
                    constrainResolution: true// 因为存在非整数的缩放级别,所以设置该参数为true来让每次缩放结束后自动缩放到距离最近的一个整数级别,这个必须要设置,当缩放在非整数级别时地图会糊
                }),
                // 按住shift进行旋转
                interactions: defaultInteractions().extend([new DragRotateAndZoom()]),
                // 控件
                controls: defaults().extend([
                    new FullScreen(), // 全屏
                    new MousePosition(), // 显示鼠标当前位置的地图坐标
                    new ScaleLine()// 显示比例尺
                ])

            })

            // 事件
            map.on('moveend', (e:any) => {
                console.log('地图移动', e)
                // 获取当前缩放级别
                var zoomLevel = map.getView().getZoom();
                    console.log('当前缩放级别:', zoomLevel);
            })
            map.on('rendercomplete', () => {
                console.log('渲染完成')
            })
            map.on('click', (e:any) => {
                console.log('地图点击', e)
                var coordinate = e.coordinate;

                // 将投影坐标转换为经纬度坐标
                var lonLatCoordinate = toLonLat(coordinate);
                // 输出转换后的经纬度坐标
                console.log('经纬度坐标:', lonLatCoordinate);
            })

        }

3.openlayers实战

(1)openlayers添加点

自己设置点位或者添加图片都可

  /**
        * Date:2024/3/26
        * Author:zx
        * Function:【点】
        * @param 无
        */
        const dotMethod = () => {
            // 创建点特征(Feature):
            let feature = new Feature({
                title: 'xian',
                geometry: new Point(fromLonLat([108.924652, 34.208527])) // 转换坐标
            })
            // 设置特征样式(Style):
            feature.setStyle(
                new Style({
                    // 使用 CircleStyle 创建一个圆形的点 

                    image: new CircleStyle({
                     fill: new Fill({
                        color: 'red',
                      }),
                      radius: 7,
                     }),
                })
            );
            // 创建和添加特征到源(Source)
            // VectorSource表示一个矢量要素源,它用于存储和显示地理数据。
            let source = new VectorSource()
            source.addFeature(feature)
            // 创建图层并设置源(Layer)
            // VectorLayer表示一个矢量图层,它由一系列矢量要素(Feature)组成,用于在地图上显示地理数据。
            let layer = new VectorLayer()
            layer.setSource(source)
            map.addLayer(layer)
        }

(2)鼠标点击生成点

     /**
        * Date:2024/3/26
        * Author:zx
        * Function:【鼠标点击生成点】
        * @param 无
        */
        const DrawMethod = () => {
            // 创建一个绘制交互(Draw)
            // 监听地图上的鼠标点击事件
            map.on('click', function (event: any) {
                // 获取点击位置的坐标
                let coordinate = event.coordinate;

                // 创建点特征(Feature)
                let pointFeature = new Feature({
                    geometry: new Point(coordinate)
                });

                // 设置点特征的样式(Style)
                pointFeature.setStyle(
                    new Style({
                        image: new CircleStyle({
                            fill: new Fill({
                                color: 'red' // 点的填充颜色为红色
                            }),
                            radius: 7, // 点的半径
                            stroke: new Stroke({
                                color: 'black', // 点的边界颜色为黑色
                                width: 2 // 点的边界宽度
                            })
                        })
                    })
                );

                // 创建和添加特征到源(Source)
                let source = new VectorSource();
                source.addFeature(pointFeature);

                // 创建图层并设置源(Layer)
                let layer = new VectorLayer();
                layer.setSource(source);

                // 将图层添加到地图上
                map.addLayer(layer);
            });

        }

(3)openlayers添加线

       /**
        * Date:2024/3/26
        * Author:zx
        * Function:【线】
        * @param 无
        */
        const lineMethod = () => {
            // 创建线特征(Feature):
            let lineFeature = new Feature({
                geometry: new LineString([
                    fromLonLat([108.924652, 34.208527]), // 起点经纬度坐标
                    fromLonLat([108.92314996295164, 34.220681741967226]), // 终点经纬度坐标
                    // 你可以在这里添加更多的坐标点,以绘制更复杂的线
                ])
            });

            // 设置线特征的样式(Style):
            lineFeature.setStyle(
                new Style({
                    stroke: new Stroke({
                        color: 'red', // 线的颜色
                        width: 2 // 线的宽度
                    })
                })
            );

            // 创建和添加特征到源(Source)
            let source = new VectorSource();
            source.addFeature(lineFeature);

            // 创建图层并设置源(Layer)
            let layer = new VectorLayer();
            layer.setSource(source);

            // 将图层添加到地图上
            map.addLayer(layer);
        }

(4)openlayers添加面

       /**
        * Date:2024/3/26
        * Author:zx
        * Function:【面】
        * @param 无
        */
        const faceMethod = () => {
            // 定义多边形的坐标数组,这里使用一个简单的正方形作为示例
            let coordinates = [
                [
                    fromLonLat([108.924652, 34.208527]),
                    fromLonLat([108.925652, 34.208527]),
                    fromLonLat([108.925652, 34.209527]),
                    fromLonLat([108.924652, 34.209527]),
                    fromLonLat([108.924652, 34.208527])
                ]
            ];

            // 创建多边形的几何对象
            let polygon = new Polygon(coordinates);

            // 创建特征(Feature)
            let polygonFeature = new Feature({
                geometry: polygon
            });

            // 设置多边形的样式(Style)
            polygonFeature.setStyle(
                new Style({
                    stroke: new Stroke({
                        color: 'red', // 多边形边界线的颜色
                        width: 2 // 多边形边界线的宽度
                    }),
                    fill: new Fill({
                        color: 'rgba(255, 0, 0, 0.5)' // 多边形填充颜色,这里设置为半透明红色
                    })
                })
            );

            // 创建和添加特征到源(Source)
            let source = new VectorSource();
            source.addFeature(polygonFeature);

            // 创建图层并设置源(Layer)
            let layer = new VectorLayer();
            layer.setSource(source);

            // 将图层添加到地图上
            map.addLayer(layer);
        }

(5)openlayers添加图片

       const dotMethod = () => {
            // 创建点特征(Feature):
            let feature = new Feature({
                title: 'xian',
                geometry: new Point(fromLonLat([108.924652, 34.208527])) // 转换坐标
            })
            // 设置特征样式(Style):
            feature.setStyle(
                new Style({
                    // 自定义图片
                    image: new Icon({
                        //   anchor: [1, 1],// 显示位置
                                //图标缩放比例
                            // scale:0.5,
                            //透明度
                            opacity: 0.75,
                        src: zq// 图片url
                    })
                })
            );
            // 创建和添加特征到源(Source)
            // VectorSource表示一个矢量要素源,它用于存储和显示地理数据。
            let source = new VectorSource()
            source.addFeature(feature)
            // 创建图层并设置源(Layer)
            // VectorLayer表示一个矢量图层,它由一系列矢量要素(Feature)组成,用于在地图上显示地理数据。
            let layer = new VectorLayer()
            layer.setSource(source)
            map.addLayer(layer)
        }

(6)openlayers添加文字标注

       /**
        * Date:2024/3/26
        * Author:zx
        * Function:【文字标注】
        * @param 无
        */
        const addTextAnnotation = (text:any, coordinates:any) => {
            // 创建一个点特征(Feature)作为文本标注的位置
            let pointFeature = new Feature({
                geometry: new Point(coordinates) // 设置点的坐标
            });

            // 创建一个带有文本的样式(Style)
            let textStyle = new Style({
                text: new Text({
                    text: text, // 文本内容
                    font: '28px Arial, sans-serif', // 字体样式
                    fill: new Fill({ color: 'red' }), // 文本填充颜色
                    stroke: new Stroke({ color: 'white', width: 5 }), // 文本边框样式
                    offsetX: 0, // 文本水平偏移量
                    offsetY: -10, // 文本垂直偏移量
                    textAlign: 'center' // 文本水平对齐方式
                })
            });

            pointFeature.setStyle(textStyle);

            // 创建一个特征源(Source)并添加点特征
            let source = new VectorSource();
            source.addFeature(pointFeature);

            // 创建一个矢量图层(Layer)并设置特征源
            let layer = new VectorLayer({
                source: source
            });

            // 将图层添加到地图上
            map.addLayer(layer);
        };

注:在需要的地方引用

 addTextAnnotation('你好呀', fromLonLat([108.924652, 34.208527]));

(7)openlayers添加popup

注:引入Text

     import { Circle as CircleStyle, Style, Text,Stroke, Fill, Icon } from "ol/style"  // OpenLayers的样式类,用于定义图层的样式,包括圆形样式、基本样式、边框、填充和图标       

       /**
        * Date:2024/3/26
        * Author:zx
        * Function:【添加popup】
        * @param 无
        */
        const createPopup = () => {
            // 创建一个弹出窗口容器元素
            const popupContainer = document.createElement('div');
            popupContainer.setAttribute('id', 'popup');
            popupContainer.innerHTML = '<p>Your Popup Content Here</p>';
            popupContainer.style.height = '50px';
            popupContainer.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'; // 设置背景颜色,这里使用了半透明白色
            popupContainer.style.textAlign = 'center';
            popupContainer.style.padding = '10px';
            popupContainer.style.border = '1px solid #ccc';
            popupContainer.style.color = 'red';
            // 创建一个 Overlay 实例,将弹出窗口容器元素添加到 Overlay 中
            const popupOverlay = new Overlay({
                element: popupContainer,
                autoPan: {
                    animation: {
                        duration: 250 // 设置自动平移动画的持续时间,单位为毫秒
                    }
                }
            });

            // 将 Overlay 添加到地图上
            map.addOverlay(popupOverlay);

            // 设置弹出窗口的位置(示例位置)
            const popupPosition = fromLonLat([108.924652, 34.208527]); // 替换 longitude 和 latitude 为实际的经纬度值
            popupOverlay.setPosition(popupPosition);

            // 显示弹出窗口
            popupContainer.style.display = 'block';
        }

(8)openlayers添加热力图

注:引入热力图库

        import HeatmapLayer from 'ol/layer/Heatmap';

        /**
        * Date:2024/3/26
        * Author:zx
        * Function:【热力图】
        * @param 无
        */
        const heatMap = ()=>{
              // 添加随机点数据
            const heatmapData = [];
            for (let i = 0; i < 100; i++) {
                const randomLon = 108.924652 + (Math.random() - 0.5) * 0.2; // 在中心经度附近随机生成经度
                const randomLat = 34.208527 + (Math.random() - 0.5) * 0.2; // 在中心纬度附近随机生成纬度
                heatmapData.push(fromLonLat([randomLon, randomLat]));
            }

            // 创建一个矢量数据源,并添加随机点数据
            const vectorSource = new VectorSource({
                features: heatmapData.map(coord => new Feature(new Point(coord)))
            });

            // 创建一个热力图层
            const heatmapLayer = new HeatmapLayer({
                source: vectorSource,
                blur: 15, // 设置模糊半径
                radius: 20 // 设置热力点半径
            });

            // 将热力图层添加到地图中
            map.addLayer(heatmapLayer);
        }

(9)openlayers添加聚合点

创建聚合点(Cluster)的逻辑通常用于在地图上显示大量的点数据,当点过于密集时,它们会被聚合到一个表示多个点的单个聚合点中。在OpenLayers等地图库中,你可以使用特定的聚合图层来实现这一功能。

       /**  
         * Date: 2024/3/27  
         * Author: zx  
         * Function: 【聚合点图层】  
         * @param 无  
         */  
        const createClusterLayer = () => {  
            // 添加随机点数据  
            const clusterData = [];  
            for (let i = 0; i < 1000; i++) { // 假设有1000个随机点  
                const randomLon = 108.924652 + (Math.random() - 0.5) * 0.2; // 在中心经度附近随机生成经度  
                const randomLat = 34.208527 + (Math.random() - 0.5) * 0.2; // 在中心纬度附近随机生成纬度  
                clusterData.push(fromLonLat([randomLon, randomLat]));  
            }  
        
            // 创建一个矢量数据源,并添加随机点数据  
            const vectorSource = new VectorSource({  
                features: clusterData.map(coord => new Feature(new Point(coord)))  
            });  
        
            // 创建一个聚合图层  
            const clusterLayer = new VectorLayer({  
                source: new Cluster({  
                    distance: 40, // 设置聚合的距离阈值  
                    source: vectorSource  
                }),  
                style: function(feature) {  
                    // 根据聚合点的数量设置不同的样式  
                    const size = feature.get('features').length;  
                    return new Style({  
                        image: new CircleStyle({  
                            radius: 10 + size / 10, // 半径根据聚合点数量进行调整  
                            stroke: new Stroke({ color: 'white', width: 2 }),  
                            fill: new Fill({ color: getColor(size) }) // 通过数量获取颜色  
                        }),  
                        text: new Text({  
                            text: size.toString(),  
                            fill: new Fill({ color: '#fff' }),  
                            stroke: new Stroke({ color: '#000', width: 3 })  
                        })  
                    });  
                }  
            });  
        
            // 辅助函数:根据聚合点的数量获取不同的颜色  
            function getColor(size: number) {  
                let color = 'blue';  
                if (size > 100) color = 'red';  
                else if (size > 50) color = 'orange';  
                else if (size > 20) color = 'yellow';  
                return color;  
            }  
        
            // 将聚合图层添加到地图中  
            map.addLayer(clusterLayer);  
        };

4.地图打印

(1)引入

先引入一个打印模块,一个样式文件

        import OlExtPrintDialog from 'ol-ext/control/PrintDialog';   //地图打印
        import 'ol-ext/dist/ol-ext.min.css';  //样式文件

(2)配置

配置打印控件

        let printControl = new OlExtPrintDialog({  
            lang: "zh",     // 设置语言为中文  
            pdf: true,      // 允许生成PDF文件  
            openWindow: false, // 不在新的浏览器窗口中打开打印对话框,而是在当前页面的某个元素中打开  
            title: '打印地图' // 打印对话框的标题  
        });

(3)添加

添加到 OpenLayers 地图实例中

//new Map完成之后  
 map.addControl(printControl);

(4)打印

点击地图左上角打印按钮,实现地图打印功能

注:打印预览的一切样式都建立在地图中

  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个简单的示例代码,用于在Vue2中使用OpenLayers 6来显示一个地图,添加一个聚合,并在聚合时显示相关的标注信息弹窗: ```html <template> <div id="map"></div> </template> <script> import 'ol/ol.css' import { Map, View } from 'ol' import Point from 'ol/geom/Point' import Feature from 'ol/Feature' import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer' import { fromLonLat } from 'ol/proj' import { Vector as VectorSource } from 'ol/source' import { Cluster } from 'ol/source' import Overlay from 'ol/Overlay' export default { name: 'MapComponent', data() { return { map: null, popup: null } }, mounted() { this.initMap() }, methods: { initMap() { // 创建地图 this.map = new Map({ target: 'map', layers: [ new TileLayer({ source: new XYZ({ url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png' }) }) ], view: new View({ center: fromLonLat([116.7, 39.5]), zoom: 10 }) }) // 创建聚合 const clusterSource = new Cluster({ distance: 40, source: new VectorSource({ features: [ new Feature(new Point(fromLonLat([116.718, 39.523]))), new Feature(new Point(fromLonLat([116.729, 39.504]))), new Feature(new Point(fromLonLat([116.752, 39.506]))), new Feature(new Point(fromLonLat([116.745, 39.521]))), new Feature(new Point(fromLonLat([116.738, 39.53]))), new Feature(new Point(fromLonLat([116.707, 39.534]))), new Feature(new Point(fromLonLat([116.698, 39.526]))), new Feature(new Point(fromLonLat([116.686, 39.517]))) ] }) }) const clusterLayer = new VectorLayer({ source: clusterSource }) this.map.addLayer(clusterLayer) // 创建弹窗 const popupContainer = document.createElement('div') popupContainer.setAttribute('id', 'popup') popupContainer.setAttribute('class', 'ol-popup') document.body.appendChild(popupContainer) this.popup = new Overlay({ element: popupContainer, autoPan: true, autoPanAnimation: { duration: 250 } }) this.map.addOverlay(this.popup) // 监听聚合击事件 this.map.on('click', (event) => { const feature = this.map.forEachFeatureAtPixel(event.pixel, (feature) => { return feature }) if (feature && feature.get('features').length > 1) { const coordinates = feature.getGeometry().getCoordinates() const count = feature.get('features').length const content = ` <p>共有${count}个标注</p> ` this.popup.setPosition(coordinates) this.popup.getElement().innerHTML = content } }) } } } </script> <style> .ol-popup { position: absolute; background-color: white; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); padding: 15px; border-radius: 10px; border: 1px solid #cccccc; bottom: 12px; left: -50px; min-width: 200px; } </style> ``` 该示例代码创建了一个地图,并在其中添加了一个聚合,每个聚合包含多个标注。当用户聚合时,会弹出一个标注信息弹窗,显示该聚合中包含的标注数量。你可以根据自己的需要修改代码中的坐标、弹窗内容等信息。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值