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

Building a set of feature selection controls

Interactions in OpenLayers 3 are related to the view or vector layers. These interactions related to vector data mostly have only this in common. Their working mechanism is highly inconsistent, it depends on the type of the given interaction. This peculiarity requires us to customize every interaction individually for our needs. In this example, called ch05_select_complex, we will create three selection tools.

Styling the controls

Firstly, we create some styles for the control buttons. We will use some nice background images to describe the controls. As we leave the text content of the buttons empty, we have to vertically center the buttons, not just the container div element. We also need to set some rules for the background images to render them properly:

.toolbar .ol-control button {
[…]
    vertical-align: middle;
    background-size: 1em;
    background-repeat: no-repeat;
    background-position: 50%;
}
[…]
.toolbar .ol-singleselect button {
    background-image: url(../../res/button_select.png);
}
.toolbar .ol-multiselect button {
    background-image: url(../../res/button_multiselect.png);
}
.toolbar .ol-deselect button {
    background-image: url(../../res/button_deselect.png);
}

Creating the selection tools

To set up and manage the selection controls, we extend the toolbar with a method that creates the required controls and adds them to the map. We will use one central select interaction. This way, if we ever need to make operations on the current selection, we only have to query a single interaction:

toolBar.prototype.addSelectControls = function () {
    var layertree = this.layertree;
    var selectInteraction = new ol.interaction.Select({
        layers: function (layer) {
            if (layertree.selectedLayer) {
                if (layer === layertree.getLayerById(layertree.selectedLayer.id)) {
                    return true;
                }
            }
            return false;
        }
    });
    var selectSingle = new ol.control.Interaction({
        label: ' ',
        tipLabel: 'Select feature',
        className: 'ol-singleselect ol-unselectable ol-control',
        interaction: selectInteraction
    });

Luckily, the select interaction accepts a filter function, with which we can narrow down the candidate layers to the currently selected one. Next, we create another custom control with a drag box interaction attached to it:

    var boxInteraction = new ol.interaction.DragBox();
    var selectMulti = new ol.control.Interaction({
        label: ' ',
        tipLabel: 'Select features with a box',
        className: 'ol-multiselect ol-unselectable ol-control',
        interaction: boxInteraction
    });

Next, we assign an event to the drag box. When a box is drawn, we clear the selected interaction's underlying feature collection, detect every feature intersecting the box in the selected layer, and add them to the collection. Note that the selected interaction doesn't have to be active to highlight selected features:

    boxInteraction.on('boxend', function (evt) {
        selectInteraction.getFeatures().clear();
        var extent = boxInteraction.getGeometry().getExtent();
        if (this.layertree.selectedLayer) {
            var source = this.layertree.getLayerById(this.layertree.selectedLayer.id).getSource();
            if (source instanceof ol.source.Vector) {
                source.forEachFeatureIntersectingExtent(extent, function (feature) {
                    selectInteraction.getFeatures().push(feature);
                });
            }
        }
    }, this);

Note

The ol.source.Vector class has two methods for hit detection. The first one, forEachFeatureInExtent, compares the supplied extent with every feature's extent. This is a very fast method, as OpenLayers 3 uses an R-Tree for spatial indexing, but often yields incorrect results. The second one, forEachFeatureIntersectingExtent, compares the supplied extent with every feature's geometry. It is slower, but also more accurate.

Finally, we close our method by creating a third control to remove selections. This control is plain simple, and cannot be toggled; thus, we build it as a custom ol.control.Control. We also add the newly created controls to the toolbar:

    var controlDiv = document.createElement('div');
    controlDiv.className = 'ol-deselect ol-unselectable ol-control';
    var controlButton = document.createElement('button');
    controlButton.title = 'Remove selection(s)';
    controlDiv.appendChild(controlButton);
    controlButton.addEventListener('click', function () {
        selectInteraction.getFeatures().clear();
    });
    var deselectControl = new ol.control.Control({
        element: controlDiv
    });
    this.addControl(selectSingle)
        .addControl(selectMulti)
        .addControl(deselectControl);
    return this;
};

The only thing left to do is to call our new method in the init function:

var tools = new toolBar({
    map: map,
    target: 'toolbar',
    layertree: tree,
}).addControl(new ol.control.Zoom()).addSelectControls();

If you save the example and load it up, you can play around with our selecting mechanism. Just don't forget to select the vector layer first:

Creating the selection tools