openlayers6 第一篇绘制点线面

小白一枚,只是单纯纪录,不喜勿喷,希望能帮到刚入门的大家

   //新建点线面图层
        addDrawLayer() {
            this.draw_vector = new VectorLayer({
                source: this.draw_source,
                title: '自由图层绘制点线面',
                name: 'operateTu',
                visible: true,
                zIndex: 99999,
                //绘制好后,在地图上呈现的样式
                style: new Style({
                    fill: new Fill({
                        color: "rgba(255, 255, 255, 0.2)",
                    }),
                    stroke: new Stroke({
                        //边界样式
                        color: "#ffcc33",
                        width: 3,
                    }),
                    //点样式继承image
                     image: new Icon({
                        src: require('@/assets/index/dingwei-tu.png'),
                            //大小
                         scale: 1,
                     }),
                }),
            });
            console.log(this.draw_vector,222222222)
            this.map.addLayer(this.draw_vector);
        },

先创建点线面图层,并添加到地图容器中

//html: 判断选择要绘制的图形
  <div class="operate" v-show="showType">
            <!-- <div style="background-color: #235298; color: white; height: 40px; line-height: 40px;cursor: default;">
                   <i class="el-icon-edit"></i> 绘制
            </div> -->
            <div @click="openSelectCategory('Point')">
                <span class="el-icon-location-information"></span>
                <span style="font-size: 18px;">点</span>
            </div>
            <div @click="openSelectCategory('LineString')">
                <span class="el-icon-share"></span>
                 <span style="font-size: 18px;">线</span>
            </div>
            <div @click="openSelectCategory('Polygon')">
                <span class="el-icon-reading"></span>
                 <span style="font-size: 18px;">面</span>
            </div>
        </div>
 openSelectCategory(type) { 
            //图层名称填写弹框显示隐藏
            this.dialogVisible = true;
            this.type = type
        },
//我是在点击选择要绘制的图形后又添加了一个图层名称填写弹框

html:
 <!-- 选择类型的弹框 -->
                 <el-dialog
                title="操作"
                :visible.sync="dialogVisible"
                width="30%"
                append-to-body
                :before-close="handleClose">
                <el-row :gutter="6">
                    <el-form :model="formData" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
                        <el-form-item label="图层名称" prop="layer">
                            <el-input v-model="formData.layer"></el-input>
                        </el-form-item>
                    </el-form>
                </el-row>
                <span slot="footer" class="dialog-footer">
                    <el-button @click="dialogVisible = false">取 消</el-button>
                    <el-button type="primary" @click="submitForm()">确 定</el-button>
                </span>
                </el-dialog>

