changeset 942:912d016275ee

client: add arrow to drawn linesegment * Add styling function that will place an icon png image at the end of each drawn line segment, in the right rotation. Note that this does not look perfectly centered, see comment in the code.
author Bernhard Reiter <bernhard@intevation.de>
date Tue, 09 Oct 2018 18:39:01 +0200
parents 8a80ef09a62c
children 532c8392048f
files client/src/application/assets/linestring_arrow.png client/src/map/Maplayer.vue
diffstat 2 files changed, 43 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
Binary file client/src/application/assets/linestring_arrow.png has changed
--- a/client/src/map/Maplayer.vue	Tue Oct 09 17:00:49 2018 +0200
+++ b/client/src/map/Maplayer.vue	Tue Oct 09 18:39:01 2018 +0200
@@ -33,11 +33,12 @@
 import { WFS, GeoJSON } from "ol/format.js";
 // import GeometryType from "ol/geom/GeometryType.js";
 import LineString from "ol/geom/LineString.js";
+import Point from "ol/geom/Point.js";
 import Draw from "ol/interaction/Draw.js";
 import { Vector as VectorLayer } from "ol/layer.js";
 import { Vector as VectorSource } from "ol/source.js";
 import { getLength } from "ol/sphere.js";
-import { Stroke, Style, Fill } from "ol/style.js";
+import { Icon, Stroke, Style, Fill } from "ol/style.js";
 
 import distance from "@turf/distance";
 import {
@@ -83,9 +84,49 @@
     createVectorSource() {
       this.vectorSource = new VectorSource({ wrapX: false });
     },
+    drawStyleFunction(feature) {
+      // adapted from OpenLayer's LineString Arrow Example
+      var geometry = feature.getGeometry();
+      var styles = [
+        // linestring
+        new Style({
+          stroke: new Stroke({
+            color: "#369aca",
+            width: 2
+          })
+        })
+      ];
+
+      geometry.forEachSegment(function(start, end) {
+        var dx = end[0] - start[0];
+        var dy = end[1] - start[1];
+        var rotation = Math.atan2(dy, dx);
+        // arrows
+        styles.push(
+          new Style({
+            geometry: new Point(end),
+            image: new Icon({
+              // we need to make sure the image is loaded by Vue Loader
+              src: require("../application/assets/linestring_arrow.png"),
+              // fiddling with the anchor's y value does not help to
+              // position the image more centered on the line ending, as the
+              // default line style seems to be slightly uncentered in the
+              // anti-aliasing, but the image is not placed with subpixel
+              // precision
+              anchor: [0.75, 0.5],
+              rotateWithView: true,
+              rotation: -rotation
+            })
+          })
+        );
+      });
+
+      return styles;
+    },
     createVectorLayer() {
       this.vectorLayer = new VectorLayer({
-        source: this.vectorSource
+        source: this.vectorSource,
+        style: this.drawStyleFunction
       });
     },
     removeCurrentInteraction() {