Table of Contents for
Mastering OpenLayers 3

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Mastering OpenLayers 3 by Gábor Farkas Published by Packt Publishing, 2016
  1. Cover
  2. Table of Contents
  3. Mastering OpenLayers 3
  4. Mastering OpenLayers 3
  5. Credits
  6. About the Author
  7. About the Reviewer
  8. www.PacktPub.com
  9. Preface
  10. What you need for this book
  11. Who this book is for
  12. Conventions
  13. Reader feedback
  14. Customer support
  15. 1. Creating Simple Maps with OpenLayers 3
  16. Structure of OpenLayers 3
  17. Building the layout
  18. Using the API documentation
  19. Debugging the code
  20. Summary
  21. 2. Applying Custom Styles
  22. Customizing the default appearance
  23. Styling vector layers
  24. Customizing the appearance with JavaScript
  25. Creating a WebGIS client layout
  26. Summary
  27. 3. Working with Layers
  28. Building a layer tree
  29. Adding layers dynamically
  30. Adding vector layers with the File API
  31. Adding vector layers with a library
  32. Removing layers dynamically
  33. Changing layer attributes
  34. Changing the layer order with the Drag and Drop API
  35. Clearing the message bar
  36. Summary
  37. 4. Using Vector Data
  38. Accessing attributes
  39. Setting attributes
  40. Validating attributes
  41. Creating thematic layers
  42. Saving vector data
  43. Saving with WFS-T
  44. Modifying the geometry
  45. Summary
  46. 5. Creating Responsive Applications with Interactions and Controls
  47. Building the toolbar
  48. Mapping interactions to controls
  49. Building a set of feature selection controls
  50. Adding new vector layers
  51. Building a set of drawing tools
  52. Modifying and snapping to features
  53. Creating new interactions
  54. Building a measuring control
  55. Summary
  56. 6. Controlling the Map – View and Projection
  57. Customizing a view
  58. Constraining a view
  59. Creating a navigation history
  60. Working with extents
  61. Rotating a view
  62. Changing the map's projection
  63. Creating custom animations
  64. Summary
  65. 7. Mastering Renderers
  66. Using different renderers
  67. Creating a WebGL map
  68. Drawing lines and polygons with WebGL
  69. Blending layers
  70. Clipping layers
  71. Exporting a map
  72. Creating a raster calculator
  73. Creating a convolution matrix
  74. Clipping a layer with WebGL
  75. Summary
  76. 8. OpenLayers 3 for Mobile
  77. Responsive styling with CSS
  78. Generating geocaches
  79. Adding device-dependent controls
  80. Vectorizing the mobile version
  81. Making the mobile application interactive
  82. Summary
  83. 9. Tools of the Trade – Integrating Third-Party Applications
  84. Exporting a QGIS project
  85. Importing shapefiles
  86. Spatial analysis with Turf
  87. Spatial analysis with JSTS
  88. 3D rendering with Cesium
  89. Summary
  90. 10. Compiling Custom Builds with Closure
  91. Configuring Node JS
  92. Compiling OpenLayers 3
  93. Bundling an application with OpenLayers 3
  94. Extending OpenLayers 3
  95. Creating rich documentation with JSDoc
  96. Summary
  97. Index

Removing layers dynamically

Now that we can add layers dynamically with our layer tree, it's time to add the capability of removing layers. For this task, we create a button that's designated to removing a selected layer, and add some logic to select a single layer in the layer tree. You can see this example if you look for ch03_deletelayer.

Extending a constructor

First of all, we need to make the layers selectable, and we can do this by registering further events to the layer elements in the constructor function. To make it simple and clear, we create a utility method to add this event type to the layer element:

layerTree.prototype.addSelectEvent = function (node, isChild) {
    var _this = this;
    node.addEventListener('click', function (evt) {
        var targetNode = evt.target;
        if (isChild) {
            evt.stopPropagation();
            targetNode = targetNode.parentNode;
        }
        if (_this.selectedLayer) {
            _this.selectedLayer.classList.remove('active');
        }
        _this.selectedLayer = targetNode;
        targetNode.classList.add('active');
    });
    return node;
};

