1 | ---
|
2 | title: Frequently Asked Questions (FAQ)
|
3 | layout: doc.hbs
|
4 | ---
|
5 |
|
6 | # Frequently Asked Questions (FAQ)
|
7 |
|
8 | Certain questions arise more often than others when users ask for help. This
|
9 | document tries to list some of the common questions that frequently get asked,
|
10 | e.g. on [Stack Overflow](http://stackoverflow.com/questions/tagged/openlayers).
|
11 |
|
12 | If you think a question (and naturally its answer) should be added here, feel
|
13 | free to ping us or to send a pull request enhancing this document.
|
14 |
|
15 | Table of contents:
|
16 |
|
17 | * [What projection is OpenLayers using?](#what-projection-is-openlayers-using-)
|
18 | * [How do I change the projection of my map?](#how-do-i-change-the-projection-of-my-map-)
|
19 | * [Why is my map centered on the gulf of guinea (or africa, the ocean, null-island)?](#why-is-my-map-centered-on-the-gulf-of-guinea-or-africa-the-ocean-null-island-)
|
20 | * [Why is the order of a coordinate [lon,lat], and not [lat,lon]?](#why-is-the-order-of-a-coordinate-lon-lat-and-not-lat-lon-)
|
21 | * [Why aren't there any features in my source?](#why-aren-t-there-any-features-in-my-source-)
|
22 | * [How do I force a re-render of the map?](#how-do-i-force-a-re-render-of-the-map-)
|
23 | * [Why are my features not found?](#why-are-my-features-not-found-)
|
24 | * [How do I create a custom build of OpenLayers?](#how-do-i-create-a-custom-build-of-openlayers-)
|
25 | * [Do I need to write my own code using Closure library?](#do-i-need-to-write-my-own-code-using-closure-library-)
|
26 | * [Do I need to compress my code with Closure compiler?](#do-i-need-to-compress-my-code-with-closure-compiler-)
|
27 |
|
28 |
|
29 | ## What projection is OpenLayers using?
|
30 |
|
31 | Every map that you'll create with OpenLayers will have a view, and every view
|
32 | will have a projection. As the earth is three-dimensional and round but the 2D
|
33 | view of a map isn't, we need a mathematical expression to represent it. Enter
|
34 | projections.
|
35 |
|
36 | There isn't only one projection, but there are many common ones. Each projection
|
37 | has different properties, in that it accurately represents distances, angles or
|
38 | areas. Certain projections are better suited for different regions in the world.
|
39 |
|
40 | Back to the original question: OpenLayers is capable of dealing with most
|
41 | projections. If you do not explicitly set one, your map is going to use our
|
42 | default which is the Web Mercator projection (EPSG:3857). The same projection is
|
43 | used e.g. for the maps of the OpenStreetMap-project and commercial products such
|
44 | as Bing Maps or Google Maps.
|
45 |
|
46 | This projection is a good choice if you want a map which shows the whole world,
|
47 | and you may need to have this projection if you want to e.g. use the
|
48 | OpenStreetMap or Bing tiles.
|
49 |
|
50 |
|
51 | ## How do I change the projection of my map?
|
52 |
|
53 | There is a good chance that you want to change the default projection of
|
54 | OpenLayers to something more appropriate for your region or your specific data.
|
55 |
|
56 | The projection of your map can be set through the `view`-property. Here are some
|
57 | examples:
|
58 |
|
59 | ```javascript
|
60 | // OpenLayers comes with support for the World Geodetic System 1984, EPSG:4326:
|
61 | var map = new ol.Map({
|
62 | view: new ol.View({
|
63 | projection: 'EPSG:4326'
|
64 | // other view properties like map center etc.
|
65 | })
|
66 | // other properties for your map like layers etc.
|
67 | });
|
68 | ```
|
69 |
|
70 | ```javascript
|
71 | // To use other projections, you have to register the projection in OpenLayers:
|
72 | //
|
73 | // By default OpenLayers does not know about the EPSG:21781 (Swiss) projection.
|
74 | // So we create a projection instance for EPSG:21781 and pass it to
|
75 | // ol.proj.addProjection to make it available to the library for lookup by its
|
76 | // code.
|
77 | var swissProjection = new ol.proj.Projection({
|
78 | code: 'EPSG:21781',
|
79 | // The extent is used to determine zoom level 0. Recommended values for a
|
80 | // projection's validity extent can be found at https://epsg.io/.
|
81 | extent: [485869.5728, 76443.1884, 837076.5648, 299941.7864],
|
82 | units: 'm'
|
83 | });
|
84 | ol.proj.addProjection(swissProjection);
|
85 |
|
86 | // we can now use the projection:
|
87 | var map = new ol.Map({
|
88 | view: new ol.View({
|
89 | projection: swissProjection
|
90 | // other view properties like map center etc.
|
91 | })
|
92 | // other properties for your map like layers etc.
|
93 | });
|
94 | ```
|
95 |
|
96 | We recommend to lookup parameters of your projection (like the validity extent)
|
97 | over at [epsg.io](https://epsg.io/).
|
98 |
|
99 |
|
100 | ## Why is my map centered on the gulf of guinea (or africa, the ocean, null-island)?
|
101 |
|
102 | If you have set a center in your map view, but don't see a real change in visual
|
103 | output, chances are that you have provided the coordinates of the map center in
|
104 | the wrong (a non-matching) projection.
|
105 |
|
106 | As the default projection in OpenLayers is Web Mercator (see above), the
|
107 | coordinates for the center have to be provided in that projection. Chances are
|
108 | that your map looks like this:
|
109 |
|
110 | ```javascript
|
111 | var washingtonLonLat = [-77.036667, 38.895];
|
112 | var map = new ol.Map({
|
113 | layers: [
|
114 | new ol.layer.Tile({
|
115 | source: new ol.source.OSM()
|
116 | })
|
117 | ],
|
118 | target: 'map',
|
119 | view: new ol.View({
|
120 | center: washingtonLonLat,
|
121 | zoom: 12
|
122 | })
|
123 | });
|
124 | ```
|
125 |
|
126 | Here `[-77.036667, 38.895]` is provided as the center of the view. But as Web
|
127 | Mercator is a metric projection, you are currently telling OpenLayers that the
|
128 | center shall be some meters (~77m and ~39m respectively) away from `[0, 0]`. In
|
129 | the Web Mercator projection the coordinate is right in the gulf of guinea.
|
130 |
|
131 | The solution is easy: Provide the coordinates projected into Web Mercator.
|
132 | OpenLayers has some helpful utility methods to assist you:
|
133 |
|
134 | ```javascript
|
135 | var washingtonLonLat = [-77.036667, 38.895];
|
136 | var washingtonWebMercator = ol.proj.fromLonLat(washingtonLonLat);
|
137 |
|
138 | var map = new ol.Map({
|
139 | layers: [
|
140 | new ol.layer.Tile({
|
141 | source: new ol.source.OSM()
|
142 | })
|
143 | ],
|
144 | target: 'map',
|
145 | view: new ol.View({
|
146 | center: washingtonWebMercator,
|
147 | zoom: 8
|
148 | })
|
149 | });
|
150 | ```
|
151 |
|
152 | The method `ol.proj.fromLonLat()` is available from version 3.5 onwards.
|
153 |
|
154 | If you told OpenLayers about a custom projection (see above), you can use the
|
155 | following method to transform a coordinate from WGS84 to your projection:
|
156 |
|
157 | ```javascript
|
158 | // assuming that OpenLayers knows about EPSG:21781, see above
|
159 | var swissCoord = ol.proj.transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781');
|
160 | ```
|
161 |
|
162 |
|
163 | ## Why is the order of a coordinate [lon,lat], and not [lat,lon]?
|
164 |
|
165 | Because of two different and incompatible conventions. Latitude and longitude
|
166 | are normally given in that order. Maps are 2D representations/projections
|
167 | of the earth's surface, with coordinates expressed in the `x,y` grid of the
|
168 | [Cartesian system](https://en.wikipedia.org/wiki/Cartesian_coordinate_system).
|
169 | As they are by convention drawn with west on the left and north at the top,
|
170 | this means that `x` represents longitude, and `y` latitude. As stated above,
|
171 | OpenLayers is designed to handle all projections, but the default view is in
|
172 | projected Cartesian coordinates. It would make no sense to have duplicate
|
173 | functions to handle coordinates in both the Cartesian `x,y` and `lat,lon`
|
174 | systems, so the degrees of latitude and longitude should be entered as though
|
175 | they were Cartesian, in other words, they are `lon,lat`.
|
176 |
|
177 | If you have difficulty remembering which way round it is, use the language code
|
178 | for English, `en`, as a mnemonic: East before North.
|
179 |
|
180 | #### A practical example
|
181 | So you want to center your map on a certain place on the earth and obviously you
|
182 | need to have its coordinates for this. Let's assume you want your map centered
|
183 | on Schladming, a beautiful place in Austria. Head over to the wikipedia
|
184 | page for [Schladming](http://en.wikipedia.org/wiki/Schladming). In the top-right
|
185 | corner there is a link to [GeoHack](http://tools.wmflabs.org/geohack/geohack.php?pagename=Schladming¶ms=47_23_39_N_13_41_21_E_type:city(4565)_region:AT-6),
|
186 | which effectively tells you the coordinates are:
|
187 |
|
188 | WGS84:
|
189 | 47° 23′ 39″ N, 13° 41′ 21″ E
|
190 | 47.394167, 13.689167
|
191 |
|
192 | So the next step would be to put the decimal coordinates into an array and use
|
193 | it as center:
|
194 |
|
195 | ```javascript
|
196 | var schladming = [47.394167, 13.689167]; // caution partner, read on...
|
197 | // since we are using OSM, we have to transform the coordinates...
|
198 | var schladmingWebMercator = ol.proj.fromLonLat(schladming);
|
199 |
|
200 | var map = new ol.Map({
|
201 | layers: [
|
202 | new ol.layer.Tile({
|
203 | source: new ol.source.OSM()
|
204 | })
|
205 | ],
|
206 | target: 'map',
|
207 | view: new ol.View({
|
208 | center: schladmingWebMercator,
|
209 | zoom: 9
|
210 | })
|
211 | });
|
212 | ```
|
213 |
|
214 | Running the above example will possibly surprise you, since we are not centered
|
215 | on Schladming, Austria, but instead on Abyan, a region in Yemen (possibly also a
|
216 | nice place). So what happened?
|
217 |
|
218 | Many people mix up the order of longitude and latitude in a coordinate array.
|
219 | Don't worry if you get it wrong at first, many OpenLayers developers have to
|
220 | think twice about whether to put the longitude or the latitude first when they
|
221 | e.g. try to change the map center.
|
222 |
|
223 | Ok, then let's flip the coordinates:
|
224 |
|
225 | ```javascript
|
226 | var schladming = [13.689167, 47.394167]; // longitude first, then latitude
|
227 | // since we are using OSM, we have to transform the coordinates...
|
228 | var schladmingWebMercator = ol.proj.fromLonLat(schladming);
|
229 |
|
230 | var map = new ol.Map({
|
231 | layers: [
|
232 | new ol.layer.Tile({
|
233 | source: new ol.source.OSM()
|
234 | })
|
235 | ],
|
236 | target: 'map',
|
237 | view: new ol.View({
|
238 | center: schladmingWebMercator,
|
239 | zoom: 9
|
240 | })
|
241 | });
|
242 | ```
|
243 |
|
244 | Schladming is now correctly displayed in the center of the map.
|
245 |
|
246 | So when you deal with EPSG:4326 coordinates in OpenLayers, put the longitude
|
247 | first, and then the latitude. This behaviour is the same as we had in OpenLayers
|
248 | 2, and it actually makes sense because of the natural axis order in WGS84.
|
249 |
|
250 | If you cannot remember the correct order, just have a look at the method name
|
251 | we used: `ol.proj.fromLonLat`; even there we hint that we expect longitude
|
252 | first, and then latitude.
|
253 |
|
254 |
|
255 | ## Why aren't there any features in my source?
|
256 |
|
257 | Suppose you want to load a KML file and display the contained features on the
|
258 | map. Code like the following could be used:
|
259 |
|
260 | ```javascript
|
261 | var vector = new ol.layer.Vector({
|
262 | source: new ol.source.KML({
|
263 | projection: 'EPSG:3857',
|
264 | url: 'data/kml/2012-02-10.kml'
|
265 | })
|
266 | });
|
267 | ```
|
268 |
|
269 | You may ask yourself how many features are in that KML, and try something like
|
270 | the following:
|
271 |
|
272 | ```javascript
|
273 | var vector = new ol.layer.Vector({
|
274 | source: new ol.source.KML({
|
275 | projection: 'EPSG:3857',
|
276 | url: 'data/kml/2012-02-10.kml'
|
277 | })
|
278 | });
|
279 | var numFeatures = vector.getSource().getFeatures().length;
|
280 | console.log("Count right after construction: " + numFeatures);
|
281 | ```
|
282 |
|
283 | This will log a count of `0` features to be in the source. This is because the
|
284 | loading of the KML-file will happen in an asynchronous manner. To get the count
|
285 | as soon as possible (right after the file has been fetched and the source has
|
286 | been populated with features), you should use an event listener function on the
|
287 | `source`:
|
288 |
|
289 | ```javascript
|
290 | vector.getSource().on('change', function(evt){
|
291 | var source = evt.target;
|
292 | if (source.getState() === 'ready') {
|
293 | var numFeatures = source.getFeatures().length;
|
294 | console.log("Count after change: " + numFeatures);
|
295 | }
|
296 | });
|
297 | ```
|
298 |
|
299 | This will correctly report the number of features, `1119` in that particular
|
300 | case.
|
301 |
|
302 |
|
303 | ## How do I force a re-render of the map?
|
304 |
|
305 | Usually the map is automatically re-rendered, once a source changes (for example
|
306 | when a remote source has loaded).
|
307 |
|
308 | If you actually want to manually trigger a rendering, you could use
|
309 |
|
310 | ```javascript
|
311 | map.render();
|
312 | ```
|
313 |
|
314 | ...or its companion method
|
315 |
|
316 | ```javascript
|
317 | map.renderSync();
|
318 | ```
|
319 |
|
320 | ## Why are my features not found?
|
321 |
|
322 | You are using `ol.Map#forEachFeatureAtPixel` or `ol.Map#hasFeatureAtPixel`, but
|
323 | it sometimes does not work for large icons or labels? The *hit detection* only
|
324 | checks features that are within a certain distance of the given position. For large
|
325 | icons, the actual geometry of a feature might be too far away and is not considered.
|
326 |
|
327 | In this case, set the `renderBuffer` property of `ol.layer.Vector` (the default
|
328 | value is 100px):
|
329 |
|
330 | ```javascript
|
331 | var vectorLayer = new ol.layer.Vector({
|
332 | ...
|
333 | renderBuffer: 200
|
334 | });
|
335 | ```
|
336 |
|
337 | The recommended value is the size of the largest symbol, line width or label.
|
338 |
|
339 | ## How do I create a custom build of OpenLayers?
|
340 |
|
341 | Please refer to the [official create custom builds tutorial](tutorials/custom-builds.html)
|
342 | which explains how to create a custom build of OpenLayers with just those parts
|
343 | included that you want.
|
344 |
|
345 |
|
346 | ## Do I need to write my own code using Closure library?
|
347 |
|
348 | OpenLayers is built on top of the [Google Closure JavaScript
|
349 | library](https://developers.google.com/closure/library/), but this
|
350 | does not mean that you must use that library in your application code.
|
351 |
|
352 | OpenLayers should play well with all sorts of JavaScript libraries out there,
|
353 | and you are in no way forced to use a specific one. Choose one that looks
|
354 | right for you.
|
355 |
|
356 |
|
357 | ## Do I need to compress my code with Closure compiler?
|
358 |
|
359 | No, you don't need to do compress your code with the [Google Closure
|
360 | compiler](https://developers.google.com/closure/compiler/).
|
361 |
|
362 | It may be a good choice though, because when your application code and the
|
363 | OpenLayers source code is compiled together using closure compiler, the
|
364 | resulting build will most probably be the smallest in terms of byte-size. For
|
365 | more details refer to the
|
366 | [compile application and OpenLayers together tutorial](tutorials/closure.html).
|
367 |
|
368 | If you don't want to use the closure compiler, or you can't, you are not at all
|
369 | forced to use it.
|
370 |
|
371 |
|