Table of Contents for
OpenLayers 3 : Beginner's Guide

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition OpenLayers 3 : Beginner's Guide by Erik Hazzard Published by Packt Publishing, 2015
  1. Cover
  2. Table of Contents
  3. OpenLayers 3 Beginner's Guide
  4. OpenLayers 3 Beginner's Guide
  5. Credits
  6. About the Authors
  7. About the Reviewers
  8. www.PacktPub.com
  9. Preface
  10. What you need for this book
  11. Who this book is for
  12. Sections
  13. Time for action – heading
  14. Conventions
  15. Reader feedback
  16. Customer support
  17. 1. Getting Started with OpenLayers
  18. Advantages of using OpenLayers
  19. What, technically, is OpenLayers?
  20. Anatomy of a web mapping application
  21. Connecting to Google, Bing Maps, and other mapping APIs
  22. Time for action – downloading OpenLayers
  23. Time for action – creating your first map
  24. Where to go for help
  25. OpenLayers issues
  26. OpenLayers source code repository
  27. Getting live news from RSS and social networks
  28. Summary
  29. 2. Key Concepts in OpenLayers
  30. Time for action – creating a map
  31. Time for action – using the JavaScript console
  32. Time for action – overlaying information
  33. OpenLayers' super classes
  34. Key-Value Observing with the Object class
  35. Time for action – using bindTo
  36. Working with collections
  37. Summary
  38. 3. Charting the Map Class
  39. Time for action – creating a map
  40. Map renderers
  41. Time for action – rendering a masterpiece
  42. Map properties
  43. Time for action – target practice
  44. Map methods
  45. Time for action – creating animated maps
  46. Events
  47. Views
  48. Time for action – linking two views
  49. Summary
  50. 4. Interacting with Raster Data Source
  51. Layers in OpenLayers 3
  52. Common operations on layers
  53. Time for action – changing layer properties
  54. Tiled versus untiled layers
  55. Types of raster sources
  56. Tiled images' layers and their sources
  57. Time for action – creating a Stamen layer
  58. Time for action – creating a Bing Maps layer
  59. Time for action – creating tiles and adding Zoomify layer
  60. Image layers and their sources
  61. Using Spherical Mercator raster data with other layers
  62. Time For action – playing with various sources and layers together
  63. Time For action – applying Zoomify sample knowledge to a single raw image
  64. Summary
  65. 5. Using Vector Layers
  66. Time for action – creating a vector layer
  67. How the vector layer works
  68. The vector layer class
  69. Vector sources
  70. Time for action – using the cluster source
  71. Time for action – creating a loader function
  72. Time for action – working with the TileVector source
  73. Time for action – a drag and drop viewer for vector files
  74. Features and geometries
  75. Time for action – geometries in action
  76. Time for action – interacting with features
  77. Summary
  78. 6. Styling Vector Layers
  79. Time for action – basic styling
  80. The style class
  81. Time for action – using the icon style
  82. Have a go hero – using the circle style
  83. Multiple styles
  84. Time for action – using multiple styles
  85. Style functions
  86. Time for action – using properties to style features
  87. Interactive styles
  88. Time for action – creating interactive styles
  89. Summary
  90. 7. Wrapping Our Heads Around Projections
  91. Time for action – using different projection codes
  92. Time for action – determining coordinates
  93. OpenLayers projection class
  94. Transforming coordinates
  95. Time for action – coordinate transforms
  96. Time for action – setting up Proj4js.org
  97. Time for action – reprojecting extent
  98. Time for action – using custom projection with WMS sources
  99. Time for action – reprojecting geometries in vector layers
  100. Summary
  101. 8. Interacting with Your Map
  102. Time for action – converting your local or national authorities data into web mapping formats
  103. Time for action – testing the use cases for ol.interaction.Select
  104. Time for action – more options with ol.interaction.Select
  105. Introducing methods to get information from your map
  106. Time for action – understanding the forEachFeatureAtPixel method
  107. Time for action – understanding the getGetFeatureInfoUrl method
  108. Adding a pop-up on your map
  109. Time for action – introducing ol.Overlay with a static example
  110. Time for action – using ol.Overlay dynamically with layers information
  111. Time for action – using ol.interaction.Draw to share new information on the Web
  112. Time for action – using ol.interaction.Modify to update drawing
  113. Understanding interactions and their architecture
  114. Time for action – configuring default interactions
  115. Discovering the other interactions
  116. Time for action – using ol.interaction.DragRotateAndZoom
  117. Time for action – making rectangle export to GeoJSON with ol.interaction.DragBox
  118. Summary
  119. 9. Taking Control of Controls
  120. Adding controls to your map
  121. Time for action – starting with the default controls
  122. Controls overview
  123. Time for action – changing the default attribution styles
  124. Time for action – finding your mouse position
  125. Time for action – configuring ZoomToExtent and manipulate controls
  126. Creating a custom control
  127. Time for action – extending ol.control.Control to make your own control
  128. Summary
  129. 10. OpenLayers Goes Mobile
  130. Using a web server
  131. Time for action – go mobile!
  132. The Geolocation class
  133. Time for action – location, location, location
  134. The DeviceOrientation class
  135. Time for action – a sense of direction
  136. Debugging mobile web applications
  137. Debugging on iOS
  138. Debugging on Android
  139. Going offline
  140. Time for action – MANIFEST destiny
  141. Going native with web applications
  142. Time for action – track me
  143. Summary
  144. 11. Creating Web Map Apps
  145. Using geospatial data from Flickr
  146. Time for action – getting Flickr data
  147. A simple application
  148. Time for Action – adding data to your map
  149. Styling the features
  150. Time for action – creating a style function
  151. Creating a thumbnail style
  152. Time for action – switching to JSON data
  153. Time for action – creating a thumbnail style
  154. Turning our example into an application
  155. Time for action – adding the select interaction
  156. Time for action – handling selection events
  157. Time for action – displaying photo information
  158. Using real time data
  159. Time for action – getting dynamic data
  160. Wrapping up the application
  161. Time for action – adding dynamic tags to your map
  162. Deploying an application
  163. Creating custom builds
  164. Creating a combined build
  165. Time for action – creating a combined build
  166. Creating a separate build
  167. Time for action – creating a separate build
  168. Summary
  169. A. Object-oriented Programming – Introduction and Concepts
  170. Going further
  171. B. More details on Closure Tools and Code Optimization Techniques
  172. Introducing Closure Library, yet another JavaScript library
  173. Time for action – first steps with Closure Library
  174. Making custom build for optimizing performance
  175. Time for action – playing with Closure Compiler
  176. Applying your knowledge to the OpenLayers case
  177. Time for action - running official examples with the internal OpenLayers toolkit
  178. Time for action - building your custom OpenLayers library
  179. Syntax and styles
  180. Time for action – using Closure Linter to fix JavaScript
  181. Summary
  182. C. Squashing Bugs with Web Debuggers
  183. Time for action – opening Chrome Developer Tools
  184. Explaining Chrome Developer debugging controls
  185. Time for action – using DOM manipulation with OpenStreetMap map images
  186. Time for action – using breakpoints to explore your code
  187. Time for action – playing with zoom button and map copyrights
  188. Using the Console panel
  189. Time for action – executing code in the Console
  190. Time for action – creating object literals
  191. Time for action – interacting with a map
  192. Improving Chrome and Developer Tools with extensions
  193. Debugging in other browsers
  194. Summary
  195. D. Pop Quiz Answers
  196. Chapter 5, Using Vector Layers
  197. Chapter 7, Wrapping Our Heads Around Projections
  198. Chapter 8, Interacting with Your Map
  199. Chapter 9, Taking Control of Controls
  200. Chapter 10, OpenLayers Goes Mobile
  201. Appendix B, More details on Closure Tools and Code Optimization Techniques
  202. Appendix C, Squashing Bugs with Web Debuggers
  203. Index

