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

Adding device-dependent controls

In the next example, called ch08_controls, we create some roles for the different devices identified by OpenLayers 3. Firstly, we add some CSS rules for our new text-based control:

@media only screen and (orientation: portrait) {
    […]
    .ol-geoloc {
        bottom: 0;
        right: .5em;
        white-space: pre-wrap;
    }
}
@media only screen and (orientation: landscape) {
    […]
    .ol-geoloc {
        top: 0;
        right: .5em;
    }
}

As we will place our control in a pre element for correct line break detection, we need to wrap it in portrait mode. Otherwise, the end of the lines would be off the screen. We also change the position of this control based on the orientation of the device. Next, we change our Geolocation object a little bit to request high accuracy data on a regular basis:

var geoloc = new ol.Geolocation({
    projection: map.getView().getProjection(),
    tracking: true,
    trackingOptions: {
        enableHighAccuracy: true,
        maximumAge: 2000
    }
});

Now, if we can access the GPS, the data will be updated at 2-second intervals with high accuracy.

Note

There are three tracking options in OpenLayers 3's Geolocation object, just like in the HTML5 Geolocation API. The enableHighAccuracy parameter requests data from GPS results in higher-precision and higher-power consumption. The timeout parameter defines how old the received data can be before it is considered outdated. The maximumAge parameter denotes how old a cached position can be before it is considered outdated. The last two parameters are accepted in milliseconds.

Adding controls for touch devices

As a next step, we define some controls that will only be added when we open our application from a touch device. We add a full screen control for maximum usability and a custom control to display Geolocation-related data:

Note

The full screen control of OpenLayers 3 uses the HTML5 full screen API. This API can request full screen mode for an element in a web page, displaying its content in full screen. As OpenLayers 3 requests full screen for the map element, we must put our tool bar in it for a proper display.

if (ol.has.TOUCH) {
    document.getElementById('map').classList.add('ol-touch');
    map.addControl(new ol.control.FullScreen({
        target: 'toolbar'
    }));
    var geolocData = document.createElement('pre');
    geolocData.className = 'ol-geoloc ol-unselectabble ol-control';
    geoloc.on('change', function (evt) {
        var dataString = 'Position: ' + this.getPosition() + '\nError: ' + this.getAccuracy() + 'm\nAltitude: ' + this.getAltitude() + 'm\nAltitude error: ' + this.getAltitudeAccuracy() + 'm';
        geolocData.textContent = dataString.replace(/undefined/g, 'N/A');
    });
    map.addControl(new ol.control.Control({
        element: geolocData
    }));
}

As we concatenate Geolocation-related data to a single string with line breaks, we provide them in a pre element; thus, the browsers will follow those breaks. If we cannot access a value and the library returns undefined, we simply replace that value to N/A with a regular expression. If you save the code in this state and load it up from your smartphone, you will see uniform control buttons and a nice text output in full screen. This is the way our application should be used on touch devices:

Adding controls for touch devices

Adding controls for desktop computers

If the library detects a regular device, it gives that a dispatcher role. A dispatcher should be able to move points and edit the loot of the geocaches in our scenario. Therefore, we add two such interactions to our map. We also disable Geolocation as we do not need it from a desktop computer:

} else {
    geoloc.once('change', function (evt) {
        this.setTracking(false);
        map.addInteraction(new ol.interaction.Modify({
            features: new ol.Collection(geoCaching.getSource().getFeatures())
        }));
    });

Finally, we create our next interaction by registering a listener to the map's click event. We query every feature under the click location, which has a loot attribute, and create an output with its value. We wrap this output in an overlay and display it on the map anchored on the clicked feature. We use the usual forEachFeatureAtPixel method that accepts a layer filter function and, thus, only queries our geocaches:

Tip

The ol.Overlay constructor has quite a lot of customizing possibilities. Make sure that you check it out in the API documentation.

   map.on('click', function (evt) {
        map.getOverlays().clear();
        this.forEachFeatureAtPixel(evt.pixel, function (feature) {
            if (feature && feature.get('loot')) {
                var overlayElem = document.createElement('div');
                var lootElem = document.createElement('textarea');
                lootElem.textContent = feature.get('loot');
                overlayElem.appendChild(lootElem);
                overlayElem.appendChild(document.createElement('br'));
                var saveButton = document.createElement('button');
                saveButton.textContent = 'Save';
                overlayElem.appendChild(saveButton);
                var overlay = new ol.Overlay({
                    position: feature.getGeometry().getCoordinates(),
                    element: overlayElem
                });
                saveButton.addEventListener('click', function (evt) {
                    feature.set('loot', lootElem.value);
                    map.removeOverlay(overlay);
                });
                map.addOverlay(overlay);
            }
        }, this, function (layer) {
            if (layer === geoCaching) {
                return true;
            }
            return false;
        });
    });
}

Note

As we added an interaction that creates an overlay with an alternative styling, every click returns two almost identical features. However, as in overlay object, only the selected feature's geometry is added, we can discard the dummy feature by querying its loot attribute.

If you save the code and load it up on your desktop computer, you can move the geocaches and edit their loot attribute:

Adding controls for desktop computers

Note

Note that, without a server-side component, the points won't be updated in the mobile appliation when we update them in the desktop version. Writing a server-side component is, however, beyond the scope of this book.