67

I'm trying to add makers on a OpenLayers 3 map.

The only example I have found is this one in the OpenLayers example list.

But the example uses ol.Style.Icon instead of something like OpenLayers.Marker in OpenLayers 2.

First Question

The only difference would be that you have to set the image Url but is it the only way to add a marker?

Also OpenLayers 3 doesn't seem to come with marker images so it would make sense if there's no other way than ol.Style.Icon

Second Question

It would be really nice if someone could give me an example of a function to add markers or icons after the map is loaded.

From what I understand in the example, they create a layer for the icon

var iconFeature = new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.transform([-72.0704, 46.678], 'EPSG:4326', 'EPSG:3857')),
  name: 'Null Island',
  population: 4000,
  rainfall: 500
});


var iconStyle = new ol.style.Style({
  image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
    anchor: [0.5, 46],
    anchorXUnits: 'fraction',
    anchorYUnits: 'pixels',
    opacity: 0.75,
    src: 'data/icon.png'
  }))
});

iconFeature.setStyle(iconStyle);

var vectorSource = new ol.source.Vector({
  features: [iconFeature]
});

var vectorLayer = new ol.layer.Vector({
  source: vectorSource
});

Then they set the icon layer when they initialize the map

var map = new ol.Map({
  layers: [new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer],
  target: document.getElementById('map'),
  view: new ol.View2D({
    center: [0, 0],
    zoom: 3
  })
});

If I want to add many markers, do I have to create 1 layer for each marker?

How could I add many markers to a layer? I can't figure out how this part would look like

var vectorSource = new ol.source.Vector({
  features: [iconFeature]
});

var vectorLayer = new ol.layer.Vector({
  source: vectorSource
});

Thank you

Marc
  • 16,170
  • 20
  • 76
  • 119

4 Answers4

87

Q1. Markers are considered deprecated in OpenLayers 2, though this isn't very obvious from the documentation. Instead, you should use an OpenLayers.Feature.Vector with an externalGraphic set to some image source in its style. This notion has been carried over to OpenLayers 3, so there is no marker class and it is done as in the example you cited.

Q2. The ol.source.Vector takes an array of features, note the line, features: [iconFeature], so you would create an array of icon features and add features to that, eg:

var iconFeatures=[];

var iconFeature = new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.transform([-72.0704, 46.678], 'EPSG:4326',     
  'EPSG:3857')),
  name: 'Null Island',
  population: 4000,
  rainfall: 500
});

var iconFeature1 = new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.transform([-73.1234, 45.678], 'EPSG:4326',     
  'EPSG:3857')),
  name: 'Null Island Two',
  population: 4001,
  rainfall: 501
});

iconFeatures.push(iconFeature);
iconFeatures.push(iconFeature1);

var vectorSource = new ol.source.Vector({
  features: iconFeatures //add an array of features
});

var iconStyle = new ol.style.Style({
  image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
    anchor: [0.5, 46],
    anchorXUnits: 'fraction',
    anchorYUnits: 'pixels',
    opacity: 0.75,
    src: 'data/icon.png'
  }))
});


var vectorLayer = new ol.layer.Vector({
  source: vectorSource,
  style: iconStyle
});

Obviously, this could be more elegantly handled by putting all of the ol.Feature creation inside a loop based on some data source, but I hope this demonstrates the approach. Note, also, that you can apply a style to the ol.layer.Vector so that it will be applied to all features being added to the layer, rather than having to set the style on individual features, assuming you want them to be the same, obviously.

EDIT: That answer doesn't seem to work. Here is an updated fiddle that works by adding the features (icons) to the empty vector source in a loop, using vectorSource.addFeature and then adds the whole lot to the layer vector afterwards. I will wait and see if this works for you, before updating my original answer.

