Search code examples
javascriptopenlayers

Openlayers 7 add a draw and a dragBox interactions to map


I want to allow users to drag or to click in order to draw a single box on a map. This behavior is turned on by a button. When I draw a box before dragBox a mouseup event is left by the draw and the next dragBox starts at that point rather than its mousedown. In the picture below the white dot in the lower right hand corner is the mouseup point left behind.

square with the mouseup point left behind (white pixel)

  • I've tried to setActive(false) for the interaction that isn't been drawn with and instead of removing the interaction.
  • I've tried changing the order of removing or adding the interactions.
  • I've tried capturing the mouseup point and deleting it.
  • I've tried capturing an "addfeature" event, but wasn't able to detect on

This is a similar problem How to add several draw interaction to a map.

class DrawBoxControl extends ol.control.Control {
constructor(opts) {
    const options = opts || {};
    // button code
    const s = new ol.source.Vector({wrapX: false});
    this.drawLayer = new ol.layer.Vector({source: s,});

    let draw = new ol.interaction.Draw({
        source: s,
        type: 'Circle',
        geometryFunction: ol.interaction.Draw.createBox()
    });

    let self = this;

    const dragBox = new ol.interaction.DragBox({});
    draw.on('drawend', (event) => {
        self.getMap().removeInteraction(dragBox);
        self.getMap().removeInteraction(draw);
    });

    dragBox.on('boxend', (event) => {
        let feature = new ol.Feature(ol.geom.Polygon.fromExtent(dragBox.getGeometry().getExtent()));
        s.addFeatures([feature]);
        self.getMap().removeInteraction(draw);
        self.getMap().removeInteraction(dragBox);
    });
    button.addEventListener('click', () => {
        s.clear();
        self.getMap().addInteraction(dragBox);
        self.getMap().addInteraction(draw);
    });
}
setMap(m) {
    super.setMap(m);
    this.drawLayer.setMap(m);
}

}


Solution

  • I was able to solve the main part of the problem. The white ‘dot’ still appears on the screen after drawing a box but disappears when I click the button to draw another box. I might have to live with it.

    I solved the problem by looking at the dragBox object when I first created it and then after the draw interaction. After the draw interaction, these properties had values. I reset them to match the dragBox values at initiation and that solved the problem.

                dragBox.handlingDownUpSequence = false;
                dragBox.StartPixel_ = null;
                dragBox.targetPointers = [];
                this.getMap().removeInteraction(dragBox);
    

    Here is the complete code in case it is useful to someone else:

    class DrawBoxControl extends ol.control.Control {
    constructor(opts) {
        const options = opts || {};
        //button code
    
        const s = new ol.source.Vector({
            wrapX: false
        });
        this.drawLayer = new ol.layer.Vector({source: s});
        let draw = new ol.interaction.Draw({
            source: s,
            type: 'Circle',
            geometryFunction: ol.interaction.Draw.createBox()
        });
        
        let dragBox = new ol.interaction.DragBox({});
    
        draw.on('drawend', (event) => {
                dragBox.handlingDownUpSequence = false;
                dragBox.startPixel_ = null;
                dragBox.targetPointers = [];
                this.getMap().removeInteraction(dragBox);
                this.getMap().removeInteraction(draw);
        });
    
        dragBox.on('boxend', (event) => {
                let polygon = ol.geom.Polygon.fromExtent(dragBox.getGeometry().getExtent());
                let feature = new ol.Feature(polygon);
                s.addFeatures([feature]);
                this.getMap().removeInteraction(draw);
                this.getMap().removeInteraction(dragBox);
        });
        
        button.addEventListener('click', buttonFunction.bind(this));
    
        function buttonFunction() {
            s.clear();
            this.getMap().addInteraction(dragBox);
            this.getMap().addInteraction(draw);
        }
    
    }
    setMap(m) {
        if (this.getMap()) this.getMap().removeLayer(this.drawLayer);
        super.setMap(m);
        this.drawLayer.setMap(m);
    }
    

    }