Time for action - building your custom OpenLayers library

We will reuse the animation sample, from the local OpenLayers installation, to try out both ways of building code:

  1. Copy the animation.html and animation.js files from the examples folder into animation-exports.html and animation-exports.js.
  2. Create a file config/ol-animation-exports.json inspired by the config/examples-all.json with the following content:
    {
      "exports": ["ol.Map",
      "ol.Map#*",
      "ol.View",
      "ol.animation.*",
      "ol.control.*",
      "ol.layer.Tile",
      "ol.proj.*",
      "ol.source.OSM"
      ],
      "src": ["src/**/*.js"],
      "compile": {
        "externs": [
        "externs/bingmaps.js",
        "externs/bootstrap.js",
        "externs/closure-compiler.js",
        "externs/example.js",
        "externs/geojson.js",
        "externs/jquery-1.7.js",
        "externs/oli.js",
        "externs/olx.js",
        "externs/proj4js.js",
        "externs/tilejson.js",
        "externs/topojson.js",
        "externs/vbarray.js"
        ],
        "define": [
        "goog.dom.ASSUME_STANDARDS_MODE=true",
        "goog.DEBUG=false"
        ],
        "jscomp_error": [
        "accessControls",
        "ambiguousFunctionDecl",
        "checkEventfulObjectDisposal",
        "checkRegExp",
        "checkStructDictInheritance",
        "checkTypes",
        "checkVars",
        "const",
        "constantProperty",
        "deprecated",
        "duplicateMessage",
        "es3",
        "externsValidation",
        "fileoverviewTags",
        "globalThis",
        "internetExplorerChecks",
        "invalidCasts",
        "misplacedTypeAnnotation",
        "missingGetCssName",
        "missingProperties",
        "missingProvide",
        "missingRequire",
        "missingReturn",
        "newCheckTypes",
        "nonStandardJsDocs",
        "suspiciousCode",
        "strictModuleDepCheck",
        "typeInvalidation",
        "undefinedNames",
        "undefinedVars",
        "unknownDefines",
        "uselessCode",
        "visibility"
        ],
        "extra_annotation_name": [
        "api", "observable"
        ],
        "jscomp_off": [
        "es5Strict"
        ],
        "compilation_level": "ADVANCED",
        "output_wrapper": "// OpenLayers 3. See http://ol3.js.org/\n(function(){%output%})();",
        "use_types_for_optimization": true
        
      }
    }
  3. In the animation-exports.js file, remove the goog.require statements.
  4. In animation-exports.html, change the script src attribute from loader.js?id=animation to ../build/ol-animation-exports.js and add a new script reference with <script src="animation-exports.js"></script>.
  5. Compile the ol-animation-exports.js file from the root ol3 folder using the following command:
    node tasks/build.js config/ol-animation-exports.json build/ol-animation-exports.js
    
  6. Launch ./build.py serve or build.cmd serve and open your browser at http://localhost:3000/examples/animation-exports.html.
  7. Stop the server and again copy the animation.html and animation.js from the examples folder into animation-combined.html and animation-combined.js.
  8. At the bottom of the HTML code, change the code to only get two JavaScript calls:
    <script src="jquery.min.js"></script>
        <script src="../build/ol-animation-combined.js"></script>
  9. Copy the previous config/ol-animation-exports.json into config/ol-animation-combined.json.
  10. Set exports to [] and add at the end of the array, contained in the src value, the .js files declaration to get a result like the following:
    "src": [
        "src/**/*.js",
        "examples/animation-combined.js"
      ]
  11. Add in the beginning of the examples/animation-combined.js file the code from resources/example-behaviour.js.
  12. Remove the line externs/example.js, from the config/ol-animation-combined.json file.
  13. Compile the code with:
    node tasks/build.js config/ol-animation-combined.json build/ol-animation-combined.js
    
  14. Serve files and open the browser to: http://localhost:3000/examples/animation-exports.html