John Powell
  • 12,253
  • 6
  • 59
  • 67
  • Thank you! This is exactly what I need. I couldn't figure it out with the documentation. – Marc Jun 19 '14 at 22:44
  • You are welcome. The documentation is a bit sparse still, but to be fair, they are still working on the code :D – John Powell Jun 19 '14 at 22:47
  • Thanks for catching that typo -- one of many reasons to use jsfiddle. – John Powell Jun 19 '14 at 23:00
  • No problem. Unfortunately, I have a `Uncaught TypeError: undefined is not a function` exception in the ol.js line 50 when I use an array of features. – Marc Jun 19 '14 at 23:14
  • Is that in the compressed ol.js? I have looked at the source code and it looks fine. I had better try and get to the bottom of this. – John Powell Jun 19 '14 at 23:40
  • I managed to load the uncompressed js and the exception is in event.js at the line 283. `src` is not defined – Marc Jun 20 '14 at 01:05
  • I have put a jsfiddle in the answer which does work, by using a loop to load the icons. http://jsfiddle.net/6RS2z/1/ I hope this works for you. I'm still not sure why adding the array directly doesn't work, but don't have time to debug today. You could add icons with different styles after the map has loaded using addFeature too, as you originally asked. – John Powell Jun 20 '14 at 10:56
  • Thank you for taking the time to make a jsfiddle. It works like a charm. I don't know why the previous solution doesn't work. The API documentation says that features takes an Array.. I will have to take a look to make sure that I understand. – Marc Jun 20 '14 at 14:06
  • I am also bemused, but I am still learning OL3, and the Google closure stuff takes some getting used to. I am glad you have a working solution, at least. – John Powell Jun 20 '14 at 14:10
  • 2
    The jsfiddle doesnt produce a result – Philip Rego Jan 10 '15 at 03:25
  • @PhilipRego. What result are you expecting? I have just tried it, to see if the underlying OL lib had changed, as happened a few times in beta, and I still see a bunch of random markers. – John Powell Jan 12 '15 at 16:07
  • 1
    I didn't see anything. I didn't know I needed an account to be able to see the result. – Philip Rego Jan 13 '15 at 23:21
  • same here, blank page with `Uncaught TypeError: undefined is not a function` – Paranoid Android Jun 15 '15 at 14:30
  • 1
    The fiddle by @JohnBarça (ty for the fiddle) didnt work anymore because the urls to the openlayer library en icon don't exist anymore. Here is an updated version http://jsfiddle.net/6RS2z/352/ – Alexander Sep 22 '15 at 11:04
  • @Alexander. Thanks for pointing that out. I have updated the original fiddle. – John Powell Sep 22 '15 at 12:00
14

there's a good tutorial at: http://openlayersbook.github.io

not tested but may helpful

var features = [];

//iterate through array...
for( var i = 0 ; i < data.length ; i++){
    var item = data[i];                                     //get item
    var type = item.type;                                   //get type
    var longitude = item.longitude;                         //coordinates
    var latitude = item.latitude;
    /*....
    * now get your specific icon...('..../ic_customMarker.png')
    * by e.g. switch case...
    */
    var iconPath = getIconPath(type);

    //create Feature... with coordinates
    var iconFeature = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.transform([longitude, latitude], 'EPSG:4326',     
        'EPSG:3857'))
    });

    //create style for your feature...
    var iconStyle = new ol.style.Style({
        image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
        anchor: [0.5, 46],
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        opacity: 0.75,
        src: iconPath
        }))
    });

    iconFeature.setStyle(iconStyle);
    features.push(iconFeature);
    //next item...
}

/*
* create vector source
* you could set the style for all features in your vectoreSource as well
*/
var vectorSource = new ol.source.Vector({
    features: features      //add an array of features
    //,style: iconStyle     //to set the style for all your features...
});

var vectorLayer = new ol.layer.Vector({
    source: vectorSource
});
map.addLayer(vectorLayer);
RickPat
  • 487
  • 6
  • 6
  • Thanks!!! map.addLayer() was what i was missing! i was trying to just push the layer into map.layers, that doesn't work. – deweydb Mar 13 '20 at 19:00
1
var exampleLoc = ol.proj.transform(
    [131.044922, -25.363882], 'EPSG:4326', 'EPSG:3857');

var map = new ol.Map({
  target: 'map',
  renderer: 'canvas',
  view: new ol.View2D({
    projection: 'EPSG:3857',
    zoom: 3,
    center: exampleLoc
  }),
  layers: [
    new ol.layer.Tile({source: new ol.source.MapQuest({layer: 'osm'})})
  ]
});

map.addOverlay(new ol.Overlay({
  position: exampleLoc,
  element: $('<img src="resources/img/marker-blue.png">')
      .css({marginTop: '-200%', marginLeft: '-50%', cursor: 'pointer'})
      .tooltip({title: 'Hello, world!', trigger: 'click'})
}));

map.on('postcompose', function(evt) {
  evt.vectorContext.setFillStrokeStyle(
      new ol.style.Fill({color: 'rgba(255, 0, 0, .1)'}),
      new ol.style.Stroke({color: 'rgba(255, 0, 0, .8)', width: 3}));
  evt.vectorContext.drawCircleGeometry(
      new ol.geom.Circle(exampleLoc, 400000));
});

var exampleKml = new ol.layer.Vector({
  source: new ol.source.KML({
    projection: 'EPSG:3857',
    url: 'data/example.kml'
  })
});
map.addLayer(exampleKml);
Ishaan Nigam
  • 83
  • 1
  • 10
0

We just finished updating our website NUFOSMATIC from ol2 to ol6. Both the ol2 and ol3 code is on the site. This includes Matt Walker's ol-layerswitcher https://github.com/walkermatt replacing the missing ol2 layerswitcher. We actually updated three map applications; HEATMAP replaces the Patrick Wied (http://www.patrick-wied.at) ol2 heatmap with the native ol6 heatmap.

Only took 6 days. Wonder why we waited this long... oh, yeah, we have day jobs...

Nufosmatic
  • 145
  • 1
  • 11