59.在 Vue 3 中使用 OpenLayers 绘制正方形、矩形、六芒星

发布于:2025-02-11 ⋅ 阅读:(77) ⋅ 点赞:(0)

前言

在现代 Web 开发中,地图功能已经成为许多应用的重要组成部分。OpenLayers 是一个强大的开源地图库,支持多种地图源和地图操作。结合 Vue 3 的响应式特性,我们可以轻松实现地图的交互功能。本文将详细介绍如何在 Vue 3 中使用 OpenLayers 绘制正方形、矩形和六芒星。


技术栈

  • Vue 3:用于构建用户界面。

  • OpenLayers:用于地图渲染和图形绘制。

  • Element Plus:用于 UI 组件(如下拉菜单)。


实现步骤

1. 环境准备

首先,确保你已经创建了一个 Vue 3 项目。如果还没有,可以通过以下命令创建一个:

npm create vue@latest

然后安装 OpenLayers 和 Element Plus:

npm install ol element-plus

2. 项目结构

在项目中创建一个组件,例如 OpenLayersShapes.vue,用于实现地图绘制功能。


3. 代码实现

以下是完整的代码实现:

<!--
 * @Author: 彭麒
 * @Date: 2025/1/6
 * @Email: 1062470959@qq.com
 * @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。
 -->
<template>
  <div class="container">
    <div class="w-full flex justify-center flex-wrap">
      <div class="font-bold text-[24px]">在Vue3中使用OpenLayers绘制正方形、矩形、六芒星</div>
    </div>
    <h4>
      <el-select id="type" v-model="tool" style="width: 240px; margin-top: 20px; margin-bottom: 20px">
        <el-option v-for="item in tools" :key="item.value" :value="item.value">{{ item.label }}</el-option>
      </el-select>
    </h4>

    <div id="vue-openlayers"></div>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from 'vue';
import 'ol/ol.css';
import { Map, View } from 'ol';
import Tile from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import LayerVector from 'ol/layer/Vector';
import SourceVector from 'ol/source/Vector';
import Draw, { createRegularPolygon, createBox } from 'ol/interaction/Draw';
import Polygon from 'ol/geom/Polygon';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
import Style from 'ol/style/Style';
import Circle from 'ol/style/Circle';

// 定义绘制工具类型
const tool = ref('Square');

// 定义工具选项
const tools = ref([
  { value: 'Square', label: '方形' },
  { value: 'Rectangle', label: '矩形' },
  { value: 'Hexagram', label: '六芒星' },
  { value: 'None', label: '无' },
]);

// 定义地图、绘制工具和数据源
const map = ref(null);
const draw = ref(null);
const source = new SourceVector({ wrapX: false });

// 初始化地图
const initMap = () => {
  const raster = new Tile({
    source: new OSM(), // 使用OSM底图
  });

  const vector = new LayerVector({
    source: source,
    style: new Style({
      fill: new Fill({
        color: '#00f', // 填充颜色
      }),
      stroke: new Stroke({
        width: 2,
        color: '#ff0', // 边框颜色
      }),
      image: new Circle({
        radius: 5,
        fill: new Fill({
          color: '#ff0000', // 点样式颜色
        }),
      }),
    }),
  });

  // 创建地图实例
  map.value = new Map({
    target: 'vue-openlayers', // 地图容器ID
    layers: [raster, vector], // 添加底图和矢量图层
    view: new View({
      projection: 'EPSG:4326', // 坐标系
      center: [113.1206, 23.034996], // 中心点
      zoom: 10, // 缩放级别
    }),
  });

  // 添加绘制工具
  addInteraction();
};

// 添加或更新绘制工具
const addInteraction = () => {
  if (draw.value !== null) {
    map.value.removeInteraction(draw.value); // 移除旧的绘制工具
  }

  if (tool.value !== 'None') {
    let geometryFunction;
    let type = 'Circle';

    if (tool.value === 'Square') {
      // 方形
      geometryFunction = createRegularPolygon(4);
    } else if (tool.value === 'Rectangle') {
      // 矩形
      geometryFunction = createBox();
    } else if (tool.value === 'Hexagram') {
      // 六芒星
      geometryFunction = function (coordinates, geometry) {
        const center = coordinates[0]; // 中心点
        const last = coordinates[1]; // 鼠标点击的另一个点
        const dx = center[0] - last[0];
        const dy = center[1] - last[1];
        const radius = Math.sqrt(dx * dx + dy * dy); // 半径
        const rotation = Math.atan2(dy, dx); // 旋转角度
        const newCoordinates = []; // 顶点坐标数组
        const numPoints = 12; // 顶点个数

        for (let i = 0; i < numPoints; ++i) {
          const angle = rotation + (i * 2 * Math.PI) / numPoints; // 顶点角度
          const fraction = i % 2 === 0 ? 1 : 0.58; // 凸顶点和凹顶点
          const offsetX = radius * fraction * Math.cos(angle); // X偏移
          const offsetY = radius * fraction * Math.sin(angle); // Y偏移
          newCoordinates.push([center[0] + offsetX, center[1] + offsetY]); // 添加顶点
        }

        newCoordinates.push(newCoordinates[0].slice()); // 闭合图形

        if (!geometry) {
          geometry = new Polygon([newCoordinates]); // 创建多边形
        } else {
          geometry.setCoordinates([newCoordinates]); // 更新多边形
        }

        return geometry;
      };
    }

    // 创建绘制工具
    draw.value = new Draw({
      source: source,
      type,
      geometryFunction,
    });

    // 添加绘制工具到地图
    map.value.addInteraction(draw.value);
  }
};

// 监听工具类型的变化
watch(tool, (newVal) => {
  addInteraction();
});

// 组件挂载后初始化地图
onMounted(() => {
  initMap();
});
</script>

<style scoped>
.container {
  width: 840px;
  height: 590px;
  margin: 50px auto;
  border: 1px solid #42b983;
}

#vue-openlayers {
  width: 800px;
  height: 400px;
  margin: 0 auto;
  border: 1px solid #42b983;
  position: relative;
}
</style>

4. 代码详解

4.1 地图初始化
  • 使用 Map 和 View 创建地图实例。

  • 添加 OSM 底图和矢量图层。

  • 设置地图的中心点和缩放级别。

4.2 绘制工具
  • 使用 Draw 实现正方形、矩形和六芒星的绘制。

  • 通过 geometryFunction 动态生成不同形状的几何图形。

  • 使用 watch 监听工具类型的变化,动态更新绘制工具。

4.3 六芒星实现
  • 通过数学计算生成六芒星的顶点坐标。

  • 使用 Polygon 创建六芒星的多边形。


5. 运行效果

运行项目后,页面会显示一个地图和一个下拉菜单。用户可以通过下拉菜单选择绘制类型(方形、矩形、六芒星),然后在地图上绘制相应的图形。


总结

本文详细介绍了如何在 Vue 3 中使用 OpenLayers 绘制正方形、矩形和六芒星。通过结合 Vue 3 的 Composition API 和 OpenLayers 的强大功能,我们可以轻松实现复杂的地图交互。希望本文对你有所帮助,欢迎在评论区交流讨论!


参考文档


希望这篇博文能帮助你在 CSDN 上分享你的技术经验!如果有其他问题,欢迎随时提问!


网站公告

今日签到

点亮在社区的每一天
去签到