Vue+Openlayer使用draw实现绘制点线面功能

目录

基本效果

可以手绘


import { Draw } from "ol/interaction";

    //绘制线要素
    drawFeature() {
      this.draw = new Draw({
        source: this.lineStringLayer.getSource(),
        type: "LineString", //Point,LineString,Polygon,Circle
      });
      this.map.addInteraction(this.draw);
    },

完整代码: 

<template>
  <div id="map" style="height: 100vh; width: 100vw"></div>
</template>
 
<script>
import "ol/ol.css";
import { Map, View } from "ol";
import { OSM, Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer, Tile as TileLayer } from "ol/layer";
import { Draw } from "ol/interaction";
import { Fill, Stroke, Style, Text, Circle } from "ol/style";
export default {
  data() {
    return {
      map: {},
      vectorLayer: {},
      draw: {},
    };
  },
  created() {},
  mounted() {
    this.initMap();
    this.addLayer();
    this.drawFeature();
  },
  computed: {},
  methods: {
    initMap() {
      this.map = new Map({
        target: "map",
        layers: [
          new TileLayer({
            source: new OSM(),
          }),
        ],
        view: new View({
          projection: "EPSG:4326",
          center: [104.2979180563, 30.528298024],
          zoom: 18,
        }),
      });
    },
    addLayer() {
      this.vectorLayer = new VectorLayer({
        source: new VectorSource(),
      });
      this.map.addLayer(this.vectorLayer);
    },
    //绘制线要素核心代码
    drawFeature() {
      this.draw = new Draw({
        source: this.vectorLayer.getSource(),
        type: "LineString", //Point,LineString,Polygon,Circle
      });
      this.map.addInteraction(this.draw);
    },
  },
};
</script>

基本效果

实现代码:

<template>
  <div id="map" style="height: 100vh; width: 100vw">
    <div style="position: fixed; top: 150px; left: 10px; z-index: 999">
      <el-button @click="drawFeature('Point')">画点</el-button>
      <el-button @click="drawFeature('LineString')">画线</el-button>
      <el-button @click="drawFeature('Polygon')">画面</el-button>
      <el-button @click="drawFeature('Circle')">画圆</el-button>
      <el-button @click="draw.removeLastPoint()">撤回</el-button>
      <el-button @click="map.removeInteraction(draw)">取消</el-button>
      <el-button @click="clearDrawLayer()">清除</el-button>
    </div>
  </div>
</template>
<script>
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import { Vector as VectorLayer } from "ol/layer";
import { OSM, Vector as VectorSource } from "ol/source";
import Draw from "ol/interaction/Draw";
import { Fill, Stroke, Style, Text, Circle } from "ol/style";

export default {
  name: "",
  data() {
    return {
      map: {},
      draw_source: new VectorSource(),
      draw_vector: {},
      draw: {},
    };
  },
  mounted() {
    this.initMap();
    this.addDrawLayer();
  },
  methods: {
    //添加绘制点线面图层
    addDrawLayer() {
      this.draw_vector = new VectorLayer({
        source: this.draw_source,
        //绘制好后,在地图上呈现的样式
        style: new Style({
          fill: new Fill({
            color: "rgba(255, 255, 255, 0.2)",
          }),
          stroke: new Stroke({
            //边界样式
            color: "#ffcc33",
            width: 3,
          }),
          //点样式继承image
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#ffcc33",
            }),
          }),
        }),
      });
      this.map.addLayer(this.draw_vector);
    },
    //清除绘制图层
    clearDrawLayer() {
      this.map.removeInteraction(this.draw); //移除交互
      this.draw_vector.getSource().clear(); //清除图层上的所有要素
    },
    //绘制点线面
    drawFeature(featureType = "") {
      this.map.removeInteraction(this.draw);

      this.draw = new Draw({
        source: this.draw_source,
        type: featureType,
        //绘制时,在地图上呈现的样式
        style: new Style({
          fill: new Fill({
            color: "rgba(255, 255, 255, 0.2)",
          }),
          stroke: new Stroke({
            color: "#ffcc33",
            width: 2,
          }),
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#ffcc33",
            }),
          }),
        }),
      });
      this.map.addInteraction(this.draw);
    },
    // 初始化地图
    initMap() {
      this.map = new Map({
        target: "map",
        layers: [
          new TileLayer({
            source: new OSM(),
            visible: true,
            name: "OSM",
          }),
        ],
        view: new View({
          projection: "EPSG:4326",
          center: [115, 39],
          zoom: 4,
        }),
      });
    },
  },
};
</script>

注意:绘制完后,可以通过e.feature.getGeometry().getCoordinates()获取到绘制的范围的经纬度坐标数组 。如下:

      this.draw.on("drawend", function (e) {
        console.log(" e:", e);
        console.log(" e.feature:", e.feature);
        console.log(" e.feature.getGeometry():", e.feature.getGeometry());
        console.log(
          " e.feature.getGeometry().getCoordinates():",
          e.feature.getGeometry().getCoordinates()
        );
      });