点击确定后隐藏弹框开始绘制

        // 提交表单并开始绘制点线面
         submitForm() {
             this.$refs.ruleForm.validate((valid) => {
                 if (valid) {
                     this.dialogVisible = false;
                     this.addDrawLayer();
                 }
                //  this.map.removeInteraction(this.draw);
                //  绘制层
                this.draw = new Draw({
                    source: this.draw_source,
                    type: this.type,
                    //绘制时,在地图上呈现的样式
                    style: new Style({
                        fill: new Fill({
                            color: "rgba(255, 255, 255, 0.2)",
                        }),
                        stroke: new Stroke({
                            color: "rgba(38,126,255,0.7)",
                            width: 6,
                        }),
                         image: new Circle({
                            radius: 7,
                            fill: new Fill({
                                color: "#ffcc33",
                            }),
                        }),
                    }),
                });
                // 结束时触发的事件
                 this.draw.on("drawend", (e) => {
                    // //绘制完成后的坐标数组
                    this.geometry = e.feature.getGeometry().getCoordinates();
                    this.feature = e.feature;
                    // 经过wkt 处理过的值
                    // console.log(this.feature,'要素');
                    var strwkt = new WKT().writeFeature(e.feature, {
                        dataProjection: "EPSG:4326",//目标坐标系
                        featureProjection: "EPSG:4326"  //当前坐标系
                    });
                    console.log(strwkt,'wkt');



//............处理格式用的可省略
                    //处理wkt格式数据
                    let index = strwkt.indexOf('(') + 1; // 获取第一个左括号的索引,加 1 后就是第一个数值的位置
                    let subString = strwkt.substring(index, strwkt.length - 1); // 获取括号内的子字符串
                    let newString = '(' + subString + ')'; // 在两端添加一个额外的括号
                    this.formData.coords =  'MULTI' + strwkt.replace(subString, newString);
                    // // POLYGON 面
                    // // LINESTRING 线
                    // // POINT  点
                    if (strwkt.includes('POINT')) {
                        this.formData.coordsType = '1';
                    } else if (strwkt.includes('LINESTRING')) { 
                        this.formData.coordsType = '2';
                    } else {
                         this.formData.coordsType = '3';
                     }
//............处理格式用的可省略                     



                     // 创建Overlay 覆盖物弹窗
//获取popupDOM
                    let elPopup = this.$refs.popup;
                    this.popup = new Overlay({
//要添加到覆盖物元素
                        element: elPopup,
//在地图所在的坐标系框架下,overlay 放置的位置。
                        positioning: "bottom-center",
//是否应停止事件传播到地图视口
                        stopEvent: false,
//偏移量,像素为单位
                        offset: [0, 10],
                    });
                    this.map.addOverlay(this.popup);
                    // 控制弹窗显示与隐藏的元素
                    this.popupShow = true
                     // 设置弹窗位置
                    if (e.feature.getGeometry().getCoordinates()[0] instanceof Array && e.feature.getGeometry().getCoordinates().length != 1) {
                        this.popup.setPosition(e.feature.getGeometry().getCoordinates()[e.feature.getGeometry().getCoordinates().length - 1]);
                    } else if (e.feature.getGeometry().getCoordinates().length == 1 && e.feature.getGeometry().getCoordinates()[0] instanceof Array) {
                        this.popup.setPosition(e.feature.getGeometry().getCoordinates()[0][e.feature.getGeometry().getCoordinates()[0].length - 2]);
                    }
                    else {
                        this.popup.setPosition(e.feature.getGeometry().getCoordinates());
                    }
                    this.map.removeInteraction(this.draw); //移除交互
                })
//添加绘制交互
                this.map.addInteraction(this.draw);
            });
        },

Overlay详情可看 OpenLayers - Overlay简介

他添加了一个弹窗

        <!-- 新增或者取消编辑的弹框 -->
        <div ref="popup" class="popup" v-show = "popupShow">
            <div class = "popup-header">
                <span>{{ popupTitle }}</span>
                <img src = "../../../assets/index/guanbi-big.png" class = "hand" @click = "() => {
                    //关闭提示图层
                    popup.setPosition(null);
                    popupShow = false;
                    //开启点编辑图层
                    pointPopupShow = true;
                    //开启编辑功能
                    editorFeature(true);
                    editModel = true;

                }"/>
            </div>
            <div class = "popup-content" v-html="popupContent"></div>
             <div class = "popup-footer" style=" margin-top: -30px;">
                    <el-button type="primary" @click = "openAddStreet">提交</el-button>
                    <el-button @click.stop = "clearDraw()">取消</el-button>
                </div>

 点击取消就清除点击右上关闭就可以对创建的元素进行编辑

 editorFeature(flag) { 
            //  console.log(flag)
            if (this.editModel) return;
            // this.editModel = true;
            this.editModel = flag;
            if (flag) {
                // 要素选择组件
                this.select = new Select({
                    wrapX: false,
                });
                // this.select.getFeatures().clear();
                // this.select.getFeatures().array_.push(this.feature);//将要选择的要素push进去
                this.select.dispatchEvent(new SelectEvent(
                    "select",
                    [
                    //绘制结束时的要素
                        this.feature
                    ],
                ))
                // 要素编辑
                this.modify = new Modify({
                    features: this.select.getFeatures(),
                    deleteCondition: function (e) {
                        //单机删除点位
                        if (e.type == "singleclick") {
                            return Object(true);
                        }
                    }
                });

                // 编辑完成后 监听修改feature
                var that = this;
                this.modify.on("modifyend", function (e) {
                    console.log(e.features);
                    // geometry //绘制完成后的坐标数组
                    that.geometry = e.features.array_[0].getGeometry().getCoordinates();
                    console.log('绘制完成后的坐标数组', that.geometry );
                    that.returnFeature = e.features.array_[0];
                    //    // 经过wkt 处理过的值
                    let strwkt = new WKT().writeFeature(e.features.array_[0], {
                        dataProjection: "EPSG:4326",//目标坐标系
                        featureProjection: "EPSG:4326"  //当前坐标系
                    });
                    // 将值赋给表单数据
                      that.formData.coords = 'MULTI' + strwkt;
                });
                this.select.on("select", function (e) {
                    //临时的解决方法 调用两次
                    // that.writeOverLays();
                    setTimeout(function () {
                        that.$forceUpdate();
                        // that.writeOverLays();
                    }, 100)
                });

                this.map.addInteraction(this.select);
                this.map.addInteraction(this.modify);
            } else {
                this.pointPopupShow = false;
                this.map.removeInteraction(this.select);
                this.map.removeInteraction(this.modify);
                this.select = null;
                this.modify = null;
                //清理所有提示overlay
                for (const popup of this.popupArray) {
                    this.map.removeOverlay(popup);
                }
                this.$forceUpdate();
            }
            return this.returnFeature;
        },

编辑要素就是使用SelectAPI创建对象拿到要修改的图形要素(就是你绘制的图形) 然后 使用ModifyAPI编辑 使用modifyend监听修改feature 拿到修改后的坐标

        // 最后提交
        openAddStreet() { 
            //    调接口 把数据传给后台
            this.popupShow = false
            addLayer(this.formData).then(res => {
                console.log(this.formData);
                if (res.code !== 200 || res.code == null) {
                    // 关闭弹窗
                    // 清除绘制
                    this.clearDraw()
                    this.$message.error('添加失败');
                      this.popupShow = false
                } else { 
                    this.$bus.$emit('refash', this.refash)
                      this.$message({ message: '添加成功', type: 'success'})
                    this.popupShow = false
                    this.clearDraw()
                }
                console.log(res);
             })
        },

清除方法

  // 清除绘制图层
        clearDraw() {
            this.popupShow = false
            this.map.removeInteraction(this.draw); //移除交互
            this.draw_vector.getSource().clear(); //清除图层上的所有要素
        },

至于为什么会双击弹出弹框 在mounted中使用

  var that = this;
        this.$nextTick(() => {
            this.map.getViewport().oncontextmenu = function (e) {
                if (that.editModel) {
                    e.preventDefault();
                    //删除点
                }
            }
            // 
            this.map.getViewport().ondblclick = (e) => {
                if (that.editModel) {
                    e.preventDefault();
                    // 创建Overlay
                    let elPopup = that.$refs.popup;
                    that.popup = new Overlay({
                        element: elPopup,
                        positioning: "bottom-center",
                        stopEvent: true,
                        offset: [0, 10],
                    });
                    that.map.addOverlay(that.popup);
                    that.popupShow = true;
                    // 设置弹窗位置
                    that.popup.setPosition(that.map.getEventCoordinate(e));
                }
            }
        })

最后附上引用api

 // 引入openlayers地图组件
import "ol/ol.css";
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 , Icon } from "ol/style";
import Overlay from 'ol/Overlay'
import WKT from 'ol/format/WKT'
import Select, { SelectEvent } from 'ol/interaction/Select'
import Modify from 'ol/interaction/Modify'

我是小白 这都是之前copy公司大佬写好的一部分代码 有什么不足的地方可以跟我说 大家一块进步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值