Using Vue and OpenLayers Draw Interaction for Interactive Line Drawing
This guide shows how to load a GeoServer TileWMS layer in a Vue app with OpenLayers, configure map and line layers, add a selectable draw interaction for LineString geometry, capture drawn coordinates, and provides a complete Vue component example.
The article demonstrates step‑by‑step how to integrate OpenLayers into a Vue project to display a GeoServer‑served TileWMS layer and enable interactive line drawing.
1. Load TileWMS from GeoServer
Import the required OpenLayers CSS and modules, then create a TileLayer whose source is a TileWMS pointing to http://localhost:8000/geoserver/nyc/wms with parameters LAYERS=nyc:nyc_roads, STYLES="", VERSION="1.1.1" and tiled=true. The ratio must be set to 1; a value of 0 prevents the map from rendering.
2. Declare component data
data() {
return {
map: null, // OpenLayers Map instance
layer: null, // Tile layer for the WMS source
lineLayer: null, // Vector layer for drawn lines
draw: null, // Draw interaction instance
lineSource: null, // Vector source for line features
coordinate: [] // Array to store coordinates of each line
};
}3. Initialize the map
In the mounted() hook call initMap(). Inside initMap() create the tile layer, a VectorSource (with wrapX:false) for lines, and a VectorLayer that uses this source. Then instantiate the Map with target "map", the two layers, and a View centered at [987777.93778, 213834.81024] with zoom 14, minZoom 6 and maxZoom 19.
4. Define selection style and tool
let selectedStyle = new Style({
fill: new Fill({color: 'rgba(1, 210, 241, 0.2)'}),
stroke: new Stroke({color: 'yellow', width: 4})
});
this.selectTool = new Select({
multi: true,
hitTolerance: 10,
style: selectedStyle
});The style highlights selected features with a semi‑transparent fill and a yellow stroke.
5. Add interactions and draw tool
Add the selection interaction to the map, then invoke the custom onAddInteraction('LineString') method to create a Draw interaction for line geometry.
onAddInteraction(type) {
let self = this;
this.draw = new Draw({
source: self.lineSource,
type: type
});
this.draw.on('drawend', function(e) {
const geometry = e.feature.getGeometry();
let pointArr = geometry.getCoordinates();
self.coordinate.push(pointArr);
console.log('self.coordinate=' + self.coordinate);
self.removeDraw();
});
self.map.addInteraction(this.draw);
},
removeDraw() {
this.map.removeInteraction(this.draw);
}The drawend listener extracts the line coordinates, stores them in coordinate, logs the result, and removes the draw interaction to prevent further drawing until re‑triggered.
6. Full Vue component example
<template>
<div id="app">
<div id="map" class="map"></div>
</div>
</template>
<script>
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import {Fill, Style, Stroke} from "ol/style";
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {TileWMS, Vector as VectorSource} from 'ol/source';
import {Select, Draw} from 'ol/interaction';
export default {
name: "olMapImageWMSDrawLine",
data() {
return {
map: null,
layer: null,
lineLayer: null,
draw: null,
lineSource: null,
coordinate: []
};
},
mounted() {
this.initMap();
},
methods: {
onAddInteraction(type) {
let self = this;
this.draw = new Draw({source: self.lineSource, type: type});
this.draw.on('drawend', function(e) {
const geometry = e.feature.getGeometry();
let pointArr = geometry.getCoordinates();
self.coordinate.push(pointArr);
console.log('self.coordinate=' + self.coordinate);
self.removeDraw();
});
self.map.addInteraction(this.draw);
},
removeDraw() {
this.map.removeInteraction(this.draw);
},
initMap() {
this.layer = new TileLayer({
source: new TileWMS({
ratio: 1,
url: "http://localhost:8000/geoserver/nyc/wms",
params: {LAYERS: "nyc:nyc_roads", STYLES: "", VERSION: "1.1.1", tiled: true},
serverType: "geoserver"
})
});
this.lineSource = new VectorSource({wrapX: false});
this.lineLayer = new VectorLayer({source: this.lineSource});
this.map = new Map({
target: "map",
layers: [this.layer, this.lineLayer],
view: new View({center: [987777.93778, 213834.81024], zoom: 14, minZoom: 6, maxZoom: 19})
});
let selectedStyle = new Style({
fill: new Fill({color: 'rgba(1, 210, 241, 0.2)'}),
stroke: new Stroke({color: 'yellow', width: 4})
});
this.selectTool = new Select({multi: true, hitTolerance: 10, style: selectedStyle});
this.map.addInteraction(this.selectTool);
this.onAddInteraction('LineString');
}
}
};
</script>
<style scoped>
.map {width: 100%; height: 800px;}
</style>The article also includes a GIF illustrating the interactive line‑drawing result and provides links to the original blog posts for further reference.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
The Dominant Programmer
Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