在线预览:

WebGIS之家 | 绘制要素 (webgishome.com)icon-default.png?t=N7T8https://www.webgishome.com/preview?id=58&example_name=drawFeature&title=%E7%BB%98%E5%88%B6%E8%A6%81%E7%B4%A0

js封装绘制功能:

DrawTool.js:


import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import { Vector as VectorLayer } from "ol/layer";
import { OSM, Vector as VectorSource, XYZ } from "ol/source";
import Draw from "ol/interaction/Draw";
import { Fill, Stroke, Style, Text, Icon, Circle } from "ol/style";

export default class DrawTool {
    constructor({ domId_map }) {
        this.domId_map = domId_map
        this.map = null
        this.draw_source = new VectorSource()
        this.draw_vector = null
        this.draw = null
    }
    initMap() {
        this.map = new Map({
            target: this.domId_map,
            layers: [
                new TileLayer({
                    source: new XYZ({
                        url:
                            "http://t3.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=5a257cd2df1b3311723bd77b0de14baf",
                    }),
                    visible: true,
                    // name: "OSM",
                }),
            ],
            view: new View({
                projection: "EPSG:4326",
                center: [115, 39],
                zoom: 4,
            }),
        })

        this.addDrawLayer()
    }
    //添加绘制点线面图层
    addDrawLayer() {
        this.draw_vector = new VectorLayer({
            source: this.draw_source,
            //绘制好后,在地图上呈现的样式
            style: new Style({
                fill: new Fill({
                    color: "rgba(255, 255, 255, 0.2)",
                }),
                stroke: new Stroke({
                    //边界样式
                    color: "#ffcc33",
                    width: 3,
                }),
                //点样式继承image
                image: new Circle({
                    radius: 7,
                    fill: new Fill({
                        color: "#ffcc33",
                    }),
                }),
            }),
        });
        this.map.addLayer(this.draw_vector);
    }
    //清除绘制图层
    clearDrawLayer() {
        this.map.removeInteraction(this.draw); //移除交互
        // this.draw_vector.getSource().clear(); //清除图层上的所有要素
        this.draw_source.clear(); //清除图层上的所有要素
    }
    // 撤回操作
    removeLastPoint() {
        this.draw.removeLastPoint()
    }
    // 取消绘制
    cancelDraw() {
        this.map.removeInteraction(this.draw); //移除交互
    }
    //绘制点线面
    drawFeature(featureType = "") {
        if (this.draw) {
            this.map.removeInteraction(this.draw);
        }

        this.draw = new Draw({
            source: this.draw_source,
            type: featureType,
            //绘制时,在地图上呈现的样式
            style: new Style({
                fill: new Fill({
                    color: "rgba(255, 255, 255, 0.2)",
                }),
                stroke: new Stroke({
                    color: "#ffcc33",
                    width: 2,
                }),
                image: new Circle({
                    radius: 7,
                    fill: new Fill({
                        color: "#ffcc33",
                    }),
                }),
            }),
        });
        this.map.addInteraction(this.draw);
    }
}

 测试:

<template>
    <div class="main">
        <div id="olContainer" style="height: 100vh; width: 100vw"></div>
        <div style="position: fixed; top: 150px; left: 10px; z-index: 999">
            <el-button @click="state.draw.drawFeature('Point')">画点</el-button>
            <el-button @click="state.draw.drawFeature('LineString')">画线</el-button>
            <el-button @click="state.draw.drawFeature('Polygon')">画面</el-button>
            <el-button @click="state.draw.drawFeature('Circle')">画圆</el-button>
            <el-button @click="state.draw.removeLastPoint()">撤回</el-button>
            <el-button @click="state.draw.cancelDraw()">取消</el-button>
            <el-button @click="state.draw.clearDrawLayer()">清除</el-button>
        </div>
    </div>

</template>
  
<script setup>
import { reactive } from 'vue';
import DrawTool from './DrawTool'
const state = reactive({
    draw: null
})
onMounted(() => {
    let draw = new DrawTool({ domId_map: 'olContainer' })
    draw.initMap()

    state.draw = draw
    console.log("state:", state)
})
</script>
<style lang="scss" scoped>
.main {
    position: relative;
    height: 100vh;
    width: 100vw;

    #olContainer {
        position: absolute;
        height: 100vh;
        width: 100vw;
    }

}
</style>

可以手绘

效果图

使用代码:

<template>
  <div style="height: 100vh; width: 100vw">
    <div id="map" style="height: 100%; width: 100%"></div>
    <div style="position: fixed; top: 150px; left: 490px; z-index: 999">
      <LjDraw :map="map"></LjDraw>
    </div>
  </div>