The function adds an event listener to the input element, which grabs a reference of it and saves it to the object's selectedLayer property. It also grants some visual feedback by appending an active class to the clicked layer element and removes it from the previously selected layer.

There is one problem with this. If we click on the layer name, which is a child of the layer element, we get a reference that doesn't make sense. To resolve this issue, our method accepts an isChild Boolean. If the boolean is set to true, the method simply grabs the reference of the clicked element's parent node and stops propagating to the layer element itself. Next, we create rules for the active class and the remove button in our CSS file:

.layertree-buttons .deletelayer {
    background-image: url(../../res/button_delete.png);
}
.layercontainer .layer.active {
    border-color: orange;
}

Next, we extend our constructor by adding the remove button and selection logic:

var layerTree = function (options) {
        […]
        controlDiv.appendChild(this.createButton('deletelayer', 'Remove Layer', 'deletelayer'));
        […]
        this.selectedLayer = null;
        this.createRegistry = function (layer, buffer) {
            […]
            this.addSelectEvent(layerDiv);
            […]
            layerDiv.appendChild(this.addSelectEvent(layerSpan, true));
            […]
        };
        […]
        this.map.getLayers().on('remove', function (evt) {
            this.removeRegistry(evt.element);
        }, this);
        […]
};

Tip

Don't forget about chaining methods! As we made addSelectEvent chainable by returning the input node, we can directly append it to the layer element in a single call.

We also register an event to the map's layer stack. If a layer gets deleted, we also remove its element from the layer tree with the removeRegistry method:

Note

When we register an event to one of the library's objects, we scope it out of our object, as done in traditional event listeners. However, in OpenLayers 3, the on method accepts an optional this as a third argument; therefore, we don't have to grab a reference of it.

layerTree.prototype.removeRegistry = function (layer) {
    var layerDiv = document.getElementById(layer.get('id'));
    this.layerContainer.removeChild(layerDiv);
    return this;
};

As you must have noticed, in the button creation, we used a different button type. Remember when we used a switch statement in the button creation method? It's time to extend it with the deletelayer case:

layerTree.prototype.createButton = function (elemName, elemTitle, elemType) {
    […]
        case 'deletelayer':
            var _this = this;
            buttonElem.addEventListener('click', function () {
                if (_this.selectedLayer) {
                    var layer = _this.getLayerById(_this.selectedLayer.id);
                    console.log(layer);
                    _this.map.removeLayer(layer);
                    _this.messages.textContent = 'Layer removed successfully.';
                } else {
                    _this.messages.textContent = 'No selected layer to remove.';
                }
            });
            return buttonElem;
        […]
};

When we click on the remove button, it tries to decide which layer we would like to remove. As it has the layer's id, it can easily search for it in the map's layer stack. To make things even more transparent, we create a getLayerById method for this task:

layerTree.prototype.getLayerById = function (id) {
    var layers = this.map.getLayers().getArray();
    for (var i = 0; i < layers.length; i += 1) {
        if (layers[i].get('id') === id) {
            return layers[i];
        }
    }
    return false;
};

This method grabs a reference to the internal array of the layer stack and searches for the one with the input ID. When it finds the layer, the method returns.

Note

One valid case for using the internal array of an OpenLayers 3 collection object is this method used previously. As we can have many layers, we don't want to iterate through all of them, just as many as necessary. With the collection's forEach method, we can't use a return statement to save some time.

If you save and load the example, you can try out our new functionality:

Extending a constructor

Tip

You can easily implement simple logic to deselect layers by registering a listener to the layer container, which clears the selected layer property. If you do this, don't forget to stop the layer elements from propagating; otherwise, the selected layers will be deselected instantly.