ol ext draw hole

by Vladimir Vershinin

HTML

<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdn.rawgit.com/Viglino/ol-ext/master/dist/ol-ext.min.js"></script>
<script src="https://unpkg.com/[email protected]/lib/index.umd.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/lib/style.css">
<div id="app">
  <div class="panel">
    <ul>
      <select v-model="drawType">
        <option value="draw">draw polygon</option>
        <option value="drawhole">draw hole</option>
      </select>
		</ul>
  </div>
  <vl-map ref="map" @created="onMapCreated">
    <vl-view :zoom.sync="zoom" :center.sync="center"></vl-view>
  
    <vl-layer-tile>
      <vl-source-osm></vl-source-osm>
    </vl-layer-tile>
    
    <vl-layer-vector ref="vectorLayer">
      <vl-source-vector ident="drawTarget" :features.sync="drawnFeatures"></vl-source-vector>
      <vl-style-func :factory="stylefuncFactory"></vl-style-func>
    </vl-layer-vector>
    
    <vl-interaction-draw :active="drawType === 'draw'" type="Polygon" source="drawTarget" @drawstart="onDrawStart" @drawend="onDrawEnd"></vl-interaction-draw>
  </vl-map>
</div>

CSS

html, body, #app {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.panel {
  position: absolute;
  height: 100%;
  padding: 10px;
  background: #fff;
  z-index: 1;
  width: 150px;
}

.panel ul {
  margin: 0 1em;
  padding: 0;
}

.panel ul > li {
  margin: 0 1em;
}

JavaScript

new Vue({
	el: '#app',
  data () {
  	return {
    	zoom: 2,
      center: [0, 0],
      drawnFeatures: [],
      drawType: 'draw',
    }
  },
  watch: {
  	drawType (val) {
    	// reactify drawhole
    	if (val === 'drawhole' && this.drawholeInteraction) {
        this.drawholeInteraction.setActive(true)
      } else {
      	this.drawholeInteraction.setActive(false)
      }
    },
  },
  methods: {
  	async onMapCreated (mapVm) {
    	// await for layer creation
    	await this.$refs.vectorLayer.$createPromise
      
    	this.drawholeInteraction = new ol.interaction.DrawHole ({	
      	layers: [ this.$refs.vectorLayer.$layer ],
			});
			this.drawholeInteraction.setActive(false);
			mapVm.$map.addInteraction(this.drawholeInteraction);
    },
    stylefuncFactory () {
    	const defStyle = new ol.style.Style({
      	fill: new ol.style.Fill({ color: 'red' }),
        stroke: new ol.style.Stroke({ color: 'blue', width: 3 }),
      })
    
    	return feature => {
      	// feature - ol.Feature instance
      	// here we can build and return dynamic style
        // based on feature properties
        if (feature.get('last')) {
        	return new ol.style.Style({
          	fill: new ol.style.Fill({ color: 'cyan' }),
            stroke: new ol.style.Stroke({ color: 'blue', width: 3 }),
          })
        }
      
      	return defStyle
      }
    },
    onDrawStart () {
    	this.drawnFeatures = this.drawnFeatures.map(feature => ({
      	...feature,
        properties: {
        	...feature.properties,
          last: false,
        },
      }))
    },
    onDrawEnd ({ feature }) {
    	// feature - ol.Feature instance
    	feature.set('last', true)
    },
  },
})