Skip to content

基础绘制

案例代码
vue
<template>
  <div class="map-container">
    <div ref="mapElement" class="map"></div>
    <div class="controls">
      <select v-model="drawType">
        <option value="Point">点</option>
        <option value="LineString">线</option>
        <option value="Polygon">多边形</option>
        <option value="Circle">圆</option>
      </select>
      <button @click="toggleDrawing">
        {{ isDrawing ? "停止绘制" : "开始绘制" }}
      </button>
      <button @click="clearAll">清除所有</button>
      <label style="color: black">
        <input type="checkbox" v-model="freehandMode" /> 自由绘制
      </label>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, watch } from "vue";
import { Map, View } from "ol";
import XYZ from "ol/source/XYZ";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Draw } from "ol/interaction";
import { Circle as CircleStyle, Fill, Stroke, Style } from "ol/style";
import "ol/ol.css";

const mapElement = ref(null);
const drawType = ref("Polygon");
const isDrawing = ref(false);
const freehandMode = ref(false);
let map = null;
let drawInteraction = null;
const vectorSource = new VectorSource();
const vectorLayer = new VectorLayer({ source: vectorSource });

const view = new View({
  center: [116.4074, 39.9042], // 北京市中心经纬度
  zoom: 10,
  projection: "EPSG:4326", // 默认使用Web Mercator投影,需要设置为EPSG:4326经纬度
  // extent: [73.66, 3.86, 135.05, 53.55], // 设置地图平移范围(当前为中国区域)
});

// 初始化地图
onMounted(() => {
  map = new Map({
    target: mapElement.value,
    layers: [
      new TileLayer({
        // 设置高德地图为数据源底图
        source: new XYZ({
          // 设置路网图层
          url: "https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
        }),
      }),
      vectorLayer,
    ],
    view,
  });
});

// 切换绘制类型和状态
watch([drawType, isDrawing, freehandMode], ([type, drawing, freehand]) => {
  if (drawInteraction) {
    map.removeInteraction(drawInteraction);
    drawInteraction = null;
  }

  if (drawing) {
    drawInteraction = new Draw({
      source: vectorSource,
      type: type,
      freehand: freehand,
      style: new Style({
        fill: new Fill({ color: "rgba(255,0,0,0.2)" }),
        stroke: new Stroke({
          color: "red",
          width: 2,
          lineDash: [5, 5],
        }),
        image: new CircleStyle({
          radius: 7,
          fill: new Fill({ color: "red" }),
        }),
      }),
    });

    // 事件监听
    drawInteraction.on("drawend", (event) => {
      console.log("绘制完成:", event.feature);
      // 添加自定义属性
      event.feature.set("type", type);
      event.feature.set("timestamp", new Date());
    });

    map.addInteraction(drawInteraction);
  }
});

const toggleDrawing = () => {
  isDrawing.value = !isDrawing.value;
};

const clearAll = () => {
  vectorSource.clear();
};
</script>

<style>
.map-container {
  position: relative;
  top: 0;
  bottom: 0;
  width: 100%;
  height: 100vh;
}

.map {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
}

.controls {
  position: absolute;
  top: 10px;
  left: 10px;
  background: rgba(255, 255, 255, 0.8);
  padding: 10px;
  border-radius: 4px;
  z-index: 100;
}

.controls select,
.controls button {
  margin-right: 10px;
}
</style>