What just happened?

Until now, to facilitate learning, we used code for samples within the HTML. For compressing code, firstly, you need to have all your JavaScript code in a separate .js file.

In the first case, we used exports in the ADVANCED mode. At the functional level, exporting means that you want to stop obfuscating variables, for example, renaming variables and properties to shorter ones. The advantage of this, is that you can use code from outside the library, in a third-party JavaScript file. It can help you, for example, in designing a subset of the OpenLayers 3 library for specific use cases or making your own library based on the OpenLayers 3 and a custom code augmenting the default.

At the code level, to know what we want to export, we reuse the content from goog.require statements in the example. These statements are deduced from the code namespaces and constructors . If you limit yourself to these statements to declare exports, when compiling and executing code, you will get some errors stating undefined in the browser debugger console. Mostly, it means you protect the constructor but you didn't choose some functions to protect. To protect from variable renaming, you will need to use the * character. It's what we have done with ol.Map#* or ol.proj.*.

In the ol.Map#* case, we said that we wanted to protect all functions from ol.Map.prototype to be renamed by using the # character. In the ol.proj.* use case, we just protected the all ol.transform namespace.

For externs, we will not go in to the details of how they work, but you just have to understand that it's a way to protect code from other libraries to be renamed by Closure Compiler by declaring their variables' and functions' signatures.

If we review the other parameters in the first JSON file, the most important ones are:

  • src: This helps define where your compiler has to search for code when managing dependencies. Those dependencies are declared by declarations in code.
  • compilation_level: This can be set to ADVANCED, WHITESPACE_ONLY, or SIMPLE. We chose to look at the ADVANCED case, because once we have understood how to work with the advanced option, the others can be worked on easily.
  • Another quite important parameter is use_types_for_optimization. In fact, it highlights the importance of comments also known as annotations. We will start by quoting the official Closure Compiler documentation:

    "The Closure Compiler can use data type information about JavaScript variables to provide enhanced optimization and warnings. JavaScript, however, has no way to declare types. Because JavaScript has no syntax for declaring the type of a variable, you must use comments in the code to specify the data type."

From this, we can deduce that you can use Closure Compiler without always using comments but comments can help you catch errors using variables type checking based on comments (based on a standard called JSDoc).

