user6730740
user6730740

Reputation: 101

Draw arrow without using any image in openlayers3

How do I draw an arrow over a vector layer in Openlayers 3 map? I tried creating an arrow using canvaselement but don't know how to draw it over the ol3 map.

Upvotes: 5

Views: 7651

Answers (2)

megges
megges

Reputation: 640

This is another customization of the Openlayers line-arrow Example. It uses a RegularShape instead of an image. The arrow will keep its size independent of the current map zoom.

var source = new ol.source.Vector();

var styleFunction = function(feature) {
  var geometry = feature.getGeometry();
  var styles = [
    // linestring
    new ol.style.Style({
      stroke: new ol.style.Stroke({
        color: '#000',
        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);

    styles.push(new ol.style.Style({
      geometry: new ol.geom.Point(end),
      image: new ol.style.RegularShape({
        fill: new ol.style.Fill({
          color: '#000'
        }),
        points: 3,
        radius: 8,
        displacement: [-8 * 0.8, 0],
        rotation: -rotation,
        angle: Math.PI / 2 // rotate 90°
      })
    }));
  });

  return styles;
};

ol.proj.useGeographic()
var map = new ol.Map({
  interactions: ol.interaction.defaults.defaults({
    doubleClickZoom: false
  }),
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    }),
    new ol.layer.Vector({
      source: source,
      style: styleFunction
    })
  ],
  target: 'map',
  view: new ol.View({
    center: [0, 6],
    zoom: 4
  })
});

map.addInteraction(new ol.interaction.Draw({
  source: source,
  type: ('LineString')
}));
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/ol.css">

<div id="map" class="map" tabindex="0" style="position: fixed; height: 94%; width: 98%;"></div>

Upvotes: 7

Icarus
Icarus

Reputation: 1647

A canvas element is not necessary. You can take the arrow example from the Openlayers site and add 2 custom LineString elements instead of the icon. You already have in the example the rotation angle in radians and the event where you should add your code.

Hopefully the following snippet does the trick:

var source = new ol.source.Vector();

var styleFunction = function (feature) {
    var geometry = feature.getGeometry();
    var styles = [
        // linestring
        new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: '#ffcc33',
                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);

        var lineStr1 = new ol.geom.LineString([end, [end[0] - 200000, end[1] + 200000]]);
        lineStr1.rotate(rotation, end);
        var lineStr2 = new ol.geom.LineString([end, [end[0] - 200000, end[1] - 200000]]);
        lineStr2.rotate(rotation, end);

        var stroke = new ol.style.Stroke({
            color: 'green',
            width: 1
        });

        styles.push(new ol.style.Style({
            geometry: lineStr1,
            stroke: stroke
        }));
        styles.push(new ol.style.Style({
            geometry: lineStr2,
            stroke: stroke
        }));
    });

    return styles;
};

var map = new ol.Map({
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        }),
        new ol.layer.Vector({
            source: source,
            style: styleFunction
        })
    ],
    target: 'map',
    view: new ol.View({
        center: [0, 0],
        zoom: 3
    })
});

map.addInteraction(new ol.interaction.Draw({
    source: source,
    type: ('LineString')
}));
<script src="https://openlayers.org/en/v3.20.1/build/ol.js"></script>
<link href="https://openlayers.org/en/v3.20.1/css/ol.css" rel="stylesheet"/>
<div id="map" class="map" tabindex="0"></div>

Upvotes: 7

Related Questions