TRICK系列:Openlayers 中实现Draw通过键盘按键取消全部绘制、取消上一步绘制

前言

Draw是OpenLayers中常用的一个组件,默认是单击绘制,双击结束绘制。

但是在实际工程中常常需要在绘制过程中使用按键来取消全部绘制、取消上一步绘制,如何做到呢?

闲言少叙,直接上干货。
原理

在draw中是不处理键盘的按键事件的,只有当鼠标的左右键按下的时候,才会触发ol/MapBrowserEvent 类的事件,所以我们无法使用Openlayers的机制来实现使用按键的目的。此时就需要引入方便又强大的jQuery了。通过jQuery监听document对象的按键事件,来实现我们取消全部或者取消上一步的绘制。
操作

直接上代码吧

import Map from 'ol/Map';
import View from 'ol/View';
import Draw from 'ol/interaction/Draw';
import {
    Tile as TileLayer,
    Vector as VectorLayer
} from 'ol/layer';
import {
    OSM,
    Vector as VectorSource
} from 'ol/source';
import $ from 'jquery'
var raster = new TileLayer({
    source: new OSM()
});
 
var source = new VectorSource({
    wrapX: false
});
 
var vector = new VectorLayer({
    source: source
});
 
var map = new Map({
    layers: [raster, vector],
    target: 'map',
    view: new View({
        center: [-11000000, 4600000],
        zoom: 4
    })
});
 
var typeSelect = document.getElementById('type');
 
var draw; // global so we can remove it later
function addInteraction() {
    var value = typeSelect.value;
    if (value !== 'None') {
        draw = new Draw({
            source: source,
            type: typeSelect.value,
 
        });
        map.addInteraction(draw);
    }
}
 
typeSelect.onchange = function () {
    map.removeInteraction(draw);
    addInteraction();
};
addInteraction();
 
 
$(document).keyup(function (event) {
    if (event.keyCode == 27)
        draw.abortDrawing();
    else if (event.keyCode == 90 && event.ctrlKey) {
        console.log(draw);
        if (typeSelect.value== 'Circle')
            draw.abortDrawing();
        else
            draw.removeLastPoint()
 
    }
})

需要注意的是,这个函数只有Openlayers 6.3之后才有,那么在之前的老版本里(比如5.x甚至6.0.x、6.1.x),需要自己把这个逻辑实现出来,重载Draw类添加一个abortDrawing()公有成员:

import Map from 'ol/Map';
import View from 'ol/View';
import Draw from 'ol/interaction/Draw';
import {
    Tile as TileLayer,
    Vector as VectorLayer
} from 'ol/layer';
import {
    OSM,
    Vector as VectorSource
} from 'ol/source';
import $ from 'jquery'
 
 
class DrawPlus extends Draw{
     constructor(options){
         super(options);
     } 
     abortDrawing() {
      this.abortDrawing_();
      }
}
   
 
 
var raster = new TileLayer({
    source: new OSM()
});
 
var source = new VectorSource({
    wrapX: false
});
 
var vector = new VectorLayer({
    source: source
});
 
var map = new Map({
    layers: [raster, vector],
    target: 'map',
    view: new View({
        center: [-11000000, 4600000],
        zoom: 4
    })
});
 
var typeSelect = document.getElementById('type');
 
var draw; // global so we can remove it later
function addInteraction() {
    var value = typeSelect.value;
    if (value !== 'None') {
        draw = new DrawPlus({
            source: source,
            type: typeSelect.value,
 
        });
        map.addInteraction(draw);
    }
}
 
typeSelect.onchange = function () {
    map.removeInteraction(draw);
    addInteraction();
};
addInteraction();
 
 
$(document).keyup(function (event) {
    if (event.keyCode == 27)
        draw.abortDrawing();
    else if (event.keyCode == 90 && event.ctrlKey) {
        console.log(draw);
        if (typeSelect.value== 'Circle')
            draw.abortDrawing();
        else
            draw.removeLastPoint()
 
    }
})