It's also useful, because when Closure compiler uses the ADVANCED mode, the compiler renames variables to decrease the build size and annotations act as hints for the tool. Moreover, the commenting code is anyways a good practice to maintain code: do not hesitate to use them. Navigate to the official Closure Compiler documentation (https://developers.google.com/closure/compiler/docs/js-for-compiler) to see the exact grammar.

Another good tip related to annotations is the fact that adding an annotation @api (specific to OpenLayers) is the way to export a function when you use OpenLayers 3 default build system.

For instance, you can add @api to ol.Ellipsoid and ol.Ellipsoid.prototype.vincentyDistance in the file src/ol/ellipsoid/ellipsoid.js (for reference, see src/ol/map.js line 160). Then, launch node tasks/build.js config/ol.json build/ol.js and reuse the generated ol.js instead of the usual one. You will see that you can use, in your application code, the following code:

var ellipsoid_wgs84 = new ol.Ellipsoid(6378137, 1/298.257223563);
var distance_ol3_vincenty = ellipsoid_wgs84.vincentyDistance([5, 34], [12, 56])

Note

We will not inspect all the other parameters, because it's mostly not required to understand their meanings. If you would like to read further about them, we recommend that you go to the API and to the readme file about tasks that document most parameters at https://github.com/openlayers/ol3/blob/v3.0.0/tasks/readme.md.

If we dive into the case where we build everything together, the essential part is the inclusion of the build/ol-animation-combined.js file in the src array parameter.

As we removed the script tag calling resources/example-behaviour.js from animation-combined.html, we had to combine resources/example-behaviour.js with examples/animation-combined.js files. It's because adding a file into src array is not enough. You need goog.require into the file to be combined with the main OpenLayers 3 library code.

With the inclusion of resources/example-behaviour.js, the other important part was to remove the externs/example.js line, in order to unprotect the exampleNS namespace, so that we can rename it.

You should also note that in both reviewed case, compression can be achieved because of already mentioned goog.require and goog.provide. At the code level, they allow you to create a dependencies tree to gather each required function and variable within OpenLayers core library code source files.

If you inspect the size of the resulting files, you will see that although we have more content in the ol-animation-combined.js file than ol-animation-exports.js, the first one weighs 190Ko (65Ko manually gzip compressed), whereas the second size is 212Ko (71Ko manually gzip compressed).

The conclusion is that compiling everything together is the best solution to gain size in your code.

Now, try to reuse this knowledge in your own OpenLayers samples build.

Have a go hero – applying code optimization to other OpenLayers samples

Now that you have all the basic knowledge about OpenLayers toolkit to compress code, try and apply it your own project.

To improve your skills, you can perform the same task we did in the previous Time for action section, but using a different example. You can use the JSON files from the build/examples because they may help you to solve building dependencies. Be careful, if you rely only on those files, it will not work the expected way if you use the export method or you change JavaScript calls in samples HTML files.

To try it out.

  1. You have to create an HTML and a JavaScript file.
  2. You have to change the paths in samples.
  3. Test them by interacting with your samples; it may work when they are loading, but they will fail later when clicking and panning.

You have to change the paths in samples, and then test them by interacting with your samples; it may work when they are loading, but they will fail later when clicking and panning.

Using externs

Remember we told you that without externs, you can't use external libraries in the ADVANCED mode? We recommend you comment out or remove externs, to see what will happen if we don't use them. In particular, try to remove jQuery externs, and try to build the examples from Time for action.

What do you see? If you don't have any ideas, you can see that externs' keywords refers to some JavaScript files. If you need, for example, to use a library such as Underscore (another JavaScript Library to use more functional programming), just copy the externs, add your path to the JSON file, say, "../externs/underscore.js", and after this, you are ready to use your library in the Closure Compiler ADVANCED mode.

To find out about externs, go to this Closure Compiler web page: https://github.com/google/closure-compiler/wiki/Externs-For-Common-Libraries

If you require another less common library, find it using a search engine or by generating it with this tool: http://blog.dotnetwise.com/2009/11/closure-compiler-externs-extractor.html

In the worst case, you will be stuck and will only be able to use the SIMPLE mode or to use the exports method, building a minimum Openlayers core library.

Pop quiz– advanced mode

Q1. When using the OpenLayers 3 toolkit, your code is not working in the ADVANCED compilation mode, although it's perfectly fine in the SIMPLE mode, what can be the cause (multiple choices accepted)?

  1. You didn't declare goog.require
  2. You forgot to use goog.inherits
  3. You didn't use goog functions in your custom code
  4. You used an external library without externs
  5. You forgot comments in a constructor function

Now, we have seen mainly an underlying way to compress the JavaScript code; we will introduce you to syntax and styles in JavaScript code. When you start to write more than ten lines of code, it starts to become an obligation!