mirror of
https://expo.survex.com/repositories/expoweb/.git/
synced 2024-11-27 09:42:02 +00:00
399 lines
22 KiB
HTML
399 lines
22 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
|
||
<title>OpenLayers - Frequently Asked Questions (FAQ)</title>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/components/prism-core.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/plugins/autoloader/prism-autoloader.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/plugins/toolbar/prism-toolbar.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
|
||
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Quattrocento+Sans:400,400italic,700" crossorigin="anonymous">
|
||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" crossorigin="anonymous">
|
||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.1.2/css/fontawesome.min.css" crossorigin="anonymous">
|
||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.1.2/css/solid.css" crossorigin="anonymous">
|
||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.1.2/css/brands.css" crossorigin="anonymous">
|
||
<link rel="stylesheet" type="text/css" href="/theme/ol.css">
|
||
<link rel="stylesheet" type="text/css" href="/theme/site.css">
|
||
<link rel="icon" type="image/svg+xml" href="/theme/img/logo-light.svg" media="(prefers-color-scheme: light)" />
|
||
<link rel="icon" type="image/svg+xml" href="/theme/img/logo-dark.svg" media="(prefers-color-scheme: dark)" />
|
||
</head>
|
||
<body>
|
||
<header class="navbar navbar-expand-md navbar-dark mb-3 px-3 py-0 fixed-top" role="navigation">
|
||
<a class="navbar-brand" href="/"><img src="/theme/img/logo-dark.svg" width="70" height="70" alt=""> OpenLayers</a>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#olmenu" aria-controls="olmenu" aria-expanded="false" aria-label="Toggle navigation">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
|
||
<!-- menu items that get hidden below 768px width -->
|
||
<nav class="collapse navbar-collapse" id="olmenu">
|
||
<ul class="nav navbar-nav ms-auto">
|
||
<li class="nav-item dropdown">
|
||
<a class="nav-link dropdown-toggle" href="#" id="docdropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Docs</a>
|
||
<div class="dropdown-menu dropdown-menu-end mb-3" aria-labelledby="docdropdown">
|
||
<a class="dropdown-item" href="/doc/">Docs</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item" href="/doc/quickstart.html"><i class="fa fa-check fa-fw me-2 fa-lg"></i>Quick Start</a>
|
||
<a class="dropdown-item" href="/doc/faq.html"><i class="fa fa-question fa-fw me-2 fa-lg"></i>FAQ</a>
|
||
<a class="dropdown-item" href="/doc/tutorials/"><i class="fa fa-book fa-fw me-2 fa-lg"></i>Tutorials</a>
|
||
<a class="dropdown-item" href="/workshop/"><i class="fa fa-graduation-cap fa-fw me-2 fa-lg"></i>Workshop</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item" href="https://stackoverflow.com/questions/tagged/openlayers"><i class="fab fa-stack-overflow fa-fw me-2"></i>Ask a Question</a>
|
||
</div>
|
||
</li>
|
||
<li class="nav-item"><a class="nav-link" href="/en/latest/examples/">Examples</a></li>
|
||
<li class="nav-item dropdown">
|
||
<a class="nav-link dropdown-toggle" href="#" id="apidropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||
<i class="fa fa-sitemap me-1"></i>API
|
||
</a>
|
||
<div class="dropdown-menu dropdown-menu-end mb-3" aria-labelledby="apidropdown">
|
||
<a class="dropdown-item" href="/en/latest/apidoc/"><i class="fa fa-sitemap fa-fw me-2 fa-lg"></i>v9.1.0 (latest)</a>
|
||
<a class="dropdown-item" href="/en/v8.1.0/apidoc/"><i class="fa fa-sitemap a-fw me-2 fa-lg"></i>v8.1.0</a>
|
||
<a class="dropdown-item" href="/en/v7.5.2/apidoc/"><i class="fa fa-sitemap a-fw me-2 fa-lg"></i>v7.5.2</a>
|
||
<a class="dropdown-item" href="/en/v6.15.1/apidoc/"><i class="fa fa-sitemap a-fw me-2 fa-lg"></i>v6.15.1</a>
|
||
<a class="dropdown-item" href="/en/v5.3.0/apidoc/"><i class="fa fa-sitemap fa-fw me-2 fa-lg"></i>v5.3.0</a>
|
||
<a class="dropdown-item" href="/en/v4.6.5/apidoc/"><i class="fa fa-sitemap fa-fw me-2 fa-lg"></i>v4.6.5</a>
|
||
<a class="dropdown-item" href="/en/v3.20.1/apidoc/"><i class="fa fa-sitemap fa-fw me-2 fa-lg"></i>v3.20.1</a>
|
||
</div>
|
||
</li>
|
||
<li class="nav-item dropdown">
|
||
<a class="nav-link dropdown-toggle" href="#" id="codedropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Code</a>
|
||
<div class="dropdown-menu dropdown-menu-end mb-3" aria-labelledby="codedropdown">
|
||
<a class="dropdown-item" href="https://github.com/openlayers/openlayers"><i class="fab fa-github fa-fw me-2 fa-lg"></i>Repository</a>
|
||
<a class="dropdown-item" href="/download/"><i class="fa fa-download fa-fw me-2 fa-lg"></i>Download</a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
</header>
|
||
|
||
<div class="container">
|
||
<h1 id="frequently-asked-questions-faq">Frequently Asked Questions (FAQ)</h1>
|
||
<p>Certain questions arise more often than others when users ask for help. This
|
||
document tries to list some of the common questions that frequently get asked,
|
||
e.g. on <a href="https://stackoverflow.com/questions/tagged/openlayers">Stack Overflow</a>.</p>
|
||
<p>If you think a question (and naturally its answer) should be added here, feel
|
||
free to ping us or to send a pull request enhancing this document.</p>
|
||
<p>Table of contents:</p>
|
||
<ul>
|
||
<li><a href="#what-projection-is-openlayers-using-">What projection is OpenLayers using?</a></li>
|
||
<li><a href="#how-do-i-change-the-projection-of-my-map-">How do I change the projection of my map?</a></li>
|
||
<li><a href="#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)?</a></li>
|
||
<li><a href="#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]?</a></li>
|
||
<li><a href="#why-aren-t-there-any-features-in-my-source-">Why aren't there any features in my source?</a></li>
|
||
<li><a href="#how-do-i-force-a-re-render-of-the-map-">How do I force a re-render of the map?</a></li>
|
||
<li><a href="#why-are-my-features-not-found-">Why are my features not found?</a></li>
|
||
<li><a href="#user-content-why-is-zooming-or-clicking-off-inaccurate">Why is zooming or clicking off, inaccurate?</a></li>
|
||
</ul>
|
||
<h2 id="what-projection-is-openlayers-using">What projection is OpenLayers using?</h2>
|
||
<p>Every map that you'll create with OpenLayers will have a view, and every view
|
||
will have a projection. As the earth is three-dimensional and round but the 2D
|
||
view of a map isn't, we need a mathematical expression to represent it. Enter
|
||
projections.</p>
|
||
<p>There isn't only one projection, but there are many common ones. Each projection
|
||
has different properties, in that it accurately represents distances, angles or
|
||
areas. Certain projections are better suited for different regions in the world.</p>
|
||
<p>Back to the original question: OpenLayers is capable of dealing with most
|
||
projections. If you do not explicitly set one, your map is going to use our
|
||
default which is the Web Mercator projection (EPSG:3857). The same projection is
|
||
used e.g. for the maps of the OpenStreetMap-project and commercial products such
|
||
as Bing Maps or Google Maps.</p>
|
||
<p>This projection is a good choice if you want a map which shows the whole world,
|
||
and you may need to have this projection if you want to e.g. use the
|
||
OpenStreetMap or Bing tiles.</p>
|
||
<h2 id="how-do-i-change-the-projection-of-my-map">How do I change the projection of my map?</h2>
|
||
<p>There is a good chance that you want to change the default projection of
|
||
OpenLayers to something more appropriate for your region or your specific data.</p>
|
||
<p>The projection of your map can be set through the <code>view</code>-property. Here are some
|
||
examples:</p>
|
||
<pre><code class="language-javascript">import Map from 'ol/Map.js';
|
||
import View from 'ol/View.js';
|
||
|
||
// OpenLayers comes with support for the World Geodetic System 1984, EPSG:4326:
|
||
const map = new Map({
|
||
view: new View({
|
||
projection: 'EPSG:4326'
|
||
// other view properties like map center etc.
|
||
})
|
||
// other properties for your map like layers etc.
|
||
});
|
||
</code></pre>
|
||
<pre><code class="language-javascript">import Map from 'ol/Map.js';
|
||
import View from 'ol/View.js';
|
||
import proj4 from 'proj4';
|
||
import {register} from 'ol/proj/proj4.js';
|
||
import {get as getProjection} from 'ol/proj.js';
|
||
|
||
// To use other projections, you have to register the projection in OpenLayers.
|
||
// This can easily be done with [http://proj4js.org/](proj4)
|
||
//
|
||
// By default OpenLayers does not know about the EPSG:21781 (Swiss) projection.
|
||
// So we create a projection instance for EPSG:21781 and pass it to
|
||
// register to make it available to the library for lookup by its
|
||
// code.
|
||
proj4.defs('EPSG:21781',
|
||
'+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 ' +
|
||
'+x_0=600000 +y_0=200000 +ellps=bessel ' +
|
||
'+towgs84=660.077,13.551,369.344,2.484,1.783,2.939,5.66 +units=m +no_defs');
|
||
register(proj4);
|
||
const swissProjection = getProjection('EPSG:21781');
|
||
|
||
// we can now use the projection:
|
||
const map = new Map({
|
||
view: new View({
|
||
projection: swissProjection
|
||
// other view properties like map center etc.
|
||
})
|
||
// other properties for your map like layers etc.
|
||
});
|
||
</code></pre>
|
||
<p>We recommend to lookup parameters of your projection (like the validity extent)
|
||
over at <a href="https://epsg.io/">epsg.io</a>.</p>
|
||
<h2 id="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)?</h2>
|
||
<p>If you have set a center in your map view, but don't see a real change in visual
|
||
output, chances are that you have provided the coordinates of the map center in
|
||
the wrong (a non-matching) projection.</p>
|
||
<p>As the default projection in OpenLayers is Web Mercator (see above), the
|
||
coordinates for the center have to be provided in that projection. Chances are
|
||
that your map looks like this:</p>
|
||
<pre><code class="language-javascript">import Map from 'ol/Map.js';
|
||
import View from 'ol/View.js';
|
||
import TileLayer from 'ol/layer/Tile.js';
|
||
import OSM from 'ol/source/OSM.js';
|
||
|
||
const washingtonLonLat = [-77.036667, 38.895];
|
||
const map = new Map({
|
||
layers: [
|
||
new TileLayer({
|
||
source: new OSM()
|
||
})
|
||
],
|
||
target: 'map',
|
||
view: new View({
|
||
center: washingtonLonLat,
|
||
zoom: 12
|
||
})
|
||
});
|
||
</code></pre>
|
||
<p>Here <code>[-77.036667, 38.895]</code> is provided as the center of the view. But as Web
|
||
Mercator is a metric projection, you are currently telling OpenLayers that the
|
||
center shall be some meters (~77m and ~39m respectively) away from <code>[0, 0]</code>. In
|
||
the Web Mercator projection the coordinate is right in the gulf of guinea.</p>
|
||
<p>The solution is easy: Provide the coordinates projected into Web Mercator.
|
||
OpenLayers has some helpful utility methods to assist you:</p>
|
||
<pre><code class="language-javascript">import Map from 'ol/Map.js';
|
||
import View from 'ol/View.js';
|
||
import TileLayer from 'ol/layer/Tile.js';
|
||
import OSM from 'ol/source/OSM.js';
|
||
import {fromLonLat} from 'ol/proj.js';
|
||
|
||
const washingtonLonLat = [-77.036667, 38.895];
|
||
const washingtonWebMercator = fromLonLat(washingtonLonLat);
|
||
|
||
const map = new Map({
|
||
layers: [
|
||
new TileLayer({
|
||
source: new OSM()
|
||
})
|
||
],
|
||
target: 'map',
|
||
view: new View({
|
||
center: washingtonWebMercator,
|
||
zoom: 8
|
||
})
|
||
});
|
||
</code></pre>
|
||
<p>The method <code>fromLonLat()</code> is available from version 3.5 onwards.</p>
|
||
<p>If you told OpenLayers about a custom projection (see above), you can use the
|
||
following method to transform a coordinate from WGS84 to your projection:</p>
|
||
<pre><code class="language-javascript">import {transform} from 'ol/proj.js';
|
||
// assuming that OpenLayers knows about EPSG:21781, see above
|
||
const swissCoord = transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781');
|
||
</code></pre>
|
||
<h2 id="why-is-the-order-of-a-coordinate-lonlat-and-not-latlon">Why is the order of a coordinate [lon,lat], and not [lat,lon]?</h2>
|
||
<p>Because of two different and incompatible conventions. Latitude and longitude
|
||
are normally given in that order. Maps are 2D representations/projections
|
||
of the earth's surface, with coordinates expressed in the <code>x,y</code> grid of the
|
||
<a href="https://en.wikipedia.org/wiki/Cartesian_coordinate_system">Cartesian system</a>.
|
||
As they are by convention drawn with west on the left and north at the top,
|
||
this means that <code>x</code> represents longitude, and <code>y</code> latitude. As stated above,
|
||
OpenLayers is designed to handle all projections, but the default view is in
|
||
projected Cartesian coordinates. It would make no sense to have duplicate
|
||
functions to handle coordinates in both the Cartesian <code>x,y</code> and <code>lat,lon</code>
|
||
systems, so the degrees of latitude and longitude should be entered as though
|
||
they were Cartesian, in other words, they are <code>lon,lat</code>.</p>
|
||
<p>If you have difficulty remembering which way round it is, use the language code
|
||
for English, <code>en</code>, as a mnemonic: East before North.</p>
|
||
<h4 id="a-practical-example">A practical example</h4>
|
||
<p>So you want to center your map on a certain place on the earth and obviously you
|
||
need to have its coordinates for this. Let's assume you want your map centered
|
||
on Schladming, a beautiful place in Austria. Head over to the wikipedia
|
||
page for <a href="https://en.wikipedia.org/wiki/Schladming">Schladming</a>. In the top-right
|
||
corner there is a link to <a href="https://geohack.toolforge.org/geohack.php?pagename=Schladming¶ms=47_23_39_N_13_41_21_E_type:city(4565)_region:AT-6">GeoHack</a>,
|
||
which effectively tells you the coordinates are:</p>
|
||
<pre><code>WGS84:
|
||
47° 23′ 39″ N, 13° 41′ 21″ E
|
||
47.394167, 13.689167
|
||
</code></pre>
|
||
<p>So the next step would be to put the decimal coordinates into an array and use
|
||
it as center:</p>
|
||
<pre><code class="language-javascript">import Map from 'ol/Map.js';
|
||
import View from 'ol/View.js';
|
||
import TileLayer from 'ol/layer/Tile.js';
|
||
import OSM from 'ol/source/OSM.js';
|
||
import {fromLonLat} from 'ol/proj.js';
|
||
|
||
const schladming = [47.394167, 13.689167]; // caution partner, read on...
|
||
// since we are using OSM, we have to transform the coordinates...
|
||
const schladmingWebMercator = fromLonLat(schladming);
|
||
|
||
const map = new Map({
|
||
layers: [
|
||
new TileLayer({
|
||
source: new OSM()
|
||
})
|
||
],
|
||
target: 'map',
|
||
view: new View({
|
||
center: schladmingWebMercator,
|
||
zoom: 9
|
||
})
|
||
});
|
||
</code></pre>
|
||
<p>Running the above example will possibly surprise you, since we are not centered
|
||
on Schladming, Austria, but instead on Abyan, a region in Yemen (possibly also a
|
||
nice place). So what happened?</p>
|
||
<p>Many people mix up the order of longitude and latitude in a coordinate array.
|
||
Don't worry if you get it wrong at first, many OpenLayers developers have to
|
||
think twice about whether to put the longitude or the latitude first when they
|
||
e.g. try to change the map center.</p>
|
||
<p>Ok, then let's flip the coordinates:</p>
|
||
<pre><code class="language-javascript">import Map from 'ol/Map.js';
|
||
import View from 'ol/View.js';
|
||
import TileLayer from 'ol/layer/Tile.js';
|
||
import OSM from 'ol/source/OSM.js';
|
||
import {fromLonLat} from 'ol/proj.js';
|
||
|
||
const schladming = [13.689167, 47.394167]; // longitude first, then latitude
|
||
// since we are using OSM, we have to transform the coordinates...
|
||
const schladmingWebMercator = fromLonLat(schladming);
|
||
|
||
const map = new Map({
|
||
layers: [
|
||
new TileLayer({
|
||
source: new OSM()
|
||
})
|
||
],
|
||
target: 'map',
|
||
view: new View({
|
||
center: schladmingWebMercator,
|
||
zoom: 9
|
||
})
|
||
});
|
||
</code></pre>
|
||
<p>Schladming is now correctly displayed in the center of the map.</p>
|
||
<p>So when you deal with EPSG:4326 coordinates in OpenLayers, put the longitude
|
||
first, and then the latitude. This behaviour is the same as we had in OpenLayers
|
||
2, and it actually makes sense because of the natural axis order in WGS84.</p>
|
||
<p>If you cannot remember the correct order, just have a look at the method name
|
||
we used: <code>fromLonLat</code>; even there we hint that we expect longitude
|
||
first, and then latitude.</p>
|
||
<h2 id="why-arent-there-any-features-in-my-source">Why aren't there any features in my source?</h2>
|
||
<p>Suppose you want to load a KML file and display the contained features on the
|
||
map. Code like the following could be used:</p>
|
||
<pre><code class="language-javascript">import VectorLayer from 'ol/layer/Vector.js';
|
||
import KMLSource from 'ol/source/KML.js';
|
||
|
||
const vector = new VectorLayer({
|
||
source: new KMLSource({
|
||
projection: 'EPSG:3857',
|
||
url: 'data/kml/2012-02-10.kml'
|
||
})
|
||
});
|
||
</code></pre>
|
||
<p>You may ask yourself how many features are in that KML, and try something like
|
||
the following:</p>
|
||
<pre><code class="language-javascript">import VectorLayer from 'ol/layer/Vector.js';
|
||
import KMLSource from 'ol/source/KML.js';
|
||
|
||
const vector = new VectorLayer({
|
||
source: new KMLSource({
|
||
projection: 'EPSG:3857',
|
||
url: 'data/kml/2012-02-10.kml'
|
||
})
|
||
});
|
||
const numFeatures = vector.getSource().getFeatures().length;
|
||
console.log("Count right after construction: " + numFeatures);
|
||
</code></pre>
|
||
<p>This will log a count of <code>0</code> features to be in the source. This is because the
|
||
loading of the KML-file will happen in an asynchronous manner. To get the count
|
||
as soon as possible (right after the file has been fetched and the source has
|
||
been populated with features), you should use an event listener function on the
|
||
<code>source</code>:</p>
|
||
<pre><code class="language-javascript">vector.getSource().on('change', function(evt){
|
||
const source = evt.target;
|
||
if (source.getState() === 'ready') {
|
||
const numFeatures = source.getFeatures().length;
|
||
console.log("Count after change: " + numFeatures);
|
||
}
|
||
});
|
||
</code></pre>
|
||
<p>This will correctly report the number of features, <code>1119</code> in that particular
|
||
case.</p>
|
||
<h2 id="how-do-i-force-a-re-render-of-the-map">How do I force a re-render of the map?</h2>
|
||
<p>Usually the map is automatically re-rendered, once a source changes (for example
|
||
when a remote source has loaded).</p>
|
||
<p>If you actually want to manually trigger a rendering, you could use</p>
|
||
<pre><code class="language-javascript">map.render();
|
||
</code></pre>
|
||
<p>...or its companion method</p>
|
||
<pre><code class="language-javascript">map.renderSync();
|
||
</code></pre>
|
||
<h2 id="why-are-my-features-not-found">Why are my features not found?</h2>
|
||
<p>You are using <code>Map#forEachFeatureAtPixel</code> or <code>Map#hasFeatureAtPixel</code>, but
|
||
it sometimes does not work for large icons or labels? The <em>hit detection</em> only
|
||
checks features that are within a certain distance of the given position. For large
|
||
icons, the actual geometry of a feature might be too far away and is not considered.</p>
|
||
<p>In this case, set the <code>renderBuffer</code> property of <code>VectorLayer</code> (the default value is 100px):</p>
|
||
<pre><code class="language-javascript">import VectorLayer from 'ol/layer/Vector.js';
|
||
|
||
const vectorLayer = new VectorLayer({
|
||
...
|
||
renderBuffer: 200
|
||
});
|
||
</code></pre>
|
||
<p>The recommended value is the size of the largest symbol, line width or label.</p>
|
||
<h2 id="why-is-zooming-or-clicking-in-the-map-offinaccurate">Why is zooming or clicking in the map off/inaccurate?</h2>
|
||
<p>OpenLayers does not update the map when the container element is resized. This can be caused by progressive updates
|
||
to CSS styles or manually resizing the map. When that happens, any interaction will become inaccurate: the map would zoom in and out, and end up not being centered on the pointer. This makes it hard to do certain interactions, e.g. selecting the desired feature.</p>
|
||
<p>There is currently no built-in way to react to element's size changes, as <a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver">Resize Observer API</a> is only implemented in Chrome.</p>
|
||
<p>There is however an easy to use <a href="https://github.com/que-etc/resize-observer-polyfill">polyfill</a>:</p>
|
||
<pre><code class="language-javascript">import Map from 'ol/Map.js';
|
||
import ResizeObserver from 'resize-observer-polyfill';
|
||
|
||
const mapElement = document.querySelector('#map')
|
||
const map = new Map({
|
||
target: mapElement
|
||
})
|
||
|
||
const sizeObserver = new ResizeObserver(() => {
|
||
map.updateSize()
|
||
})
|
||
sizeObserver.observe(mapElement)
|
||
|
||
// called when the map is destroyed
|
||
// sizeObserver.disconnect()
|
||
</code></pre>
|
||
|
||
</div>
|
||
<footer>
|
||
Code licensed under the <a href='http://www.tldrlegal.com/license/bsd-2-clause-license-(freebsd)'>2-Clause BSD</a>.
|
||
All documentation <a href='http://creativecommons.org/licenses/by/3.0/'>CC BY 3.0</a>.
|
||
Thanks to our <a href='https://opencollective.com/openlayers'>sponsors</a>.
|
||
<br>
|
||
<a href="https://www.netlify.com">This site is powered by Netlify.</a>
|
||
</footer>
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"></script>
|
||
</body>
|
||
</html>
|