OpenLayers 在Vue中画点线面

本文介绍如何使用VUE和OpenLayers库实现地图绘制功能,包括创建地图、添加图层、设置坐标系及中心点,以及通过下拉菜单选择不同几何类型(如点、线、多边形等)进行地图上的绘制交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VUE代码如下

<template>
    <div id="map" ref="rootmap">
        <div style="position: absolute;z-index: 9999; background: ghostwhite;display: flex;">
            <div>Geometry type &nbsp;</div>
            <select v-model="typeSelected" @change="getTypeSelected">
                <option value="Point">Point</option>
                <option value="LineString">LineString</option>
                <option value="Polygon">Polygon</option>
                <option value="Circle">Circle</option>
                <option value="None">None</option>
            </select>
        </div>
    </div>
</template>

<script>
    import "ol/ol.css";
    import { Map, View } from "ol";
    import TileLayer from "ol/layer/Tile";
    import VectorLayer from "ol/layer/Vector"
    import {OSM, TileWMS,Vector} from "ol/source";
    import GeoJSON from "ol/format/GeoJSON";
    import {Style,Stroke} from "ol/style";
    import Draw from "ol/interaction/Draw";

    export default {
        data() {
            return {
                typeSelected:'LineString',
                drawLayer:null,
                draw:null,
                map: null
            };
        },
        mounted() {
            let osmLayer = new TileLayer({
                source: new OSM()
            });
            this.map = new Map({
                target: "map",
                layers: [
                    osmLayer
                ],
                view: new View({
                    projection: "EPSG:4326",    //使用这个坐标系
                    center: [114.064839, 22.548857],  //深圳
                    zoom: 12
                })
            });

            // 添加一个绘制的线使用的layer
            this.drawLayer = new VectorLayer({
                //layer所对应的source
                source: new Vector(),

            })
            //把layer加入到地图中
            this.map.addLayer(this.drawLayer);
        },
        methods:{
            getTypeSelected(){
                this.draw && this.map.removeInteraction(this.draw);
                //再根据typeSelect的值绘制新的Interaction
                this.addInteraction();
            },
            addInteraction() {
                let value = this.typeSelected;
                if (value !== 'None') {
                    this.draw = new Draw({
                        source: this.drawLayer.getSource(),
                        type: this.typeSelected,
                        style: new Style({
                            stroke: new Stroke({
                                color: 'blue',
                                width: 3
                            })
                        })
                    });
                    this.map.addInteraction(this.draw);
                }
            }
        }
    };
</script>

<style>
    #map{height:100%;}
    /*隐藏ol的一些自带元素*/
    .ol-attribution,.ol-zoom { display: none;}
</style>

效果如下

在这里插入图片描述

关键代码

  1. 创建openlayers地图,使用OpenStreetMap的开放地图数据。
     let osmLayer = new TileLayer({
         source: new OSM()
     });
     this.map = new Map({
         target: "map",
         layers: [
             osmLayer,
         ],
         view: new View({
             projection: "EPSG:4326",    //使用这个坐标系
             center: [114.064839, 22.548857],  //深圳
             zoom: 12
         })
     });
  1. 添加一个绘制使用的layer,并添加到地图中
      // 添加一个绘制的线使用的layer
      this.drawLayer = new VectorLayer({
          //layer所对应的source
          source: new Vector(),

      })
      //把layer加入到地图中
      this.map.addLayer(this.drawLayer);
  1. 根据选择类型,进行地图交互
     addInteraction() {
         let value = this.typeSelected;
         if (value !== 'None') {
             this.draw = new Draw({
                 source: this.drawLayer.getSource(),
                 type: this.typeSelected,
                 style: new Style({
                     stroke: new Stroke({
                         color: 'blue',
                         width: 3
                     })
                 })
             });
             this.map.addInteraction(this.draw);
         }
     }
  1. 下拉框值的变化,修改地图交互
     getTypeSelected() {
         this.draw && this.map.removeInteraction(this.draw);
         //再根据typeSelect的值绘制新的Interaction
         this.addInteraction();
     },
