vue+openlayers绘制多边形过程中的撤销和恢复

32 阅读2分钟

废话不多说,先看操作

撤销恢复.gif openlayers在图形的绘制过程中是没有提供直接使用方法的,但是我们可以利用Draw的condition方法实现,下面就是实现过程:

初始化绘制方法
/**
* 该代码块为class类中的部分代码
**/

// 存储变量
filledIndex = 0
filledList = []

// 图层样式变量
drawStyleConfig = {
    'stroke': {
        'color': '#FF8139',
        'width': 3
    },
    'fill': {
        'color': 'rgba(255, 129, 57, 0.3)'
    },
    'image': {
        'stroke': {
            'color': '#fff',
            'width': 2
        },
        'fill': {
            'color': '#FF8139'
        },
        'radius': 5
    }
}

// 绘制图层变量
drawLayer = null

// 样式转换方法
createStyle(styleConfig) {
    /**
     * 根据 json 格式,创建样式,并返回 Style 对象
     */
    styleConfig = styleConfig || {};
    // 创建图层样式
    const styleObj = new Style();

    // 边框
    const stroke = styleConfig['stroke'] || {};
    let strokeObj: any = {
        'color': stroke['color'] || 'rgba(0,0,255,1.0)',
        'width': stroke['width'] || 2
    }
    if (stroke['lineDash']) {
        strokeObj['lineDash'] = stroke['lineDash'] || [20, 10, 40, 20]
    }
    const strokeStyle = new Stroke(strokeObj);
    styleObj.setStroke(strokeStyle);

    // 填充
    const fill = styleConfig['fill'] || {};
    const fillStyle = new Fill({
        'color': fill['color'] || 'rgba(255,0,0,0.5)',
    });
    styleObj.setFill(fillStyle);

    // 文字
    const text = styleConfig['text'] || {};
    const textStyle = new Text({
        'text': text['text'] || '',
        'padding': text['padding'] || [0, 0, 0, 0],
        'placement': text['placement'] || 'point',
        'overflow': text['overflow'] || false,
        'font': text['font'] || 'normal 16px 微软雅黑',
        'offsetX': text['offsetX'] || 0,
        'offsetY': text['offsetY'] || 0
    });
    if (!!text['fill']) {
        const fill = new Fill({
            'color': text.fill['color']
        });
        textStyle.setFill(fill);
    }
    if (!!text['backgroundFill']) {
        const backgroundFill = new Fill({
            'color': text.backgroundFill['color']
        });
        textStyle.setBackgroundFill(backgroundFill);
    }
    if (!!text['stroke']) {
        const stroke = new Stroke({
            'color': text.stroke['color']
        });
        textStyle.setStroke(stroke);
    }
    styleObj.setText(textStyle);

    // 图片
    const icon = styleConfig['icon'];
    if (!!icon) {
        const iconStyle = new Icon({
            'anchor': icon['anchor'] || [0, 0],
            'src': icon['src'],
            'displacement': icon['displacement'] || [0, 0],
            'img': icon['img'],
            'imgSize': icon['imgSize'] || 0,
            "scale": icon['scale'] || 1
        });
        styleObj.setImage(iconStyle);
    }

    const image = styleConfig['image'];
    if (!!image) {
        const imageStyle = new Circle();
        if (!!image['radius']) {
            imageStyle.setRadius(image['radius'])
        }
        if (!!image['stroke']) {
            const stroke = new Stroke({
                'color': image.stroke['color'],
                'width': image.stroke['width'] || 2
            });
            imageStyle.setStroke(stroke)
        }
        if (!!image['fill']) {
            const fill = new Fill({
                'color': image.fill['color']
            });
            imageStyle.setFill(fill)
        }
        styleObj.setImage(imageStyle);
    }

    return styleObj;
}
// 判断二维数组中是否存在另外一个数组
isArrayContained(arr1, arr2) {
    return arr2.every(item => arr1.some(subArray =>
        Array.isArray(subArray) && subArray.every((val, index) => val === item[index])
    ));
}
// 添加Draw绘制方法
addInteractionFun(drawType) {
    if (!this.drawLayer) {
        const drawSource = new VectorSource({
            'format': jsonFormat
        });
        this.drawLayer = new VectorLayer({
            'zIndex': 2, /* TODO 图层层级  */
            'style': {
                'fill-color': 'rgba(255, 129, 57, 0.30)',
                'stroke-color': '#FF8139',
                'stroke-width': 3,
                'circle-radius': 5,
                'circle-fill-color': '#FF8139',
            },
            'source': drawSource
        });
        this.map.addLayer(this.drawLayer)
    } else {
        this.drawLayer.getSource().clear()
    }
    this.draw = new Draw({
        source: this.drawLayer.getSource(),
        style: this.createStyle(this.drawStyleConfig),
        type: drawType,
        condition: (evt) => {
            const coordinate = evt.coordinate
            if(!this.isArrayContained(this.filledList, [coordinate])) {
                // 存储点击后的点
                this.prevAndNextFilling(coordinate)
            }
            return true
        }
    });
    this.map.addInteraction(this.draw);
    this.drawLayer.getSource().on('addfeature', () => {
        this.drawLayer.getSource().clear()
    })
}
存储点方法

对绘制过程中点击的点进行存储

prevAndNextFilling(coordinates) {
    if (this.filledIndex != this.filledList.length - 1) {
        this.filledList.splice(this.filledIndex + 1,this.filledList.length - 1)
    }
    this.filledList.push(coordinates)
    this.filledIndex = this.filledList.length - 1
}
开启绘制功能
drawLiveStockYf() {
    this.filledIndex = 0
    this.filledList = ['']
    this.drawInteractionClickFun('Polygon');
}
撤销恢复公共方法
  • 参数val
  • prev 撤销
  • next 恢复
prevAndNext(val) {
    if(val == 'prev') {
        if (this.filledIndex == 0) {
            if (this.filledList.length == 1) {
                console.log('未进行过任何操作!')
            } else {
                console.log('当前已经是第一步!')
            }
            return false
        }
        this.draw.removeLastPoint()
        this.filledIndex--
    } else if(val == 'next') {
        if (this.filledIndex == this.filledList.length - 1) {
            if (this.filledList.length == 1) {
                console.log('未进行过任何操作!')
            } else {
                console.log('当前已经是最后一步!')
            }
            return false
        }
        this.draw.appendCoordinates([this.filledList[this.filledIndex + 1]])
        this.filledIndex++
    }
}