OpenLayers 2 has these layer events "loadstart & loadend."

What is equivalent to them in OpenLayers 3?

While a vector layer loads and is rendered, I need to show a loading icon.


5 Answers 5


Assuming you use an ol.layer.Vector with an ol.source.GeoJSON you can use something like this:

var vectorSource = new ol.source.GeoJSON({
  projection : 'EPSG:3857',
  url: 'http://examples.org/fearures.json'

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


// show loading icon
// ...

var listenerKey = vectorSource.on('change', function(e) {
  if (vectorSource.getState() == 'ready') {
    // hide loading icon
    // ...
    // and unregister the "change" listener 
    // or vectorSource.unByKey(listenerKey) if
    // you don't use the current master branch
    // of ol3

This shows how to get a notification when the vector source is loaded. It only works with sources inheriting from ol.source.StaticVector. Examples include ol.source.GeoJSON and ol.source.KML .

Also, note that this code may no longer work in the future when ol3 will provide a consistent way to know if/when a source is loaded.

  • Great! I was looking for this too. Wondering why OL3 does not include it yet. Feb 8, 2015 at 16:40
  • Why not vectorSource.once('change', function(e){...}? Jun 15, 2015 at 13:11

In ol3 version 3.10.0 things have changed. So is more clear than older versions but still more complicated than ol2.

So for TILE (ol.layer.Tile) layers your code snip should look like:

//declare the layer
var osmLayer =  new ol.layer.Tile({
  source: new ol.source.OSM()
//asign the listeners on the source of tile layer
osmLayer.getSource().on('tileloadstart', function(event) {
//replace with your custom action
document.getElementById('tilesloaderindicatorimg').src = 'css/images/tree_loading.gif';

osmLayer.getSource().on('tileloadend', function(event) {
//replace with your custom action
document.getElementById('tilesloaderindicatorimg').src = 'css/images/ok.png';
osmLayer.getSource().on('tileloaderror', function(event) {
//replace with your custom action        
document.getElementById('tilesloaderindicatorimg').src = 'css/images/no.png';

while for WMS layers the approach is a bit different:

//declare the layer
var wmsLayer =   new ol.layer.Image({
source: new ol.source.ImageWMS({
  attributions: [new ol.Attribution({
    html: '© ' +
        '<a href="http://www.geo.admin.ch/internet/geoportal/' +
        'en/home.html">' +
        'National parks / geo.admin.ch</a>'
  crossOrigin: 'anonymous',
  params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'},
  serverType: 'mapserver',
  url: 'http://wms.geo.admin.ch/'

//and now asign the listeners on the source of it
var lyrSource = wmsLayer.getSource();
  lyrSource.on('imageloadstart', function(event) {
  console.log('imageloadstart event',event);
  //replace with your custom action
  var elemId = event.target.params_.ELEMENTID;
  document.getElementById(elemId).src = 'css/images/tree_loading.gif'; 

  lyrSource.on('imageloadend', function(event) {
   console.log('imageloadend event',event);
  //replace with your custom action
  var elemId = event.target.params_.ELEMENTID;
  document.getElementById(elemId).src = 'css/images/ok.png'; 

  lyrSource.on('imageloaderror', function(event) {
   console.log('imageloaderror event',event);
  //replace with your custom action
  var elemId = event.target.params_.ELEMENTID;
  document.getElementById(elemId).src = 'css/images/no.png'; 

For WFS Vector layers things are even more complicated:

//declare the vector source
sourceVector = new ol.source.Vector({
    loader: function (extent) {
        //place here any actions on start loading layer
        document.getElementById('laodingcont').innerHTML = "<font color='orange'>start loading.....</font>";
        $.ajax('http://demo.opengeo.org/geoserver/wfs', {
            type: 'GET',
            data: {
                service: 'WFS',
                version: '1.1.0',
                request: 'GetFeature',
                typename: 'water_areas',
                srsname: 'EPSG:3857',
                bbox: extent.join(',') + ',EPSG:3857'
            .fail(function () {
            //FAIL LOADING
            //place here any actions on fail loading layer
            document.getElementById('laodingcont').innerHTML = "<font color='red'>error loading vector layer.</font>";
    strategy: ol.loadingstrategy.bbox

//once we have a success responce, we need to parse it and add fetaures on map
function loadFeatures(response) {
formatWFS = new ol.format.WFS(),
document.getElementById('laodingcont').innerHTML = "<font color='green'>finish loading vector layer.</font>";

check this post. it has all the above + a fiddle for the WFS vector layers

  • 1
    Welcome to GIS.SE! Can you please expand your answer and provide a short synopsis of the article you linked to and what part is relevant to the answer of this question. This way the answer will be able to help people on this site, even after the link dies.
    – Kersten
    Oct 13, 2015 at 10:38
  • sorry newby. done!!!!!!!!
    – pavlos
    Oct 13, 2015 at 10:56
  • to check which layer type you have, here is how you van do it for OL3 gis.stackexchange.com/a/140852/63141 May 20, 2016 at 9:00
  • This should be the top answer!
    – joaorodr84
    Aug 2, 2016 at 1:33
  • 1
    Please OL guys.... KISS man...KISS....
    – Magno C
    Jan 24, 2017 at 11:32

I have not found the class ol.source.GeoJSON, and could not find a case where vectorSource.getState() != 'ready'. So I ended up doing something like this:

    function spin(active) {
        if (active) {
            // start spinning the spinner
        } else {
            // stop spinning the spinner

    // Toggle spinner on layer loading
    layer.on('change', function() {
    layer.getSource().on('change', function() {
  • please also post the spin function, it looks like you are just spinning them and not stopping the spinning on finish loading the layer May 20, 2016 at 8:59

you can also use the getState() function

if (source instanceof ol.source.Vector) {
        source.on("change", function () {
            //console.log("Vector change, state: " + source.getState());
            switch (source.getState()) {
                case "loading":
  • I am using ol-v4.2.0. source.getState() always returns 'ready'
    – himyata
    Oct 26, 2017 at 8:09

On OL 4.5.0, for vector layers I haven't found a way to deal with the source, instead I use the following on the layer events:

if (layer instanceof ol.layer.Vector) {
    layer.on("precompose", function () {
    layer.on("render", function () {

Hope it can help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.