<think>嗯,用户想在Vue3中使用OpenLayers实现绘制点、线、面的功能按钮,并且集成高德地图作为栅格地图源。首先,我需要回忆一下OpenLayers的基本用法,以及如何在Vue3中集成它。对了,OpenLayers是一个开源的JavaScript库,用于在网页上显示地图,支持多种地图源,包括高德地图。 用户提到要使用高德地图作为栅格图层,我记得高德地图的Web墨卡托投影是EPSG:3857,所以需要确保OpenLayers的视图设置正确。高德的瓦片服务URL需要按照他们的格式来写,比如https://webrd0{1-4}.is.autonavi.com/appmaptile?参数。还要注意版权信息,可能需要添加attribution。 接下来是绘制功能。OpenLayers有交互式绘制的模块,比如Draw交互。用户需要点、线、面三种绘制类型,所以可能需要三个按钮,分别触发不同的绘制模式。在Vue中,可以使用ref来引用地图容器,然后在onMounted钩子中初始化地图和图层。 然后,组件的结构部分,需要一个地图容器div,设置好样式,比如宽度和高度。在脚本部分,引入必要的OpenLayers模块,如Map, View, TileLayer,以及Draw和VectorSource等。地图初始化时,创建高德的瓦片图层,添加到地图实例中。同时,需要一个矢量图层来存储用户绘制的图形。 对于绘制功能,需要为每个按钮绑定点击事件,切换不同的绘制类型。比如,点击点按钮时,创建Draw交互,设置type为'Point',添加到地图中。完成绘制后,可能需要监听addfeature事件,将图形添加到矢量图层。同时,每次开始新的绘制前,需要移除之前的绘制交互,避免冲突。 另外,用户可能希望示例代码尽可能完整,所以需要包括引入的模块、地图初始化、绘制功能的实现,以及清除所有绘制的功能。可能还需要注意Vue3的组合式API,使用setup函数和ref等响应式引用。 还有,测试时可能需要申请高德地图的key,但用户示例中可能不需要,直接使用公开的URL。但需要注意高德地图的服务条款,确保合法使用。 最后,整理代码结构,确保在Vue组件中正确初始化和销毁地图,避免内存泄漏。比如,在onUnmounted钩子中销毁地图实例。可能还需要处理地图的缩放控件和默认交互,比如禁用旋转等。 总结一下,步骤应该是:安装依赖、创建组件、初始化地图、添加高德图层、实现绘制交互、绑定按钮事件、处理绘制结果和清除功能。然后,验证代码是否能在Vue3项目中正确运行,绘制点线面并显示在高德地图上。</think>在Vue3中集成OpenLayers实现地图绘制功能的完整实现步骤如下: ### 一、环境准备 1. 安装依赖 ```bash npm install ol vue3-openlayers ``` ### 二、组件实现 ```vue <template> <div class="map-container"> <div ref="mapContainer" class="map"></div> <div class="controls"> <button @click="startDrawing('Point')">绘制点</button> <button @click="startDrawing('LineString')">绘制线</button> <button @click="startDrawing('Polygon')">绘制面</button> <button @click="clearAll">清除全部</button> </div> </div> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue' import Map from 'ol/Map' import View from 'ol/View' import TileLayer from 'ol/layer/Tile' import XYZ from 'ol/source/XYZ' import VectorLayer from 'ol/layer/Vector' import VectorSource from 'ol/source/Vector' import Draw from 'ol/interaction/Draw' import { Style, Fill, Stroke, Circle } from 'ol/style' const mapContainer = ref(null) let map = null let drawInteraction = null // 初始化矢量图层 const vectorSource = new VectorSource() const vectorLayer = new VectorLayer({ source: vectorSource, style: new Style({ fill: new Fill({ color: 'rgba(255, 0, 0, 0.2)' }), stroke: new Stroke({ color: '#ff0000', width: 2 }), image: new Circle({ radius: 7, fill: new Fill({ color: '#ff0000' }) }) }) }) // 初始化高德地图图层 const gaodeLayer = new TileLayer({ source: new XYZ({ url: 'https://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', attributions: '高德地图提供' }) }) onMounted(() => { // 初始化地图 map = new Map({ target: mapContainer.value, layers: [gaodeLayer, vectorLayer], view: new View({ center: [12600000, 2650000], // 高德坐标系坐标 zoom: 10, projection: 'EPSG:3857' }) }) }) // 绘制功能 const startDrawing = (type) => { // 移除已有绘制交互 if (drawInteraction) { map.removeInteraction(drawInteraction) } // 创建新绘制交互 drawInteraction = new Draw({ source: vectorSource, type: type }) map.addInteraction(drawInteraction) } // 清除所有要素 const clearAll = () => { vectorSource.clear() } onUnmounted(() => { if (map) map.dispose() }) </script> <style> .map-container { position: relative; width: 100%; height: 600px; } .map { width: 100%; height: 100%; } .controls { position: absolute; top: 10px; left: 50px; z-index: 1000; background: rgba(255,255,255,0.8); padding: 10px; border-radius: 4px; } button { margin: 0 5px; padding: 5px 10px; } </style> ``` ### 三、关键技术解析 1. **坐标系适配**:高德地图采用Web墨卡托投影(EPSG:3857),需在View中显式声明坐标系[^2] 2. **瓦片加载**:通过XYZ源加载高德地图服务,使用模板URL中的{z}/{x}/{y}参数实现动态瓦片请求 3. **绘制交互**: - 使用`ol/interaction/Draw`创建绘制交互 - 根据类型参数切换点/线/面模式 - 矢量要素存储在`VectorSource`中并通过`VectorLayer`渲染 4. **样式控制**:通过OpenLayers样式对象统一管理要素样式,支持动态样式调整 ### 四、优化建议 1. **坐标转换**:如需展示WGS84坐标,需使用`ol/proj`进行坐标转换 2. **绘制限制**:可添加拓扑校验、长度/面积计算等扩展功能 3. **性能优化**:对大量要素建议使用WebGL渲染器
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值