</template>
<script>
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import { Vector as VectorLayer } from "ol/layer";
import { OSM, Vector as VectorSource } from "ol/source";
import Draw from "ol/interaction/Draw";
import { Fill, Stroke, Style, Text, Circle } from "ol/style";
import LjDraw from "@/components/LjDraw/index.vue";
export default {
  name: "",
  components: { LjDraw },
  data() {
    return {
      map: {},
    };
  },

  beforeMount() {
    // _isMounted是当前实例mouned()是否执行 此时为false
    window.parentMounted = this._isMounted;
  },
  mounted() {
    //父组件中初始化地图对象map
    this.initMap();
    // _isMounted是当前实例mouned()是否执行 此时为true
    window.parentMounted = this._isMounted;
  },
  methods: {
    // 初始化地图
    initMap() {
      this.map = new Map({
        target: "map",
        layers: [
          new TileLayer({
            source: new OSM(),
            visible: true,
            name: "OSM",
          }),
        ],
        view: new View({
          projection: "EPSG:4326",
          center: [115, 39],
          zoom: 4,
        }),
      });
    },
  },
  watch: {},
};
</script>

 LjDraw 组件代码:

<!--LjDraw-->
<template>
  <div>
    <el-button size="mini">
      <select
        v-model="currentDrawFeature"
        style="
          background-color: rgb(66, 66, 66);
          color: white;
          padding: 2px 7px;
          outline: none;
        "
        @change="drawFeature()"
      >
        <option value="">请选择</option>
        <option value="Point" label="画点"></option>
        <option value="LineString">画线</option>
        <option value="Polygon">画面</option>
        <option value="Circle">画圆</option>
      </select>
    </el-button>

    <el-button size="mini"
      ><el-checkbox v-model="enableFreeHand">手绘</el-checkbox></el-button
    >
    <el-button size="mini" @click="draw.removeLastPoint()">撤回</el-button>
    <el-button size="mini" @click="cancelDraw()">取消</el-button>
    <el-button size="mini" @click="clearDrawLayer()">清除</el-button>
  </div>
</template>
<script>
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import { Vector as VectorLayer } from "ol/layer";
import { OSM, Vector as VectorSource } from "ol/source";
import Draw from "ol/interaction/Draw";
import { Fill, Stroke, Style, Text, Icon, Circle } from "ol/style";

export default {
  name: "LjDraw",
  props: {
    map: {
      default: {},
      required: true,
    },
  },
  data() {
    return {
      draw_source: new VectorSource(),
      draw_vector: {},
      draw: {},
      currentDrawFeature: "", //当前正在绘制的要素类型
      enableFreeHand: false, //是否允许手绘
    };
  },
  mounted() {
    let pMountedTimer = {}; //定时器
    pMountedTimer = setInterval(() => {
      if (window.parentMounted) {
        //在这里执行初始化
        this.addDrawLayer();

        clearInterval(pMountedTimer); //清除定时器
      }
    }, 1000);
  },
  methods: {
    //添加绘制点线面图层
    addDrawLayer() {
      this.draw_vector = new VectorLayer({
        source: this.draw_source,
        //绘制好后,在地图上呈现的样式
        style: new Style({
          fill: new Fill({
            color: "rgba(255, 255, 255, 0.2)",
          }),
          stroke: new Stroke({
            //边界样式
            color: "#ffcc33",
            width: 3,
          }),
          //点样式继承image
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#ffcc33",
            }),
          }),
        }),
        zIndex: 9999,
      });
      this.map.addLayer(this.draw_vector);
    },
    //取消绘制
    cancelDraw() {
      this.map.removeInteraction(this.draw); //移除交互
      this.currentDrawFeature = ""; //取消选中要素!!
    },
    //清空绘制图层
    clearDrawLayer() {
      this.map.removeInteraction(this.draw); //移除交互
      this.draw_vector.getSource().clear(); //清除图层上的所有要素
      this.currentDrawFeature = ""; //取消选中要素!!
    },
    //绘制点线面
    drawFeature() {
      this.map.removeInteraction(this.draw); //移除交互

      if (!this.currentDrawFeature) return; //这里一定要判断

      this.draw = new Draw({
        source: this.draw_source,
        type: this.currentDrawFeature,
        //绘制时,在地图上呈现的样式
        style: new Style({
          fill: new Fill({
            color: "rgba(255, 255, 255, 0.2)",
          }),
          stroke: new Stroke({
            color: "#ffcc33",
            width: 2,
          }),
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#ffcc33",
            }),
          }),
        }),
        freehand: this.enableFreeHand, //手绘
      });
      this.map.addInteraction(this.draw);
    },
    // 初始化地图
    initMap() {
      this.map = new Map({
        target: "map",
        layers: [
          new TileLayer({
            source: new OSM(),
            visible: true,
            name: "OSM",
          }),
        ],
        view: new View({
          projection: "EPSG:4326",
          center: [115, 39],
          zoom: 4,
        }),
      });
    },
  },
  watch: {
    enableFreeHand: {
      handler() {
        this.drawFeature();
      },
    },
  },
};
</script>

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值