Select with overlay

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://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">
    Selection
    <ul>
      <li v-for="feature in selectedFeatures" :key="feature.id">
        Feature {{ feature.id }}
      </li>
    </ul>
  </div>
  <div class="filter">
    <select v-model="status">
      <option value="-1">-</option>
      <option value="0">Off</option>
      <option value="1">On</option>
    </select>
  </div>
  <vl-map ref="map" data-projection="EPSG:4326">
    <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="featuresLayer">
      <vl-source-vector :features="filteredFeatures"></vl-source-vector>
    </vl-layer-vector>
    
    <vl-interaction-select :features.sync="selectedFeatures">
      <template slot-scope="select">
        <vl-overlay v-for="feature in select.features" :key="feature.id" :id="feature.id"
                      :position="feature.geometry.coordinates" :auto-pan="true">
          <div style="background: white; border: 1px solid black">
            Feature {{ feature.id }}<br>
            Name: {{ feature.properties.name }}<br>
            ...<br>
          </div>
        </vl-overlay>
      </template>
    </vl-interaction-select>
  </vl-map>
  
</div>

CSS

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

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

.filter {
  position: absolute;
  top: 0;
  left: 150px;
  z-index: 1;
}

JavaScript

// external loaded features
let features = [
	{
      "type": "Feature",
      "id": 1,
      "properties": {
        "status": 1,
        "name": "Feature One",
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -30.761718749999996,
          58.90464570302001
        ]
      }
    },
    {
      "type": "Feature",
      "id": 2,
      "properties": {
      	"status": 1,
        "name": "Feature Two",
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          36.73828124999999,
          44.59046718130883
        ]
      }
    },
    {
      "type": "Feature",
      "id": 3,
      "properties": {
        "status": 0,
        "name": "Feature Three",
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -23.37890625,
          32.10118973232094
        ]
      }
    }
]

new Vue({
	el: '#app',
  computed: {
  	filteredFeatures () {
    	return this.features.filter(feature => {
      	if (this.status != -1) {
        	return feature.properties.status === Number(this.status)
        }
        return feature
      })
    },
  },
  data () {
  	return {
    	zoom: 3,
      center: [-10, 35],
      features: features,
      selectedFeatures: [],
      status: -1,
    }
  },
})