简体   繁体   中英

LineString direction arrows in Openlayers 4

I'm trying to make a LineString which has arrows in the end of each line to show direction of the route. I use an example from the official site: https://openlayers.org/en/latest/examples/line-arrows.html The example code creates arrows by user's drawing, but I need arrows for given LineString. My code contains icons for end and finish of the route. When I use

'route': new ol.style.Style({
      stroke: new ol.style.Stroke({
        width: 6, color: [23, 120, 22, 0.6]
      })
    }),

in styles, my code works. But when I put style for Linestring from the example, it gives me an error saying "Uncaught TypeError: cY is not a function".

Here is my code:

 var points = [ [76.8412, 43.2245], [76.8405, 43.2210], [76.8479, 43.2200], [76.8512, 43.2220] ]; var route = new ol.geom.LineString(points); route.transform('EPSG:4326', 'EPSG:3857'); var routeFeature = new ol.Feature({ type: 'route', geometry: route }); var startMarker = new ol.Feature({ type: 'icon-a', geometry: new ol.geom.Point(ol.proj.fromLonLat(points[0])) }); var endMarker = new ol.Feature({ type: 'icon-b', geometry: new ol.geom.Point(ol.proj.fromLonLat(points[points.length - 1])) }); var styles = { 'route': function(feature) { var geometry = feature.getGeometry(); var styles = [ // linestring new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#ffcc33', width: 2 }), image: new ol.style.Icon({ anchor: [0.5, 1], src: 'img/icon-a.png' }) }) ]; 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 ol.style.Style({ geometry: new ol.geom.Point(end), image: new ol.style.Icon({ src: 'https://openlayers.org/en/v4.6.3/examples/data/arrow.png', anchor: [0.75, 0.5], rotateWithView: true, rotation: -rotation }) })); }); return styles; }, 'icon-a': new ol.style.Style({ image: new ol.style.Icon({ anchor: [0.5, 1], src: 'img/icon-a.png' }) }), 'icon-b': new ol.style.Style({ image: new ol.style.Icon({ anchor: [0.5, 1], src: 'img/icon-b.png' }) }) }; var vectorLayer = new ol.layer.Vector({ source: new ol.source.Vector({ features: [routeFeature, startMarker, endMarker] }), style: function(feature) { return styles[feature.get('type')]; } }); var center = ol.proj.fromLonLat([76.8512, 43.2220]); var map = new ol.Map({ target: document.getElementById('map'), view: new ol.View({ center: center, zoom: 15, minZoom: 2, maxZoom: 19 }), layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer ] });
 #map { /* just for testing purposes */ width: 100%; min-width: 100px; max-width: 500px; margin-top: 50px; height: 50px; }
 <link href="https://openlayers.org/en/v4.6.4/css/ol.css" rel="stylesheet"/> <script src="https://openlayers.org/en/v4.6.4/build/ol-debug.js"></script> <div id="map"></div>

Firstly, you can use ol-debug.js instead of ol.js , which is uncompressed and helps debugging. The exception you get is

TypeError: style.getImage is not a function (Line 30443)

You get that error because your styles object is mixed: some styles are functions, some are plain Style objects.

You might think that OL can handle both, and you are normally right. However, you provide a function to vectorLayer , so OL detects that you provided a function and calls it. The return value of that function is expected to be a style object. But for route , that returns a function instead!

So when OL calls

style: function(feature) {
    return styles[feature.get('type')];
}

It gets styles for the types icon-a , icon-b , but an function for route . You need to enhance your style function to handle that special case:

style: function(feature) {
  const myStyle = stylesMap[feature.get('type')];
  if (myStyle instanceof Function) {
    return myStyle(feature);
  }
  return myStyle;
}

PS: Using the same name for a variable twice (styles) is bad practice and can lead to weird bugs.

Here is the runnable example:

 var points = [ [76.8412, 43.2245], [76.8405, 43.2210], [76.8479, 43.2200], [76.8512, 43.2220] ]; var route = new ol.geom.LineString(points); route.transform('EPSG:4326', 'EPSG:3857'); var routeFeature = new ol.Feature({ type: 'route', geometry: route }); var startMarker = new ol.Feature({ type: 'icon-a', geometry: new ol.geom.Point(ol.proj.fromLonLat(points[0])) }); var endMarker = new ol.Feature({ type: 'icon-b', geometry: new ol.geom.Point(ol.proj.fromLonLat(points[points.length - 1])) }); var stylesMap = { 'route': function(feature) { var geometry = feature.getGeometry(); var styles = [ // linestring new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#ffcc33', width: 2 }), image: new ol.style.Icon({ anchor: [0.5, 1], src: 'img/icon-a.png' }) }) ]; 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 ol.style.Style({ geometry: new ol.geom.Point(end), image: new ol.style.Icon({ src: 'https://openlayers.org/en/v4.6.5/examples/data/arrow.png', anchor: [0.75, 0.5], rotateWithView: true, rotation: -rotation }) })); }); return styles; }, 'icon-a': new ol.style.Style({ image: new ol.style.Icon({ anchor: [0.5, 1], src: 'img/icon-a.png' }) }), 'icon-b': new ol.style.Style({ image: new ol.style.Icon({ anchor: [0.5, 1], src: 'img/icon-b.png' }) }) }; var vectorLayer = new ol.layer.Vector({ source: new ol.source.Vector({ features: [routeFeature, startMarker, endMarker] }), style: function(feature) { const myStyle = stylesMap[feature.get('type')]; if (myStyle instanceof Function) { return myStyle(feature); } return myStyle; } }); var center = ol.proj.fromLonLat([76.8512, 43.2220]); var map = new ol.Map({ target: document.getElementById('map'), view: new ol.View({ center: center, zoom: 15, minZoom: 2, maxZoom: 19 }), layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer ] });
 html, body { width: 100%; height: 100%; padding: 0px; margin: 0px; } #map { /* just for testing purposes */ width: 100%; height: 100%; }
 <link href="https://openlayers.org/en/v4.6.5/css/ol.css" rel="stylesheet" /> <script src="https://openlayers.org/en/v4.6.5/build/ol-debug.js"></script> <div id="map"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM