Compare commits
240 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2767ddfdc7 | ||
|
|
cd85e30d08 | ||
|
|
139fcd7bae | ||
|
|
2a04415264 | ||
|
|
515eca797f | ||
|
|
0b0d5c63da | ||
|
|
1ad3e8fe37 | ||
|
|
e5d7b30c31 | ||
|
|
1b745dc7b7 | ||
|
|
f8c5a79242 | ||
|
|
9061e93c59 | ||
|
|
b04728d907 | ||
|
|
154827c5d5 | ||
|
|
f1d03702b2 | ||
|
|
23f9110f1f | ||
|
|
d3e221bd10 | ||
|
|
e3e6a28e18 | ||
|
|
f3089efd19 | ||
|
|
2cfc2fd369 | ||
|
|
c860aed960 | ||
|
|
83972b00a5 | ||
|
|
cf58ee9bf1 | ||
|
|
e5493d1288 | ||
|
|
f77b6be8e9 | ||
|
|
1c5cc6ea7f | ||
|
|
b7c49e1007 | ||
|
|
e1e34e5636 | ||
|
|
d46471d763 | ||
|
|
dae843a98d | ||
|
|
85d836d909 | ||
|
|
323eb3f251 | ||
|
|
5d2cf66380 | ||
|
|
2e60961700 | ||
|
|
c1ffb0a2a9 | ||
|
|
8f7b52f266 | ||
|
|
bcefb07cf2 | ||
|
|
52c75e32ee | ||
|
|
60c8360330 | ||
|
|
b8c9125602 | ||
|
|
71555002a8 | ||
|
|
5d029f4256 | ||
|
|
6fa4fa59d6 | ||
|
|
b4ce8e4b3d | ||
|
|
4cdab30201 | ||
|
|
47c58d8a34 | ||
|
|
5124c98fb5 | ||
|
|
aecb7e1789 | ||
|
|
0a126b620c | ||
|
|
9ed3540edf | ||
|
|
4589345fac | ||
|
|
e52cabcb31 | ||
|
|
6f32d1a15b | ||
|
|
95533bef66 | ||
|
|
4adab51768 | ||
|
|
b813937991 | ||
|
|
87a3510c83 | ||
|
|
d6190a0cd7 | ||
|
|
8991dc9718 | ||
|
|
65b306891b | ||
|
|
b4e0d4c188 | ||
|
|
1309cf9b69 | ||
|
|
023bb638b2 | ||
|
|
d885771d8d | ||
|
|
7713015b26 | ||
|
|
fe8fcfbc7e | ||
|
|
3f4ba0af5f | ||
|
|
1e4ab17513 | ||
|
|
5f058e877f | ||
|
|
9ce36da349 | ||
|
|
b7b15eb7f0 | ||
|
|
1a5cf52b61 | ||
|
|
f6046c023c | ||
|
|
c4e5a7467e | ||
|
|
9ee5edf19c | ||
|
|
792e7e54f1 | ||
|
|
45e0926896 | ||
|
|
069187859d | ||
|
|
d855f5ba0a | ||
|
|
2f4aa5aa05 | ||
|
|
bd7328675a | ||
|
|
7c6755d3ec | ||
|
|
524b4c99d5 | ||
|
|
e79add2e77 | ||
|
|
fd962caa1c | ||
|
|
414d1556a7 | ||
|
|
a02c1713a4 | ||
|
|
ba431421a1 | ||
|
|
a4abd990df | ||
|
|
df89b0718a | ||
|
|
942a219c30 | ||
|
|
788f932550 | ||
|
|
c969afcddc | ||
|
|
9b2b921f7b | ||
|
|
092441017d | ||
|
|
5e71e6ce80 | ||
|
|
cf15af43e3 | ||
|
|
a8bd0c5dd7 | ||
|
|
ad4e192ee9 | ||
|
|
6a39b9f412 | ||
|
|
f140ff368d | ||
|
|
e1e5e54d74 | ||
|
|
9a28af76ca | ||
|
|
7f05bf1d7e | ||
|
|
84e9d7c72e | ||
|
|
672a462b1e | ||
|
|
c707b4c746 | ||
|
|
44bea898b8 | ||
|
|
a235dc906f | ||
|
|
f5272bb391 | ||
|
|
6530119918 | ||
|
|
11f1f5b25c | ||
|
|
600205f4d9 | ||
|
|
1da14a6d97 | ||
|
|
7d5efd0348 | ||
|
|
6ffda39b14 | ||
|
|
353a00af89 | ||
|
|
b9f08c6a2a | ||
|
|
322a51d822 | ||
|
|
49c4a75777 | ||
|
|
778e867c79 | ||
|
|
4f26f145ae | ||
|
|
9c994138ad | ||
|
|
603f489708 | ||
|
|
2e5054d11c | ||
|
|
64190b7109 | ||
|
|
9e259c471d | ||
|
|
505f88031b | ||
|
|
0f6ee28c19 | ||
|
|
2fd022d215 | ||
|
|
2792ba701a | ||
|
|
e1fedca22e | ||
|
|
5a90203aa0 | ||
|
|
edd23dbf6a | ||
|
|
16849a3611 | ||
|
|
de104d6e22 | ||
|
|
5f40b5b66b | ||
|
|
6ca865375e | ||
|
|
61c48ce09f | ||
|
|
fb59d7a65b | ||
|
|
ec495bfcec | ||
|
|
6f4d2e34a9 | ||
|
|
aa7b6350ec | ||
|
|
0224e2b3c5 | ||
|
|
540b1793e7 | ||
|
|
f2d0b11d24 | ||
|
|
384920734f | ||
|
|
7e3e0e54ca | ||
|
|
c49d2e0115 | ||
|
|
d0ab8dce38 | ||
|
|
f78d0d4cfa | ||
|
|
7b4a73f3b9 | ||
|
|
60e85e7d89 | ||
|
|
2096a1d0db | ||
|
|
41fd1d4222 | ||
|
|
b1f80a5998 | ||
|
|
19ca2c25c6 | ||
|
|
84d2c3a42e | ||
|
|
88fbd6e35d | ||
|
|
33ef64c912 | ||
|
|
ed7788ca37 | ||
|
|
623c887579 | ||
|
|
f2b7dfc26c | ||
|
|
349e602ee5 | ||
|
|
9cb10efe4b | ||
|
|
871a283601 | ||
|
|
d1a609e0a3 | ||
|
|
e0c5529878 | ||
|
|
186d5466f4 | ||
|
|
dc9e0a6bc4 | ||
|
|
b74dd515d5 | ||
|
|
1ee1ea6a1a | ||
|
|
fe0f91cb29 | ||
|
|
5d6721192d | ||
|
|
d0a8043edc | ||
|
|
f3f0403cec | ||
|
|
84a88616a8 | ||
|
|
4055a08043 | ||
|
|
afec93ae62 | ||
|
|
e7d6bc055a | ||
|
|
97f6171b4c | ||
|
|
e2f8d96763 | ||
|
|
ce97cee6a6 | ||
|
|
0ec0491ef6 | ||
|
|
a09b6c91c9 | ||
|
|
3871f7785a | ||
|
|
160f1bc286 | ||
|
|
c0d04ea077 | ||
|
|
da0838dde2 | ||
|
|
1da43d90af | ||
|
|
9ddd7e4751 | ||
|
|
538315f682 | ||
|
|
b8db6bf087 | ||
|
|
42228ed87d | ||
|
|
707afeab06 | ||
|
|
7a7414447f | ||
|
|
fb28071dd1 | ||
|
|
6b39353ccb | ||
|
|
6f6e9a2af1 | ||
|
|
bc3e348b0d | ||
|
|
59c3eedbab | ||
|
|
60600d3108 | ||
|
|
49050063d5 | ||
|
|
1b9cad6b8d | ||
|
|
9c16cc4200 | ||
|
|
c9b638f5fd | ||
|
|
f3b79c57f7 | ||
|
|
769a14d0dc | ||
|
|
11024ad294 | ||
|
|
73f1428701 | ||
|
|
a579b168f7 | ||
|
|
537a21fd48 | ||
|
|
e18d485d01 | ||
|
|
853fc77f2a | ||
|
|
c678354aec | ||
|
|
1f06f7c2ac | ||
|
|
9c085e37de | ||
|
|
a6896ed531 | ||
|
|
9304ee25af | ||
|
|
f0f21d583a | ||
|
|
54d50af2c3 | ||
|
|
9f84494b02 | ||
|
|
e18a23c877 | ||
|
|
cb78019825 | ||
|
|
352d77e2ec | ||
|
|
a978467726 | ||
|
|
ddeb091871 | ||
|
|
bc60c8ec32 | ||
|
|
6da2e4cef4 | ||
|
|
001add5a28 | ||
|
|
8c4c70e9f0 | ||
|
|
0c300d651f | ||
|
|
b072dc5968 | ||
|
|
52e286b03c | ||
|
|
7dcc720029 | ||
|
|
770407f1ba | ||
|
|
53cb47cab9 | ||
|
|
5ba08b7291 | ||
|
|
43e67b73c2 | ||
|
|
4ed9f27cd1 | ||
|
|
bde6caf082 |
11
.github/ISSUE_TEMPLATE.md
vendored
11
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,8 +1,9 @@
|
|||||||
|
<!--
|
||||||
Thank you for your interest in making OpenLayers better!
|
Thank you for your interest in making OpenLayers better!
|
||||||
|
|
||||||
To keep this project manageable for maintainers, we ask you to please check all boxes below before submitting an issue.
|
If you are reporting a bug, please link to an example that reproduces the problem. This will make it easier for people who may want to help you debug.
|
||||||
|
|
||||||
- [ ] I am submitting a bug or feature request, not a usage question. Go to https://stackoverflow.com/questions/tagged/openlayers for questions.
|
If you have a usage question, you might want to try Stack Overflow first: https://stackoverflow.com/questions/tagged/openlayers
|
||||||
- [ ] I have searched GitHub to see if a similar bug or feature request has already been reported.
|
|
||||||
- [ ] I have verified that the issue is present in the latest version of OpenLayers (see 'LATEST' on https://openlayers.org/).
|
Thanks
|
||||||
- [ ] If reporting a bug, I have created a [CodePen](https://codepen.io) or prepared a stack trace (using the latest version and unminified code, so e.g. `ol-debug.js`, not `ol.js`) that shows the issue.
|
-->
|
||||||
|
|||||||
15
.github/PULL_REQUEST_TEMPLATE.md
vendored
15
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,8 +1,13 @@
|
|||||||
|
<!--
|
||||||
Thank you for your interest in making OpenLayers better!
|
Thank you for your interest in making OpenLayers better!
|
||||||
|
|
||||||
In order to get your proposed changes merged into the master branch, we ask you to please make sure the following boxes are checked *before* submitting your pull request.
|
Before submitting a pull request, it is best to open an issue describing the bug you are fixing or the feature you are proposing to add.
|
||||||
|
|
||||||
- [ ] This pull request addresses an issue that has been marked with the 'Pull request accepted' label & I have added the link to that issue.
|
Here are some other tips that make pull requests easier to review:
|
||||||
- [ ] It contains one or more small, incremental, logically separate commits, with no merge commits.
|
|
||||||
- [ ] I have used clear commit messages.
|
* Commits in the branch are small and logically separated (with no unnecessary merge commits).
|
||||||
- [ ] Existing tests pass for me locally & I have added or updated tests for new or changed functionality.
|
* Commit messages are clear.
|
||||||
|
* Existing tests pass, new functionality is covered by new tests, and fixes have regression tests.
|
||||||
|
|
||||||
|
Thanks
|
||||||
|
-->
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,4 +2,3 @@
|
|||||||
/coverage/
|
/coverage/
|
||||||
/dist/
|
/dist/
|
||||||
node_modules/
|
node_modules/
|
||||||
src/index.js
|
|
||||||
|
|||||||
47
README.md
47
README.md
@@ -1,23 +1,44 @@
|
|||||||
# OpenLayers
|
# OpenLayers
|
||||||
|
|
||||||
[](http://travis-ci.org/#!/openlayers/openlayers)
|
|
||||||
[](https://greenkeeper.io/)
|
|
||||||
[](https://coveralls.io/github/openlayers/openlayers?branch=master)
|
|
||||||
[](http://osgeo.org/)
|
|
||||||
[](https://www.jsdelivr.com/package/npm/openlayers)
|
|
||||||
|
|
||||||
[OpenLayers](https://openlayers.org/) is a high-performance, feature-packed library for creating interactive maps on the web. It can display map tiles, vector data and markers loaded from any source on any web page. OpenLayers has been developed to further the use of geographic information of all kinds. It is completely free, Open Source JavaScript, released under the 2-clause BSD License (also known as the FreeBSD).
|
[OpenLayers](https://openlayers.org/) is a high-performance, feature-packed library for creating interactive maps on the web. It can display map tiles, vector data and markers loaded from any source on any web page. OpenLayers has been developed to further the use of geographic information of all kinds. It is completely free, Open Source JavaScript, released under the 2-clause BSD License (also known as the FreeBSD).
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
Use one of the following methods to use OpenLayers in your project:
|
Install the [`ol` package](https://www.npmjs.com/package/ol):
|
||||||
|
|
||||||
* For use with webpack, Rollup, Browserify, or other module bundlers, install the [`ol` package](https://www.npmjs.com/package/ol):
|
```
|
||||||
```
|
npm install ol
|
||||||
npm install ol
|
```
|
||||||
```
|
|
||||||
|
|
||||||
* If you just want to add a `<script>` tag to test things out, you can link directly to one of the full builds from [cdnjs](https://cdnjs.com/libraries/openlayers) (not recommended for production)
|
Import just what you need for your application:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Map from 'ol/Map';
|
||||||
|
import View from 'ol/View';
|
||||||
|
import TileLayer from 'ol/layer/Tile';
|
||||||
|
import XYZ from 'ol/source/XYZ';
|
||||||
|
|
||||||
|
new Map({
|
||||||
|
target: 'map',
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
source: new XYZ({
|
||||||
|
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
],
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 2
|
||||||
|
})
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
See the following examples for more detail on bundling OpenLayers with your application:
|
||||||
|
|
||||||
|
* Using [Rollup](https://github.com/openlayers/ol-rollup)
|
||||||
|
* Using [Webpack](https://github.com/openlayers/ol-webpack)
|
||||||
|
* Using [Parcel](https://github.com/openlayers/ol-parcel)
|
||||||
|
|
||||||
## Supported Browsers
|
## Supported Browsers
|
||||||
|
|
||||||
@@ -39,3 +60,5 @@ Please see our guide on [contributing](CONTRIBUTING.md) if you're interested in
|
|||||||
|
|
||||||
- Need help? Find it on [Stack Overflow using the tag 'openlayers'](http://stackoverflow.com/questions/tagged/openlayers)
|
- Need help? Find it on [Stack Overflow using the tag 'openlayers'](http://stackoverflow.com/questions/tagged/openlayers)
|
||||||
- Follow [@openlayers](https://twitter.com/openlayers) on Twitter
|
- Follow [@openlayers](https://twitter.com/openlayers) on Twitter
|
||||||
|
|
||||||
|
[](https://travis-ci.org/openlayers/openlayers)
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
## Upgrade notes
|
## Upgrade notes
|
||||||
|
|
||||||
|
### v5.1.0
|
||||||
|
|
||||||
|
#### Geometry constructor and `setCoordinates` no longer accept `null` coordinates
|
||||||
|
|
||||||
|
Geometries (`ol/geom/*`) now need to be constructed with valid coordinates (center for `ol/geom/Circle`) as first constructor argument. The same applies to the `setCoordinates()` (`setCenter() for `ol/geom/Circle`) method.
|
||||||
|
|
||||||
### v5.0.0
|
### v5.0.0
|
||||||
|
|
||||||
#### Renamed `ol/source/TileUTFGrid` to `ol/source/UTFGrid`
|
#### Renamed `ol/source/TileUTFGrid` to `ol/source/UTFGrid`
|
||||||
@@ -170,7 +176,7 @@ The optional this (i.e. opt_this) arguments were removed from the following meth
|
|||||||
|
|
||||||
|
|
||||||
#### `Map#forEachLayerAtPixel` parameters have changed
|
#### `Map#forEachLayerAtPixel` parameters have changed
|
||||||
|
|
||||||
If you are using the layer filter, please note that you now have to pass in the layer filter via an `AtPixelOptions` object. If you are not using the layer filter the usage has not changed.
|
If you are using the layer filter, please note that you now have to pass in the layer filter via an `AtPixelOptions` object. If you are not using the layer filter the usage has not changed.
|
||||||
|
|
||||||
Old syntax:
|
Old syntax:
|
||||||
|
|||||||
8
changelog/v5.0.1.md
Normal file
8
changelog/v5.0.1.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# 5.0.1
|
||||||
|
|
||||||
|
The v5.0.1 release helps reduce bundle sizes for bundlers that support the `"sideEffects": "false"`option in `package.json`, and fixes website documentation regarding cdn locations and debug build which has been replaced by source maps.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
* [#8341](https://github.com/openlayers/openlayers/pull/8341) - Set sideEffects: false flag ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8342](https://github.com/openlayers/openlayers/pull/8342) - Fix links and description in quickstart tutorial ([@ahocevar](https://github.com/ahocevar))
|
||||||
7
changelog/v5.0.2.md
Normal file
7
changelog/v5.0.2.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# 5.0.2
|
||||||
|
|
||||||
|
The v5.0.2 release updates the package readme with new example projects.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
* [#8332](https://github.com/openlayers/openlayers/pull/8343) - Starter projects ([@tschaub](https://github.com/tschaub))
|
||||||
9
changelog/v5.0.3.md
Normal file
9
changelog/v5.0.3.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# 5.0.3
|
||||||
|
|
||||||
|
The v5.0.3 fixes a regression in the vector tile renderer and improves the built examples and release package.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
* [#8364](https://github.com/openlayers/openlayers/pull/8364) - Make examples work in IE11 ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8363](https://github.com/openlayers/openlayers/pull/8363) - Autogenerate src/ol/package.json ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8371](https://github.com/openlayers/openlayers/pull/8371) - Skip rendering when there is no replay group ([@ahocevar](https://github.com/ahocevar))
|
||||||
64
changelog/v5.1.0.md
Normal file
64
changelog/v5.1.0.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# v5.1.0
|
||||||
|
|
||||||
|
The 5.1 release adds a few new features a handful of fixes. You should be able to upgrade without any additional work. See the one note below regarding `null` geometry coordinates.
|
||||||
|
|
||||||
|
We're working toward type checking with TypeScript. This will complete our move away from using the Closure Compiler for type checking and compilation. We're excited about the improved experience for application developers and will highlight some of the benefit in upcoming releases.
|
||||||
|
|
||||||
|
### Upgrade Notes
|
||||||
|
|
||||||
|
#### Geometry constructor and `setCoordinates` no longer accept `null` coordinates
|
||||||
|
|
||||||
|
Geometries (`ol/geom/*`) now need to be constructed with valid coordinates (center for `ol/geom/Circle`) as first constructor argument. The same applies to the `setCoordinates()` (`setCenter() for `ol/geom/Circle`) method.
|
||||||
|
|
||||||
|
### New Features and Fixes
|
||||||
|
|
||||||
|
* [#8409](https://github.com/openlayers/openlayers/pull/8409) - Add abstract translate to ol/geom/Geometry ([@pjeweb](https://github.com/pjeweb))
|
||||||
|
* [#8405](https://github.com/openlayers/openlayers/pull/8405) - Minor type fixes ([@tschaub](https://github.com/tschaub))
|
||||||
|
* [#8401](https://github.com/openlayers/openlayers/pull/8401) - Make webpack's css loader work ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8403](https://github.com/openlayers/openlayers/pull/8403) - Markdown links ([@tschaub](https://github.com/tschaub))
|
||||||
|
* [#8402](https://github.com/openlayers/openlayers/pull/8402) - Type fixes from the typescript checks ([@fredj](https://github.com/fredj))
|
||||||
|
* [#8400](https://github.com/openlayers/openlayers/pull/8400) - ESLint config update ([@tschaub](https://github.com/tschaub))
|
||||||
|
* [#8399](https://github.com/openlayers/openlayers/pull/8399) - Copy ol.css to build dir when building package ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8397](https://github.com/openlayers/openlayers/pull/8397) - Update rollup ([@tschaub](https://github.com/tschaub))
|
||||||
|
* [#8385](https://github.com/openlayers/openlayers/pull/8385) - Use class syntax ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8383](https://github.com/openlayers/openlayers/pull/8383) - style/Icon: Add `setAnchor()` method ([@Turbo87](https://github.com/Turbo87))
|
||||||
|
* [#8368](https://github.com/openlayers/openlayers/pull/8368) - Make render listeners work with image render mode ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8376](https://github.com/openlayers/openlayers/pull/8376) - copy ZM values to polygon in makeRegular ([@virtualcitySYSTEMS](https://github.com/virtualcitySYSTEMS))
|
||||||
|
* [#8372](https://github.com/openlayers/openlayers/pull/8372) - Release v5.0.3 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8364](https://github.com/openlayers/openlayers/pull/8364) - Make examples work in IE11 ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8363](https://github.com/openlayers/openlayers/pull/8363) - Autogenerate src/ol/package.json ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8371](https://github.com/openlayers/openlayers/pull/8371) - Skip rendering when there is no replay group ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8362](https://github.com/openlayers/openlayers/pull/8362) - Smart flat coordinates ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8352](https://github.com/openlayers/openlayers/pull/8352) - Set `sideEffects` to `false` instead of `"false"` ([@tschaub](https://github.com/tschaub))
|
||||||
|
* [#8351](https://github.com/openlayers/openlayers/pull/8351) - Fix typo in release notes ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8350](https://github.com/openlayers/openlayers/pull/8350) - Updates for v5.0.2 ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8349](https://github.com/openlayers/openlayers/pull/8349) - Release v5.0.1 ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8343](https://github.com/openlayers/openlayers/pull/8343) - Starter projects ([@tschaub](https://github.com/tschaub))
|
||||||
|
* [#8347](https://github.com/openlayers/openlayers/pull/8347) - Fix typos in release notes ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8346](https://github.com/openlayers/openlayers/pull/8346) - Release v5.0.1 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8342](https://github.com/openlayers/openlayers/pull/8342) - Fix links and description in quickstart tutorial ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8344](https://github.com/openlayers/openlayers/pull/8344) - Updated issue and pr templates ([@tschaub](https://github.com/tschaub))
|
||||||
|
* [#8341](https://github.com/openlayers/openlayers/pull/8341) - Set sideEffects: false flag ([@ahocevar](https://github.com/ahocevar))
|
||||||
|
* [#8333](https://github.com/openlayers/openlayers/pull/8333) - Fix wrong return type for readHref function ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8329](https://github.com/openlayers/openlayers/pull/8329) - Better jsdoc typing ([@fredj](https://github.com/fredj))
|
||||||
|
* [#8319](https://github.com/openlayers/openlayers/pull/8319) - Remove reference to setProj4 function in documentation ([@fredj](https://github.com/fredj))
|
||||||
|
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Dependency Updates</summary>
|
||||||
|
|
||||||
|
* [#8410](https://github.com/openlayers/openlayers/pull/8410) - Update rollup to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8408](https://github.com/openlayers/openlayers/pull/8408) - Update rollup to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8386](https://github.com/openlayers/openlayers/pull/8386) - Update fs-extra to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8382](https://github.com/openlayers/openlayers/pull/8382) - Update webpack to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8373](https://github.com/openlayers/openlayers/pull/8373) - Update webpack to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8355](https://github.com/openlayers/openlayers/pull/8355) - Update recast to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8354](https://github.com/openlayers/openlayers/pull/8354) - Update webpack to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8348](https://github.com/openlayers/openlayers/pull/8348) - Update webpack to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8338](https://github.com/openlayers/openlayers/pull/8338) - Update recast to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8332](https://github.com/openlayers/openlayers/pull/8332) - Update webpack to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8326](https://github.com/openlayers/openlayers/pull/8326) - Update webpack to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8321](https://github.com/openlayers/openlayers/pull/8321) - Update rollup to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
* [#8318](https://github.com/openlayers/openlayers/pull/8318) - Update webpack to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
|
||||||
|
|
||||||
|
</details>
|
||||||
3
changelog/v5.1.1.md
Normal file
3
changelog/v5.1.1.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# 5.1.1
|
||||||
|
|
||||||
|
The 5.1.1 release is a patch to include the readme in the package. See the [5.1.0 notes](https://github.com/openlayers/openlayers/releases/tag/v5.1.0) for detail on the 5.1 release.
|
||||||
5
changelog/v5.1.2.md
Normal file
5
changelog/v5.1.2.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# 5.1.2
|
||||||
|
|
||||||
|
The 5.1.2 release is a patch to fix the API docs. See the [5.1.0 notes](https://github.com/openlayers/openlayers/releases/tag/v5.1.0) for detail on the 5.1 release.
|
||||||
|
|
||||||
|
* [#8413](https://github.com/openlayers/openlayers/pull/8413) - Remove extra curly in type ([@tschaub](https://github.com/tschaub))
|
||||||
@@ -313,7 +313,7 @@ exports.publish = function(taffyData, opts, tutorials) {
|
|||||||
|
|
||||||
if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
|
if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
|
||||||
caption = RegExp.$1;
|
caption = RegExp.$1;
|
||||||
code = RegExp.$3;
|
code = RegExp.$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import buble from 'rollup-plugin-buble';
|
|||||||
import sourcemaps from 'rollup-plugin-sourcemaps';
|
import sourcemaps from 'rollup-plugin-sourcemaps';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
input: 'src/index.js',
|
input: 'build/index.js',
|
||||||
output: [
|
output: [
|
||||||
{file: 'build/ol.js', format: 'iife', sourcemap: true}
|
{file: 'build/ol.js', format: 'iife', sourcemap: true}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ layout: doc.hbs
|
|||||||
|
|
||||||
This primer shows you how to put a simple map on a web page.
|
This primer shows you how to put a simple map on a web page.
|
||||||
|
|
||||||
|
**For production, we strongly recommend bundling the application together with its dependencies, as explained in the [Building an OpenLayers Application](./tutorials/bundle.html) tutorial.**
|
||||||
|
|
||||||
|
|
||||||
## Put a map on a page
|
## Put a map on a page
|
||||||
|
|
||||||
Below you'll find a complete working example. Create a new file, copy in the contents below, and open in a browser:
|
Below you'll find a complete working example. Create a new file, copy in the contents below, and open in a browser:
|
||||||
@@ -15,14 +18,14 @@ Below you'll find a complete working example. Create a new file, copy in the co
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="https://openlayers.org/en/{{ latest }}/css/ol.css" type="text/css">
|
<link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/{{ latest }}/css/ol.css" type="text/css">
|
||||||
<style>
|
<style>
|
||||||
.map {
|
.map {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="https://openlayers.org/en/{{ latest }}/build/ol.js" type="text/javascript"></script>
|
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/{{ latest }}/build/ol.js"></script>
|
||||||
<title>OpenLayers example</title>
|
<title>OpenLayers example</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -56,10 +59,8 @@ To include a map a web page you will need 3 things:
|
|||||||
|
|
||||||
### Include OpenLayers
|
### Include OpenLayers
|
||||||
|
|
||||||
**Caveat:** In production, it is not recommended to include dependencies as script tag. Instead, we recommend bundling the application together with its dependencies, as explained in the [Building an OpenLayers Application](./tutorials/bundle.html) tutorial.
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<script src="https://openlayers.org/en/{{ latest }}/build/ol.js" type="text/javascript"></script>
|
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/{{ latest }}/build/ol.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
The first part is to include the JavaScript library. For the purpose of this tutorial, here we simply point to the openlayers.org website to get the whole library. In a production environment, we would build a custom version of the library including only the module needed for our application.
|
The first part is to include the JavaScript library. For the purpose of this tutorial, here we simply point to the openlayers.org website to get the whole library. In a production environment, we would build a custom version of the library including only the module needed for our application.
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ Class hierarchies grouped by their parent are provided in a subfolder of the pac
|
|||||||
For convenience, these are also available as named exports, e.g.
|
For convenience, these are also available as named exports, e.g.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {Map, View} from `ol`;
|
import {Map, View} from 'ol';
|
||||||
import {Tile, Vector} from `ol/layer`;
|
import {Tile, Vector} from 'ol/layer';
|
||||||
```
|
```
|
||||||
|
|
||||||
In addition to these re-exported classes, modules with lowercase names also provide constants or functions as named exports:
|
In addition to these re-exported classes, modules with lowercase names also provide constants or functions as named exports:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {inherits} from `ol`;
|
import {inherits} from 'ol';
|
||||||
import {fromLonLat} from `ol/proj`;
|
import {fromLonLat} from 'ol/proj';
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {inherits} from '../src/ol/index.js';
|
import {inherits} from '../src/ol/util.js';
|
||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import {defaults as defaultControls, Control} from '../src/ol/control.js';
|
import {defaults as defaultControls, Control} from '../src/ol/control.js';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {inherits} from '../src/ol/index.js';
|
import {inherits} from '../src/ol/util.js';
|
||||||
import Feature from '../src/ol/Feature.js';
|
import Feature from '../src/ol/Feature.js';
|
||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
@@ -29,7 +29,7 @@ app.Drag = function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {module:ol~Pixel}
|
* @type {module:ol/pixel~Pixel}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.coordinate_ = null;
|
this.coordinate_ = null;
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ const map = new Map({
|
|||||||
layers: [raster, vector],
|
layers: [raster, vector],
|
||||||
interactions: defaultInteractions().extend([new Select({
|
interactions: defaultInteractions().extend([new Select({
|
||||||
condition: function(evt) {
|
condition: function(evt) {
|
||||||
return evt.type == 'pointermove' ||
|
return evt.type == 'pointermove' ||
|
||||||
evt.type == 'singleclick';
|
evt.type == 'singleclick';
|
||||||
},
|
},
|
||||||
style: selectStyleFunction
|
style: selectStyleFunction
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const map = new Map({
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let select = null; // ref to currently selected interaction
|
let select = null; // ref to currently selected interaction
|
||||||
|
|
||||||
// select interaction working on "singleclick"
|
// select interaction working on "singleclick"
|
||||||
const selectSingleClick = new Select();
|
const selectSingleClick = new Select();
|
||||||
|
|||||||
@@ -18,6 +18,18 @@ module.exports = {
|
|||||||
context: src,
|
context: src,
|
||||||
target: 'web',
|
target: 'web',
|
||||||
entry: entry,
|
entry: entry,
|
||||||
|
module: {
|
||||||
|
rules: [{
|
||||||
|
use: {
|
||||||
|
loader: 'buble-loader'
|
||||||
|
},
|
||||||
|
test: /\.js$/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '..', '..', 'src'),
|
||||||
|
path.join(__dirname, '..')
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
runtimeChunk: {
|
runtimeChunk: {
|
||||||
name: 'common'
|
name: 'common'
|
||||||
|
|||||||
@@ -64,20 +64,20 @@ function createWordIndex(exampleData) {
|
|||||||
/**
|
/**
|
||||||
* Gets the source for the chunk that matches the jsPath
|
* Gets the source for the chunk that matches the jsPath
|
||||||
* @param {Object} chunk Chunk.
|
* @param {Object} chunk Chunk.
|
||||||
* @param {string} jsPath Path of the file.
|
* @param {string} jsName Name of the file.
|
||||||
* @return {string} The source.
|
* @return {string} The source.
|
||||||
*/
|
*/
|
||||||
function getJsSource(chunk, jsPath) {
|
function getJsSource(chunk, jsName) {
|
||||||
let jsSource;
|
let jsSource;
|
||||||
for (let i = 0, ii = chunk.modules.length; i < ii; ++i) {
|
for (let i = 0, ii = chunk.modules.length; i < ii; ++i) {
|
||||||
const module = chunk.modules[i];
|
const module = chunk.modules[i];
|
||||||
if (module.modules) {
|
if (module.modules) {
|
||||||
jsSource = getJsSource(module, jsPath);
|
jsSource = getJsSource(module, jsName);
|
||||||
if (jsSource) {
|
if (jsSource) {
|
||||||
return jsSource;
|
return jsSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (module.identifier == jsPath) {
|
if (module.identifier.endsWith(jsName)) {
|
||||||
return module.source;
|
return module.source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,8 +151,7 @@ ExampleBuilder.prototype.render = async function(dir, chunk) {
|
|||||||
|
|
||||||
// add in script tag
|
// add in script tag
|
||||||
const jsName = `${name}.js`;
|
const jsName = `${name}.js`;
|
||||||
const jsPath = path.join(dir, jsName);
|
let jsSource = getJsSource(chunk, path.join('.', jsName));
|
||||||
let jsSource = getJsSource(chunk, jsPath);
|
|
||||||
jsSource = jsSource.replace(/'\.\.\/src\//g, '\'');
|
jsSource = jsSource.replace(/'\.\.\/src\//g, '\'');
|
||||||
if (data.cloak) {
|
if (data.cloak) {
|
||||||
for (const entry of data.cloak) {
|
for (const entry of data.cloak) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const imgHeight = 6100;
|
|||||||
|
|
||||||
const zoomifyUrl = 'http://vips.vtech.fr/cgi-bin/iipsrv.fcgi?zoomify=' +
|
const zoomifyUrl = 'http://vips.vtech.fr/cgi-bin/iipsrv.fcgi?zoomify=' +
|
||||||
'/mnt/MD1/AD00/plan_CHU-4HD-01/FOND.TIF/';
|
'/mnt/MD1/AD00/plan_CHU-4HD-01/FOND.TIF/';
|
||||||
const iipUrl = 'http://vips.vtech.fr/cgi-bin/iipsrv.fcgi?FIF=' + '/mnt/MD1/AD00/plan_CHU-4HD-01/FOND.TIF' + '&JTL={z},{tileIndex}';
|
const iipUrl = 'http://vips.vtech.fr/cgi-bin/iipsrv.fcgi?FIF=' + '/mnt/MD1/AD00/plan_CHU-4HD-01/FOND.TIF' + '&JTL={z},{tileIndex}';
|
||||||
|
|
||||||
const layer = new TileLayer({
|
const layer = new TileLayer({
|
||||||
source: new Zoomify({
|
source: new Zoomify({
|
||||||
|
|||||||
45
package.json
45
package.json
@@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "openlayers",
|
"name": "ol",
|
||||||
"version": "5.0.0",
|
"version": "5.1.2",
|
||||||
"description": "OpenLayers mapping library",
|
"description": "OpenLayers mapping library",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"map",
|
"map",
|
||||||
"mapping",
|
"mapping",
|
||||||
"ol"
|
"ol"
|
||||||
],
|
],
|
||||||
|
"private": true,
|
||||||
"homepage": "https://openlayers.org/",
|
"homepage": "https://openlayers.org/",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint tasks test src/ol examples config",
|
"lint": "eslint tasks test src/ol examples config",
|
||||||
@@ -15,18 +16,14 @@
|
|||||||
"karma": "karma start test/karma.config.js",
|
"karma": "karma start test/karma.config.js",
|
||||||
"serve-examples": "webpack-dev-server --config examples/webpack/config.js --mode development --watch",
|
"serve-examples": "webpack-dev-server --config examples/webpack/config.js --mode development --watch",
|
||||||
"build-examples": "webpack --config examples/webpack/config.js --mode production",
|
"build-examples": "webpack --config examples/webpack/config.js --mode production",
|
||||||
"build-index": "node tasks/generate-index",
|
"build-package": "npm run transpile && npm run copy-css && node tasks/prepare-package && cp README.md build/ol",
|
||||||
"set-version": "node tasks/set-version",
|
"build-index": "npm run build-package && node tasks/generate-index",
|
||||||
"prebuild": "npm run set-version && npm run build-index",
|
"build-legacy": "rm -rf build && npm run build-index && rollup --config config/rollup.js && cleancss --source-map src/ol/ol.css -o build/ol.css",
|
||||||
"prepare": "npm run set-version",
|
"copy-css": "cp src/ol/ol.css build/ol/ol.css",
|
||||||
"build": "rollup --config config/rollup.js && cleancss --source-map src/ol/ol.css -o build/ol.css",
|
"transpile": "rm -rf build/ol && mkdir -p build && buble --input src/ol --output build/ol --no modules --sourcemap",
|
||||||
"presrc-closure": "npm run prebuild",
|
|
||||||
"src-closure": "node tasks/transform-types",
|
|
||||||
"pretypecheck": "npm run src-closure",
|
|
||||||
"typecheck": "node tasks/typecheck",
|
|
||||||
"apidoc": "jsdoc config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc"
|
"apidoc": "jsdoc config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc"
|
||||||
},
|
},
|
||||||
"main": "src/ol/index.js",
|
"main": "index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git://github.com/openlayers/openlayers.git"
|
"url": "git://github.com/openlayers/openlayers.git"
|
||||||
@@ -35,29 +32,24 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/openlayers/openlayers/issues"
|
"url": "https://github.com/openlayers/openlayers/issues"
|
||||||
},
|
},
|
||||||
"browser": "dist/ol.js",
|
|
||||||
"style": [
|
|
||||||
"css/ol.css"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pbf": "3.1.0",
|
"pbf": "3.1.0",
|
||||||
"pixelworks": "1.1.0",
|
"pixelworks": "1.1.0",
|
||||||
"rbush": "2.0.2"
|
"rbush": "2.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "^6.26.3",
|
"buble": "^0.19.3",
|
||||||
"babel-plugin-jsdoc-closure": "1.5.1",
|
"buble-loader": "^0.5.1",
|
||||||
"chaikin-smooth": "^1.0.4",
|
"chaikin-smooth": "^1.0.4",
|
||||||
"clean-css-cli": "4.1.11",
|
"clean-css-cli": "4.1.11",
|
||||||
"copy-webpack-plugin": "^4.4.1",
|
"copy-webpack-plugin": "^4.4.1",
|
||||||
"coveralls": "3.0.1",
|
"coveralls": "3.0.1",
|
||||||
"eslint": "5.0.1",
|
"eslint": "5.0.1",
|
||||||
"eslint-config-openlayers": "^9.2.0",
|
"eslint-config-openlayers": "^11.0.0",
|
||||||
"expect.js": "0.3.1",
|
"expect.js": "0.3.1",
|
||||||
"front-matter": "^2.1.2",
|
"front-matter": "^2.1.2",
|
||||||
"fs-extra": "^6.0.0",
|
"fs-extra": "^7.0.0",
|
||||||
"glob": "^7.1.2",
|
"glob": "^7.1.2",
|
||||||
"google-closure-compiler": "20180610.0.2",
|
|
||||||
"handlebars": "4.0.11",
|
"handlebars": "4.0.11",
|
||||||
"istanbul": "0.4.5",
|
"istanbul": "0.4.5",
|
||||||
"jquery": "3.3.1",
|
"jquery": "3.3.1",
|
||||||
@@ -75,8 +67,7 @@
|
|||||||
"mustache": "^2.3.0",
|
"mustache": "^2.3.0",
|
||||||
"pixelmatch": "^4.0.2",
|
"pixelmatch": "^4.0.2",
|
||||||
"proj4": "2.4.4",
|
"proj4": "2.4.4",
|
||||||
"recast": "0.15.0",
|
"rollup": "0.63.4",
|
||||||
"rollup": "0.61.2",
|
|
||||||
"rollup-plugin-buble": "0.19.2",
|
"rollup-plugin-buble": "0.19.2",
|
||||||
"rollup-plugin-commonjs": "9.1.3",
|
"rollup-plugin-commonjs": "9.1.3",
|
||||||
"rollup-plugin-node-resolve": "3.3.0",
|
"rollup-plugin-node-resolve": "3.3.0",
|
||||||
@@ -86,12 +77,14 @@
|
|||||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||||
"url-polyfill": "^1.0.13",
|
"url-polyfill": "^1.0.13",
|
||||||
"walk": "^2.3.9",
|
"walk": "^2.3.9",
|
||||||
"webpack": "4.12.1",
|
"webpack": "4.16.1",
|
||||||
"webpack-cli": "^3.0.3",
|
"webpack-cli": "^3.0.8",
|
||||||
"webpack-dev-server": "^3.1.4"
|
"webpack-dev-server": "^3.1.4"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "openlayers"
|
"extends": "openlayers"
|
||||||
},
|
},
|
||||||
"sideEffects": false
|
"sideEffects": [
|
||||||
|
"ol.css"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,44 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/AssertionError
|
* @module ol/AssertionError
|
||||||
*/
|
*/
|
||||||
import {VERSION, inherits} from './util.js';
|
import {VERSION} from './util.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error object thrown when an assertion failed. This is an ECMA-262 Error,
|
* Error object thrown when an assertion failed. This is an ECMA-262 Error,
|
||||||
* extended with a `code` property.
|
* extended with a `code` property.
|
||||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error}
|
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error.
|
||||||
* @constructor
|
|
||||||
* @extends {Error}
|
|
||||||
* @param {number} code Error code.
|
|
||||||
*/
|
*/
|
||||||
const AssertionError = function(code) {
|
class AssertionError extends Error {
|
||||||
|
|
||||||
const path = VERSION.split('-')[0];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {string}
|
* @param {number} code Error code.
|
||||||
*/
|
*/
|
||||||
this.message = 'Assertion failed. See https://openlayers.org/en/' + path +
|
constructor(code) {
|
||||||
'/doc/errors/#' + code + ' for details.';
|
const path = VERSION.split('-')[0];
|
||||||
|
const message = 'Assertion failed. See https://openlayers.org/en/' + path +
|
||||||
|
'/doc/errors/#' + code + ' for details.';
|
||||||
|
|
||||||
/**
|
super(message);
|
||||||
* Error code. The meaning of the code can be found on
|
|
||||||
* {@link https://openlayers.org/en/latest/doc/errors/} (replace `latest` with
|
|
||||||
* the version found in the OpenLayers script's header comment if a version
|
|
||||||
* other than the latest is used).
|
|
||||||
* @type {number}
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
this.code = code;
|
|
||||||
|
|
||||||
this.name = 'AssertionError';
|
/**
|
||||||
|
* Error code. The meaning of the code can be found on
|
||||||
|
* https://openlayers.org/en/latest/doc/errors/ (replace `latest` with
|
||||||
|
* the version found in the OpenLayers script's header comment if a version
|
||||||
|
* other than the latest is used).
|
||||||
|
* @type {number}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.code = code;
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.name = 'AssertionError';
|
||||||
|
|
||||||
inherits(AssertionError, Error);
|
// Re-assign message, see https://github.com/Rich-Harris/buble/issues/40
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export default AssertionError;
|
export default AssertionError;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/Collection
|
* @module ol/Collection
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import AssertionError from './AssertionError.js';
|
import AssertionError from './AssertionError.js';
|
||||||
import CollectionEventType from './CollectionEventType.js';
|
import CollectionEventType from './CollectionEventType.js';
|
||||||
import BaseObject from './Object.js';
|
import BaseObject from './Object.js';
|
||||||
@@ -21,26 +20,26 @@ const Property = {
|
|||||||
* @classdesc
|
* @classdesc
|
||||||
* Events emitted by {@link module:ol/Collection~Collection} instances are instances of this
|
* Events emitted by {@link module:ol/Collection~Collection} instances are instances of this
|
||||||
* type.
|
* type.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/events/Event}
|
|
||||||
* @param {module:ol/CollectionEventType} type Type.
|
|
||||||
* @param {*=} opt_element Element.
|
|
||||||
*/
|
*/
|
||||||
export const CollectionEvent = function(type, opt_element) {
|
export class CollectionEvent extends Event {
|
||||||
|
|
||||||
Event.call(this, type);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The element that is added to or removed from the collection.
|
* @param {module:ol/CollectionEventType} type Type.
|
||||||
* @type {*}
|
* @param {*=} opt_element Element.
|
||||||
* @api
|
|
||||||
*/
|
*/
|
||||||
this.element = opt_element;
|
constructor(type, opt_element) {
|
||||||
|
super(type);
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* The element that is added to or removed from the collection.
|
||||||
|
* @type {*}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.element = opt_element;
|
||||||
|
|
||||||
inherits(CollectionEvent, Event);
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,244 +56,231 @@ inherits(CollectionEvent, Event);
|
|||||||
* Collection; they trigger events on the appropriate object, not on the
|
* Collection; they trigger events on the appropriate object, not on the
|
||||||
* Collection as a whole.
|
* Collection as a whole.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Object}
|
|
||||||
* @fires module:ol/Collection~CollectionEvent
|
|
||||||
* @param {Array.<T>=} opt_array Array.
|
|
||||||
* @param {module:ol/Collection~Options=} opt_options Collection options.
|
|
||||||
* @template T
|
* @template T
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Collection = function(opt_array, opt_options) {
|
class Collection extends BaseObject {
|
||||||
|
|
||||||
BaseObject.call(this);
|
|
||||||
|
|
||||||
const options = opt_options || {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {Array.<T>=} opt_array Array.
|
||||||
* @type {boolean}
|
* @param {module:ol/Collection~Options=} opt_options Collection options.
|
||||||
*/
|
*/
|
||||||
this.unique_ = !!options.unique;
|
constructor(opt_array, opt_options) {
|
||||||
|
|
||||||
/**
|
super();
|
||||||
* @private
|
|
||||||
* @type {!Array.<T>}
|
|
||||||
*/
|
|
||||||
this.array_ = opt_array ? opt_array : [];
|
|
||||||
|
|
||||||
if (this.unique_) {
|
const options = opt_options || {};
|
||||||
for (let i = 0, ii = this.array_.length; i < ii; ++i) {
|
|
||||||
this.assertUnique_(this.array_[i], i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateLength_();
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.unique_ = !!options.unique;
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {!Array.<T>}
|
||||||
|
*/
|
||||||
|
this.array_ = opt_array ? opt_array : [];
|
||||||
|
|
||||||
inherits(Collection, BaseObject);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all elements from the collection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.clear = function() {
|
|
||||||
while (this.getLength() > 0) {
|
|
||||||
this.pop();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add elements to the collection. This pushes each item in the provided array
|
|
||||||
* to the end of the collection.
|
|
||||||
* @param {!Array.<T>} arr Array.
|
|
||||||
* @return {module:ol/Collection.<T>} This collection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.extend = function(arr) {
|
|
||||||
for (let i = 0, ii = arr.length; i < ii; ++i) {
|
|
||||||
this.push(arr[i]);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterate over each element, calling the provided callback.
|
|
||||||
* @param {function(T, number, Array.<T>): *} f The function to call
|
|
||||||
* for every element. This function takes 3 arguments (the element, the
|
|
||||||
* index and the array). The return value is ignored.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.forEach = function(f) {
|
|
||||||
const array = this.array_;
|
|
||||||
for (let i = 0, ii = array.length; i < ii; ++i) {
|
|
||||||
f(array[i], i, array);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a reference to the underlying Array object. Warning: if the array
|
|
||||||
* is mutated, no events will be dispatched by the collection, and the
|
|
||||||
* collection's "length" property won't be in sync with the actual length
|
|
||||||
* of the array.
|
|
||||||
* @return {!Array.<T>} Array.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.getArray = function() {
|
|
||||||
return this.array_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the element at the provided index.
|
|
||||||
* @param {number} index Index.
|
|
||||||
* @return {T} Element.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.item = function(index) {
|
|
||||||
return this.array_[index];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the length of this collection.
|
|
||||||
* @return {number} The length of the array.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.getLength = function() {
|
|
||||||
return /** @type {number} */ (this.get(Property.LENGTH));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert an element at the provided index.
|
|
||||||
* @param {number} index Index.
|
|
||||||
* @param {T} elem Element.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.insertAt = function(index, elem) {
|
|
||||||
if (this.unique_) {
|
|
||||||
this.assertUnique_(elem);
|
|
||||||
}
|
|
||||||
this.array_.splice(index, 0, elem);
|
|
||||||
this.updateLength_();
|
|
||||||
this.dispatchEvent(
|
|
||||||
new CollectionEvent(CollectionEventType.ADD, elem));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the last element of the collection and return it.
|
|
||||||
* Return `undefined` if the collection is empty.
|
|
||||||
* @return {T|undefined} Element.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.pop = function() {
|
|
||||||
return this.removeAt(this.getLength() - 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert the provided element at the end of the collection.
|
|
||||||
* @param {T} elem Element.
|
|
||||||
* @return {number} New length of the collection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.push = function(elem) {
|
|
||||||
if (this.unique_) {
|
|
||||||
this.assertUnique_(elem);
|
|
||||||
}
|
|
||||||
const n = this.getLength();
|
|
||||||
this.insertAt(n, elem);
|
|
||||||
return this.getLength();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the first occurrence of an element from the collection.
|
|
||||||
* @param {T} elem Element.
|
|
||||||
* @return {T|undefined} The removed element or undefined if none found.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.remove = function(elem) {
|
|
||||||
const arr = this.array_;
|
|
||||||
for (let i = 0, ii = arr.length; i < ii; ++i) {
|
|
||||||
if (arr[i] === elem) {
|
|
||||||
return this.removeAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the element at the provided index and return it.
|
|
||||||
* Return `undefined` if the collection does not contain this index.
|
|
||||||
* @param {number} index Index.
|
|
||||||
* @return {T|undefined} Value.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.removeAt = function(index) {
|
|
||||||
const prev = this.array_[index];
|
|
||||||
this.array_.splice(index, 1);
|
|
||||||
this.updateLength_();
|
|
||||||
this.dispatchEvent(new CollectionEvent(CollectionEventType.REMOVE, prev));
|
|
||||||
return prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the element at the provided index.
|
|
||||||
* @param {number} index Index.
|
|
||||||
* @param {T} elem Element.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Collection.prototype.setAt = function(index, elem) {
|
|
||||||
const n = this.getLength();
|
|
||||||
if (index < n) {
|
|
||||||
if (this.unique_) {
|
if (this.unique_) {
|
||||||
this.assertUnique_(elem, index);
|
for (let i = 0, ii = this.array_.length; i < ii; ++i) {
|
||||||
|
this.assertUnique_(this.array_[i], i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const prev = this.array_[index];
|
|
||||||
this.array_[index] = elem;
|
this.updateLength_();
|
||||||
this.dispatchEvent(
|
|
||||||
new CollectionEvent(CollectionEventType.REMOVE, prev));
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all elements from the collection.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
clear() {
|
||||||
|
while (this.getLength() > 0) {
|
||||||
|
this.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add elements to the collection. This pushes each item in the provided array
|
||||||
|
* to the end of the collection.
|
||||||
|
* @param {!Array.<T>} arr Array.
|
||||||
|
* @return {module:ol/Collection.<T>} This collection.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
extend(arr) {
|
||||||
|
for (let i = 0, ii = arr.length; i < ii; ++i) {
|
||||||
|
this.push(arr[i]);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over each element, calling the provided callback.
|
||||||
|
* @param {function(T, number, Array.<T>): *} f The function to call
|
||||||
|
* for every element. This function takes 3 arguments (the element, the
|
||||||
|
* index and the array). The return value is ignored.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
forEach(f) {
|
||||||
|
const array = this.array_;
|
||||||
|
for (let i = 0, ii = array.length; i < ii; ++i) {
|
||||||
|
f(array[i], i, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a reference to the underlying Array object. Warning: if the array
|
||||||
|
* is mutated, no events will be dispatched by the collection, and the
|
||||||
|
* collection's "length" property won't be in sync with the actual length
|
||||||
|
* of the array.
|
||||||
|
* @return {!Array.<T>} Array.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getArray() {
|
||||||
|
return this.array_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the element at the provided index.
|
||||||
|
* @param {number} index Index.
|
||||||
|
* @return {T} Element.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
item(index) {
|
||||||
|
return this.array_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the length of this collection.
|
||||||
|
* @return {number} The length of the array.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getLength() {
|
||||||
|
return /** @type {number} */ (this.get(Property.LENGTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert an element at the provided index.
|
||||||
|
* @param {number} index Index.
|
||||||
|
* @param {T} elem Element.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
insertAt(index, elem) {
|
||||||
|
if (this.unique_) {
|
||||||
|
this.assertUnique_(elem);
|
||||||
|
}
|
||||||
|
this.array_.splice(index, 0, elem);
|
||||||
|
this.updateLength_();
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CollectionEvent(CollectionEventType.ADD, elem));
|
new CollectionEvent(CollectionEventType.ADD, elem));
|
||||||
} else {
|
|
||||||
for (let j = n; j < index; ++j) {
|
|
||||||
this.insertAt(j, undefined);
|
|
||||||
}
|
|
||||||
this.insertAt(index, elem);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the last element of the collection and return it.
|
||||||
|
* Return `undefined` if the collection is empty.
|
||||||
|
* @return {T|undefined} Element.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
pop() {
|
||||||
|
return this.removeAt(this.getLength() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* Insert the provided element at the end of the collection.
|
||||||
*/
|
* @param {T} elem Element.
|
||||||
Collection.prototype.updateLength_ = function() {
|
* @return {number} New length of the collection.
|
||||||
this.set(Property.LENGTH, this.array_.length);
|
* @api
|
||||||
};
|
*/
|
||||||
|
push(elem) {
|
||||||
|
if (this.unique_) {
|
||||||
|
this.assertUnique_(elem);
|
||||||
|
}
|
||||||
|
const n = this.getLength();
|
||||||
|
this.insertAt(n, elem);
|
||||||
|
return this.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the first occurrence of an element from the collection.
|
||||||
|
* @param {T} elem Element.
|
||||||
|
* @return {T|undefined} The removed element or undefined if none found.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
remove(elem) {
|
||||||
|
const arr = this.array_;
|
||||||
|
for (let i = 0, ii = arr.length; i < ii; ++i) {
|
||||||
|
if (arr[i] === elem) {
|
||||||
|
return this.removeAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* Remove the element at the provided index and return it.
|
||||||
* @param {T} elem Element.
|
* Return `undefined` if the collection does not contain this index.
|
||||||
* @param {number=} opt_except Optional index to ignore.
|
* @param {number} index Index.
|
||||||
*/
|
* @return {T|undefined} Value.
|
||||||
Collection.prototype.assertUnique_ = function(elem, opt_except) {
|
* @api
|
||||||
for (let i = 0, ii = this.array_.length; i < ii; ++i) {
|
*/
|
||||||
if (this.array_[i] === elem && i !== opt_except) {
|
removeAt(index) {
|
||||||
throw new AssertionError(58);
|
const prev = this.array_[index];
|
||||||
|
this.array_.splice(index, 1);
|
||||||
|
this.updateLength_();
|
||||||
|
this.dispatchEvent(new CollectionEvent(CollectionEventType.REMOVE, prev));
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the element at the provided index.
|
||||||
|
* @param {number} index Index.
|
||||||
|
* @param {T} elem Element.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setAt(index, elem) {
|
||||||
|
const n = this.getLength();
|
||||||
|
if (index < n) {
|
||||||
|
if (this.unique_) {
|
||||||
|
this.assertUnique_(elem, index);
|
||||||
|
}
|
||||||
|
const prev = this.array_[index];
|
||||||
|
this.array_[index] = elem;
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CollectionEvent(CollectionEventType.REMOVE, prev));
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CollectionEvent(CollectionEventType.ADD, elem));
|
||||||
|
} else {
|
||||||
|
for (let j = n; j < index; ++j) {
|
||||||
|
this.insertAt(j, undefined);
|
||||||
|
}
|
||||||
|
this.insertAt(index, elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
updateLength_() {
|
||||||
|
this.set(Property.LENGTH, this.array_.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param {T} elem Element.
|
||||||
|
* @param {number=} opt_except Optional index to ignore.
|
||||||
|
*/
|
||||||
|
assertUnique_(elem, opt_except) {
|
||||||
|
for (let i = 0, ii = this.array_.length; i < ii; ++i) {
|
||||||
|
if (this.array_[i] === elem && i !== opt_except) {
|
||||||
|
throw new AssertionError(58);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default Collection;
|
export default Collection;
|
||||||
|
|||||||
@@ -5,9 +5,18 @@ import {UNDEFINED} from './functions.js';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Objects that need to clean up after themselves.
|
* Objects that need to clean up after themselves.
|
||||||
* @constructor
|
|
||||||
*/
|
*/
|
||||||
const Disposable = function() {};
|
class Disposable {
|
||||||
|
/**
|
||||||
|
* Clean up.
|
||||||
|
*/
|
||||||
|
dispose() {
|
||||||
|
if (!this.disposed_) {
|
||||||
|
this.disposed_ = true;
|
||||||
|
this.disposeInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object has already been disposed.
|
* The object has already been disposed.
|
||||||
@@ -16,16 +25,6 @@ const Disposable = function() {};
|
|||||||
*/
|
*/
|
||||||
Disposable.prototype.disposed_ = false;
|
Disposable.prototype.disposed_ = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean up.
|
|
||||||
*/
|
|
||||||
Disposable.prototype.dispose = function() {
|
|
||||||
if (!this.disposed_) {
|
|
||||||
this.disposed_ = true;
|
|
||||||
this.disposeInternal();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension point for disposable objects.
|
* Extension point for disposable objects.
|
||||||
* @protected
|
* @protected
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
import {assert} from './asserts.js';
|
import {assert} from './asserts.js';
|
||||||
import {listen, unlisten, unlistenByKey} from './events.js';
|
import {listen, unlisten, unlistenByKey} from './events.js';
|
||||||
import EventType from './events/EventType.js';
|
import EventType from './events/EventType.js';
|
||||||
import {inherits} from './util.js';
|
|
||||||
import BaseObject, {getChangeEventType} from './Object.js';
|
import BaseObject, {getChangeEventType} from './Object.js';
|
||||||
import Geometry from './geom/Geometry.js';
|
import Geometry from './geom/Geometry.js';
|
||||||
import Style from './style/Style.js';
|
import Style from './style/Style.js';
|
||||||
@@ -51,235 +50,224 @@ import Style from './style/Style.js';
|
|||||||
* var point = feature.getGeometry();
|
* var point = feature.getGeometry();
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Object}
|
|
||||||
* @param {module:ol/geom/Geometry|Object.<string, *>=} opt_geometryOrProperties
|
|
||||||
* You may pass a Geometry object directly, or an object literal containing
|
|
||||||
* properties. If you pass an object literal, you may include a Geometry
|
|
||||||
* associated with a `geometry` key.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Feature = function(opt_geometryOrProperties) {
|
class Feature extends BaseObject {
|
||||||
|
|
||||||
BaseObject.call(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {module:ol/geom/Geometry|Object.<string, *>=} opt_geometryOrProperties
|
||||||
* @type {number|string|undefined}
|
* You may pass a Geometry object directly, or an object literal containing
|
||||||
|
* properties. If you pass an object literal, you may include a Geometry
|
||||||
|
* associated with a `geometry` key.
|
||||||
*/
|
*/
|
||||||
this.id_ = undefined;
|
constructor(opt_geometryOrProperties) {
|
||||||
|
|
||||||
/**
|
super();
|
||||||
* @type {string}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.geometryName_ = 'geometry';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User provided style.
|
* @private
|
||||||
* @private
|
* @type {number|string|undefined}
|
||||||
* @type {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction}
|
*/
|
||||||
*/
|
this.id_ = undefined;
|
||||||
this.style_ = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @type {string}
|
||||||
* @type {module:ol/style/Style~StyleFunction|undefined}
|
* @private
|
||||||
*/
|
*/
|
||||||
this.styleFunction_ = undefined;
|
this.geometryName_ = 'geometry';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* User provided style.
|
||||||
* @type {?module:ol/events~EventsKey}
|
* @private
|
||||||
*/
|
* @type {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction}
|
||||||
this.geometryChangeKey_ = null;
|
*/
|
||||||
|
this.style_ = null;
|
||||||
|
|
||||||
listen(
|
/**
|
||||||
this, getChangeEventType(this.geometryName_),
|
* @private
|
||||||
this.handleGeometryChanged_, this);
|
* @type {module:ol/style/Style~StyleFunction|undefined}
|
||||||
|
*/
|
||||||
|
this.styleFunction_ = undefined;
|
||||||
|
|
||||||
if (opt_geometryOrProperties !== undefined) {
|
/**
|
||||||
if (opt_geometryOrProperties instanceof Geometry ||
|
* @private
|
||||||
!opt_geometryOrProperties) {
|
* @type {?module:ol/events~EventsKey}
|
||||||
const geometry = opt_geometryOrProperties;
|
*/
|
||||||
this.setGeometry(geometry);
|
this.geometryChangeKey_ = null;
|
||||||
} else {
|
|
||||||
/** @type {Object.<string, *>} */
|
listen(
|
||||||
const properties = opt_geometryOrProperties;
|
this, getChangeEventType(this.geometryName_),
|
||||||
this.setProperties(properties);
|
this.handleGeometryChanged_, this);
|
||||||
|
|
||||||
|
if (opt_geometryOrProperties !== undefined) {
|
||||||
|
if (opt_geometryOrProperties instanceof Geometry ||
|
||||||
|
!opt_geometryOrProperties) {
|
||||||
|
const geometry = opt_geometryOrProperties;
|
||||||
|
this.setGeometry(geometry);
|
||||||
|
} else {
|
||||||
|
/** @type {Object.<string, *>} */
|
||||||
|
const properties = opt_geometryOrProperties;
|
||||||
|
this.setProperties(properties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
inherits(Feature, BaseObject);
|
/**
|
||||||
|
* Clone this feature. If the original feature has a geometry it
|
||||||
|
* is also cloned. The feature id is not set in the clone.
|
||||||
/**
|
* @return {module:ol/Feature} The clone.
|
||||||
* Clone this feature. If the original feature has a geometry it
|
* @api
|
||||||
* is also cloned. The feature id is not set in the clone.
|
*/
|
||||||
* @return {module:ol/Feature} The clone.
|
clone() {
|
||||||
* @api
|
const clone = new Feature(this.getProperties());
|
||||||
*/
|
clone.setGeometryName(this.getGeometryName());
|
||||||
Feature.prototype.clone = function() {
|
const geometry = this.getGeometry();
|
||||||
const clone = new Feature(this.getProperties());
|
if (geometry) {
|
||||||
clone.setGeometryName(this.getGeometryName());
|
clone.setGeometry(geometry.clone());
|
||||||
const geometry = this.getGeometry();
|
}
|
||||||
if (geometry) {
|
const style = this.getStyle();
|
||||||
clone.setGeometry(geometry.clone());
|
if (style) {
|
||||||
|
clone.setStyle(style);
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
}
|
}
|
||||||
const style = this.getStyle();
|
|
||||||
if (style) {
|
/**
|
||||||
clone.setStyle(style);
|
* Get the feature's default geometry. A feature may have any number of named
|
||||||
|
* geometries. The "default" geometry (the one that is rendered by default) is
|
||||||
|
* set when calling {@link module:ol/Feature~Feature#setGeometry}.
|
||||||
|
* @return {module:ol/geom/Geometry|undefined} The default geometry for the feature.
|
||||||
|
* @api
|
||||||
|
* @observable
|
||||||
|
*/
|
||||||
|
getGeometry() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/geom/Geometry|undefined} */ (this.get(this.geometryName_))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return clone;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* Get the feature identifier. This is a stable identifier for the feature and
|
||||||
* Get the feature's default geometry. A feature may have any number of named
|
* is either set when reading data from a remote source or set explicitly by
|
||||||
* geometries. The "default" geometry (the one that is rendered by default) is
|
* calling {@link module:ol/Feature~Feature#setId}.
|
||||||
* set when calling {@link module:ol/Feature~Feature#setGeometry}.
|
* @return {number|string|undefined} Id.
|
||||||
* @return {module:ol/geom/Geometry|undefined} The default geometry for the feature.
|
* @api
|
||||||
* @api
|
*/
|
||||||
* @observable
|
getId() {
|
||||||
*/
|
return this.id_;
|
||||||
Feature.prototype.getGeometry = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/geom/Geometry|undefined} */ (this.get(this.geometryName_))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the feature identifier. This is a stable identifier for the feature and
|
|
||||||
* is either set when reading data from a remote source or set explicitly by
|
|
||||||
* calling {@link module:ol/Feature~Feature#setId}.
|
|
||||||
* @return {number|string|undefined} Id.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Feature.prototype.getId = function() {
|
|
||||||
return this.id_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the feature's default geometry. By default, the default
|
|
||||||
* geometry is named `geometry`.
|
|
||||||
* @return {string} Get the property name associated with the default geometry
|
|
||||||
* for this feature.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Feature.prototype.getGeometryName = function() {
|
|
||||||
return this.geometryName_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the feature's style. Will return what was provided to the
|
|
||||||
* {@link module:ol/Feature~Feature#setStyle} method.
|
|
||||||
* @return {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction} The feature style.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Feature.prototype.getStyle = function() {
|
|
||||||
return this.style_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the feature's style function.
|
|
||||||
* @return {module:ol/style/Style~StyleFunction|undefined} Return a function
|
|
||||||
* representing the current style of this feature.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Feature.prototype.getStyleFunction = function() {
|
|
||||||
return this.styleFunction_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Feature.prototype.handleGeometryChange_ = function() {
|
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Feature.prototype.handleGeometryChanged_ = function() {
|
|
||||||
if (this.geometryChangeKey_) {
|
|
||||||
unlistenByKey(this.geometryChangeKey_);
|
|
||||||
this.geometryChangeKey_ = null;
|
|
||||||
}
|
}
|
||||||
const geometry = this.getGeometry();
|
|
||||||
if (geometry) {
|
/**
|
||||||
this.geometryChangeKey_ = listen(geometry,
|
* Get the name of the feature's default geometry. By default, the default
|
||||||
EventType.CHANGE, this.handleGeometryChange_, this);
|
* geometry is named `geometry`.
|
||||||
|
* @return {string} Get the property name associated with the default geometry
|
||||||
|
* for this feature.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getGeometryName() {
|
||||||
|
return this.geometryName_;
|
||||||
}
|
}
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the feature's style. Will return what was provided to the
|
||||||
|
* {@link module:ol/Feature~Feature#setStyle} method.
|
||||||
|
* @return {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction} The feature style.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getStyle() {
|
||||||
|
return this.style_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the default geometry for the feature. This will update the property
|
* Get the feature's style function.
|
||||||
* with the name returned by {@link module:ol/Feature~Feature#getGeometryName}.
|
* @return {module:ol/style/Style~StyleFunction|undefined} Return a function
|
||||||
* @param {module:ol/geom/Geometry|undefined} geometry The new geometry.
|
* representing the current style of this feature.
|
||||||
* @api
|
* @api
|
||||||
* @observable
|
*/
|
||||||
*/
|
getStyleFunction() {
|
||||||
Feature.prototype.setGeometry = function(geometry) {
|
return this.styleFunction_;
|
||||||
this.set(this.geometryName_, geometry);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleGeometryChange_() {
|
||||||
|
this.changed();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the style for the feature. This can be a single style object, an array
|
* @private
|
||||||
* of styles, or a function that takes a resolution and returns an array of
|
*/
|
||||||
* styles. If it is `null` the feature has no style (a `null` style).
|
handleGeometryChanged_() {
|
||||||
* @param {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction} style Style for this feature.
|
if (this.geometryChangeKey_) {
|
||||||
* @api
|
unlistenByKey(this.geometryChangeKey_);
|
||||||
* @fires module:ol/events/Event~Event#event:change
|
this.geometryChangeKey_ = null;
|
||||||
*/
|
}
|
||||||
Feature.prototype.setStyle = function(style) {
|
const geometry = this.getGeometry();
|
||||||
this.style_ = style;
|
if (geometry) {
|
||||||
this.styleFunction_ = !style ? undefined : createStyleFunction(style);
|
this.geometryChangeKey_ = listen(geometry,
|
||||||
this.changed();
|
EventType.CHANGE, this.handleGeometryChange_, this);
|
||||||
};
|
}
|
||||||
|
this.changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default geometry for the feature. This will update the property
|
||||||
|
* with the name returned by {@link module:ol/Feature~Feature#getGeometryName}.
|
||||||
|
* @param {module:ol/geom/Geometry|undefined} geometry The new geometry.
|
||||||
|
* @api
|
||||||
|
* @observable
|
||||||
|
*/
|
||||||
|
setGeometry(geometry) {
|
||||||
|
this.set(this.geometryName_, geometry);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the feature id. The feature id is considered stable and may be used when
|
* Set the style for the feature. This can be a single style object, an array
|
||||||
* requesting features or comparing identifiers returned from a remote source.
|
* of styles, or a function that takes a resolution and returns an array of
|
||||||
* The feature id can be used with the
|
* styles. If it is `null` the feature has no style (a `null` style).
|
||||||
* {@link module:ol/source/Vector~VectorSource#getFeatureById} method.
|
* @param {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction} style Style for this feature.
|
||||||
* @param {number|string|undefined} id The feature id.
|
* @api
|
||||||
* @api
|
* @fires module:ol/events/Event~Event#event:change
|
||||||
* @fires module:ol/events/Event~Event#event:change
|
*/
|
||||||
*/
|
setStyle(style) {
|
||||||
Feature.prototype.setId = function(id) {
|
this.style_ = style;
|
||||||
this.id_ = id;
|
this.styleFunction_ = !style ? undefined : createStyleFunction(style);
|
||||||
this.changed();
|
this.changed();
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the feature id. The feature id is considered stable and may be used when
|
||||||
|
* requesting features or comparing identifiers returned from a remote source.
|
||||||
|
* The feature id can be used with the
|
||||||
|
* {@link module:ol/source/Vector~VectorSource#getFeatureById} method.
|
||||||
|
* @param {number|string|undefined} id The feature id.
|
||||||
|
* @api
|
||||||
|
* @fires module:ol/events/Event~Event#event:change
|
||||||
|
*/
|
||||||
|
setId(id) {
|
||||||
|
this.id_ = id;
|
||||||
|
this.changed();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the property name to be used when getting the feature's default geometry.
|
* Set the property name to be used when getting the feature's default geometry.
|
||||||
* When calling {@link module:ol/Feature~Feature#getGeometry}, the value of the property with
|
* When calling {@link module:ol/Feature~Feature#getGeometry}, the value of the property with
|
||||||
* this name will be returned.
|
* this name will be returned.
|
||||||
* @param {string} name The property name of the default geometry.
|
* @param {string} name The property name of the default geometry.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
Feature.prototype.setGeometryName = function(name) {
|
setGeometryName(name) {
|
||||||
unlisten(
|
unlisten(
|
||||||
this, getChangeEventType(this.geometryName_),
|
this, getChangeEventType(this.geometryName_),
|
||||||
this.handleGeometryChanged_, this);
|
this.handleGeometryChanged_, this);
|
||||||
this.geometryName_ = name;
|
this.geometryName_ = name;
|
||||||
listen(
|
listen(
|
||||||
this, getChangeEventType(this.geometryName_),
|
this, getChangeEventType(this.geometryName_),
|
||||||
this.handleGeometryChanged_, this);
|
this.handleGeometryChanged_, this);
|
||||||
this.handleGeometryChanged_();
|
this.handleGeometryChanged_();
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/Geolocation
|
* @module ol/Geolocation
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import GeolocationProperty from './GeolocationProperty.js';
|
import GeolocationProperty from './GeolocationProperty.js';
|
||||||
import BaseObject, {getChangeEventType} from './Object.js';
|
import BaseObject, {getChangeEventType} from './Object.js';
|
||||||
import {listen} from './events.js';
|
import {listen} from './events.js';
|
||||||
@@ -16,8 +15,8 @@ import {get as getProjection, getTransformFromProjections, identityTransform} fr
|
|||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {boolean} [tracking=false] Start Tracking right after
|
* @property {boolean} [tracking=false] Start Tracking right after
|
||||||
* instantiation.
|
* instantiation.
|
||||||
* @property {GeolocationPositionOptions} [trackingOptions] Tracking options.
|
* @property {PositionOptions} [trackingOptions] Tracking options.
|
||||||
* See {@link http://www.w3.org/TR/geolocation-API/#position_options_interface}.
|
* See http://www.w3.org/TR/geolocation-API/#position_options_interface.
|
||||||
* @property {module:ol/proj~ProjectionLike} [projection] The projection the position
|
* @property {module:ol/proj~ProjectionLike} [projection] The projection the position
|
||||||
* is reported in.
|
* is reported in.
|
||||||
*/
|
*/
|
||||||
@@ -44,307 +43,293 @@ import {get as getProjection, getTransformFromProjections, identityTransform} fr
|
|||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* @fires error
|
* @fires error
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Object}
|
|
||||||
* @param {module:ol/Geolocation~Options=} opt_options Options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Geolocation = function(opt_options) {
|
class Geolocation extends BaseObject {
|
||||||
|
|
||||||
BaseObject.call(this);
|
|
||||||
|
|
||||||
const options = opt_options || {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The unprojected (EPSG:4326) device position.
|
* @param {module:ol/Geolocation~Options=} opt_options Options.
|
||||||
* @private
|
|
||||||
* @type {module:ol/coordinate~Coordinate}
|
|
||||||
*/
|
*/
|
||||||
this.position_ = null;
|
constructor(opt_options) {
|
||||||
|
|
||||||
/**
|
super();
|
||||||
* @private
|
|
||||||
* @type {module:ol/proj~TransformFunction}
|
|
||||||
*/
|
|
||||||
this.transform_ = identityTransform;
|
|
||||||
|
|
||||||
/**
|
const options = opt_options || {};
|
||||||
* @private
|
|
||||||
* @type {number|undefined}
|
|
||||||
*/
|
|
||||||
this.watchId_ = undefined;
|
|
||||||
|
|
||||||
listen(
|
/**
|
||||||
this, getChangeEventType(GeolocationProperty.PROJECTION),
|
* The unprojected (EPSG:4326) device position.
|
||||||
this.handleProjectionChanged_, this);
|
* @private
|
||||||
listen(
|
* @type {module:ol/coordinate~Coordinate}
|
||||||
this, getChangeEventType(GeolocationProperty.TRACKING),
|
*/
|
||||||
this.handleTrackingChanged_, this);
|
this.position_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/proj~TransformFunction}
|
||||||
|
*/
|
||||||
|
this.transform_ = identityTransform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number|undefined}
|
||||||
|
*/
|
||||||
|
this.watchId_ = undefined;
|
||||||
|
|
||||||
|
listen(
|
||||||
|
this, getChangeEventType(GeolocationProperty.PROJECTION),
|
||||||
|
this.handleProjectionChanged_, this);
|
||||||
|
listen(
|
||||||
|
this, getChangeEventType(GeolocationProperty.TRACKING),
|
||||||
|
this.handleTrackingChanged_, this);
|
||||||
|
|
||||||
|
if (options.projection !== undefined) {
|
||||||
|
this.setProjection(options.projection);
|
||||||
|
}
|
||||||
|
if (options.trackingOptions !== undefined) {
|
||||||
|
this.setTrackingOptions(options.trackingOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setTracking(options.tracking !== undefined ? options.tracking : false);
|
||||||
|
|
||||||
if (options.projection !== undefined) {
|
|
||||||
this.setProjection(options.projection);
|
|
||||||
}
|
|
||||||
if (options.trackingOptions !== undefined) {
|
|
||||||
this.setTrackingOptions(options.trackingOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setTracking(options.tracking !== undefined ? options.tracking : false);
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
disposeInternal() {
|
||||||
|
this.setTracking(false);
|
||||||
|
super.disposeInternal();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @private
|
||||||
inherits(Geolocation, BaseObject);
|
*/
|
||||||
|
handleProjectionChanged_() {
|
||||||
|
const projection = this.getProjection();
|
||||||
/**
|
if (projection) {
|
||||||
* @inheritDoc
|
this.transform_ = getTransformFromProjections(
|
||||||
*/
|
getProjection('EPSG:4326'), projection);
|
||||||
Geolocation.prototype.disposeInternal = function() {
|
if (this.position_) {
|
||||||
this.setTracking(false);
|
this.set(GeolocationProperty.POSITION, this.transform_(this.position_));
|
||||||
BaseObject.prototype.disposeInternal.call(this);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.handleProjectionChanged_ = function() {
|
|
||||||
const projection = this.getProjection();
|
|
||||||
if (projection) {
|
|
||||||
this.transform_ = getTransformFromProjections(
|
|
||||||
getProjection('EPSG:4326'), projection);
|
|
||||||
if (this.position_) {
|
|
||||||
this.set(GeolocationProperty.POSITION, this.transform_(this.position_));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @private
|
||||||
* @private
|
*/
|
||||||
*/
|
handleTrackingChanged_() {
|
||||||
Geolocation.prototype.handleTrackingChanged_ = function() {
|
if (GEOLOCATION) {
|
||||||
if (GEOLOCATION) {
|
const tracking = this.getTracking();
|
||||||
const tracking = this.getTracking();
|
if (tracking && this.watchId_ === undefined) {
|
||||||
if (tracking && this.watchId_ === undefined) {
|
this.watchId_ = navigator.geolocation.watchPosition(
|
||||||
this.watchId_ = navigator.geolocation.watchPosition(
|
this.positionChange_.bind(this),
|
||||||
this.positionChange_.bind(this),
|
this.positionError_.bind(this),
|
||||||
this.positionError_.bind(this),
|
this.getTrackingOptions());
|
||||||
this.getTrackingOptions());
|
} else if (!tracking && this.watchId_ !== undefined) {
|
||||||
} else if (!tracking && this.watchId_ !== undefined) {
|
navigator.geolocation.clearWatch(this.watchId_);
|
||||||
navigator.geolocation.clearWatch(this.watchId_);
|
this.watchId_ = undefined;
|
||||||
this.watchId_ = undefined;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @private
|
||||||
* @private
|
* @param {Position} position position event.
|
||||||
* @param {GeolocationPosition} position position event.
|
*/
|
||||||
*/
|
positionChange_(position) {
|
||||||
Geolocation.prototype.positionChange_ = function(position) {
|
const coords = position.coords;
|
||||||
const coords = position.coords;
|
this.set(GeolocationProperty.ACCURACY, coords.accuracy);
|
||||||
this.set(GeolocationProperty.ACCURACY, coords.accuracy);
|
this.set(GeolocationProperty.ALTITUDE,
|
||||||
this.set(GeolocationProperty.ALTITUDE,
|
coords.altitude === null ? undefined : coords.altitude);
|
||||||
coords.altitude === null ? undefined : coords.altitude);
|
this.set(GeolocationProperty.ALTITUDE_ACCURACY,
|
||||||
this.set(GeolocationProperty.ALTITUDE_ACCURACY,
|
coords.altitudeAccuracy === null ?
|
||||||
coords.altitudeAccuracy === null ?
|
undefined : coords.altitudeAccuracy);
|
||||||
undefined : coords.altitudeAccuracy);
|
this.set(GeolocationProperty.HEADING, coords.heading === null ?
|
||||||
this.set(GeolocationProperty.HEADING, coords.heading === null ?
|
undefined : toRadians(coords.heading));
|
||||||
undefined : toRadians(coords.heading));
|
if (!this.position_) {
|
||||||
if (!this.position_) {
|
this.position_ = [coords.longitude, coords.latitude];
|
||||||
this.position_ = [coords.longitude, coords.latitude];
|
} else {
|
||||||
} else {
|
this.position_[0] = coords.longitude;
|
||||||
this.position_[0] = coords.longitude;
|
this.position_[1] = coords.latitude;
|
||||||
this.position_[1] = coords.latitude;
|
}
|
||||||
|
const projectedPosition = this.transform_(this.position_);
|
||||||
|
this.set(GeolocationProperty.POSITION, projectedPosition);
|
||||||
|
this.set(GeolocationProperty.SPEED,
|
||||||
|
coords.speed === null ? undefined : coords.speed);
|
||||||
|
const geometry = circularPolygon(this.position_, coords.accuracy);
|
||||||
|
geometry.applyTransform(this.transform_);
|
||||||
|
this.set(GeolocationProperty.ACCURACY_GEOMETRY, geometry);
|
||||||
|
this.changed();
|
||||||
}
|
}
|
||||||
const projectedPosition = this.transform_(this.position_);
|
|
||||||
this.set(GeolocationProperty.POSITION, projectedPosition);
|
|
||||||
this.set(GeolocationProperty.SPEED,
|
|
||||||
coords.speed === null ? undefined : coords.speed);
|
|
||||||
const geometry = circularPolygon(this.position_, coords.accuracy);
|
|
||||||
geometry.applyTransform(this.transform_);
|
|
||||||
this.set(GeolocationProperty.ACCURACY_GEOMETRY, geometry);
|
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when the Geolocation returns an error.
|
* Triggered when the Geolocation returns an error.
|
||||||
* @event error
|
* @event error
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @param {GeolocationPositionError} error error object.
|
* @param {PositionError} error error object.
|
||||||
*/
|
*/
|
||||||
Geolocation.prototype.positionError_ = function(error) {
|
positionError_(error) {
|
||||||
error.type = EventType.ERROR;
|
error.type = EventType.ERROR;
|
||||||
this.setTracking(false);
|
this.setTracking(false);
|
||||||
this.dispatchEvent(/** @type {{type: string, target: undefined}} */ (error));
|
this.dispatchEvent(/** @type {{type: string, target: undefined}} */ (error));
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the accuracy of the position in meters.
|
||||||
|
* @return {number|undefined} The accuracy of the position measurement in
|
||||||
|
* meters.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getAccuracy() {
|
||||||
|
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ACCURACY));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a geometry of the position accuracy.
|
||||||
|
* @return {?module:ol/geom/Polygon} A geometry of the position accuracy.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getAccuracyGeometry() {
|
||||||
|
return (
|
||||||
|
/** @type {?module:ol/geom/Polygon} */ (this.get(GeolocationProperty.ACCURACY_GEOMETRY) || null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the altitude associated with the position.
|
||||||
|
* @return {number|undefined} The altitude of the position in meters above mean
|
||||||
|
* sea level.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getAltitude() {
|
||||||
|
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ALTITUDE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the altitude accuracy of the position.
|
||||||
|
* @return {number|undefined} The accuracy of the altitude measurement in
|
||||||
|
* meters.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getAltitudeAccuracy() {
|
||||||
|
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ALTITUDE_ACCURACY));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the heading as radians clockwise from North.
|
||||||
|
* Note: depending on the browser, the heading is only defined if the `enableHighAccuracy`
|
||||||
|
* is set to `true` in the tracking options.
|
||||||
|
* @return {number|undefined} The heading of the device in radians from north.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getHeading() {
|
||||||
|
return /** @type {number|undefined} */ (this.get(GeolocationProperty.HEADING));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position of the device.
|
||||||
|
* @return {module:ol/coordinate~Coordinate|undefined} The current position of the device reported
|
||||||
|
* in the current projection.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getPosition() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/coordinate~Coordinate|undefined} */ (this.get(GeolocationProperty.POSITION))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the projection associated with the position.
|
||||||
|
* @return {module:ol/proj/Projection|undefined} The projection the position is
|
||||||
|
* reported in.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getProjection() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/proj/Projection|undefined} */ (this.get(GeolocationProperty.PROJECTION))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the speed in meters per second.
|
||||||
|
* @return {number|undefined} The instantaneous speed of the device in meters
|
||||||
|
* per second.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getSpeed() {
|
||||||
|
return /** @type {number|undefined} */ (this.get(GeolocationProperty.SPEED));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the device location is being tracked.
|
||||||
|
* @return {boolean} The device location is being tracked.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getTracking() {
|
||||||
|
return /** @type {boolean} */ (this.get(GeolocationProperty.TRACKING));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the tracking options.
|
||||||
|
* See http://www.w3.org/TR/geolocation-API/#position-options.
|
||||||
|
* @return {PositionOptions|undefined} PositionOptions as defined by
|
||||||
|
* the [HTML5 Geolocation spec
|
||||||
|
* ](http://www.w3.org/TR/geolocation-API/#position_options_interface).
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getTrackingOptions() {
|
||||||
|
return /** @type {PositionOptions|undefined} */ (this.get(GeolocationProperty.TRACKING_OPTIONS));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the projection to use for transforming the coordinates.
|
||||||
|
* @param {module:ol/proj~ProjectionLike} projection The projection the position is
|
||||||
|
* reported in.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setProjection(projection) {
|
||||||
|
this.set(GeolocationProperty.PROJECTION, getProjection(projection));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable tracking.
|
||||||
|
* @param {boolean} tracking Enable tracking.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setTracking(tracking) {
|
||||||
|
this.set(GeolocationProperty.TRACKING, tracking);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the tracking options.
|
||||||
|
* See http://www.w3.org/TR/geolocation-API/#position-options.
|
||||||
|
* @param {PositionOptions} options PositionOptions as defined by the
|
||||||
|
* [HTML5 Geolocation spec
|
||||||
|
* ](http://www.w3.org/TR/geolocation-API/#position_options_interface).
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setTrackingOptions(options) {
|
||||||
|
this.set(GeolocationProperty.TRACKING_OPTIONS, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the accuracy of the position in meters.
|
|
||||||
* @return {number|undefined} The accuracy of the position measurement in
|
|
||||||
* meters.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getAccuracy = function() {
|
|
||||||
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ACCURACY));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a geometry of the position accuracy.
|
|
||||||
* @return {?module:ol/geom/Polygon} A geometry of the position accuracy.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getAccuracyGeometry = function() {
|
|
||||||
return (
|
|
||||||
/** @type {?module:ol/geom/Polygon} */ (this.get(GeolocationProperty.ACCURACY_GEOMETRY) || null)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the altitude associated with the position.
|
|
||||||
* @return {number|undefined} The altitude of the position in meters above mean
|
|
||||||
* sea level.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getAltitude = function() {
|
|
||||||
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ALTITUDE));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the altitude accuracy of the position.
|
|
||||||
* @return {number|undefined} The accuracy of the altitude measurement in
|
|
||||||
* meters.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getAltitudeAccuracy = function() {
|
|
||||||
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ALTITUDE_ACCURACY));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the heading as radians clockwise from North.
|
|
||||||
* Note: depending on the browser, the heading is only defined if the `enableHighAccuracy`
|
|
||||||
* is set to `true` in the tracking options.
|
|
||||||
* @return {number|undefined} The heading of the device in radians from north.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getHeading = function() {
|
|
||||||
return /** @type {number|undefined} */ (this.get(GeolocationProperty.HEADING));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the position of the device.
|
|
||||||
* @return {module:ol/coordinate~Coordinate|undefined} The current position of the device reported
|
|
||||||
* in the current projection.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getPosition = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/coordinate~Coordinate|undefined} */ (this.get(GeolocationProperty.POSITION))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the projection associated with the position.
|
|
||||||
* @return {module:ol/proj/Projection|undefined} The projection the position is
|
|
||||||
* reported in.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getProjection = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/proj/Projection|undefined} */ (this.get(GeolocationProperty.PROJECTION))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the speed in meters per second.
|
|
||||||
* @return {number|undefined} The instantaneous speed of the device in meters
|
|
||||||
* per second.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getSpeed = function() {
|
|
||||||
return /** @type {number|undefined} */ (this.get(GeolocationProperty.SPEED));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the device location is being tracked.
|
|
||||||
* @return {boolean} The device location is being tracked.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getTracking = function() {
|
|
||||||
return /** @type {boolean} */ (this.get(GeolocationProperty.TRACKING));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the tracking options.
|
|
||||||
* @see http://www.w3.org/TR/geolocation-API/#position-options
|
|
||||||
* @return {GeolocationPositionOptions|undefined} PositionOptions as defined by
|
|
||||||
* the [HTML5 Geolocation spec
|
|
||||||
* ](http://www.w3.org/TR/geolocation-API/#position_options_interface).
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.getTrackingOptions = function() {
|
|
||||||
return /** @type {GeolocationPositionOptions|undefined} */ (this.get(GeolocationProperty.TRACKING_OPTIONS));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the projection to use for transforming the coordinates.
|
|
||||||
* @param {module:ol/proj~ProjectionLike} projection The projection the position is
|
|
||||||
* reported in.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.setProjection = function(projection) {
|
|
||||||
this.set(GeolocationProperty.PROJECTION, getProjection(projection));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable or disable tracking.
|
|
||||||
* @param {boolean} tracking Enable tracking.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.setTracking = function(tracking) {
|
|
||||||
this.set(GeolocationProperty.TRACKING, tracking);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the tracking options.
|
|
||||||
* @see http://www.w3.org/TR/geolocation-API/#position-options
|
|
||||||
* @param {GeolocationPositionOptions} options PositionOptions as defined by the
|
|
||||||
* [HTML5 Geolocation spec
|
|
||||||
* ](http://www.w3.org/TR/geolocation-API/#position_options_interface).
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Geolocation.prototype.setTrackingOptions = function(options) {
|
|
||||||
this.set(GeolocationProperty.TRACKING_OPTIONS, options);
|
|
||||||
};
|
|
||||||
export default Geolocation;
|
export default Geolocation;
|
||||||
|
|||||||
1174
src/ol/Graticule.js
1174
src/ol/Graticule.js
File diff suppressed because it is too large
Load Diff
217
src/ol/Image.js
217
src/ol/Image.js
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/Image
|
* @module ol/Image
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import ImageBase from './ImageBase.js';
|
import ImageBase from './ImageBase.js';
|
||||||
import ImageState from './ImageState.js';
|
import ImageState from './ImageState.js';
|
||||||
import {listenOnce, unlistenByKey} from './events.js';
|
import {listenOnce, unlistenByKey} from './events.js';
|
||||||
@@ -28,132 +27,126 @@ import {getHeight} from './extent.js';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
class ImageWrapper extends ImageBase {
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/ImageBase}
|
|
||||||
* @param {module:ol/extent~Extent} extent Extent.
|
|
||||||
* @param {number|undefined} resolution Resolution.
|
|
||||||
* @param {number} pixelRatio Pixel ratio.
|
|
||||||
* @param {string} src Image source URI.
|
|
||||||
* @param {?string} crossOrigin Cross origin.
|
|
||||||
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
|
|
||||||
*/
|
|
||||||
const ImageWrapper = function(extent, resolution, pixelRatio, src, crossOrigin, imageLoadFunction) {
|
|
||||||
|
|
||||||
ImageBase.call(this, extent, resolution, pixelRatio, ImageState.IDLE);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {module:ol/extent~Extent} extent Extent.
|
||||||
* @type {string}
|
* @param {number|undefined} resolution Resolution.
|
||||||
|
* @param {number} pixelRatio Pixel ratio.
|
||||||
|
* @param {string} src Image source URI.
|
||||||
|
* @param {?string} crossOrigin Cross origin.
|
||||||
|
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
|
||||||
*/
|
*/
|
||||||
this.src_ = src;
|
constructor(extent, resolution, pixelRatio, src, crossOrigin, imageLoadFunction) {
|
||||||
|
|
||||||
|
super(extent, resolution, pixelRatio, ImageState.IDLE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.src_ = src;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement}
|
||||||
|
*/
|
||||||
|
this.image_ = new Image();
|
||||||
|
if (crossOrigin !== null) {
|
||||||
|
this.image_.crossOrigin = crossOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Array.<module:ol/events~EventsKey>}
|
||||||
|
*/
|
||||||
|
this.imageListenerKeys_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {module:ol/ImageState}
|
||||||
|
*/
|
||||||
|
this.state = ImageState.IDLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/Image~LoadFunction}
|
||||||
|
*/
|
||||||
|
this.imageLoadFunction_ = imageLoadFunction;
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {HTMLCanvasElement|Image|HTMLVideoElement}
|
|
||||||
*/
|
|
||||||
this.image_ = new Image();
|
|
||||||
if (crossOrigin !== null) {
|
|
||||||
this.image_.crossOrigin = crossOrigin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @inheritDoc
|
||||||
* @type {Array.<module:ol/events~EventsKey>}
|
* @api
|
||||||
*/
|
*/
|
||||||
this.imageListenerKeys_ = null;
|
getImage() {
|
||||||
|
return this.image_;
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
* @type {module:ol/ImageState}
|
|
||||||
*/
|
|
||||||
this.state = ImageState.IDLE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {module:ol/Image~LoadFunction}
|
|
||||||
*/
|
|
||||||
this.imageLoadFunction_ = imageLoadFunction;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(ImageWrapper, ImageBase);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
ImageWrapper.prototype.getImage = function() {
|
|
||||||
return this.image_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks loading or read errors.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ImageWrapper.prototype.handleImageError_ = function() {
|
|
||||||
this.state = ImageState.ERROR;
|
|
||||||
this.unlistenImage_();
|
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks successful image load.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ImageWrapper.prototype.handleImageLoad_ = function() {
|
|
||||||
if (this.resolution === undefined) {
|
|
||||||
this.resolution = getHeight(this.extent) / this.image_.height;
|
|
||||||
}
|
}
|
||||||
this.state = ImageState.LOADED;
|
|
||||||
this.unlistenImage_();
|
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* Tracks loading or read errors.
|
||||||
* Load the image or retry if loading previously failed.
|
*
|
||||||
* Loading is taken care of by the tile queue, and calling this method is
|
* @private
|
||||||
* only needed for preloading or for reloading in case of an error.
|
*/
|
||||||
* @override
|
handleImageError_() {
|
||||||
* @api
|
this.state = ImageState.ERROR;
|
||||||
*/
|
this.unlistenImage_();
|
||||||
ImageWrapper.prototype.load = function() {
|
|
||||||
if (this.state == ImageState.IDLE || this.state == ImageState.ERROR) {
|
|
||||||
this.state = ImageState.LOADING;
|
|
||||||
this.changed();
|
this.changed();
|
||||||
this.imageListenerKeys_ = [
|
|
||||||
listenOnce(this.image_, EventType.ERROR,
|
|
||||||
this.handleImageError_, this),
|
|
||||||
listenOnce(this.image_, EventType.LOAD,
|
|
||||||
this.handleImageLoad_, this)
|
|
||||||
];
|
|
||||||
this.imageLoadFunction_(this, this.src_);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks successful image load.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleImageLoad_() {
|
||||||
|
if (this.resolution === undefined) {
|
||||||
|
this.resolution = getHeight(this.extent) / this.image_.height;
|
||||||
|
}
|
||||||
|
this.state = ImageState.LOADED;
|
||||||
|
this.unlistenImage_();
|
||||||
|
this.changed();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {HTMLCanvasElement|Image|HTMLVideoElement} image Image.
|
* Load the image or retry if loading previously failed.
|
||||||
*/
|
* Loading is taken care of by the tile queue, and calling this method is
|
||||||
ImageWrapper.prototype.setImage = function(image) {
|
* only needed for preloading or for reloading in case of an error.
|
||||||
this.image_ = image;
|
* @override
|
||||||
};
|
* @api
|
||||||
|
*/
|
||||||
|
load() {
|
||||||
|
if (this.state == ImageState.IDLE || this.state == ImageState.ERROR) {
|
||||||
|
this.state = ImageState.LOADING;
|
||||||
|
this.changed();
|
||||||
|
this.imageListenerKeys_ = [
|
||||||
|
listenOnce(this.image_, EventType.ERROR,
|
||||||
|
this.handleImageError_, this),
|
||||||
|
listenOnce(this.image_, EventType.LOAD,
|
||||||
|
this.handleImageLoad_, this)
|
||||||
|
];
|
||||||
|
this.imageLoadFunction_(this, this.src_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image.
|
||||||
|
*/
|
||||||
|
setImage(image) {
|
||||||
|
this.image_ = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discards event handlers which listen for load completion or errors.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
unlistenImage_() {
|
||||||
|
this.imageListenerKeys_.forEach(unlistenByKey);
|
||||||
|
this.imageListenerKeys_ = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Discards event handlers which listen for load completion or errors.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ImageWrapper.prototype.unlistenImage_ = function() {
|
|
||||||
this.imageListenerKeys_.forEach(unlistenByKey);
|
|
||||||
this.imageListenerKeys_ = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ImageWrapper;
|
export default ImageWrapper;
|
||||||
|
|||||||
@@ -1,103 +1,97 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/ImageBase
|
* @module ol/ImageBase
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import EventTarget from './events/EventTarget.js';
|
import EventTarget from './events/EventTarget.js';
|
||||||
import EventType from './events/EventType.js';
|
import EventType from './events/EventType.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @extends {module:ol/events/EventTarget}
|
|
||||||
* @param {module:ol/extent~Extent} extent Extent.
|
|
||||||
* @param {number|undefined} resolution Resolution.
|
|
||||||
* @param {number} pixelRatio Pixel ratio.
|
|
||||||
* @param {module:ol/ImageState} state State.
|
|
||||||
*/
|
*/
|
||||||
const ImageBase = function(extent, resolution, pixelRatio, state) {
|
class ImageBase extends EventTarget {
|
||||||
|
|
||||||
EventTarget.call(this);
|
/**
|
||||||
|
* @param {module:ol/extent~Extent} extent Extent.
|
||||||
|
* @param {number|undefined} resolution Resolution.
|
||||||
|
* @param {number} pixelRatio Pixel ratio.
|
||||||
|
* @param {module:ol/ImageState} state State.
|
||||||
|
*/
|
||||||
|
constructor(extent, resolution, pixelRatio, state) {
|
||||||
|
|
||||||
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {module:ol/extent~Extent}
|
||||||
|
*/
|
||||||
|
this.extent = extent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.pixelRatio_ = pixelRatio;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {number|undefined}
|
||||||
|
*/
|
||||||
|
this.resolution = resolution;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {module:ol/ImageState}
|
||||||
|
*/
|
||||||
|
this.state = state;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {module:ol/extent~Extent}
|
|
||||||
*/
|
*/
|
||||||
this.extent = extent;
|
changed() {
|
||||||
|
this.dispatchEvent(EventType.CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @return {module:ol/extent~Extent} Extent.
|
||||||
* @type {number}
|
|
||||||
*/
|
*/
|
||||||
this.pixelRatio_ = pixelRatio;
|
getExtent() {
|
||||||
|
return this.extent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @abstract
|
||||||
* @type {number|undefined}
|
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
||||||
*/
|
*/
|
||||||
this.resolution = resolution;
|
getImage() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @return {number} PixelRatio.
|
||||||
* @type {module:ol/ImageState}
|
|
||||||
*/
|
*/
|
||||||
this.state = state;
|
getPixelRatio() {
|
||||||
|
return this.pixelRatio_;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @return {number} Resolution.
|
||||||
|
*/
|
||||||
|
getResolution() {
|
||||||
|
return /** @type {number} */ (this.resolution);
|
||||||
|
}
|
||||||
|
|
||||||
inherits(ImageBase, EventTarget);
|
/**
|
||||||
|
* @return {module:ol/ImageState} State.
|
||||||
|
*/
|
||||||
|
getState() {
|
||||||
|
return this.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load not yet loaded URI.
|
||||||
|
* @abstract
|
||||||
|
*/
|
||||||
|
load() {}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
ImageBase.prototype.changed = function() {
|
|
||||||
this.dispatchEvent(EventType.CHANGE);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {module:ol/extent~Extent} Extent.
|
|
||||||
*/
|
|
||||||
ImageBase.prototype.getExtent = function() {
|
|
||||||
return this.extent;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @return {HTMLCanvasElement|Image|HTMLVideoElement} Image.
|
|
||||||
*/
|
|
||||||
ImageBase.prototype.getImage = function() {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {number} PixelRatio.
|
|
||||||
*/
|
|
||||||
ImageBase.prototype.getPixelRatio = function() {
|
|
||||||
return this.pixelRatio_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {number} Resolution.
|
|
||||||
*/
|
|
||||||
ImageBase.prototype.getResolution = function() {
|
|
||||||
return /** @type {number} */ (this.resolution);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {module:ol/ImageState} State.
|
|
||||||
*/
|
|
||||||
ImageBase.prototype.getState = function() {
|
|
||||||
return this.state;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load not yet loaded URI.
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
ImageBase.prototype.load = function() {};
|
|
||||||
|
|
||||||
export default ImageBase;
|
export default ImageBase;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/ImageCanvas
|
* @module ol/ImageCanvas
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import ImageBase from './ImageBase.js';
|
import ImageBase from './ImageBase.js';
|
||||||
import ImageState from './ImageState.js';
|
import ImageState from './ImageState.js';
|
||||||
|
|
||||||
@@ -16,87 +15,84 @@ import ImageState from './ImageState.js';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
class ImageCanvas extends ImageBase {
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/ImageBase}
|
|
||||||
* @param {module:ol/extent~Extent} extent Extent.
|
|
||||||
* @param {number} resolution Resolution.
|
|
||||||
* @param {number} pixelRatio Pixel ratio.
|
|
||||||
* @param {HTMLCanvasElement} canvas Canvas.
|
|
||||||
* @param {module:ol/ImageCanvas~Loader=} opt_loader Optional loader function to
|
|
||||||
* support asynchronous canvas drawing.
|
|
||||||
*/
|
|
||||||
const ImageCanvas = function(extent, resolution, pixelRatio, canvas, opt_loader) {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional canvas loader function.
|
* @param {module:ol/extent~Extent} extent Extent.
|
||||||
* @type {?module:ol/ImageCanvas~Loader}
|
* @param {number} resolution Resolution.
|
||||||
* @private
|
* @param {number} pixelRatio Pixel ratio.
|
||||||
|
* @param {HTMLCanvasElement} canvas Canvas.
|
||||||
|
* @param {module:ol/ImageCanvas~Loader=} opt_loader Optional loader function to
|
||||||
|
* support asynchronous canvas drawing.
|
||||||
*/
|
*/
|
||||||
this.loader_ = opt_loader !== undefined ? opt_loader : null;
|
constructor(extent, resolution, pixelRatio, canvas, opt_loader) {
|
||||||
|
|
||||||
const state = opt_loader !== undefined ? ImageState.IDLE : ImageState.LOADED;
|
const state = opt_loader !== undefined ? ImageState.IDLE : ImageState.LOADED;
|
||||||
|
|
||||||
ImageBase.call(this, extent, resolution, pixelRatio, state);
|
super(extent, resolution, pixelRatio, state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* Optional canvas loader function.
|
||||||
* @type {HTMLCanvasElement}
|
* @type {?module:ol/ImageCanvas~Loader}
|
||||||
*/
|
* @private
|
||||||
this.canvas_ = canvas;
|
*/
|
||||||
|
this.loader_ = opt_loader !== undefined ? opt_loader : null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {Error}
|
* @type {HTMLCanvasElement}
|
||||||
*/
|
*/
|
||||||
this.error_ = null;
|
this.canvas_ = canvas;
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Error}
|
||||||
|
*/
|
||||||
|
this.error_ = null;
|
||||||
|
|
||||||
inherits(ImageCanvas, ImageBase);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get any error associated with asynchronous rendering.
|
|
||||||
* @return {Error} Any error that occurred during rendering.
|
|
||||||
*/
|
|
||||||
ImageCanvas.prototype.getError = function() {
|
|
||||||
return this.error_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle async drawing complete.
|
|
||||||
* @param {Error} err Any error during drawing.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ImageCanvas.prototype.handleLoad_ = function(err) {
|
|
||||||
if (err) {
|
|
||||||
this.error_ = err;
|
|
||||||
this.state = ImageState.ERROR;
|
|
||||||
} else {
|
|
||||||
this.state = ImageState.LOADED;
|
|
||||||
}
|
}
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get any error associated with asynchronous rendering.
|
||||||
|
* @return {Error} Any error that occurred during rendering.
|
||||||
|
*/
|
||||||
|
getError() {
|
||||||
|
return this.error_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* Handle async drawing complete.
|
||||||
*/
|
* @param {Error} err Any error during drawing.
|
||||||
ImageCanvas.prototype.load = function() {
|
* @private
|
||||||
if (this.state == ImageState.IDLE) {
|
*/
|
||||||
this.state = ImageState.LOADING;
|
handleLoad_(err) {
|
||||||
|
if (err) {
|
||||||
|
this.error_ = err;
|
||||||
|
this.state = ImageState.ERROR;
|
||||||
|
} else {
|
||||||
|
this.state = ImageState.LOADED;
|
||||||
|
}
|
||||||
this.changed();
|
this.changed();
|
||||||
this.loader_(this.handleLoad_.bind(this));
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
load() {
|
||||||
|
if (this.state == ImageState.IDLE) {
|
||||||
|
this.state = ImageState.LOADING;
|
||||||
|
this.changed();
|
||||||
|
this.loader_(this.handleLoad_.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {HTMLCanvasElement} Canvas element.
|
||||||
|
*/
|
||||||
|
getImage() {
|
||||||
|
return this.canvas_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {HTMLCanvasElement} Canvas element.
|
|
||||||
*/
|
|
||||||
ImageCanvas.prototype.getImage = function() {
|
|
||||||
return this.canvas_;
|
|
||||||
};
|
|
||||||
export default ImageCanvas;
|
export default ImageCanvas;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/ImageTile
|
* @module ol/ImageTile
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import Tile from './Tile.js';
|
import Tile from './Tile.js';
|
||||||
import TileState from './TileState.js';
|
import TileState from './TileState.js';
|
||||||
import {createCanvasContext2D} from './dom.js';
|
import {createCanvasContext2D} from './dom.js';
|
||||||
@@ -14,159 +13,151 @@ import EventType from './events/EventType.js';
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
class ImageTile extends Tile {
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Tile}
|
|
||||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
|
||||||
* @param {module:ol/TileState} state State.
|
|
||||||
* @param {string} src Image source URI.
|
|
||||||
* @param {?string} crossOrigin Cross origin.
|
|
||||||
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
|
|
||||||
* @param {module:ol/Tile~Options=} opt_options Tile options.
|
|
||||||
*/
|
|
||||||
const ImageTile = function(tileCoord, state, src, crossOrigin, tileLoadFunction, opt_options) {
|
|
||||||
|
|
||||||
Tile.call(this, tileCoord, state, opt_options);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||||
* @type {?string}
|
* @param {module:ol/TileState} state State.
|
||||||
|
* @param {string} src Image source URI.
|
||||||
|
* @param {?string} crossOrigin Cross origin.
|
||||||
|
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
|
||||||
|
* @param {module:ol/Tile~Options=} opt_options Tile options.
|
||||||
*/
|
*/
|
||||||
this.crossOrigin_ = crossOrigin;
|
constructor(tileCoord, state, src, crossOrigin, tileLoadFunction, opt_options) {
|
||||||
|
|
||||||
|
super(tileCoord, state, opt_options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {?string}
|
||||||
|
*/
|
||||||
|
this.crossOrigin_ = crossOrigin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image URI
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.src_ = src;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {HTMLImageElement|HTMLCanvasElement}
|
||||||
|
*/
|
||||||
|
this.image_ = new Image();
|
||||||
|
if (crossOrigin !== null) {
|
||||||
|
this.image_.crossOrigin = crossOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Array.<module:ol/events~EventsKey>}
|
||||||
|
*/
|
||||||
|
this.imageListenerKeys_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/Tile~LoadFunction}
|
||||||
|
*/
|
||||||
|
this.tileLoadFunction_ = tileLoadFunction;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image URI
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
disposeInternal() {
|
||||||
|
if (this.state == TileState.LOADING) {
|
||||||
|
this.unlistenImage_();
|
||||||
|
this.image_ = getBlankImage();
|
||||||
|
}
|
||||||
|
if (this.interimTile) {
|
||||||
|
this.interimTile.dispose();
|
||||||
|
}
|
||||||
|
this.state = TileState.ABORT;
|
||||||
|
this.changed();
|
||||||
|
super.disposeInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the HTML image element for this tile (may be a Canvas, Image, or Video).
|
||||||
|
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getImage() {
|
||||||
|
return this.image_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
getKey() {
|
||||||
|
return this.src_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks loading or read errors.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {string}
|
|
||||||
*/
|
*/
|
||||||
this.src_ = src;
|
handleImageError_() {
|
||||||
|
this.state = TileState.ERROR;
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Image|HTMLCanvasElement}
|
|
||||||
*/
|
|
||||||
this.image_ = new Image();
|
|
||||||
if (crossOrigin !== null) {
|
|
||||||
this.image_.crossOrigin = crossOrigin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Array.<module:ol/events~EventsKey>}
|
|
||||||
*/
|
|
||||||
this.imageListenerKeys_ = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {module:ol/Tile~LoadFunction}
|
|
||||||
*/
|
|
||||||
this.tileLoadFunction_ = tileLoadFunction;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(ImageTile, Tile);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
ImageTile.prototype.disposeInternal = function() {
|
|
||||||
if (this.state == TileState.LOADING) {
|
|
||||||
this.unlistenImage_();
|
this.unlistenImage_();
|
||||||
this.image_ = getBlankImage();
|
this.image_ = getBlankImage();
|
||||||
|
this.changed();
|
||||||
}
|
}
|
||||||
if (this.interimTile) {
|
|
||||||
this.interimTile.dispose();
|
/**
|
||||||
|
* Tracks successful image load.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleImageLoad_() {
|
||||||
|
if (this.image_.naturalWidth && this.image_.naturalHeight) {
|
||||||
|
this.state = TileState.LOADED;
|
||||||
|
} else {
|
||||||
|
this.state = TileState.EMPTY;
|
||||||
|
}
|
||||||
|
this.unlistenImage_();
|
||||||
|
this.changed();
|
||||||
}
|
}
|
||||||
this.state = TileState.ABORT;
|
|
||||||
this.changed();
|
|
||||||
Tile.prototype.disposeInternal.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @inheritDoc
|
||||||
* Get the HTML image element for this tile (may be a Canvas, Image, or Video).
|
* @api
|
||||||
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
*/
|
||||||
* @api
|
load() {
|
||||||
*/
|
if (this.state == TileState.ERROR) {
|
||||||
ImageTile.prototype.getImage = function() {
|
this.state = TileState.IDLE;
|
||||||
return this.image_;
|
this.image_ = new Image();
|
||||||
};
|
if (this.crossOrigin_ !== null) {
|
||||||
|
this.image_.crossOrigin = this.crossOrigin_;
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* @inheritDoc
|
if (this.state == TileState.IDLE) {
|
||||||
*/
|
this.state = TileState.LOADING;
|
||||||
ImageTile.prototype.getKey = function() {
|
this.changed();
|
||||||
return this.src_;
|
this.imageListenerKeys_ = [
|
||||||
};
|
listenOnce(this.image_, EventType.ERROR,
|
||||||
|
this.handleImageError_, this),
|
||||||
|
listenOnce(this.image_, EventType.LOAD,
|
||||||
/**
|
this.handleImageLoad_, this)
|
||||||
* Tracks loading or read errors.
|
];
|
||||||
*
|
this.tileLoadFunction_(this, this.src_);
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ImageTile.prototype.handleImageError_ = function() {
|
|
||||||
this.state = TileState.ERROR;
|
|
||||||
this.unlistenImage_();
|
|
||||||
this.image_ = getBlankImage();
|
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks successful image load.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ImageTile.prototype.handleImageLoad_ = function() {
|
|
||||||
if (this.image_.naturalWidth && this.image_.naturalHeight) {
|
|
||||||
this.state = TileState.LOADED;
|
|
||||||
} else {
|
|
||||||
this.state = TileState.EMPTY;
|
|
||||||
}
|
|
||||||
this.unlistenImage_();
|
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
ImageTile.prototype.load = function() {
|
|
||||||
if (this.state == TileState.ERROR) {
|
|
||||||
this.state = TileState.IDLE;
|
|
||||||
this.image_ = new Image();
|
|
||||||
if (this.crossOrigin_ !== null) {
|
|
||||||
this.image_.crossOrigin = this.crossOrigin_;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.state == TileState.IDLE) {
|
|
||||||
this.state = TileState.LOADING;
|
/**
|
||||||
this.changed();
|
* Discards event handlers which listen for load completion or errors.
|
||||||
this.imageListenerKeys_ = [
|
*
|
||||||
listenOnce(this.image_, EventType.ERROR,
|
* @private
|
||||||
this.handleImageError_, this),
|
*/
|
||||||
listenOnce(this.image_, EventType.LOAD,
|
unlistenImage_() {
|
||||||
this.handleImageLoad_, this)
|
this.imageListenerKeys_.forEach(unlistenByKey);
|
||||||
];
|
this.imageListenerKeys_ = null;
|
||||||
this.tileLoadFunction_(this, this.src_);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Discards event handlers which listen for load completion or errors.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ImageTile.prototype.unlistenImage_ = function() {
|
|
||||||
this.imageListenerKeys_.forEach(unlistenByKey);
|
|
||||||
this.imageListenerKeys_ = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,124 +6,123 @@
|
|||||||
* @classdesc
|
* @classdesc
|
||||||
* Implementation of inertial deceleration for map movement.
|
* Implementation of inertial deceleration for map movement.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @param {number} decay Rate of decay (must be negative).
|
|
||||||
* @param {number} minVelocity Minimum velocity (pixels/millisecond).
|
|
||||||
* @param {number} delay Delay to consider to calculate the kinetic
|
|
||||||
* initial values (milliseconds).
|
|
||||||
* @struct
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Kinetic = function(decay, minVelocity, delay) {
|
class Kinetic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {number} decay Rate of decay (must be negative).
|
||||||
* @type {number}
|
* @param {number} minVelocity Minimum velocity (pixels/millisecond).
|
||||||
|
* @param {number} delay Delay to consider to calculate the kinetic
|
||||||
|
* initial values (milliseconds).
|
||||||
*/
|
*/
|
||||||
this.decay_ = decay;
|
constructor(decay, minVelocity, delay) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.minVelocity_ = minVelocity;
|
this.decay_ = decay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.delay_ = delay;
|
this.minVelocity_ = minVelocity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {Array.<number>}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.points_ = [];
|
this.delay_ = delay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {number}
|
* @type {Array.<number>}
|
||||||
*/
|
*/
|
||||||
this.angle_ = 0;
|
this.points_ = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.initialVelocity_ = 0;
|
this.angle_ = 0;
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @private
|
||||||
* FIXME empty description for jsdoc
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
Kinetic.prototype.begin = function() {
|
this.initialVelocity_ = 0;
|
||||||
this.points_.length = 0;
|
|
||||||
this.angle_ = 0;
|
|
||||||
this.initialVelocity_ = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} x X.
|
|
||||||
* @param {number} y Y.
|
|
||||||
*/
|
|
||||||
Kinetic.prototype.update = function(x, y) {
|
|
||||||
this.points_.push(x, y, Date.now());
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {boolean} Whether we should do kinetic animation.
|
|
||||||
*/
|
|
||||||
Kinetic.prototype.end = function() {
|
|
||||||
if (this.points_.length < 6) {
|
|
||||||
// at least 2 points are required (i.e. there must be at least 6 elements
|
|
||||||
// in the array)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const delay = Date.now() - this.delay_;
|
|
||||||
const lastIndex = this.points_.length - 3;
|
|
||||||
if (this.points_[lastIndex + 2] < delay) {
|
|
||||||
// the last tracked point is too old, which means that the user stopped
|
|
||||||
// panning before releasing the map
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the first point which still falls into the delay time
|
/**
|
||||||
let firstIndex = lastIndex - 3;
|
* FIXME empty description for jsdoc
|
||||||
while (firstIndex > 0 && this.points_[firstIndex + 2] > delay) {
|
*/
|
||||||
firstIndex -= 3;
|
begin() {
|
||||||
|
this.points_.length = 0;
|
||||||
|
this.angle_ = 0;
|
||||||
|
this.initialVelocity_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const duration = this.points_[lastIndex + 2] - this.points_[firstIndex + 2];
|
/**
|
||||||
// we don't want a duration of 0 (divide by zero)
|
* @param {number} x X.
|
||||||
// we also make sure the user panned for a duration of at least one frame
|
* @param {number} y Y.
|
||||||
// (1/60s) to compute sane displacement values
|
*/
|
||||||
if (duration < 1000 / 60) {
|
update(x, y) {
|
||||||
return false;
|
this.points_.push(x, y, Date.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
const dx = this.points_[lastIndex] - this.points_[firstIndex];
|
/**
|
||||||
const dy = this.points_[lastIndex + 1] - this.points_[firstIndex + 1];
|
* @return {boolean} Whether we should do kinetic animation.
|
||||||
this.angle_ = Math.atan2(dy, dx);
|
*/
|
||||||
this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration;
|
end() {
|
||||||
return this.initialVelocity_ > this.minVelocity_;
|
if (this.points_.length < 6) {
|
||||||
};
|
// at least 2 points are required (i.e. there must be at least 6 elements
|
||||||
|
// in the array)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const delay = Date.now() - this.delay_;
|
||||||
|
const lastIndex = this.points_.length - 3;
|
||||||
|
if (this.points_[lastIndex + 2] < delay) {
|
||||||
|
// the last tracked point is too old, which means that the user stopped
|
||||||
|
// panning before releasing the map
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the first point which still falls into the delay time
|
||||||
|
let firstIndex = lastIndex - 3;
|
||||||
|
while (firstIndex > 0 && this.points_[firstIndex + 2] > delay) {
|
||||||
|
firstIndex -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
const duration = this.points_[lastIndex + 2] - this.points_[firstIndex + 2];
|
||||||
* @return {number} Total distance travelled (pixels).
|
// we don't want a duration of 0 (divide by zero)
|
||||||
*/
|
// we also make sure the user panned for a duration of at least one frame
|
||||||
Kinetic.prototype.getDistance = function() {
|
// (1/60s) to compute sane displacement values
|
||||||
return (this.minVelocity_ - this.initialVelocity_) / this.decay_;
|
if (duration < 1000 / 60) {
|
||||||
};
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dx = this.points_[lastIndex] - this.points_[firstIndex];
|
||||||
|
const dy = this.points_[lastIndex + 1] - this.points_[firstIndex + 1];
|
||||||
|
this.angle_ = Math.atan2(dy, dx);
|
||||||
|
this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration;
|
||||||
|
return this.initialVelocity_ > this.minVelocity_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {number} Total distance travelled (pixels).
|
||||||
|
*/
|
||||||
|
getDistance() {
|
||||||
|
return (this.minVelocity_ - this.initialVelocity_) / this.decay_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {number} Angle of the kinetic panning animation (radians).
|
||||||
|
*/
|
||||||
|
getAngle() {
|
||||||
|
return this.angle_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {number} Angle of the kinetic panning animation (radians).
|
|
||||||
*/
|
|
||||||
Kinetic.prototype.getAngle = function() {
|
|
||||||
return this.angle_;
|
|
||||||
};
|
|
||||||
export default Kinetic;
|
export default Kinetic;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/Map
|
* @module ol/Map
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import PluggableMap from './PluggableMap.js';
|
import PluggableMap from './PluggableMap.js';
|
||||||
import {defaults as defaultControls} from './control/util.js';
|
import {defaults as defaultControls} from './control/util.js';
|
||||||
import {defaults as defaultInteractions} from './interaction.js';
|
import {defaults as defaultInteractions} from './interaction.js';
|
||||||
@@ -57,38 +56,40 @@ import CanvasVectorTileLayerRenderer from './renderer/canvas/VectorTileLayer.js'
|
|||||||
* options or added with `addLayer` can be groups, which can contain further
|
* options or added with `addLayer` can be groups, which can contain further
|
||||||
* groups, and so on.
|
* groups, and so on.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/PluggableMap}
|
|
||||||
* @param {module:ol/PluggableMap~MapOptions} options Map options.
|
|
||||||
* @fires module:ol/MapBrowserEvent~MapBrowserEvent
|
* @fires module:ol/MapBrowserEvent~MapBrowserEvent
|
||||||
* @fires module:ol/MapEvent~MapEvent
|
* @fires module:ol/MapEvent~MapEvent
|
||||||
* @fires module:ol/render/Event~RenderEvent#postcompose
|
* @fires module:ol/render/Event~RenderEvent#postcompose
|
||||||
* @fires module:ol/render/Event~RenderEvent#precompose
|
* @fires module:ol/render/Event~RenderEvent#precompose
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Map = function(options) {
|
class Map extends PluggableMap {
|
||||||
options = assign({}, options);
|
|
||||||
if (!options.controls) {
|
/**
|
||||||
options.controls = defaultControls();
|
* @param {module:ol/PluggableMap~MapOptions} options Map options.
|
||||||
}
|
*/
|
||||||
if (!options.interactions) {
|
constructor(options) {
|
||||||
options.interactions = defaultInteractions();
|
options = assign({}, options);
|
||||||
|
if (!options.controls) {
|
||||||
|
options.controls = defaultControls();
|
||||||
|
}
|
||||||
|
if (!options.interactions) {
|
||||||
|
options.interactions = defaultInteractions();
|
||||||
|
}
|
||||||
|
|
||||||
|
super(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluggableMap.call(this, options);
|
createRenderer() {
|
||||||
};
|
const renderer = new CanvasMapRenderer(this);
|
||||||
|
renderer.registerLayerRenderers([
|
||||||
|
CanvasImageLayerRenderer,
|
||||||
|
CanvasTileLayerRenderer,
|
||||||
|
CanvasVectorLayerRenderer,
|
||||||
|
CanvasVectorTileLayerRenderer
|
||||||
|
]);
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inherits(Map, PluggableMap);
|
|
||||||
|
|
||||||
Map.prototype.createRenderer = function() {
|
|
||||||
const renderer = new CanvasMapRenderer(this);
|
|
||||||
renderer.registerLayerRenderers([
|
|
||||||
CanvasImageLayerRenderer,
|
|
||||||
CanvasTileLayerRenderer,
|
|
||||||
CanvasVectorLayerRenderer,
|
|
||||||
CanvasVectorTileLayerRenderer
|
|
||||||
]);
|
|
||||||
return renderer;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Map;
|
export default Map;
|
||||||
|
|||||||
@@ -1,82 +1,81 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/MapBrowserEvent
|
* @module ol/MapBrowserEvent
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import MapEvent from './MapEvent.js';
|
import MapEvent from './MapEvent.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Events emitted as map browser events are instances of this type.
|
* Events emitted as map browser events are instances of this type.
|
||||||
* See {@link module:ol/Map~Map} for which events trigger a map browser event.
|
* See {@link module:ol/Map~Map} for which events trigger a map browser event.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/MapEvent}
|
|
||||||
* @param {string} type Event type.
|
|
||||||
* @param {module:ol/PluggableMap} map Map.
|
|
||||||
* @param {Event} browserEvent Browser event.
|
|
||||||
* @param {boolean=} opt_dragging Is the map currently being dragged?
|
|
||||||
* @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state.
|
|
||||||
*/
|
*/
|
||||||
const MapBrowserEvent = function(type, map, browserEvent, opt_dragging, opt_frameState) {
|
class MapBrowserEvent extends MapEvent {
|
||||||
|
|
||||||
MapEvent.call(this, type, map, opt_frameState);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The original browser event.
|
* @param {string} type Event type.
|
||||||
* @const
|
* @param {module:ol/PluggableMap} map Map.
|
||||||
* @type {Event}
|
* @param {Event} browserEvent Browser event.
|
||||||
* @api
|
* @param {boolean=} opt_dragging Is the map currently being dragged?
|
||||||
|
* @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state.
|
||||||
*/
|
*/
|
||||||
this.originalEvent = browserEvent;
|
constructor(type, map, browserEvent, opt_dragging, opt_frameState) {
|
||||||
|
|
||||||
|
super(type, map, opt_frameState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The original browser event.
|
||||||
|
* @const
|
||||||
|
* @type {Event}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.originalEvent = browserEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map pixel relative to the viewport corresponding to the original browser event.
|
||||||
|
* @type {module:ol/pixel~Pixel}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.pixel = map.getEventPixel(browserEvent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The coordinate in view projection corresponding to the original browser event.
|
||||||
|
* @type {module:ol/coordinate~Coordinate}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.coordinate = map.getCoordinateFromPixel(this.pixel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the map is currently being dragged. Only set for
|
||||||
|
* `POINTERDRAG` and `POINTERMOVE` events. Default is `false`.
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.dragging = opt_dragging !== undefined ? opt_dragging : false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map pixel relative to the viewport corresponding to the original browser event.
|
* Prevents the default browser action.
|
||||||
* @type {module:ol~Pixel}
|
* See https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault.
|
||||||
|
* @override
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
this.pixel = map.getEventPixel(browserEvent);
|
preventDefault() {
|
||||||
|
super.preventDefault();
|
||||||
|
this.originalEvent.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The coordinate in view projection corresponding to the original browser event.
|
* Prevents further propagation of the current event.
|
||||||
* @type {module:ol/coordinate~Coordinate}
|
* See https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation.
|
||||||
|
* @override
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
this.coordinate = map.getCoordinateFromPixel(this.pixel);
|
stopPropagation() {
|
||||||
|
super.stopPropagation();
|
||||||
/**
|
this.originalEvent.stopPropagation();
|
||||||
* Indicates if the map is currently being dragged. Only set for
|
}
|
||||||
* `POINTERDRAG` and `POINTERMOVE` events. Default is `false`.
|
}
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
this.dragging = opt_dragging !== undefined ? opt_dragging : false;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(MapBrowserEvent, MapEvent);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevents the default browser action.
|
|
||||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MapBrowserEvent.prototype.preventDefault = function() {
|
|
||||||
MapEvent.prototype.preventDefault.call(this);
|
|
||||||
this.originalEvent.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevents further propagation of the current event.
|
|
||||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MapBrowserEvent.prototype.stopPropagation = function() {
|
|
||||||
MapEvent.prototype.stopPropagation.call(this);
|
|
||||||
this.originalEvent.stopPropagation();
|
|
||||||
};
|
|
||||||
export default MapBrowserEvent;
|
export default MapBrowserEvent;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/MapBrowserEventHandler
|
* @module ol/MapBrowserEventHandler
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import {DEVICE_PIXEL_RATIO} from './has.js';
|
import {DEVICE_PIXEL_RATIO} from './has.js';
|
||||||
import MapBrowserEventType from './MapBrowserEventType.js';
|
import MapBrowserEventType from './MapBrowserEventType.js';
|
||||||
import MapBrowserPointerEvent from './MapBrowserPointerEvent.js';
|
import MapBrowserPointerEvent from './MapBrowserPointerEvent.js';
|
||||||
@@ -10,327 +9,317 @@ import EventTarget from './events/EventTarget.js';
|
|||||||
import PointerEventType from './pointer/EventType.js';
|
import PointerEventType from './pointer/EventType.js';
|
||||||
import PointerEventHandler from './pointer/PointerEventHandler.js';
|
import PointerEventHandler from './pointer/PointerEventHandler.js';
|
||||||
|
|
||||||
/**
|
class MapBrowserEventHandler extends EventTarget {
|
||||||
* @param {module:ol/PluggableMap} map The map with the viewport to
|
|
||||||
* listen to events on.
|
|
||||||
* @param {number=} moveTolerance The minimal distance the pointer must travel
|
|
||||||
* to trigger a move.
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/events/EventTarget}
|
|
||||||
*/
|
|
||||||
const MapBrowserEventHandler = function(map, moveTolerance) {
|
|
||||||
|
|
||||||
EventTarget.call(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the element that we will listen to the real events on.
|
* @param {module:ol/PluggableMap} map The map with the viewport to listen to events on.
|
||||||
* @type {module:ol/PluggableMap}
|
* @param {number=} moveTolerance The minimal distance the pointer must travel to trigger a move.
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
this.map_ = map;
|
constructor(map, moveTolerance) {
|
||||||
|
|
||||||
/**
|
super();
|
||||||
* @type {number}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.clickTimeoutId_ = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {boolean}
|
* This is the element that we will listen to the real events on.
|
||||||
* @private
|
* @type {module:ol/PluggableMap}
|
||||||
*/
|
* @private
|
||||||
this.dragging_ = false;
|
*/
|
||||||
|
this.map_ = map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {!Array.<module:ol/events~EventsKey>}
|
* @type {number}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.dragListenerKeys_ = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.moveTolerance_ = moveTolerance ?
|
|
||||||
moveTolerance * DEVICE_PIXEL_RATIO : DEVICE_PIXEL_RATIO;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The most recent "down" type event (or null if none have occurred).
|
|
||||||
* Set on pointerdown.
|
|
||||||
* @type {module:ol/pointer/PointerEvent}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.down_ = null;
|
|
||||||
|
|
||||||
const element = this.map_.getViewport();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.activePointers_ = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {!Object.<number, boolean>}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.trackedTouches_ = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler which generates pointer events for
|
|
||||||
* the viewport element.
|
|
||||||
*
|
|
||||||
* @type {module:ol/pointer/PointerEventHandler}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.pointerEventHandler_ = new PointerEventHandler(element);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler which generates pointer events for
|
|
||||||
* the document (used when dragging).
|
|
||||||
*
|
|
||||||
* @type {module:ol/pointer/PointerEventHandler}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.documentPointerEventHandler_ = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {?module:ol/events~EventsKey}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.pointerdownListenerKey_ = listen(this.pointerEventHandler_,
|
|
||||||
PointerEventType.POINTERDOWN,
|
|
||||||
this.handlePointerDown_, this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {?module:ol/events~EventsKey}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.relayedListenerKey_ = listen(this.pointerEventHandler_,
|
|
||||||
PointerEventType.POINTERMOVE,
|
|
||||||
this.relayEvent_, this);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(MapBrowserEventHandler, EventTarget);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
|
||||||
* event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.emulateClick_ = function(pointerEvent) {
|
|
||||||
let newEvent = new MapBrowserPointerEvent(
|
|
||||||
MapBrowserEventType.CLICK, this.map_, pointerEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
if (this.clickTimeoutId_ !== 0) {
|
|
||||||
// double-click
|
|
||||||
clearTimeout(this.clickTimeoutId_);
|
|
||||||
this.clickTimeoutId_ = 0;
|
this.clickTimeoutId_ = 0;
|
||||||
newEvent = new MapBrowserPointerEvent(
|
|
||||||
MapBrowserEventType.DBLCLICK, this.map_, pointerEvent);
|
/**
|
||||||
|
* @type {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.dragging_ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {!Array.<module:ol/events~EventsKey>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.dragListenerKeys_ = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.moveTolerance_ = moveTolerance ?
|
||||||
|
moveTolerance * DEVICE_PIXEL_RATIO : DEVICE_PIXEL_RATIO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The most recent "down" type event (or null if none have occurred).
|
||||||
|
* Set on pointerdown.
|
||||||
|
* @type {module:ol/pointer/PointerEvent}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.down_ = null;
|
||||||
|
|
||||||
|
const element = this.map_.getViewport();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.activePointers_ = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {!Object.<number, boolean>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.trackedTouches_ = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler which generates pointer events for
|
||||||
|
* the viewport element.
|
||||||
|
*
|
||||||
|
* @type {module:ol/pointer/PointerEventHandler}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.pointerEventHandler_ = new PointerEventHandler(element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler which generates pointer events for
|
||||||
|
* the document (used when dragging).
|
||||||
|
*
|
||||||
|
* @type {module:ol/pointer/PointerEventHandler}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.documentPointerEventHandler_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {?module:ol/events~EventsKey}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.pointerdownListenerKey_ = listen(this.pointerEventHandler_,
|
||||||
|
PointerEventType.POINTERDOWN,
|
||||||
|
this.handlePointerDown_, this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {?module:ol/events~EventsKey}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.relayedListenerKey_ = listen(this.pointerEventHandler_,
|
||||||
|
PointerEventType.POINTERMOVE,
|
||||||
|
this.relayEvent_, this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
||||||
|
* event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
emulateClick_(pointerEvent) {
|
||||||
|
let newEvent = new MapBrowserPointerEvent(
|
||||||
|
MapBrowserEventType.CLICK, this.map_, pointerEvent);
|
||||||
this.dispatchEvent(newEvent);
|
this.dispatchEvent(newEvent);
|
||||||
} else {
|
if (this.clickTimeoutId_ !== 0) {
|
||||||
// click
|
// double-click
|
||||||
this.clickTimeoutId_ = setTimeout(function() {
|
clearTimeout(this.clickTimeoutId_);
|
||||||
this.clickTimeoutId_ = 0;
|
this.clickTimeoutId_ = 0;
|
||||||
const newEvent = new MapBrowserPointerEvent(
|
newEvent = new MapBrowserPointerEvent(
|
||||||
MapBrowserEventType.SINGLECLICK, this.map_, pointerEvent);
|
MapBrowserEventType.DBLCLICK, this.map_, pointerEvent);
|
||||||
this.dispatchEvent(newEvent);
|
this.dispatchEvent(newEvent);
|
||||||
}.bind(this), 250);
|
} else {
|
||||||
}
|
// click
|
||||||
};
|
this.clickTimeoutId_ = setTimeout(function() {
|
||||||
|
this.clickTimeoutId_ = 0;
|
||||||
|
const newEvent = new MapBrowserPointerEvent(
|
||||||
/**
|
MapBrowserEventType.SINGLECLICK, this.map_, pointerEvent);
|
||||||
* Keeps track on how many pointers are currently active.
|
this.dispatchEvent(newEvent);
|
||||||
*
|
}.bind(this), 250);
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
}
|
||||||
* event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.updateActivePointers_ = function(pointerEvent) {
|
|
||||||
const event = pointerEvent;
|
|
||||||
|
|
||||||
if (event.type == MapBrowserEventType.POINTERUP ||
|
|
||||||
event.type == MapBrowserEventType.POINTERCANCEL) {
|
|
||||||
delete this.trackedTouches_[event.pointerId];
|
|
||||||
} else if (event.type == MapBrowserEventType.POINTERDOWN) {
|
|
||||||
this.trackedTouches_[event.pointerId] = true;
|
|
||||||
}
|
|
||||||
this.activePointers_ = Object.keys(this.trackedTouches_).length;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
|
||||||
* event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.handlePointerUp_ = function(pointerEvent) {
|
|
||||||
this.updateActivePointers_(pointerEvent);
|
|
||||||
const newEvent = new MapBrowserPointerEvent(
|
|
||||||
MapBrowserEventType.POINTERUP, this.map_, pointerEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
|
|
||||||
// We emulate click events on left mouse button click, touch contact, and pen
|
|
||||||
// contact. isMouseActionButton returns true in these cases (evt.button is set
|
|
||||||
// to 0).
|
|
||||||
// See http://www.w3.org/TR/pointerevents/#button-states
|
|
||||||
// We only fire click, singleclick, and doubleclick if nobody has called
|
|
||||||
// event.stopPropagation() or event.preventDefault().
|
|
||||||
if (!newEvent.propagationStopped && !this.dragging_ && this.isMouseActionButton_(pointerEvent)) {
|
|
||||||
this.emulateClick_(this.down_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.activePointers_ === 0) {
|
/**
|
||||||
|
* Keeps track on how many pointers are currently active.
|
||||||
|
*
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
||||||
|
* event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
updateActivePointers_(pointerEvent) {
|
||||||
|
const event = pointerEvent;
|
||||||
|
|
||||||
|
if (event.type == MapBrowserEventType.POINTERUP ||
|
||||||
|
event.type == MapBrowserEventType.POINTERCANCEL) {
|
||||||
|
delete this.trackedTouches_[event.pointerId];
|
||||||
|
} else if (event.type == MapBrowserEventType.POINTERDOWN) {
|
||||||
|
this.trackedTouches_[event.pointerId] = true;
|
||||||
|
}
|
||||||
|
this.activePointers_ = Object.keys(this.trackedTouches_).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
||||||
|
* event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handlePointerUp_(pointerEvent) {
|
||||||
|
this.updateActivePointers_(pointerEvent);
|
||||||
|
const newEvent = new MapBrowserPointerEvent(
|
||||||
|
MapBrowserEventType.POINTERUP, this.map_, pointerEvent);
|
||||||
|
this.dispatchEvent(newEvent);
|
||||||
|
|
||||||
|
// We emulate click events on left mouse button click, touch contact, and pen
|
||||||
|
// contact. isMouseActionButton returns true in these cases (evt.button is set
|
||||||
|
// to 0).
|
||||||
|
// See http://www.w3.org/TR/pointerevents/#button-states
|
||||||
|
// We only fire click, singleclick, and doubleclick if nobody has called
|
||||||
|
// event.stopPropagation() or event.preventDefault().
|
||||||
|
if (!newEvent.propagationStopped && !this.dragging_ && this.isMouseActionButton_(pointerEvent)) {
|
||||||
|
this.emulateClick_(this.down_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.activePointers_ === 0) {
|
||||||
|
this.dragListenerKeys_.forEach(unlistenByKey);
|
||||||
|
this.dragListenerKeys_.length = 0;
|
||||||
|
this.dragging_ = false;
|
||||||
|
this.down_ = null;
|
||||||
|
this.documentPointerEventHandler_.dispose();
|
||||||
|
this.documentPointerEventHandler_ = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
||||||
|
* event.
|
||||||
|
* @return {boolean} If the left mouse button was pressed.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
isMouseActionButton_(pointerEvent) {
|
||||||
|
return pointerEvent.button === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
||||||
|
* event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handlePointerDown_(pointerEvent) {
|
||||||
|
this.updateActivePointers_(pointerEvent);
|
||||||
|
const newEvent = new MapBrowserPointerEvent(
|
||||||
|
MapBrowserEventType.POINTERDOWN, this.map_, pointerEvent);
|
||||||
|
this.dispatchEvent(newEvent);
|
||||||
|
|
||||||
|
this.down_ = pointerEvent;
|
||||||
|
|
||||||
|
if (this.dragListenerKeys_.length === 0) {
|
||||||
|
/* Set up a pointer event handler on the `document`,
|
||||||
|
* which is required when the pointer is moved outside
|
||||||
|
* the viewport when dragging.
|
||||||
|
*/
|
||||||
|
this.documentPointerEventHandler_ =
|
||||||
|
new PointerEventHandler(document);
|
||||||
|
|
||||||
|
this.dragListenerKeys_.push(
|
||||||
|
listen(this.documentPointerEventHandler_,
|
||||||
|
MapBrowserEventType.POINTERMOVE,
|
||||||
|
this.handlePointerMove_, this),
|
||||||
|
listen(this.documentPointerEventHandler_,
|
||||||
|
MapBrowserEventType.POINTERUP,
|
||||||
|
this.handlePointerUp_, this),
|
||||||
|
/* Note that the listener for `pointercancel is set up on
|
||||||
|
* `pointerEventHandler_` and not `documentPointerEventHandler_` like
|
||||||
|
* the `pointerup` and `pointermove` listeners.
|
||||||
|
*
|
||||||
|
* The reason for this is the following: `TouchSource.vacuumTouches_()`
|
||||||
|
* issues `pointercancel` events, when there was no `touchend` for a
|
||||||
|
* `touchstart`. Now, let's say a first `touchstart` is registered on
|
||||||
|
* `pointerEventHandler_`. The `documentPointerEventHandler_` is set up.
|
||||||
|
* But `documentPointerEventHandler_` doesn't know about the first
|
||||||
|
* `touchstart`. If there is no `touchend` for the `touchstart`, we can
|
||||||
|
* only receive a `touchcancel` from `pointerEventHandler_`, because it is
|
||||||
|
* only registered there.
|
||||||
|
*/
|
||||||
|
listen(this.pointerEventHandler_,
|
||||||
|
MapBrowserEventType.POINTERCANCEL,
|
||||||
|
this.handlePointerUp_, this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
||||||
|
* event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handlePointerMove_(pointerEvent) {
|
||||||
|
// Between pointerdown and pointerup, pointermove events are triggered.
|
||||||
|
// To avoid a 'false' touchmove event to be dispatched, we test if the pointer
|
||||||
|
// moved a significant distance.
|
||||||
|
if (this.isMoving_(pointerEvent)) {
|
||||||
|
this.dragging_ = true;
|
||||||
|
const newEvent = new MapBrowserPointerEvent(
|
||||||
|
MapBrowserEventType.POINTERDRAG, this.map_, pointerEvent,
|
||||||
|
this.dragging_);
|
||||||
|
this.dispatchEvent(newEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some native android browser triggers mousemove events during small period
|
||||||
|
// of time. See: https://code.google.com/p/android/issues/detail?id=5491 or
|
||||||
|
// https://code.google.com/p/android/issues/detail?id=19827
|
||||||
|
// ex: Galaxy Tab P3110 + Android 4.1.1
|
||||||
|
pointerEvent.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap and relay a pointer event. Note that this requires that the type
|
||||||
|
* string for the MapBrowserPointerEvent matches the PointerEvent type.
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
||||||
|
* event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
relayEvent_(pointerEvent) {
|
||||||
|
const dragging = !!(this.down_ && this.isMoving_(pointerEvent));
|
||||||
|
this.dispatchEvent(new MapBrowserPointerEvent(
|
||||||
|
pointerEvent.type, this.map_, pointerEvent, dragging));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
||||||
|
* event.
|
||||||
|
* @return {boolean} Is moving.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
isMoving_(pointerEvent) {
|
||||||
|
return this.dragging_ ||
|
||||||
|
Math.abs(pointerEvent.clientX - this.down_.clientX) > this.moveTolerance_ ||
|
||||||
|
Math.abs(pointerEvent.clientY - this.down_.clientY) > this.moveTolerance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
disposeInternal() {
|
||||||
|
if (this.relayedListenerKey_) {
|
||||||
|
unlistenByKey(this.relayedListenerKey_);
|
||||||
|
this.relayedListenerKey_ = null;
|
||||||
|
}
|
||||||
|
if (this.pointerdownListenerKey_) {
|
||||||
|
unlistenByKey(this.pointerdownListenerKey_);
|
||||||
|
this.pointerdownListenerKey_ = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.dragListenerKeys_.forEach(unlistenByKey);
|
this.dragListenerKeys_.forEach(unlistenByKey);
|
||||||
this.dragListenerKeys_.length = 0;
|
this.dragListenerKeys_.length = 0;
|
||||||
this.dragging_ = false;
|
|
||||||
this.down_ = null;
|
if (this.documentPointerEventHandler_) {
|
||||||
this.documentPointerEventHandler_.dispose();
|
this.documentPointerEventHandler_.dispose();
|
||||||
this.documentPointerEventHandler_ = null;
|
this.documentPointerEventHandler_ = null;
|
||||||
|
}
|
||||||
|
if (this.pointerEventHandler_) {
|
||||||
|
this.pointerEventHandler_.dispose();
|
||||||
|
this.pointerEventHandler_ = null;
|
||||||
|
}
|
||||||
|
super.disposeInternal();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
|
||||||
* event.
|
|
||||||
* @return {boolean} If the left mouse button was pressed.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.isMouseActionButton_ = function(pointerEvent) {
|
|
||||||
return pointerEvent.button === 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
|
||||||
* event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.handlePointerDown_ = function(pointerEvent) {
|
|
||||||
this.updateActivePointers_(pointerEvent);
|
|
||||||
const newEvent = new MapBrowserPointerEvent(
|
|
||||||
MapBrowserEventType.POINTERDOWN, this.map_, pointerEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
|
|
||||||
this.down_ = pointerEvent;
|
|
||||||
|
|
||||||
if (this.dragListenerKeys_.length === 0) {
|
|
||||||
/* Set up a pointer event handler on the `document`,
|
|
||||||
* which is required when the pointer is moved outside
|
|
||||||
* the viewport when dragging.
|
|
||||||
*/
|
|
||||||
this.documentPointerEventHandler_ =
|
|
||||||
new PointerEventHandler(document);
|
|
||||||
|
|
||||||
this.dragListenerKeys_.push(
|
|
||||||
listen(this.documentPointerEventHandler_,
|
|
||||||
MapBrowserEventType.POINTERMOVE,
|
|
||||||
this.handlePointerMove_, this),
|
|
||||||
listen(this.documentPointerEventHandler_,
|
|
||||||
MapBrowserEventType.POINTERUP,
|
|
||||||
this.handlePointerUp_, this),
|
|
||||||
/* Note that the listener for `pointercancel is set up on
|
|
||||||
* `pointerEventHandler_` and not `documentPointerEventHandler_` like
|
|
||||||
* the `pointerup` and `pointermove` listeners.
|
|
||||||
*
|
|
||||||
* The reason for this is the following: `TouchSource.vacuumTouches_()`
|
|
||||||
* issues `pointercancel` events, when there was no `touchend` for a
|
|
||||||
* `touchstart`. Now, let's say a first `touchstart` is registered on
|
|
||||||
* `pointerEventHandler_`. The `documentPointerEventHandler_` is set up.
|
|
||||||
* But `documentPointerEventHandler_` doesn't know about the first
|
|
||||||
* `touchstart`. If there is no `touchend` for the `touchstart`, we can
|
|
||||||
* only receive a `touchcancel` from `pointerEventHandler_`, because it is
|
|
||||||
* only registered there.
|
|
||||||
*/
|
|
||||||
listen(this.pointerEventHandler_,
|
|
||||||
MapBrowserEventType.POINTERCANCEL,
|
|
||||||
this.handlePointerUp_, this)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
|
||||||
* event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.handlePointerMove_ = function(pointerEvent) {
|
|
||||||
// Between pointerdown and pointerup, pointermove events are triggered.
|
|
||||||
// To avoid a 'false' touchmove event to be dispatched, we test if the pointer
|
|
||||||
// moved a significant distance.
|
|
||||||
if (this.isMoving_(pointerEvent)) {
|
|
||||||
this.dragging_ = true;
|
|
||||||
const newEvent = new MapBrowserPointerEvent(
|
|
||||||
MapBrowserEventType.POINTERDRAG, this.map_, pointerEvent,
|
|
||||||
this.dragging_);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some native android browser triggers mousemove events during small period
|
|
||||||
// of time. See: https://code.google.com/p/android/issues/detail?id=5491 or
|
|
||||||
// https://code.google.com/p/android/issues/detail?id=19827
|
|
||||||
// ex: Galaxy Tab P3110 + Android 4.1.1
|
|
||||||
pointerEvent.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap and relay a pointer event. Note that this requires that the type
|
|
||||||
* string for the MapBrowserPointerEvent matches the PointerEvent type.
|
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
|
||||||
* event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.relayEvent_ = function(pointerEvent) {
|
|
||||||
const dragging = !!(this.down_ && this.isMoving_(pointerEvent));
|
|
||||||
this.dispatchEvent(new MapBrowserPointerEvent(
|
|
||||||
pointerEvent.type, this.map_, pointerEvent, dragging));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
|
||||||
* event.
|
|
||||||
* @return {boolean} Is moving.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.isMoving_ = function(pointerEvent) {
|
|
||||||
return this.dragging_ ||
|
|
||||||
Math.abs(pointerEvent.clientX - this.down_.clientX) > this.moveTolerance_ ||
|
|
||||||
Math.abs(pointerEvent.clientY - this.down_.clientY) > this.moveTolerance_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
MapBrowserEventHandler.prototype.disposeInternal = function() {
|
|
||||||
if (this.relayedListenerKey_) {
|
|
||||||
unlistenByKey(this.relayedListenerKey_);
|
|
||||||
this.relayedListenerKey_ = null;
|
|
||||||
}
|
|
||||||
if (this.pointerdownListenerKey_) {
|
|
||||||
unlistenByKey(this.pointerdownListenerKey_);
|
|
||||||
this.pointerdownListenerKey_ = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dragListenerKeys_.forEach(unlistenByKey);
|
|
||||||
this.dragListenerKeys_.length = 0;
|
|
||||||
|
|
||||||
if (this.documentPointerEventHandler_) {
|
|
||||||
this.documentPointerEventHandler_.dispose();
|
|
||||||
this.documentPointerEventHandler_ = null;
|
|
||||||
}
|
|
||||||
if (this.pointerEventHandler_) {
|
|
||||||
this.pointerEventHandler_.dispose();
|
|
||||||
this.pointerEventHandler_ = null;
|
|
||||||
}
|
|
||||||
EventTarget.prototype.disposeInternal.call(this);
|
|
||||||
};
|
|
||||||
export default MapBrowserEventHandler;
|
export default MapBrowserEventHandler;
|
||||||
|
|||||||
@@ -1,32 +1,29 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/MapBrowserPointerEvent
|
* @module ol/MapBrowserPointerEvent
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import MapBrowserEvent from './MapBrowserEvent.js';
|
import MapBrowserEvent from './MapBrowserEvent.js';
|
||||||
|
|
||||||
/**
|
class MapBrowserPointerEvent extends MapBrowserEvent {
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/MapBrowserEvent}
|
|
||||||
* @param {string} type Event type.
|
|
||||||
* @param {module:ol/PluggableMap} map Map.
|
|
||||||
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
|
|
||||||
* event.
|
|
||||||
* @param {boolean=} opt_dragging Is the map currently being dragged?
|
|
||||||
* @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state.
|
|
||||||
*/
|
|
||||||
const MapBrowserPointerEvent = function(type, map, pointerEvent, opt_dragging,
|
|
||||||
opt_frameState) {
|
|
||||||
|
|
||||||
MapBrowserEvent.call(this, type, map, pointerEvent.originalEvent, opt_dragging,
|
|
||||||
opt_frameState);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @param {string} type Event type.
|
||||||
* @type {module:ol/pointer/PointerEvent}
|
* @param {module:ol/PluggableMap} map Map.
|
||||||
|
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer event.
|
||||||
|
* @param {boolean=} opt_dragging Is the map currently being dragged?
|
||||||
|
* @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state.
|
||||||
*/
|
*/
|
||||||
this.pointerEvent = pointerEvent;
|
constructor(type, map, pointerEvent, opt_dragging, opt_frameState) {
|
||||||
|
|
||||||
};
|
super(type, map, pointerEvent.originalEvent, opt_dragging, opt_frameState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {module:ol/pointer/PointerEvent}
|
||||||
|
*/
|
||||||
|
this.pointerEvent = pointerEvent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
inherits(MapBrowserPointerEvent, MapBrowserEvent);
|
|
||||||
export default MapBrowserPointerEvent;
|
export default MapBrowserPointerEvent;
|
||||||
|
|||||||
@@ -1,39 +1,40 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/MapEvent
|
* @module ol/MapEvent
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import Event from './events/Event.js';
|
import Event from './events/Event.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Events emitted as map events are instances of this type.
|
* Events emitted as map events are instances of this type.
|
||||||
* See {@link module:ol/Map~Map} for which events trigger a map event.
|
* See {@link module:ol/Map~Map} for which events trigger a map event.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/events/Event}
|
|
||||||
* @param {string} type Event type.
|
|
||||||
* @param {module:ol/PluggableMap} map Map.
|
|
||||||
* @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state.
|
|
||||||
*/
|
*/
|
||||||
const MapEvent = function(type, map, opt_frameState) {
|
class MapEvent extends Event {
|
||||||
|
|
||||||
Event.call(this, type);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map where the event occurred.
|
* @param {string} type Event type.
|
||||||
* @type {module:ol/PluggableMap}
|
* @param {module:ol/PluggableMap} map Map.
|
||||||
* @api
|
* @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state.
|
||||||
*/
|
*/
|
||||||
this.map = map;
|
constructor(type, map, opt_frameState) {
|
||||||
|
|
||||||
/**
|
super(type);
|
||||||
* The frame state at the time of the event.
|
|
||||||
* @type {?module:ol/PluggableMap~FrameState}
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
this.frameState = opt_frameState !== undefined ? opt_frameState : null;
|
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* The map where the event occurred.
|
||||||
|
* @type {module:ol/PluggableMap}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.map = map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The frame state at the time of the event.
|
||||||
|
* @type {?module:ol/PluggableMap~FrameState}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.frameState = opt_frameState !== undefined ? opt_frameState : null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
inherits(MapEvent, Event);
|
|
||||||
export default MapEvent;
|
export default MapEvent;
|
||||||
|
|||||||
279
src/ol/Object.js
279
src/ol/Object.js
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/Object
|
* @module ol/Object
|
||||||
*/
|
*/
|
||||||
import {getUid, inherits} from './util.js';
|
import {getUid} from './util.js';
|
||||||
import ObjectEventType from './ObjectEventType.js';
|
import ObjectEventType from './ObjectEventType.js';
|
||||||
import Observable from './Observable.js';
|
import Observable from './Observable.js';
|
||||||
import Event from './events/Event.js';
|
import Event from './events/Event.js';
|
||||||
@@ -10,35 +10,36 @@ import {assign} from './obj.js';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Events emitted by {@link module:ol/Object~BaseObject} instances are instances of
|
* Events emitted by {@link module:ol/Object~BaseObject} instances are instances of this type.
|
||||||
* this type.
|
*/
|
||||||
*
|
class ObjectEvent extends Event {
|
||||||
* @param {string} type The event type.
|
|
||||||
* @param {string} key The property name.
|
|
||||||
* @param {*} oldValue The old value for `key`.
|
|
||||||
* @extends {module:ol/events/Event}
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
const ObjectEvent = function(type, key, oldValue) {
|
|
||||||
Event.call(this, type);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the property whose value is changing.
|
* @param {string} type The event type.
|
||||||
* @type {string}
|
* @param {string} key The property name.
|
||||||
* @api
|
* @param {*} oldValue The old value for `key`.
|
||||||
*/
|
*/
|
||||||
this.key = key;
|
constructor(type, key, oldValue) {
|
||||||
|
super(type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The old value. To get the new value use `e.target.get(e.key)` where
|
* The name of the property whose value is changing.
|
||||||
* `e` is the event object.
|
* @type {string}
|
||||||
* @type {*}
|
* @api
|
||||||
* @api
|
*/
|
||||||
*/
|
this.key = key;
|
||||||
this.oldValue = oldValue;
|
|
||||||
|
|
||||||
};
|
/**
|
||||||
inherits(ObjectEvent, Event);
|
* The old value. To get the new value use `e.target.get(e.key)` where
|
||||||
|
* `e` is the event object.
|
||||||
|
* @type {*}
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
this.oldValue = oldValue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,33 +82,126 @@ inherits(ObjectEvent, Event);
|
|||||||
* Properties can be deleted by using the unset method. E.g.
|
* Properties can be deleted by using the unset method. E.g.
|
||||||
* object.unset('foo').
|
* object.unset('foo').
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Observable}
|
|
||||||
* @param {Object.<string, *>=} opt_values An object with key-value pairs.
|
|
||||||
* @fires module:ol/Object~ObjectEvent
|
* @fires module:ol/Object~ObjectEvent
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const BaseObject = function(opt_values) {
|
class BaseObject extends Observable {
|
||||||
Observable.call(this);
|
|
||||||
|
|
||||||
// Call {@link module:ol~getUid} to ensure that the order of objects' ids is
|
|
||||||
// the same as the order in which they were created. This also helps to
|
|
||||||
// ensure that object properties are always added in the same order, which
|
|
||||||
// helps many JavaScript engines generate faster code.
|
|
||||||
getUid(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {Object.<string, *>=} opt_values An object with key-value pairs.
|
||||||
* @type {!Object.<string, *>}
|
|
||||||
*/
|
*/
|
||||||
this.values_ = {};
|
constructor(opt_values) {
|
||||||
|
super();
|
||||||
|
|
||||||
if (opt_values !== undefined) {
|
// Call {@link module:ol/util~getUid} to ensure that the order of objects' ids is
|
||||||
this.setProperties(opt_values);
|
// the same as the order in which they were created. This also helps to
|
||||||
|
// ensure that object properties are always added in the same order, which
|
||||||
|
// helps many JavaScript engines generate faster code.
|
||||||
|
getUid(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {!Object.<string, *>}
|
||||||
|
*/
|
||||||
|
this.values_ = {};
|
||||||
|
|
||||||
|
if (opt_values !== undefined) {
|
||||||
|
this.setProperties(opt_values);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
inherits(BaseObject, Observable);
|
/**
|
||||||
|
* Gets a value.
|
||||||
|
* @param {string} key Key name.
|
||||||
|
* @return {*} Value.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
get(key) {
|
||||||
|
let value;
|
||||||
|
if (this.values_.hasOwnProperty(key)) {
|
||||||
|
value = this.values_[key];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of object property names.
|
||||||
|
* @return {Array.<string>} List of property names.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getKeys() {
|
||||||
|
return Object.keys(this.values_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an object of all property names and values.
|
||||||
|
* @return {Object.<string, *>} Object.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getProperties() {
|
||||||
|
return assign({}, this.values_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} key Key name.
|
||||||
|
* @param {*} oldValue Old value.
|
||||||
|
*/
|
||||||
|
notify(key, oldValue) {
|
||||||
|
let eventType;
|
||||||
|
eventType = getChangeEventType(key);
|
||||||
|
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
|
||||||
|
eventType = ObjectEventType.PROPERTYCHANGE;
|
||||||
|
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a value.
|
||||||
|
* @param {string} key Key name.
|
||||||
|
* @param {*} value Value.
|
||||||
|
* @param {boolean=} opt_silent Update without triggering an event.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
set(key, value, opt_silent) {
|
||||||
|
if (opt_silent) {
|
||||||
|
this.values_[key] = value;
|
||||||
|
} else {
|
||||||
|
const oldValue = this.values_[key];
|
||||||
|
this.values_[key] = value;
|
||||||
|
if (oldValue !== value) {
|
||||||
|
this.notify(key, oldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a collection of key-value pairs. Note that this changes any existing
|
||||||
|
* properties and adds new ones (it does not remove any existing properties).
|
||||||
|
* @param {Object.<string, *>} values Values.
|
||||||
|
* @param {boolean=} opt_silent Update without triggering an event.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setProperties(values, opt_silent) {
|
||||||
|
for (const key in values) {
|
||||||
|
this.set(key, values[key], opt_silent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsets a property.
|
||||||
|
* @param {string} key Key name.
|
||||||
|
* @param {boolean=} opt_silent Unset without triggering an event.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
unset(key, opt_silent) {
|
||||||
|
if (key in this.values_) {
|
||||||
|
const oldValue = this.values_[key];
|
||||||
|
delete this.values_[key];
|
||||||
|
if (!opt_silent) {
|
||||||
|
this.notify(key, oldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,103 +221,4 @@ export function getChangeEventType(key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a value.
|
|
||||||
* @param {string} key Key name.
|
|
||||||
* @return {*} Value.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
BaseObject.prototype.get = function(key) {
|
|
||||||
let value;
|
|
||||||
if (this.values_.hasOwnProperty(key)) {
|
|
||||||
value = this.values_[key];
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of object property names.
|
|
||||||
* @return {Array.<string>} List of property names.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
BaseObject.prototype.getKeys = function() {
|
|
||||||
return Object.keys(this.values_);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an object of all property names and values.
|
|
||||||
* @return {Object.<string, *>} Object.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
BaseObject.prototype.getProperties = function() {
|
|
||||||
return assign({}, this.values_);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} key Key name.
|
|
||||||
* @param {*} oldValue Old value.
|
|
||||||
*/
|
|
||||||
BaseObject.prototype.notify = function(key, oldValue) {
|
|
||||||
let eventType;
|
|
||||||
eventType = getChangeEventType(key);
|
|
||||||
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
|
|
||||||
eventType = ObjectEventType.PROPERTYCHANGE;
|
|
||||||
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a value.
|
|
||||||
* @param {string} key Key name.
|
|
||||||
* @param {*} value Value.
|
|
||||||
* @param {boolean=} opt_silent Update without triggering an event.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
BaseObject.prototype.set = function(key, value, opt_silent) {
|
|
||||||
if (opt_silent) {
|
|
||||||
this.values_[key] = value;
|
|
||||||
} else {
|
|
||||||
const oldValue = this.values_[key];
|
|
||||||
this.values_[key] = value;
|
|
||||||
if (oldValue !== value) {
|
|
||||||
this.notify(key, oldValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a collection of key-value pairs. Note that this changes any existing
|
|
||||||
* properties and adds new ones (it does not remove any existing properties).
|
|
||||||
* @param {Object.<string, *>} values Values.
|
|
||||||
* @param {boolean=} opt_silent Update without triggering an event.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
BaseObject.prototype.setProperties = function(values, opt_silent) {
|
|
||||||
for (const key in values) {
|
|
||||||
this.set(key, values[key], opt_silent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsets a property.
|
|
||||||
* @param {string} key Key name.
|
|
||||||
* @param {boolean=} opt_silent Unset without triggering an event.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
BaseObject.prototype.unset = function(key, opt_silent) {
|
|
||||||
if (key in this.values_) {
|
|
||||||
const oldValue = this.values_[key];
|
|
||||||
delete this.values_[key];
|
|
||||||
if (!opt_silent) {
|
|
||||||
this.notify(key, oldValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default BaseObject;
|
export default BaseObject;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/Observable
|
* @module ol/Observable
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import {listen, unlistenByKey, unlisten, listenOnce} from './events.js';
|
import {listen, unlistenByKey, unlisten, listenOnce} from './events.js';
|
||||||
import EventTarget from './events/EventTarget.js';
|
import EventTarget from './events/EventTarget.js';
|
||||||
import EventType from './events/EventType.js';
|
import EventType from './events/EventType.js';
|
||||||
@@ -14,25 +13,102 @@ import EventType from './events/EventType.js';
|
|||||||
* and unregistration. A generic `change` event is always available through
|
* and unregistration. A generic `change` event is always available through
|
||||||
* {@link module:ol/Observable~Observable#changed}.
|
* {@link module:ol/Observable~Observable#changed}.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/events/EventTarget}
|
|
||||||
* @fires module:ol/events/Event~Event
|
* @fires module:ol/events/Event~Event
|
||||||
* @struct
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Observable = function() {
|
class Observable extends EventTarget {
|
||||||
|
constructor() {
|
||||||
|
|
||||||
EventTarget.call(this);
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.revision_ = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* Increases the revision counter and dispatches a 'change' event.
|
||||||
* @type {number}
|
* @api
|
||||||
*/
|
*/
|
||||||
this.revision_ = 0;
|
changed() {
|
||||||
|
++this.revision_;
|
||||||
|
this.dispatchEvent(EventType.CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* Get the version number for this object. Each time the object is modified,
|
||||||
|
* its version number will be incremented.
|
||||||
|
* @return {number} Revision.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getRevision() {
|
||||||
|
return this.revision_;
|
||||||
|
}
|
||||||
|
|
||||||
inherits(Observable, EventTarget);
|
/**
|
||||||
|
* Listen for a certain type of event.
|
||||||
|
* @param {string|Array.<string>} type The event type or array of event types.
|
||||||
|
* @param {function(?): ?} listener The listener function.
|
||||||
|
* @return {module:ol/events~EventsKey|Array.<module:ol/events~EventsKey>} Unique key for the listener. If
|
||||||
|
* called with an array of event types as the first argument, the return
|
||||||
|
* will be an array of keys.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
on(type, listener) {
|
||||||
|
if (Array.isArray(type)) {
|
||||||
|
const len = type.length;
|
||||||
|
const keys = new Array(len);
|
||||||
|
for (let i = 0; i < len; ++i) {
|
||||||
|
keys[i] = listen(this, type[i], listener);
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
} else {
|
||||||
|
return listen(this, /** @type {string} */ (type), listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen once for a certain type of event.
|
||||||
|
* @param {string|Array.<string>} type The event type or array of event types.
|
||||||
|
* @param {function(?): ?} listener The listener function.
|
||||||
|
* @return {module:ol/events~EventsKey|Array.<module:ol/events~EventsKey>} Unique key for the listener. If
|
||||||
|
* called with an array of event types as the first argument, the return
|
||||||
|
* will be an array of keys.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
once(type, listener) {
|
||||||
|
if (Array.isArray(type)) {
|
||||||
|
const len = type.length;
|
||||||
|
const keys = new Array(len);
|
||||||
|
for (let i = 0; i < len; ++i) {
|
||||||
|
keys[i] = listenOnce(this, type[i], listener);
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
} else {
|
||||||
|
return listenOnce(this, /** @type {string} */ (type), listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlisten for a certain type of event.
|
||||||
|
* @param {string|Array.<string>} type The event type or array of event types.
|
||||||
|
* @param {function(?): ?} listener The listener function.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
un(type, listener) {
|
||||||
|
if (Array.isArray(type)) {
|
||||||
|
for (let i = 0, ii = type.length; i < ii; ++i) {
|
||||||
|
unlisten(this, type[i], listener);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
unlisten(this, /** @type {string} */ (type), listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,101 +128,4 @@ export function unByKey(key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increases the revision counter and dispatches a 'change' event.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Observable.prototype.changed = function() {
|
|
||||||
++this.revision_;
|
|
||||||
this.dispatchEvent(EventType.CHANGE);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an event and calls all listeners listening for events
|
|
||||||
* of this type. The event parameter can either be a string or an
|
|
||||||
* Object with a `type` property.
|
|
||||||
*
|
|
||||||
* @param {{type: string,
|
|
||||||
* target: (EventTarget|module:ol/events/EventTarget|undefined)}|
|
|
||||||
* module:ol/events/Event|string} event Event object.
|
|
||||||
* @function
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Observable.prototype.dispatchEvent;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the version number for this object. Each time the object is modified,
|
|
||||||
* its version number will be incremented.
|
|
||||||
* @return {number} Revision.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Observable.prototype.getRevision = function() {
|
|
||||||
return this.revision_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listen for a certain type of event.
|
|
||||||
* @param {string|Array.<string>} type The event type or array of event types.
|
|
||||||
* @param {function(?): ?} listener The listener function.
|
|
||||||
* @return {module:ol/events~EventsKey|Array.<module:ol/events~EventsKey>} Unique key for the listener. If
|
|
||||||
* called with an array of event types as the first argument, the return
|
|
||||||
* will be an array of keys.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Observable.prototype.on = function(type, listener) {
|
|
||||||
if (Array.isArray(type)) {
|
|
||||||
const len = type.length;
|
|
||||||
const keys = new Array(len);
|
|
||||||
for (let i = 0; i < len; ++i) {
|
|
||||||
keys[i] = listen(this, type[i], listener);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
} else {
|
|
||||||
return listen(this, /** @type {string} */ (type), listener);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listen once for a certain type of event.
|
|
||||||
* @param {string|Array.<string>} type The event type or array of event types.
|
|
||||||
* @param {function(?): ?} listener The listener function.
|
|
||||||
* @return {module:ol/events~EventsKey|Array.<module:ol/events~EventsKey>} Unique key for the listener. If
|
|
||||||
* called with an array of event types as the first argument, the return
|
|
||||||
* will be an array of keys.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Observable.prototype.once = function(type, listener) {
|
|
||||||
if (Array.isArray(type)) {
|
|
||||||
const len = type.length;
|
|
||||||
const keys = new Array(len);
|
|
||||||
for (let i = 0; i < len; ++i) {
|
|
||||||
keys[i] = listenOnce(this, type[i], listener);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
} else {
|
|
||||||
return listenOnce(this, /** @type {string} */ (type), listener);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlisten for a certain type of event.
|
|
||||||
* @param {string|Array.<string>} type The event type or array of event types.
|
|
||||||
* @param {function(?): ?} listener The listener function.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Observable.prototype.un = function(type, listener) {
|
|
||||||
if (Array.isArray(type)) {
|
|
||||||
for (let i = 0, ii = type.length; i < ii; ++i) {
|
|
||||||
unlisten(this, type[i], listener);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
unlisten(this, /** @type {string} */ (type), listener);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export default Observable;
|
export default Observable;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/Overlay
|
* @module ol/Overlay
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import MapEventType from './MapEventType.js';
|
import MapEventType from './MapEventType.js';
|
||||||
import BaseObject, {getChangeEventType} from './Object.js';
|
import BaseObject, {getChangeEventType} from './Object.js';
|
||||||
import OverlayPositioning from './OverlayPositioning.js';
|
import OverlayPositioning from './OverlayPositioning.js';
|
||||||
@@ -15,7 +14,7 @@ import {containsExtent} from './extent.js';
|
|||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {number|string} [id] Set the overlay id. The overlay id can be used
|
* @property {number|string} [id] Set the overlay id. The overlay id can be used
|
||||||
* with the {@link module:ol/Map~Map#getOverlayById} method.
|
* with the {@link module:ol/Map~Map#getOverlayById} method.
|
||||||
* @property {Element} [element] The overlay element.
|
* @property {HTMLElement} [element] The overlay element.
|
||||||
* @property {Array.<number>} [offset=[0, 0]] Offsets in pixels used when positioning
|
* @property {Array.<number>} [offset=[0, 0]] Offsets in pixels used when positioning
|
||||||
* the overlay. The first element in the
|
* the overlay. The first element in the
|
||||||
* array is the horizontal offset. A positive value shifts the overlay right.
|
* array is the horizontal offset. A positive value shifts the overlay right.
|
||||||
@@ -93,515 +92,494 @@ const Property = {
|
|||||||
* popup.setPosition(coordinate);
|
* popup.setPosition(coordinate);
|
||||||
* map.addOverlay(popup);
|
* map.addOverlay(popup);
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Object}
|
|
||||||
* @param {module:ol/Overlay~Options} options Overlay options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Overlay = function(options) {
|
class Overlay extends BaseObject {
|
||||||
|
|
||||||
BaseObject.call(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @param {module:ol/Overlay~Options} options Overlay options.
|
||||||
* @type {module:ol/Overlay~Options}
|
|
||||||
*/
|
*/
|
||||||
this.options = options;
|
constructor(options) {
|
||||||
|
|
||||||
/**
|
super();
|
||||||
* @protected
|
|
||||||
* @type {number|string|undefined}
|
|
||||||
*/
|
|
||||||
this.id = options.id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {boolean}
|
* @type {module:ol/Overlay~Options}
|
||||||
*/
|
*/
|
||||||
this.insertFirst = options.insertFirst !== undefined ?
|
this.options = options;
|
||||||
options.insertFirst : true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {boolean}
|
* @type {number|string|undefined}
|
||||||
*/
|
*/
|
||||||
this.stopEvent = options.stopEvent !== undefined ? options.stopEvent : true;
|
this.id = options.id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {Element}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
this.element = document.createElement('DIV');
|
this.insertFirst = options.insertFirst !== undefined ?
|
||||||
this.element.className = options.className !== undefined ?
|
options.insertFirst : true;
|
||||||
options.className : 'ol-overlay-container ' + CLASS_SELECTABLE;
|
|
||||||
this.element.style.position = 'absolute';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
this.autoPan = options.autoPan !== undefined ? options.autoPan : false;
|
this.stopEvent = options.stopEvent !== undefined ? options.stopEvent : true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {module:ol/Overlay~PanOptions}
|
* @type {HTMLElement}
|
||||||
*/
|
*/
|
||||||
this.autoPanAnimation = options.autoPanAnimation || /** @type {module:ol/Overlay~PanOptions} */ ({});
|
this.element = document.createElement('DIV');
|
||||||
|
this.element.className = options.className !== undefined ?
|
||||||
|
options.className : 'ol-overlay-container ' + CLASS_SELECTABLE;
|
||||||
|
this.element.style.position = 'absolute';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {number}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
this.autoPanMargin = options.autoPanMargin !== undefined ?
|
this.autoPan = options.autoPan !== undefined ? options.autoPan : false;
|
||||||
options.autoPanMargin : 20;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {{bottom_: string,
|
* @type {module:ol/Overlay~PanOptions}
|
||||||
* left_: string,
|
*/
|
||||||
* right_: string,
|
this.autoPanAnimation = options.autoPanAnimation || /** @type {module:ol/Overlay~PanOptions} */ ({});
|
||||||
* top_: string,
|
|
||||||
* visible: boolean}}
|
|
||||||
*/
|
|
||||||
this.rendered = {
|
|
||||||
bottom_: '',
|
|
||||||
left_: '',
|
|
||||||
right_: '',
|
|
||||||
top_: '',
|
|
||||||
visible: true
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {?module:ol/events~EventsKey}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.mapPostrenderListenerKey = null;
|
this.autoPanMargin = options.autoPanMargin !== undefined ?
|
||||||
|
options.autoPanMargin : 20;
|
||||||
|
|
||||||
listen(
|
/**
|
||||||
this, getChangeEventType(Property.ELEMENT),
|
* @protected
|
||||||
this.handleElementChanged, this);
|
* @type {{bottom_: string,
|
||||||
|
* left_: string,
|
||||||
|
* right_: string,
|
||||||
|
* top_: string,
|
||||||
|
* visible: boolean}}
|
||||||
|
*/
|
||||||
|
this.rendered = {
|
||||||
|
bottom_: '',
|
||||||
|
left_: '',
|
||||||
|
right_: '',
|
||||||
|
top_: '',
|
||||||
|
visible: true
|
||||||
|
};
|
||||||
|
|
||||||
listen(
|
/**
|
||||||
this, getChangeEventType(Property.MAP),
|
* @protected
|
||||||
this.handleMapChanged, this);
|
* @type {?module:ol/events~EventsKey}
|
||||||
|
*/
|
||||||
listen(
|
|
||||||
this, getChangeEventType(Property.OFFSET),
|
|
||||||
this.handleOffsetChanged, this);
|
|
||||||
|
|
||||||
listen(
|
|
||||||
this, getChangeEventType(Property.POSITION),
|
|
||||||
this.handlePositionChanged, this);
|
|
||||||
|
|
||||||
listen(
|
|
||||||
this, getChangeEventType(Property.POSITIONING),
|
|
||||||
this.handlePositioningChanged, this);
|
|
||||||
|
|
||||||
if (options.element !== undefined) {
|
|
||||||
this.setElement(options.element);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setOffset(options.offset !== undefined ? options.offset : [0, 0]);
|
|
||||||
|
|
||||||
this.setPositioning(options.positioning !== undefined ?
|
|
||||||
/** @type {module:ol/OverlayPositioning} */ (options.positioning) :
|
|
||||||
OverlayPositioning.TOP_LEFT);
|
|
||||||
|
|
||||||
if (options.position !== undefined) {
|
|
||||||
this.setPosition(options.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(Overlay, BaseObject);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the DOM element of this overlay.
|
|
||||||
* @return {Element|undefined} The Element containing the overlay.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.getElement = function() {
|
|
||||||
return /** @type {Element|undefined} */ (this.get(Property.ELEMENT));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the overlay identifier which is set on constructor.
|
|
||||||
* @return {number|string|undefined} Id.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.getId = function() {
|
|
||||||
return this.id;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the map associated with this overlay.
|
|
||||||
* @return {module:ol/PluggableMap|undefined} The map that the
|
|
||||||
* overlay is part of.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.getMap = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/PluggableMap|undefined} */ (this.get(Property.MAP))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the offset of this overlay.
|
|
||||||
* @return {Array.<number>} The offset.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.getOffset = function() {
|
|
||||||
return /** @type {Array.<number>} */ (this.get(Property.OFFSET));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current position of this overlay.
|
|
||||||
* @return {module:ol/coordinate~Coordinate|undefined} The spatial point that the overlay is
|
|
||||||
* anchored at.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.getPosition = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/coordinate~Coordinate|undefined} */ (this.get(Property.POSITION))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current positioning of this overlay.
|
|
||||||
* @return {module:ol/OverlayPositioning} How the overlay is positioned
|
|
||||||
* relative to its point on the map.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.getPositioning = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/OverlayPositioning} */ (this.get(Property.POSITIONING))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.handleElementChanged = function() {
|
|
||||||
removeChildren(this.element);
|
|
||||||
const element = this.getElement();
|
|
||||||
if (element) {
|
|
||||||
this.element.appendChild(element);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.handleMapChanged = function() {
|
|
||||||
if (this.mapPostrenderListenerKey) {
|
|
||||||
removeNode(this.element);
|
|
||||||
unlistenByKey(this.mapPostrenderListenerKey);
|
|
||||||
this.mapPostrenderListenerKey = null;
|
this.mapPostrenderListenerKey = null;
|
||||||
|
|
||||||
|
listen(
|
||||||
|
this, getChangeEventType(Property.ELEMENT),
|
||||||
|
this.handleElementChanged, this);
|
||||||
|
|
||||||
|
listen(
|
||||||
|
this, getChangeEventType(Property.MAP),
|
||||||
|
this.handleMapChanged, this);
|
||||||
|
|
||||||
|
listen(
|
||||||
|
this, getChangeEventType(Property.OFFSET),
|
||||||
|
this.handleOffsetChanged, this);
|
||||||
|
|
||||||
|
listen(
|
||||||
|
this, getChangeEventType(Property.POSITION),
|
||||||
|
this.handlePositionChanged, this);
|
||||||
|
|
||||||
|
listen(
|
||||||
|
this, getChangeEventType(Property.POSITIONING),
|
||||||
|
this.handlePositioningChanged, this);
|
||||||
|
|
||||||
|
if (options.element !== undefined) {
|
||||||
|
this.setElement(options.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setOffset(options.offset !== undefined ? options.offset : [0, 0]);
|
||||||
|
|
||||||
|
this.setPositioning(options.positioning !== undefined ?
|
||||||
|
/** @type {module:ol/OverlayPositioning} */ (options.positioning) :
|
||||||
|
OverlayPositioning.TOP_LEFT);
|
||||||
|
|
||||||
|
if (options.position !== undefined) {
|
||||||
|
this.setPosition(options.position);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
const map = this.getMap();
|
|
||||||
if (map) {
|
/**
|
||||||
this.mapPostrenderListenerKey = listen(map,
|
* Get the DOM element of this overlay.
|
||||||
MapEventType.POSTRENDER, this.render, this);
|
* @return {HTMLElement|undefined} The Element containing the overlay.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getElement() {
|
||||||
|
return /** @type {HTMLElement|undefined} */ (this.get(Property.ELEMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the overlay identifier which is set on constructor.
|
||||||
|
* @return {number|string|undefined} Id.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the map associated with this overlay.
|
||||||
|
* @return {module:ol/PluggableMap|undefined} The map that the
|
||||||
|
* overlay is part of.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getMap() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/PluggableMap|undefined} */ (this.get(Property.MAP))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the offset of this overlay.
|
||||||
|
* @return {Array.<number>} The offset.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getOffset() {
|
||||||
|
return /** @type {Array.<number>} */ (this.get(Property.OFFSET));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current position of this overlay.
|
||||||
|
* @return {module:ol/coordinate~Coordinate|undefined} The spatial point that the overlay is
|
||||||
|
* anchored at.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getPosition() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/coordinate~Coordinate|undefined} */ (this.get(Property.POSITION))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current positioning of this overlay.
|
||||||
|
* @return {module:ol/OverlayPositioning} How the overlay is positioned
|
||||||
|
* relative to its point on the map.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getPositioning() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/OverlayPositioning} */ (this.get(Property.POSITIONING))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
handleElementChanged() {
|
||||||
|
removeChildren(this.element);
|
||||||
|
const element = this.getElement();
|
||||||
|
if (element) {
|
||||||
|
this.element.appendChild(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
handleMapChanged() {
|
||||||
|
if (this.mapPostrenderListenerKey) {
|
||||||
|
removeNode(this.element);
|
||||||
|
unlistenByKey(this.mapPostrenderListenerKey);
|
||||||
|
this.mapPostrenderListenerKey = null;
|
||||||
|
}
|
||||||
|
const map = this.getMap();
|
||||||
|
if (map) {
|
||||||
|
this.mapPostrenderListenerKey = listen(map,
|
||||||
|
MapEventType.POSTRENDER, this.render, this);
|
||||||
|
this.updatePixelPosition();
|
||||||
|
const container = this.stopEvent ?
|
||||||
|
map.getOverlayContainerStopEvent() : map.getOverlayContainer();
|
||||||
|
if (this.insertFirst) {
|
||||||
|
container.insertBefore(this.element, container.childNodes[0] || null);
|
||||||
|
} else {
|
||||||
|
container.appendChild(this.element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
this.updatePixelPosition();
|
this.updatePixelPosition();
|
||||||
const container = this.stopEvent ?
|
}
|
||||||
map.getOverlayContainerStopEvent() : map.getOverlayContainer();
|
|
||||||
if (this.insertFirst) {
|
/**
|
||||||
container.insertBefore(this.element, container.childNodes[0] || null);
|
* @protected
|
||||||
|
*/
|
||||||
|
handleOffsetChanged() {
|
||||||
|
this.updatePixelPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
handlePositionChanged() {
|
||||||
|
this.updatePixelPosition();
|
||||||
|
if (this.get(Property.POSITION) && this.autoPan) {
|
||||||
|
this.panIntoView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
handlePositioningChanged() {
|
||||||
|
this.updatePixelPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the DOM element to be associated with this overlay.
|
||||||
|
* @param {HTMLElement|undefined} element The Element containing the overlay.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setElement(element) {
|
||||||
|
this.set(Property.ELEMENT, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the map to be associated with this overlay.
|
||||||
|
* @param {module:ol/PluggableMap|undefined} map The map that the
|
||||||
|
* overlay is part of.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setMap(map) {
|
||||||
|
this.set(Property.MAP, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the offset for this overlay.
|
||||||
|
* @param {Array.<number>} offset Offset.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setOffset(offset) {
|
||||||
|
this.set(Property.OFFSET, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the position for this overlay. If the position is `undefined` the
|
||||||
|
* overlay is hidden.
|
||||||
|
* @param {module:ol/coordinate~Coordinate|undefined} position The spatial point that the overlay
|
||||||
|
* is anchored at.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setPosition(position) {
|
||||||
|
this.set(Property.POSITION, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pan the map so that the overlay is entirely visible in the current viewport
|
||||||
|
* (if necessary).
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
panIntoView() {
|
||||||
|
const map = this.getMap();
|
||||||
|
|
||||||
|
if (!map || !map.getTargetElement()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapRect = this.getRect(map.getTargetElement(), map.getSize());
|
||||||
|
const element = this.getElement();
|
||||||
|
const overlayRect = this.getRect(element, [outerWidth(element), outerHeight(element)]);
|
||||||
|
|
||||||
|
const margin = this.autoPanMargin;
|
||||||
|
if (!containsExtent(mapRect, overlayRect)) {
|
||||||
|
// the overlay is not completely inside the viewport, so pan the map
|
||||||
|
const offsetLeft = overlayRect[0] - mapRect[0];
|
||||||
|
const offsetRight = mapRect[2] - overlayRect[2];
|
||||||
|
const offsetTop = overlayRect[1] - mapRect[1];
|
||||||
|
const offsetBottom = mapRect[3] - overlayRect[3];
|
||||||
|
|
||||||
|
const delta = [0, 0];
|
||||||
|
if (offsetLeft < 0) {
|
||||||
|
// move map to the left
|
||||||
|
delta[0] = offsetLeft - margin;
|
||||||
|
} else if (offsetRight < 0) {
|
||||||
|
// move map to the right
|
||||||
|
delta[0] = Math.abs(offsetRight) + margin;
|
||||||
|
}
|
||||||
|
if (offsetTop < 0) {
|
||||||
|
// move map up
|
||||||
|
delta[1] = offsetTop - margin;
|
||||||
|
} else if (offsetBottom < 0) {
|
||||||
|
// move map down
|
||||||
|
delta[1] = Math.abs(offsetBottom) + margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta[0] !== 0 || delta[1] !== 0) {
|
||||||
|
const center = /** @type {module:ol/coordinate~Coordinate} */ (map.getView().getCenter());
|
||||||
|
const centerPx = map.getPixelFromCoordinate(center);
|
||||||
|
const newCenterPx = [
|
||||||
|
centerPx[0] + delta[0],
|
||||||
|
centerPx[1] + delta[1]
|
||||||
|
];
|
||||||
|
|
||||||
|
map.getView().animate({
|
||||||
|
center: map.getCoordinateFromPixel(newCenterPx),
|
||||||
|
duration: this.autoPanAnimation.duration,
|
||||||
|
easing: this.autoPanAnimation.easing
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the extent of an element relative to the document
|
||||||
|
* @param {HTMLElement|undefined} element The element.
|
||||||
|
* @param {module:ol/size~Size|undefined} size The size of the element.
|
||||||
|
* @return {module:ol/extent~Extent} The extent.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
getRect(element, size) {
|
||||||
|
const box = element.getBoundingClientRect();
|
||||||
|
const offsetX = box.left + window.pageXOffset;
|
||||||
|
const offsetY = box.top + window.pageYOffset;
|
||||||
|
return [
|
||||||
|
offsetX,
|
||||||
|
offsetY,
|
||||||
|
offsetX + size[0],
|
||||||
|
offsetY + size[1]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the positioning for this overlay.
|
||||||
|
* @param {module:ol/OverlayPositioning} positioning how the overlay is
|
||||||
|
* positioned relative to its point on the map.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setPositioning(positioning) {
|
||||||
|
this.set(Property.POSITIONING, positioning);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the visibility of the element.
|
||||||
|
* @param {boolean} visible Element visibility.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
setVisible(visible) {
|
||||||
|
if (this.rendered.visible !== visible) {
|
||||||
|
this.element.style.display = visible ? '' : 'none';
|
||||||
|
this.rendered.visible = visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update pixel position.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
updatePixelPosition() {
|
||||||
|
const map = this.getMap();
|
||||||
|
const position = this.getPosition();
|
||||||
|
if (!map || !map.isRendered() || !position) {
|
||||||
|
this.setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pixel = map.getPixelFromCoordinate(position);
|
||||||
|
const mapSize = map.getSize();
|
||||||
|
this.updateRenderedPosition(pixel, mapSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/pixel~Pixel} pixel The pixel location.
|
||||||
|
* @param {module:ol/size~Size|undefined} mapSize The map size.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
updateRenderedPosition(pixel, mapSize) {
|
||||||
|
const style = this.element.style;
|
||||||
|
const offset = this.getOffset();
|
||||||
|
|
||||||
|
const positioning = this.getPositioning();
|
||||||
|
|
||||||
|
this.setVisible(true);
|
||||||
|
|
||||||
|
let offsetX = offset[0];
|
||||||
|
let offsetY = offset[1];
|
||||||
|
if (positioning == OverlayPositioning.BOTTOM_RIGHT ||
|
||||||
|
positioning == OverlayPositioning.CENTER_RIGHT ||
|
||||||
|
positioning == OverlayPositioning.TOP_RIGHT) {
|
||||||
|
if (this.rendered.left_ !== '') {
|
||||||
|
this.rendered.left_ = style.left = '';
|
||||||
|
}
|
||||||
|
const right = Math.round(mapSize[0] - pixel[0] - offsetX) + 'px';
|
||||||
|
if (this.rendered.right_ != right) {
|
||||||
|
this.rendered.right_ = style.right = right;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
container.appendChild(this.element);
|
if (this.rendered.right_ !== '') {
|
||||||
|
this.rendered.right_ = style.right = '';
|
||||||
|
}
|
||||||
|
if (positioning == OverlayPositioning.BOTTOM_CENTER ||
|
||||||
|
positioning == OverlayPositioning.CENTER_CENTER ||
|
||||||
|
positioning == OverlayPositioning.TOP_CENTER) {
|
||||||
|
offsetX -= this.element.offsetWidth / 2;
|
||||||
|
}
|
||||||
|
const left = Math.round(pixel[0] + offsetX) + 'px';
|
||||||
|
if (this.rendered.left_ != left) {
|
||||||
|
this.rendered.left_ = style.left = left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (positioning == OverlayPositioning.BOTTOM_LEFT ||
|
||||||
|
positioning == OverlayPositioning.BOTTOM_CENTER ||
|
||||||
|
positioning == OverlayPositioning.BOTTOM_RIGHT) {
|
||||||
|
if (this.rendered.top_ !== '') {
|
||||||
|
this.rendered.top_ = style.top = '';
|
||||||
|
}
|
||||||
|
const bottom = Math.round(mapSize[1] - pixel[1] - offsetY) + 'px';
|
||||||
|
if (this.rendered.bottom_ != bottom) {
|
||||||
|
this.rendered.bottom_ = style.bottom = bottom;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.rendered.bottom_ !== '') {
|
||||||
|
this.rendered.bottom_ = style.bottom = '';
|
||||||
|
}
|
||||||
|
if (positioning == OverlayPositioning.CENTER_LEFT ||
|
||||||
|
positioning == OverlayPositioning.CENTER_CENTER ||
|
||||||
|
positioning == OverlayPositioning.CENTER_RIGHT) {
|
||||||
|
offsetY -= this.element.offsetHeight / 2;
|
||||||
|
}
|
||||||
|
const top = Math.round(pixel[1] + offsetY) + 'px';
|
||||||
|
if (this.rendered.top_ != top) {
|
||||||
|
this.rendered.top_ = style.top = top;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* returns the options this Overlay has been created with
|
||||||
* @protected
|
* @return {module:ol/Overlay~Options} overlay options
|
||||||
*/
|
*/
|
||||||
Overlay.prototype.render = function() {
|
getOptions() {
|
||||||
this.updatePixelPosition();
|
return this.options;
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.handleOffsetChanged = function() {
|
|
||||||
this.updatePixelPosition();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.handlePositionChanged = function() {
|
|
||||||
this.updatePixelPosition();
|
|
||||||
if (this.get(Property.POSITION) && this.autoPan) {
|
|
||||||
this.panIntoView();
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.handlePositioningChanged = function() {
|
|
||||||
this.updatePixelPosition();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the DOM element to be associated with this overlay.
|
|
||||||
* @param {Element|undefined} element The Element containing the overlay.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.setElement = function(element) {
|
|
||||||
this.set(Property.ELEMENT, element);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the map to be associated with this overlay.
|
|
||||||
* @param {module:ol/PluggableMap|undefined} map The map that the
|
|
||||||
* overlay is part of.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.setMap = function(map) {
|
|
||||||
this.set(Property.MAP, map);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the offset for this overlay.
|
|
||||||
* @param {Array.<number>} offset Offset.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.setOffset = function(offset) {
|
|
||||||
this.set(Property.OFFSET, offset);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the position for this overlay. If the position is `undefined` the
|
|
||||||
* overlay is hidden.
|
|
||||||
* @param {module:ol/coordinate~Coordinate|undefined} position The spatial point that the overlay
|
|
||||||
* is anchored at.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.setPosition = function(position) {
|
|
||||||
this.set(Property.POSITION, position);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pan the map so that the overlay is entirely visible in the current viewport
|
|
||||||
* (if necessary).
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.panIntoView = function() {
|
|
||||||
const map = this.getMap();
|
|
||||||
|
|
||||||
if (!map || !map.getTargetElement()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapRect = this.getRect(map.getTargetElement(), map.getSize());
|
|
||||||
const element = /** @type {!Element} */ (this.getElement());
|
|
||||||
const overlayRect = this.getRect(element, [outerWidth(element), outerHeight(element)]);
|
|
||||||
|
|
||||||
const margin = this.autoPanMargin;
|
|
||||||
if (!containsExtent(mapRect, overlayRect)) {
|
|
||||||
// the overlay is not completely inside the viewport, so pan the map
|
|
||||||
const offsetLeft = overlayRect[0] - mapRect[0];
|
|
||||||
const offsetRight = mapRect[2] - overlayRect[2];
|
|
||||||
const offsetTop = overlayRect[1] - mapRect[1];
|
|
||||||
const offsetBottom = mapRect[3] - overlayRect[3];
|
|
||||||
|
|
||||||
const delta = [0, 0];
|
|
||||||
if (offsetLeft < 0) {
|
|
||||||
// move map to the left
|
|
||||||
delta[0] = offsetLeft - margin;
|
|
||||||
} else if (offsetRight < 0) {
|
|
||||||
// move map to the right
|
|
||||||
delta[0] = Math.abs(offsetRight) + margin;
|
|
||||||
}
|
|
||||||
if (offsetTop < 0) {
|
|
||||||
// move map up
|
|
||||||
delta[1] = offsetTop - margin;
|
|
||||||
} else if (offsetBottom < 0) {
|
|
||||||
// move map down
|
|
||||||
delta[1] = Math.abs(offsetBottom) + margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delta[0] !== 0 || delta[1] !== 0) {
|
|
||||||
const center = /** @type {module:ol/coordinate~Coordinate} */ (map.getView().getCenter());
|
|
||||||
const centerPx = map.getPixelFromCoordinate(center);
|
|
||||||
const newCenterPx = [
|
|
||||||
centerPx[0] + delta[0],
|
|
||||||
centerPx[1] + delta[1]
|
|
||||||
];
|
|
||||||
|
|
||||||
map.getView().animate({
|
|
||||||
center: map.getCoordinateFromPixel(newCenterPx),
|
|
||||||
duration: this.autoPanAnimation.duration,
|
|
||||||
easing: this.autoPanAnimation.easing
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the extent of an element relative to the document
|
|
||||||
* @param {Element|undefined} element The element.
|
|
||||||
* @param {module:ol/size~Size|undefined} size The size of the element.
|
|
||||||
* @return {module:ol/extent~Extent} The extent.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.getRect = function(element, size) {
|
|
||||||
const box = element.getBoundingClientRect();
|
|
||||||
const offsetX = box.left + window.pageXOffset;
|
|
||||||
const offsetY = box.top + window.pageYOffset;
|
|
||||||
return [
|
|
||||||
offsetX,
|
|
||||||
offsetY,
|
|
||||||
offsetX + size[0],
|
|
||||||
offsetY + size[1]
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the positioning for this overlay.
|
|
||||||
* @param {module:ol/OverlayPositioning} positioning how the overlay is
|
|
||||||
* positioned relative to its point on the map.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Overlay.prototype.setPositioning = function(positioning) {
|
|
||||||
this.set(Property.POSITIONING, positioning);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modify the visibility of the element.
|
|
||||||
* @param {boolean} visible Element visibility.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.setVisible = function(visible) {
|
|
||||||
if (this.rendered.visible !== visible) {
|
|
||||||
this.element.style.display = visible ? '' : 'none';
|
|
||||||
this.rendered.visible = visible;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update pixel position.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.updatePixelPosition = function() {
|
|
||||||
const map = this.getMap();
|
|
||||||
const position = this.getPosition();
|
|
||||||
if (!map || !map.isRendered() || !position) {
|
|
||||||
this.setVisible(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pixel = map.getPixelFromCoordinate(position);
|
|
||||||
const mapSize = map.getSize();
|
|
||||||
this.updateRenderedPosition(pixel, mapSize);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol~Pixel} pixel The pixel location.
|
|
||||||
* @param {module:ol/size~Size|undefined} mapSize The map size.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Overlay.prototype.updateRenderedPosition = function(pixel, mapSize) {
|
|
||||||
const style = this.element.style;
|
|
||||||
const offset = this.getOffset();
|
|
||||||
|
|
||||||
const positioning = this.getPositioning();
|
|
||||||
|
|
||||||
this.setVisible(true);
|
|
||||||
|
|
||||||
let offsetX = offset[0];
|
|
||||||
let offsetY = offset[1];
|
|
||||||
if (positioning == OverlayPositioning.BOTTOM_RIGHT ||
|
|
||||||
positioning == OverlayPositioning.CENTER_RIGHT ||
|
|
||||||
positioning == OverlayPositioning.TOP_RIGHT) {
|
|
||||||
if (this.rendered.left_ !== '') {
|
|
||||||
this.rendered.left_ = style.left = '';
|
|
||||||
}
|
|
||||||
const right = Math.round(mapSize[0] - pixel[0] - offsetX) + 'px';
|
|
||||||
if (this.rendered.right_ != right) {
|
|
||||||
this.rendered.right_ = style.right = right;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.rendered.right_ !== '') {
|
|
||||||
this.rendered.right_ = style.right = '';
|
|
||||||
}
|
|
||||||
if (positioning == OverlayPositioning.BOTTOM_CENTER ||
|
|
||||||
positioning == OverlayPositioning.CENTER_CENTER ||
|
|
||||||
positioning == OverlayPositioning.TOP_CENTER) {
|
|
||||||
offsetX -= this.element.offsetWidth / 2;
|
|
||||||
}
|
|
||||||
const left = Math.round(pixel[0] + offsetX) + 'px';
|
|
||||||
if (this.rendered.left_ != left) {
|
|
||||||
this.rendered.left_ = style.left = left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (positioning == OverlayPositioning.BOTTOM_LEFT ||
|
|
||||||
positioning == OverlayPositioning.BOTTOM_CENTER ||
|
|
||||||
positioning == OverlayPositioning.BOTTOM_RIGHT) {
|
|
||||||
if (this.rendered.top_ !== '') {
|
|
||||||
this.rendered.top_ = style.top = '';
|
|
||||||
}
|
|
||||||
const bottom = Math.round(mapSize[1] - pixel[1] - offsetY) + 'px';
|
|
||||||
if (this.rendered.bottom_ != bottom) {
|
|
||||||
this.rendered.bottom_ = style.bottom = bottom;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.rendered.bottom_ !== '') {
|
|
||||||
this.rendered.bottom_ = style.bottom = '';
|
|
||||||
}
|
|
||||||
if (positioning == OverlayPositioning.CENTER_LEFT ||
|
|
||||||
positioning == OverlayPositioning.CENTER_CENTER ||
|
|
||||||
positioning == OverlayPositioning.CENTER_RIGHT) {
|
|
||||||
offsetY -= this.element.offsetHeight / 2;
|
|
||||||
}
|
|
||||||
const top = Math.round(pixel[1] + offsetY) + 'px';
|
|
||||||
if (this.rendered.top_ != top) {
|
|
||||||
this.rendered.top_ = style.top = top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the options this Overlay has been created with
|
|
||||||
* @return {module:ol/Overlay~Options} overlay options
|
|
||||||
*/
|
|
||||||
Overlay.prototype.getOptions = function() {
|
|
||||||
return this.options;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Overlay;
|
export default Overlay;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +0,0 @@
|
|||||||
# ol
|
|
||||||
|
|
||||||
OpenLayers as ES modules.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Add the `ol` package as a dependency to your project.
|
|
||||||
|
|
||||||
npm install ol --save
|
|
||||||
|
|
||||||
Import just what you need for your application:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import Map from 'ol/Map';
|
|
||||||
import View from 'ol/View';
|
|
||||||
import TileLayer from 'ol/layer/Tile';
|
|
||||||
import XYZ from 'ol/source/XYZ';
|
|
||||||
|
|
||||||
new Map({
|
|
||||||
target: 'map',
|
|
||||||
layers: [
|
|
||||||
new TileLayer({
|
|
||||||
source: new XYZ({
|
|
||||||
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
],
|
|
||||||
view: new View({
|
|
||||||
center: [0, 0],
|
|
||||||
zoom: 2
|
|
||||||
})
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
See the following examples for more detail on bundling OpenLayers with your application:
|
|
||||||
|
|
||||||
* Using [Rollup & Uglify](https://gist.github.com/tschaub/8beb328ea72b36446fc2198d008287de)
|
|
||||||
* Using [Rollup & Closure Compiler](https://gist.github.com/tschaub/32a5692bedac5254da24fa3b12072f35)
|
|
||||||
* Using [Webpack & Uglify](https://gist.github.com/tschaub/79025aef325cd2837364400a105405b8)
|
|
||||||
* Using [Webpack & Closure Compiler](https://gist.github.com/ahocevar/8ceafc6293455ba491dd9be12c15761f)
|
|
||||||
* Using [Browserify & Uglify](https://gist.github.com/tschaub/4bfb209a8f809823f1495b2e4436018e)
|
|
||||||
|
|
||||||
## Module Identifiers
|
|
||||||
|
|
||||||
The module identifiers shown in the above snippet (e.g. `ol/Map`, note the CamelCase module name) are default exports of constructors. There are also modules like 'ol/proj' (note the lowercase module name), which provide named exports for utility functions and constants, e.g.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import {fromLonLat} from 'ol/proj';
|
|
||||||
|
|
||||||
map.setCenter(fromLonLat([16, 48]));
|
|
||||||
```
|
|
||||||
See the [API documentation](http://openlayers.org/en/latest/apidoc/) for a reference of all modules, and just keep in mind: CamelCase modules provide a default export, lowercase modules provide named exports.
|
|
||||||
365
src/ol/Tile.js
365
src/ol/Tile.js
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/Tile
|
* @module ol/Tile
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import TileState from './TileState.js';
|
import TileState from './TileState.js';
|
||||||
import {easeIn} from './easing.js';
|
import {easeIn} from './easing.js';
|
||||||
import EventTarget from './events/EventTarget.js';
|
import EventTarget from './events/EventTarget.js';
|
||||||
@@ -44,221 +43,221 @@ import EventType from './events/EventType.js';
|
|||||||
* @classdesc
|
* @classdesc
|
||||||
* Base class for tiles.
|
* Base class for tiles.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @extends {module:ol/events/EventTarget}
|
*/
|
||||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
class Tile extends EventTarget {
|
||||||
* @param {module:ol/TileState} state State.
|
|
||||||
* @param {module:ol/Tile~Options=} opt_options Tile options.
|
|
||||||
*/
|
|
||||||
const Tile = function(tileCoord, state, opt_options) {
|
|
||||||
EventTarget.call(this);
|
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {module:ol/tilecoord~TileCoord}
|
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||||
|
* @param {module:ol/TileState} state State.
|
||||||
|
* @param {module:ol/Tile~Options=} opt_options Tile options.
|
||||||
*/
|
*/
|
||||||
this.tileCoord = tileCoord;
|
constructor(tileCoord, state, opt_options) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {module:ol/tilecoord~TileCoord}
|
||||||
|
*/
|
||||||
|
this.tileCoord = tileCoord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {module:ol/TileState}
|
||||||
|
*/
|
||||||
|
this.state = state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An "interim" tile for this tile. The interim tile may be used while this
|
||||||
|
* one is loading, for "smooth" transitions when changing params/dimensions
|
||||||
|
* on the source.
|
||||||
|
* @type {module:ol/Tile}
|
||||||
|
*/
|
||||||
|
this.interimTile = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A key assigned to the tile. This is used by the tile source to determine
|
||||||
|
* if this tile can effectively be used, or if a new tile should be created
|
||||||
|
* and this one be used as an interim tile for this new tile.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.key = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The duration for the opacity transition.
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.transition_ = options.transition === undefined ? 250 : options.transition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup of start times for rendering transitions. If the start time is
|
||||||
|
* equal to -1, the transition is complete.
|
||||||
|
* @type {Object.<number, number>}
|
||||||
|
*/
|
||||||
|
this.transitionStarts_ = {};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {module:ol/TileState}
|
|
||||||
*/
|
*/
|
||||||
this.state = state;
|
changed() {
|
||||||
|
this.dispatchEvent(EventType.CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An "interim" tile for this tile. The interim tile may be used while this
|
* @return {string} Key.
|
||||||
* one is loading, for "smooth" transitions when changing params/dimensions
|
|
||||||
* on the source.
|
|
||||||
* @type {module:ol/Tile}
|
|
||||||
*/
|
*/
|
||||||
this.interimTile = null;
|
getKey() {
|
||||||
|
return this.key + '/' + this.tileCoord;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key assigned to the tile. This is used by the tile source to determine
|
* Get the interim tile most suitable for rendering using the chain of interim
|
||||||
* if this tile can effectively be used, or if a new tile should be created
|
* tiles. This corresponds to the most recent tile that has been loaded, if no
|
||||||
* and this one be used as an interim tile for this new tile.
|
* such tile exists, the original tile is returned.
|
||||||
* @type {string}
|
* @return {!module:ol/Tile} Best tile for rendering.
|
||||||
*/
|
*/
|
||||||
this.key = '';
|
getInterimTile() {
|
||||||
|
if (!this.interimTile) {
|
||||||
|
//empty chain
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
let tile = this.interimTile;
|
||||||
|
|
||||||
/**
|
// find the first loaded tile and return it. Since the chain is sorted in
|
||||||
* The duration for the opacity transition.
|
// decreasing order of creation time, there is no need to search the remainder
|
||||||
* @type {number}
|
// of the list (all those tiles correspond to older requests and will be
|
||||||
*/
|
// cleaned up by refreshInterimChain)
|
||||||
this.transition_ = options.transition === undefined ? 250 : options.transition;
|
do {
|
||||||
|
if (tile.getState() == TileState.LOADED) {
|
||||||
|
return tile;
|
||||||
|
}
|
||||||
|
tile = tile.interimTile;
|
||||||
|
} while (tile);
|
||||||
|
|
||||||
/**
|
// we can not find a better tile
|
||||||
* Lookup of start times for rendering transitions. If the start time is
|
|
||||||
* equal to -1, the transition is complete.
|
|
||||||
* @type {Object.<number, number>}
|
|
||||||
*/
|
|
||||||
this.transitionStarts_ = {};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(Tile, EventTarget);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
Tile.prototype.changed = function() {
|
|
||||||
this.dispatchEvent(EventType.CHANGE);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {string} Key.
|
|
||||||
*/
|
|
||||||
Tile.prototype.getKey = function() {
|
|
||||||
return this.key + '/' + this.tileCoord;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the interim tile most suitable for rendering using the chain of interim
|
|
||||||
* tiles. This corresponds to the most recent tile that has been loaded, if no
|
|
||||||
* such tile exists, the original tile is returned.
|
|
||||||
* @return {!module:ol/Tile} Best tile for rendering.
|
|
||||||
*/
|
|
||||||
Tile.prototype.getInterimTile = function() {
|
|
||||||
if (!this.interimTile) {
|
|
||||||
//empty chain
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
let tile = this.interimTile;
|
|
||||||
|
|
||||||
// find the first loaded tile and return it. Since the chain is sorted in
|
/**
|
||||||
// decreasing order of creation time, there is no need to search the remainder
|
* Goes through the chain of interim tiles and discards sections of the chain
|
||||||
// of the list (all those tiles correspond to older requests and will be
|
* that are no longer relevant.
|
||||||
// cleaned up by refreshInterimChain)
|
*/
|
||||||
do {
|
refreshInterimChain() {
|
||||||
if (tile.getState() == TileState.LOADED) {
|
if (!this.interimTile) {
|
||||||
return tile;
|
return;
|
||||||
}
|
}
|
||||||
tile = tile.interimTile;
|
|
||||||
} while (tile);
|
|
||||||
|
|
||||||
// we can not find a better tile
|
let tile = this.interimTile;
|
||||||
return this;
|
let prev = this;
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
do {
|
||||||
* Goes through the chain of interim tiles and discards sections of the chain
|
if (tile.getState() == TileState.LOADED) {
|
||||||
* that are no longer relevant.
|
//we have a loaded tile, we can discard the rest of the list
|
||||||
*/
|
//we would could abort any LOADING tile request
|
||||||
Tile.prototype.refreshInterimChain = function() {
|
//older than this tile (i.e. any LOADING tile following this entry in the chain)
|
||||||
if (!this.interimTile) {
|
tile.interimTile = null;
|
||||||
return;
|
break;
|
||||||
|
} else if (tile.getState() == TileState.LOADING) {
|
||||||
|
//keep this LOADING tile any loaded tiles later in the chain are
|
||||||
|
//older than this tile, so we're still interested in the request
|
||||||
|
prev = tile;
|
||||||
|
} else if (tile.getState() == TileState.IDLE) {
|
||||||
|
//the head of the list is the most current tile, we don't need
|
||||||
|
//to start any other requests for this chain
|
||||||
|
prev.interimTile = tile.interimTile;
|
||||||
|
} else {
|
||||||
|
prev = tile;
|
||||||
|
}
|
||||||
|
tile = prev.interimTile;
|
||||||
|
} while (tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tile = this.interimTile;
|
/**
|
||||||
let prev = this;
|
* Get the tile coordinate for this tile.
|
||||||
|
* @return {module:ol/tilecoord~TileCoord} The tile coordinate.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getTileCoord() {
|
||||||
|
return this.tileCoord;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
/**
|
||||||
if (tile.getState() == TileState.LOADED) {
|
* @return {module:ol/TileState} State.
|
||||||
//we have a loaded tile, we can discard the rest of the list
|
*/
|
||||||
//we would could abort any LOADING tile request
|
getState() {
|
||||||
//older than this tile (i.e. any LOADING tile following this entry in the chain)
|
return this.state;
|
||||||
tile.interimTile = null;
|
}
|
||||||
break;
|
|
||||||
} else if (tile.getState() == TileState.LOADING) {
|
/**
|
||||||
//keep this LOADING tile any loaded tiles later in the chain are
|
* @param {module:ol/TileState} state State.
|
||||||
//older than this tile, so we're still interested in the request
|
*/
|
||||||
prev = tile;
|
setState(state) {
|
||||||
} else if (tile.getState() == TileState.IDLE) {
|
this.state = state;
|
||||||
//the head of the list is the most current tile, we don't need
|
this.changed();
|
||||||
//to start any other requests for this chain
|
}
|
||||||
prev.interimTile = tile.interimTile;
|
|
||||||
} else {
|
/**
|
||||||
prev = tile;
|
* Load the image or retry if loading previously failed.
|
||||||
|
* Loading is taken care of by the tile queue, and calling this method is
|
||||||
|
* only needed for preloading or for reloading in case of an error.
|
||||||
|
* @abstract
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
load() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the alpha value for rendering.
|
||||||
|
* @param {number} id An id for the renderer.
|
||||||
|
* @param {number} time The render frame time.
|
||||||
|
* @return {number} A number between 0 and 1.
|
||||||
|
*/
|
||||||
|
getAlpha(id, time) {
|
||||||
|
if (!this.transition_) {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
tile = prev.interimTile;
|
|
||||||
} while (tile);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
let start = this.transitionStarts_[id];
|
||||||
* Get the tile coordinate for this tile.
|
if (!start) {
|
||||||
* @return {module:ol/tilecoord~TileCoord} The tile coordinate.
|
start = time;
|
||||||
* @api
|
this.transitionStarts_[id] = start;
|
||||||
*/
|
} else if (start === -1) {
|
||||||
Tile.prototype.getTileCoord = function() {
|
return 1;
|
||||||
return this.tileCoord;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
const delta = time - start + (1000 / 60); // avoid rendering at 0
|
||||||
/**
|
if (delta >= this.transition_) {
|
||||||
* @return {module:ol/TileState} State.
|
return 1;
|
||||||
*/
|
}
|
||||||
Tile.prototype.getState = function() {
|
return easeIn(delta / this.transition_);
|
||||||
return this.state;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/TileState} state State.
|
|
||||||
*/
|
|
||||||
Tile.prototype.setState = function(state) {
|
|
||||||
this.state = state;
|
|
||||||
this.changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the image or retry if loading previously failed.
|
|
||||||
* Loading is taken care of by the tile queue, and calling this method is
|
|
||||||
* only needed for preloading or for reloading in case of an error.
|
|
||||||
* @abstract
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Tile.prototype.load = function() {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the alpha value for rendering.
|
|
||||||
* @param {number} id An id for the renderer.
|
|
||||||
* @param {number} time The render frame time.
|
|
||||||
* @return {number} A number between 0 and 1.
|
|
||||||
*/
|
|
||||||
Tile.prototype.getAlpha = function(id, time) {
|
|
||||||
if (!this.transition_) {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = this.transitionStarts_[id];
|
/**
|
||||||
if (!start) {
|
* Determine if a tile is in an alpha transition. A tile is considered in
|
||||||
start = time;
|
* transition if tile.getAlpha() has not yet been called or has been called
|
||||||
this.transitionStarts_[id] = start;
|
* and returned 1.
|
||||||
} else if (start === -1) {
|
* @param {number} id An id for the renderer.
|
||||||
return 1;
|
* @return {boolean} The tile is in transition.
|
||||||
|
*/
|
||||||
|
inTransition(id) {
|
||||||
|
if (!this.transition_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.transitionStarts_[id] !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const delta = time - start + (1000 / 60); // avoid rendering at 0
|
/**
|
||||||
if (delta >= this.transition_) {
|
* Mark a transition as complete.
|
||||||
return 1;
|
* @param {number} id An id for the renderer.
|
||||||
|
*/
|
||||||
|
endTransition(id) {
|
||||||
|
if (this.transition_) {
|
||||||
|
this.transitionStarts_[id] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return easeIn(delta / this.transition_);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if a tile is in an alpha transition. A tile is considered in
|
|
||||||
* transition if tile.getAlpha() has not yet been called or has been called
|
|
||||||
* and returned 1.
|
|
||||||
* @param {number} id An id for the renderer.
|
|
||||||
* @return {boolean} The tile is in transition.
|
|
||||||
*/
|
|
||||||
Tile.prototype.inTransition = function(id) {
|
|
||||||
if (!this.transition_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this.transitionStarts_[id] !== -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark a transition as complete.
|
|
||||||
* @param {number} id An id for the renderer.
|
|
||||||
*/
|
|
||||||
Tile.prototype.endTransition = function(id) {
|
|
||||||
if (this.transition_) {
|
|
||||||
this.transitionStarts_[id] = -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export default Tile;
|
export default Tile;
|
||||||
|
|||||||
@@ -1,56 +1,53 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/TileCache
|
* @module ol/TileCache
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import LRUCache from './structs/LRUCache.js';
|
import LRUCache from './structs/LRUCache.js';
|
||||||
import {fromKey, getKey} from './tilecoord.js';
|
import {fromKey, getKey} from './tilecoord.js';
|
||||||
|
|
||||||
/**
|
class TileCache extends LRUCache {
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/structs/LRUCache.<module:ol/Tile>}
|
|
||||||
* @param {number=} opt_highWaterMark High water mark.
|
|
||||||
* @struct
|
|
||||||
*/
|
|
||||||
const TileCache = function(opt_highWaterMark) {
|
|
||||||
|
|
||||||
LRUCache.call(this, opt_highWaterMark);
|
/**
|
||||||
|
* @param {number=} opt_highWaterMark High water mark.
|
||||||
|
*/
|
||||||
|
constructor(opt_highWaterMark) {
|
||||||
|
|
||||||
};
|
super(opt_highWaterMark);
|
||||||
|
|
||||||
inherits(TileCache, LRUCache);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @param {!Object.<string, module:ol/TileRange>} usedTiles Used tiles.
|
||||||
* @param {!Object.<string, module:ol/TileRange>} usedTiles Used tiles.
|
*/
|
||||||
*/
|
expireCache(usedTiles) {
|
||||||
TileCache.prototype.expireCache = function(usedTiles) {
|
while (this.canExpireCache()) {
|
||||||
while (this.canExpireCache()) {
|
const tile = this.peekLast();
|
||||||
const tile = this.peekLast();
|
const zKey = tile.tileCoord[0].toString();
|
||||||
const zKey = tile.tileCoord[0].toString();
|
if (zKey in usedTiles && usedTiles[zKey].contains(tile.tileCoord)) {
|
||||||
if (zKey in usedTiles && usedTiles[zKey].contains(tile.tileCoord)) {
|
break;
|
||||||
break;
|
} else {
|
||||||
} else {
|
this.pop().dispose();
|
||||||
this.pop().dispose();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* Prune all tiles from the cache that don't have the same z as the newest tile.
|
||||||
* Prune all tiles from the cache that don't have the same z as the newest tile.
|
*/
|
||||||
*/
|
pruneExceptNewestZ() {
|
||||||
TileCache.prototype.pruneExceptNewestZ = function() {
|
if (this.getCount() === 0) {
|
||||||
if (this.getCount() === 0) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
const key = this.peekFirstKey();
|
|
||||||
const tileCoord = fromKey(key);
|
|
||||||
const z = tileCoord[0];
|
|
||||||
this.forEach(function(tile) {
|
|
||||||
if (tile.tileCoord[0] !== z) {
|
|
||||||
this.remove(getKey(tile.tileCoord));
|
|
||||||
tile.dispose();
|
|
||||||
}
|
}
|
||||||
}, this);
|
const key = this.peekFirstKey();
|
||||||
};
|
const tileCoord = fromKey(key);
|
||||||
|
const z = tileCoord[0];
|
||||||
|
this.forEach(function(tile) {
|
||||||
|
if (tile.tileCoord[0] !== z) {
|
||||||
|
this.remove(getKey(tile.tileCoord));
|
||||||
|
tile.dispose();
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default TileCache;
|
export default TileCache;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/TileQueue
|
* @module ol/TileQueue
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import TileState from './TileState.js';
|
import TileState from './TileState.js';
|
||||||
import {listen, unlisten} from './events.js';
|
import {listen, unlisten} from './events.js';
|
||||||
import EventType from './events/EventType.js';
|
import EventType from './events/EventType.js';
|
||||||
@@ -13,124 +12,117 @@ import PriorityQueue from './structs/PriorityQueue.js';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
class TileQueue extends PriorityQueue {
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/structs/PriorityQueue.<Array>}
|
/**
|
||||||
* @param {module:ol/TileQueue~PriorityFunction} tilePriorityFunction
|
* @param {module:ol/TileQueue~PriorityFunction} tilePriorityFunction Tile priority function.
|
||||||
* Tile priority function.
|
* @param {function(): ?} tileChangeCallback Function called on each tile change event.
|
||||||
* @param {function(): ?} tileChangeCallback
|
*/
|
||||||
* Function called on each tile change event.
|
constructor(tilePriorityFunction, tileChangeCallback) {
|
||||||
* @struct
|
|
||||||
*/
|
super(
|
||||||
const TileQueue = function(tilePriorityFunction, tileChangeCallback) {
|
/**
|
||||||
|
* @param {Array} element Element.
|
||||||
|
* @return {number} Priority.
|
||||||
|
*/
|
||||||
|
function(element) {
|
||||||
|
return tilePriorityFunction.apply(null, element);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {Array} element Element.
|
||||||
|
* @return {string} Key.
|
||||||
|
*/
|
||||||
|
function(element) {
|
||||||
|
return (/** @type {module:ol/Tile} */ (element[0]).getKey());
|
||||||
|
});
|
||||||
|
|
||||||
PriorityQueue.call(
|
|
||||||
this,
|
|
||||||
/**
|
/**
|
||||||
* @param {Array} element Element.
|
* @private
|
||||||
* @return {number} Priority.
|
* @type {function(): ?}
|
||||||
*/
|
*/
|
||||||
function(element) {
|
this.tileChangeCallback_ = tileChangeCallback;
|
||||||
return tilePriorityFunction.apply(null, element);
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* @param {Array} element Element.
|
* @private
|
||||||
* @return {string} Key.
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
function(element) {
|
this.tilesLoading_ = 0;
|
||||||
return (/** @type {module:ol/Tile} */ (element[0]).getKey());
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {function(): ?}
|
* @type {!Object.<string,boolean>}
|
||||||
*/
|
*/
|
||||||
this.tileChangeCallback_ = tileChangeCallback;
|
this.tilesLoadingKeys_ = {};
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
this.tilesLoading_ = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {!Object.<string,boolean>}
|
|
||||||
*/
|
|
||||||
this.tilesLoadingKeys_ = {};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(TileQueue, PriorityQueue);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TileQueue.prototype.enqueue = function(element) {
|
|
||||||
const added = PriorityQueue.prototype.enqueue.call(this, element);
|
|
||||||
if (added) {
|
|
||||||
const tile = element[0];
|
|
||||||
listen(tile, EventType.CHANGE, this.handleTileChange, this);
|
|
||||||
}
|
}
|
||||||
return added;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @inheritDoc
|
||||||
* @return {number} Number of tiles loading.
|
*/
|
||||||
*/
|
enqueue(element) {
|
||||||
TileQueue.prototype.getTilesLoading = function() {
|
const added = super.enqueue(element);
|
||||||
return this.tilesLoading_;
|
if (added) {
|
||||||
};
|
const tile = element[0];
|
||||||
|
listen(tile, EventType.CHANGE, this.handleTileChange, this);
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/events/Event} event Event.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
TileQueue.prototype.handleTileChange = function(event) {
|
|
||||||
const tile = /** @type {module:ol/Tile} */ (event.target);
|
|
||||||
const state = tile.getState();
|
|
||||||
if (state === TileState.LOADED || state === TileState.ERROR ||
|
|
||||||
state === TileState.EMPTY || state === TileState.ABORT) {
|
|
||||||
unlisten(tile, EventType.CHANGE, this.handleTileChange, this);
|
|
||||||
const tileKey = tile.getKey();
|
|
||||||
if (tileKey in this.tilesLoadingKeys_) {
|
|
||||||
delete this.tilesLoadingKeys_[tileKey];
|
|
||||||
--this.tilesLoading_;
|
|
||||||
}
|
}
|
||||||
this.tileChangeCallback_();
|
return added;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {number} Number of tiles loading.
|
||||||
|
*/
|
||||||
|
getTilesLoading() {
|
||||||
|
return this.tilesLoading_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} maxTotalLoading Maximum number tiles to load simultaneously.
|
* @param {module:ol/events/Event} event Event.
|
||||||
* @param {number} maxNewLoads Maximum number of new tiles to load.
|
* @protected
|
||||||
*/
|
*/
|
||||||
TileQueue.prototype.loadMoreTiles = function(maxTotalLoading, maxNewLoads) {
|
handleTileChange(event) {
|
||||||
let newLoads = 0;
|
const tile = /** @type {module:ol/Tile} */ (event.target);
|
||||||
let abortedTiles = false;
|
const state = tile.getState();
|
||||||
let state, tile, tileKey;
|
if (state === TileState.LOADED || state === TileState.ERROR ||
|
||||||
while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads &&
|
state === TileState.EMPTY || state === TileState.ABORT) {
|
||||||
this.getCount() > 0) {
|
unlisten(tile, EventType.CHANGE, this.handleTileChange, this);
|
||||||
tile = /** @type {module:ol/Tile} */ (this.dequeue()[0]);
|
const tileKey = tile.getKey();
|
||||||
tileKey = tile.getKey();
|
if (tileKey in this.tilesLoadingKeys_) {
|
||||||
state = tile.getState();
|
delete this.tilesLoadingKeys_[tileKey];
|
||||||
if (state === TileState.ABORT) {
|
--this.tilesLoading_;
|
||||||
abortedTiles = true;
|
}
|
||||||
} else if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
|
this.tileChangeCallback_();
|
||||||
this.tilesLoadingKeys_[tileKey] = true;
|
|
||||||
++this.tilesLoading_;
|
|
||||||
++newLoads;
|
|
||||||
tile.load();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newLoads === 0 && abortedTiles) {
|
|
||||||
// Do not stop the render loop when all wanted tiles were aborted due to
|
/**
|
||||||
// a small, saturated tile cache.
|
* @param {number} maxTotalLoading Maximum number tiles to load simultaneously.
|
||||||
this.tileChangeCallback_();
|
* @param {number} maxNewLoads Maximum number of new tiles to load.
|
||||||
|
*/
|
||||||
|
loadMoreTiles(maxTotalLoading, maxNewLoads) {
|
||||||
|
let newLoads = 0;
|
||||||
|
let abortedTiles = false;
|
||||||
|
let state, tile, tileKey;
|
||||||
|
while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads &&
|
||||||
|
this.getCount() > 0) {
|
||||||
|
tile = /** @type {module:ol/Tile} */ (this.dequeue()[0]);
|
||||||
|
tileKey = tile.getKey();
|
||||||
|
state = tile.getState();
|
||||||
|
if (state === TileState.ABORT) {
|
||||||
|
abortedTiles = true;
|
||||||
|
} else if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
|
||||||
|
this.tilesLoadingKeys_[tileKey] = true;
|
||||||
|
++this.tilesLoading_;
|
||||||
|
++newLoads;
|
||||||
|
tile.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newLoads === 0 && abortedTiles) {
|
||||||
|
// Do not stop the render loop when all wanted tiles were aborted due to
|
||||||
|
// a small, saturated tile cache.
|
||||||
|
this.tileChangeCallback_();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
export default TileQueue;
|
export default TileQueue;
|
||||||
|
|||||||
@@ -1,40 +1,128 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/TileRange
|
* @module ol/TileRange
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of a contiguous block of tiles. A tile range is specified
|
* A representation of a contiguous block of tiles. A tile range is specified
|
||||||
* by its min/max tile coordinates and is inclusive of coordinates.
|
* by its min/max tile coordinates and is inclusive of coordinates.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {number} minX Minimum X.
|
|
||||||
* @param {number} maxX Maximum X.
|
|
||||||
* @param {number} minY Minimum Y.
|
|
||||||
* @param {number} maxY Maximum Y.
|
|
||||||
* @struct
|
|
||||||
*/
|
*/
|
||||||
const TileRange = function(minX, maxX, minY, maxY) {
|
class TileRange {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* @param {number} minX Minimum X.
|
||||||
|
* @param {number} maxX Maximum X.
|
||||||
|
* @param {number} minY Minimum Y.
|
||||||
|
* @param {number} maxY Maximum Y.
|
||||||
*/
|
*/
|
||||||
this.minX = minX;
|
constructor(minX, maxX, minY, maxY) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.minX = minX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.maxX = maxX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.minY = minY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.maxY = maxY;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||||
|
* @return {boolean} Contains tile coordinate.
|
||||||
*/
|
*/
|
||||||
this.maxX = maxX;
|
contains(tileCoord) {
|
||||||
|
return this.containsXY(tileCoord[1], tileCoord[2]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* @param {module:ol/TileRange} tileRange Tile range.
|
||||||
|
* @return {boolean} Contains.
|
||||||
*/
|
*/
|
||||||
this.minY = minY;
|
containsTileRange(tileRange) {
|
||||||
|
return this.minX <= tileRange.minX && tileRange.maxX <= this.maxX &&
|
||||||
|
this.minY <= tileRange.minY && tileRange.maxY <= this.maxY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* @param {number} x Tile coordinate x.
|
||||||
|
* @param {number} y Tile coordinate y.
|
||||||
|
* @return {boolean} Contains coordinate.
|
||||||
*/
|
*/
|
||||||
this.maxY = maxY;
|
containsXY(x, y) {
|
||||||
|
return this.minX <= x && x <= this.maxX && this.minY <= y && y <= this.maxY;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @param {module:ol/TileRange} tileRange Tile range.
|
||||||
|
* @return {boolean} Equals.
|
||||||
|
*/
|
||||||
|
equals(tileRange) {
|
||||||
|
return this.minX == tileRange.minX && this.minY == tileRange.minY &&
|
||||||
|
this.maxX == tileRange.maxX && this.maxY == tileRange.maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/TileRange} tileRange Tile range.
|
||||||
|
*/
|
||||||
|
extend(tileRange) {
|
||||||
|
if (tileRange.minX < this.minX) {
|
||||||
|
this.minX = tileRange.minX;
|
||||||
|
}
|
||||||
|
if (tileRange.maxX > this.maxX) {
|
||||||
|
this.maxX = tileRange.maxX;
|
||||||
|
}
|
||||||
|
if (tileRange.minY < this.minY) {
|
||||||
|
this.minY = tileRange.minY;
|
||||||
|
}
|
||||||
|
if (tileRange.maxY > this.maxY) {
|
||||||
|
this.maxY = tileRange.maxY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {number} Height.
|
||||||
|
*/
|
||||||
|
getHeight() {
|
||||||
|
return this.maxY - this.minY + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {module:ol/size~Size} Size.
|
||||||
|
*/
|
||||||
|
getSize() {
|
||||||
|
return [this.getWidth(), this.getHeight()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {number} Width.
|
||||||
|
*/
|
||||||
|
getWidth() {
|
||||||
|
return this.maxX - this.minX + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/TileRange} tileRange Tile range.
|
||||||
|
* @return {boolean} Intersects.
|
||||||
|
*/
|
||||||
|
intersects(tileRange) {
|
||||||
|
return this.minX <= tileRange.maxX &&
|
||||||
|
this.maxX >= tileRange.minX &&
|
||||||
|
this.minY <= tileRange.maxY &&
|
||||||
|
this.maxY >= tileRange.minY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,96 +146,4 @@ export function createOrUpdate(minX, maxX, minY, maxY, tileRange) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
|
||||||
* @return {boolean} Contains tile coordinate.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.contains = function(tileCoord) {
|
|
||||||
return this.containsXY(tileCoord[1], tileCoord[2]);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/TileRange} tileRange Tile range.
|
|
||||||
* @return {boolean} Contains.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.containsTileRange = function(tileRange) {
|
|
||||||
return this.minX <= tileRange.minX && tileRange.maxX <= this.maxX &&
|
|
||||||
this.minY <= tileRange.minY && tileRange.maxY <= this.maxY;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} x Tile coordinate x.
|
|
||||||
* @param {number} y Tile coordinate y.
|
|
||||||
* @return {boolean} Contains coordinate.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.containsXY = function(x, y) {
|
|
||||||
return this.minX <= x && x <= this.maxX && this.minY <= y && y <= this.maxY;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/TileRange} tileRange Tile range.
|
|
||||||
* @return {boolean} Equals.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.equals = function(tileRange) {
|
|
||||||
return this.minX == tileRange.minX && this.minY == tileRange.minY &&
|
|
||||||
this.maxX == tileRange.maxX && this.maxY == tileRange.maxY;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/TileRange} tileRange Tile range.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.extend = function(tileRange) {
|
|
||||||
if (tileRange.minX < this.minX) {
|
|
||||||
this.minX = tileRange.minX;
|
|
||||||
}
|
|
||||||
if (tileRange.maxX > this.maxX) {
|
|
||||||
this.maxX = tileRange.maxX;
|
|
||||||
}
|
|
||||||
if (tileRange.minY < this.minY) {
|
|
||||||
this.minY = tileRange.minY;
|
|
||||||
}
|
|
||||||
if (tileRange.maxY > this.maxY) {
|
|
||||||
this.maxY = tileRange.maxY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {number} Height.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.getHeight = function() {
|
|
||||||
return this.maxY - this.minY + 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {module:ol/size~Size} Size.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.getSize = function() {
|
|
||||||
return [this.getWidth(), this.getHeight()];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {number} Width.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.getWidth = function() {
|
|
||||||
return this.maxX - this.minX + 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/TileRange} tileRange Tile range.
|
|
||||||
* @return {boolean} Intersects.
|
|
||||||
*/
|
|
||||||
TileRange.prototype.intersects = function(tileRange) {
|
|
||||||
return this.minX <= tileRange.maxX &&
|
|
||||||
this.maxX >= tileRange.minX &&
|
|
||||||
this.minY <= tileRange.maxY &&
|
|
||||||
this.maxY >= tileRange.minY;
|
|
||||||
};
|
|
||||||
export default TileRange;
|
export default TileRange;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/VectorImageTile
|
* @module ol/VectorImageTile
|
||||||
*/
|
*/
|
||||||
import {getUid, inherits} from './util.js';
|
import {getUid} from './util.js';
|
||||||
import Tile from './Tile.js';
|
import Tile from './Tile.js';
|
||||||
import TileState from './TileState.js';
|
import TileState from './TileState.js';
|
||||||
import {createCanvasContext2D} from './dom.js';
|
import {createCanvasContext2D} from './dom.js';
|
||||||
@@ -21,307 +21,299 @@ import {UNDEFINED} from './functions.js';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
class VectorImageTile extends Tile {
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Tile}
|
|
||||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
|
||||||
* @param {module:ol/TileState} state State.
|
|
||||||
* @param {number} sourceRevision Source revision.
|
|
||||||
* @param {module:ol/format/Feature} format Feature format.
|
|
||||||
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
|
|
||||||
* @param {module:ol/tilecoord~TileCoord} urlTileCoord Wrapped tile coordinate for source urls.
|
|
||||||
* @param {module:ol/Tile~UrlFunction} tileUrlFunction Tile url function.
|
|
||||||
* @param {module:ol/tilegrid/TileGrid} sourceTileGrid Tile grid of the source.
|
|
||||||
* @param {module:ol/tilegrid/TileGrid} tileGrid Tile grid of the renderer.
|
|
||||||
* @param {Object.<string, module:ol/VectorTile>} sourceTiles Source tiles.
|
|
||||||
* @param {number} pixelRatio Pixel ratio.
|
|
||||||
* @param {module:ol/proj/Projection} projection Projection.
|
|
||||||
* @param {function(new: module:ol/VectorTile, module:ol/tilecoord~TileCoord, module:ol/TileState, string,
|
|
||||||
* module:ol/format/Feature, module:ol/Tile~LoadFunction)} tileClass Class to
|
|
||||||
* instantiate for source tiles.
|
|
||||||
* @param {function(this: module:ol/source/VectorTile, module:ol/events/Event)} handleTileChange
|
|
||||||
* Function to call when a source tile's state changes.
|
|
||||||
* @param {number} zoom Integer zoom to render the tile for.
|
|
||||||
*/
|
|
||||||
const VectorImageTile = function(tileCoord, state, sourceRevision, format,
|
|
||||||
tileLoadFunction, urlTileCoord, tileUrlFunction, sourceTileGrid, tileGrid,
|
|
||||||
sourceTiles, pixelRatio, projection, tileClass, handleTileChange, zoom) {
|
|
||||||
|
|
||||||
Tile.call(this, tileCoord, state, {transition: 0});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||||
* @type {!Object.<string, CanvasRenderingContext2D>}
|
* @param {module:ol/TileState} state State.
|
||||||
|
* @param {number} sourceRevision Source revision.
|
||||||
|
* @param {module:ol/format/Feature} format Feature format.
|
||||||
|
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
|
||||||
|
* @param {module:ol/tilecoord~TileCoord} urlTileCoord Wrapped tile coordinate for source urls.
|
||||||
|
* @param {module:ol/Tile~UrlFunction} tileUrlFunction Tile url function.
|
||||||
|
* @param {module:ol/tilegrid/TileGrid} sourceTileGrid Tile grid of the source.
|
||||||
|
* @param {module:ol/tilegrid/TileGrid} tileGrid Tile grid of the renderer.
|
||||||
|
* @param {Object.<string, module:ol/VectorTile>} sourceTiles Source tiles.
|
||||||
|
* @param {number} pixelRatio Pixel ratio.
|
||||||
|
* @param {module:ol/proj/Projection} projection Projection.
|
||||||
|
* @param {function(new: module:ol/VectorTile, module:ol/tilecoord~TileCoord, module:ol/TileState, string,
|
||||||
|
* module:ol/format/Feature, module:ol/Tile~LoadFunction)} tileClass Class to
|
||||||
|
* instantiate for source tiles.
|
||||||
|
* @param {function(this: module:ol/source/VectorTile, module:ol/events/Event)} handleTileChange
|
||||||
|
* Function to call when a source tile's state changes.
|
||||||
|
* @param {number} zoom Integer zoom to render the tile for.
|
||||||
*/
|
*/
|
||||||
this.context_ = {};
|
constructor(tileCoord, state, sourceRevision, format, tileLoadFunction,
|
||||||
|
urlTileCoord, tileUrlFunction, sourceTileGrid, tileGrid, sourceTiles,
|
||||||
|
pixelRatio, projection, tileClass, handleTileChange, zoom) {
|
||||||
|
|
||||||
/**
|
super(tileCoord, state, {transition: 0});
|
||||||
* @private
|
|
||||||
* @type {module:ol/featureloader~FeatureLoader}
|
|
||||||
*/
|
|
||||||
this.loader_;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {!Object.<string, module:ol/VectorImageTile~ReplayState>}
|
* @type {!Object.<string, CanvasRenderingContext2D>}
|
||||||
*/
|
*/
|
||||||
this.replayState_ = {};
|
this.context_ = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {Object.<string, module:ol/VectorTile>}
|
* @type {module:ol/featureloader~FeatureLoader}
|
||||||
*/
|
*/
|
||||||
this.sourceTiles_ = sourceTiles;
|
this.loader_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keys of source tiles used by this tile. Use with {@link #getTile}.
|
* @private
|
||||||
* @type {Array.<string>}
|
* @type {!Object.<string, module:ol/VectorImageTile~ReplayState>}
|
||||||
*/
|
*/
|
||||||
this.tileKeys = [];
|
this.replayState_ = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {module:ol/extent~Extent}
|
* @private
|
||||||
*/
|
* @type {Object.<string, module:ol/VectorTile>}
|
||||||
this.extent = null;
|
*/
|
||||||
|
this.sourceTiles_ = sourceTiles;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* Keys of source tiles used by this tile. Use with {@link #getTile}.
|
||||||
*/
|
* @type {Array.<string>}
|
||||||
this.sourceRevision_ = sourceRevision;
|
*/
|
||||||
|
this.tileKeys = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {module:ol/tilecoord~TileCoord}
|
* @type {module:ol/extent~Extent}
|
||||||
*/
|
*/
|
||||||
this.wrappedTileCoord = urlTileCoord;
|
this.extent = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Array.<module:ol/events~EventsKey>}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.loadListenerKeys_ = [];
|
this.sourceRevision_ = sourceRevision;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Array.<module:ol/events~EventsKey>}
|
* @type {module:ol/tilecoord~TileCoord}
|
||||||
*/
|
*/
|
||||||
this.sourceTileListenerKeys_ = [];
|
this.wrappedTileCoord = urlTileCoord;
|
||||||
|
|
||||||
if (urlTileCoord) {
|
/**
|
||||||
const extent = this.extent = tileGrid.getTileCoordExtent(urlTileCoord);
|
* @type {Array.<module:ol/events~EventsKey>}
|
||||||
const resolution = tileGrid.getResolution(zoom);
|
*/
|
||||||
const sourceZ = sourceTileGrid.getZForResolution(resolution);
|
this.loadListenerKeys_ = [];
|
||||||
const useLoadedOnly = zoom != tileCoord[0];
|
|
||||||
let loadCount = 0;
|
/**
|
||||||
sourceTileGrid.forEachTileCoord(extent, sourceZ, function(sourceTileCoord) {
|
* @type {Array.<module:ol/events~EventsKey>}
|
||||||
let sharedExtent = getIntersection(extent,
|
*/
|
||||||
sourceTileGrid.getTileCoordExtent(sourceTileCoord));
|
this.sourceTileListenerKeys_ = [];
|
||||||
const sourceExtent = sourceTileGrid.getExtent();
|
|
||||||
if (sourceExtent) {
|
if (urlTileCoord) {
|
||||||
sharedExtent = getIntersection(sharedExtent, sourceExtent, sharedExtent);
|
const extent = this.extent = tileGrid.getTileCoordExtent(urlTileCoord);
|
||||||
}
|
const resolution = tileGrid.getResolution(zoom);
|
||||||
if (getWidth(sharedExtent) / resolution >= 0.5 &&
|
const sourceZ = sourceTileGrid.getZForResolution(resolution);
|
||||||
getHeight(sharedExtent) / resolution >= 0.5) {
|
const useLoadedOnly = zoom != tileCoord[0];
|
||||||
// only include source tile if overlap is at least 1 pixel
|
let loadCount = 0;
|
||||||
++loadCount;
|
sourceTileGrid.forEachTileCoord(extent, sourceZ, function(sourceTileCoord) {
|
||||||
const sourceTileKey = sourceTileCoord.toString();
|
let sharedExtent = getIntersection(extent,
|
||||||
let sourceTile = sourceTiles[sourceTileKey];
|
sourceTileGrid.getTileCoordExtent(sourceTileCoord));
|
||||||
if (!sourceTile && !useLoadedOnly) {
|
const sourceExtent = sourceTileGrid.getExtent();
|
||||||
const tileUrl = tileUrlFunction(sourceTileCoord, pixelRatio, projection);
|
if (sourceExtent) {
|
||||||
sourceTile = sourceTiles[sourceTileKey] = new tileClass(sourceTileCoord,
|
sharedExtent = getIntersection(sharedExtent, sourceExtent, sharedExtent);
|
||||||
tileUrl == undefined ? TileState.EMPTY : TileState.IDLE,
|
|
||||||
tileUrl == undefined ? '' : tileUrl,
|
|
||||||
format, tileLoadFunction);
|
|
||||||
this.sourceTileListenerKeys_.push(
|
|
||||||
listen(sourceTile, EventType.CHANGE, handleTileChange));
|
|
||||||
}
|
}
|
||||||
if (sourceTile && (!useLoadedOnly || sourceTile.getState() == TileState.LOADED)) {
|
if (getWidth(sharedExtent) / resolution >= 0.5 &&
|
||||||
sourceTile.consumers++;
|
getHeight(sharedExtent) / resolution >= 0.5) {
|
||||||
this.tileKeys.push(sourceTileKey);
|
// only include source tile if overlap is at least 1 pixel
|
||||||
}
|
++loadCount;
|
||||||
}
|
const sourceTileKey = sourceTileCoord.toString();
|
||||||
}.bind(this));
|
let sourceTile = sourceTiles[sourceTileKey];
|
||||||
|
if (!sourceTile && !useLoadedOnly) {
|
||||||
if (useLoadedOnly && loadCount == this.tileKeys.length) {
|
const tileUrl = tileUrlFunction(sourceTileCoord, pixelRatio, projection);
|
||||||
this.finishLoading_();
|
sourceTile = sourceTiles[sourceTileKey] = new tileClass(sourceTileCoord,
|
||||||
}
|
tileUrl == undefined ? TileState.EMPTY : TileState.IDLE,
|
||||||
|
tileUrl == undefined ? '' : tileUrl,
|
||||||
if (zoom <= tileCoord[0] && this.state != TileState.LOADED) {
|
format, tileLoadFunction);
|
||||||
while (zoom > tileGrid.getMinZoom()) {
|
this.sourceTileListenerKeys_.push(
|
||||||
const tile = new VectorImageTile(tileCoord, state, sourceRevision,
|
listen(sourceTile, EventType.CHANGE, handleTileChange));
|
||||||
format, tileLoadFunction, urlTileCoord, tileUrlFunction,
|
|
||||||
sourceTileGrid, tileGrid, sourceTiles, pixelRatio, projection,
|
|
||||||
tileClass, UNDEFINED, --zoom);
|
|
||||||
if (tile.state == TileState.LOADED) {
|
|
||||||
this.interimTile = tile;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(VectorImageTile, Tile);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
VectorImageTile.prototype.disposeInternal = function() {
|
|
||||||
this.state = TileState.ABORT;
|
|
||||||
this.changed();
|
|
||||||
if (this.interimTile) {
|
|
||||||
this.interimTile.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0, ii = this.tileKeys.length; i < ii; ++i) {
|
|
||||||
const sourceTileKey = this.tileKeys[i];
|
|
||||||
const sourceTile = this.getTile(sourceTileKey);
|
|
||||||
sourceTile.consumers--;
|
|
||||||
if (sourceTile.consumers == 0) {
|
|
||||||
delete this.sourceTiles_[sourceTileKey];
|
|
||||||
sourceTile.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.tileKeys.length = 0;
|
|
||||||
this.sourceTiles_ = null;
|
|
||||||
this.loadListenerKeys_.forEach(unlistenByKey);
|
|
||||||
this.loadListenerKeys_.length = 0;
|
|
||||||
this.sourceTileListenerKeys_.forEach(unlistenByKey);
|
|
||||||
this.sourceTileListenerKeys_.length = 0;
|
|
||||||
Tile.prototype.disposeInternal.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/layer/Layer} layer Layer.
|
|
||||||
* @return {CanvasRenderingContext2D} The rendering context.
|
|
||||||
*/
|
|
||||||
VectorImageTile.prototype.getContext = function(layer) {
|
|
||||||
const key = getUid(layer).toString();
|
|
||||||
if (!(key in this.context_)) {
|
|
||||||
this.context_[key] = createCanvasContext2D();
|
|
||||||
}
|
|
||||||
return this.context_[key];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the Canvas for this tile.
|
|
||||||
* @param {module:ol/layer/Layer} layer Layer.
|
|
||||||
* @return {HTMLCanvasElement} Canvas.
|
|
||||||
*/
|
|
||||||
VectorImageTile.prototype.getImage = function(layer) {
|
|
||||||
return this.getReplayState(layer).renderedTileRevision == -1 ?
|
|
||||||
null : this.getContext(layer).canvas;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/layer/Layer} layer Layer.
|
|
||||||
* @return {module:ol/VectorImageTile~ReplayState} The replay state.
|
|
||||||
*/
|
|
||||||
VectorImageTile.prototype.getReplayState = function(layer) {
|
|
||||||
const key = getUid(layer).toString();
|
|
||||||
if (!(key in this.replayState_)) {
|
|
||||||
this.replayState_[key] = {
|
|
||||||
dirty: false,
|
|
||||||
renderedRenderOrder: null,
|
|
||||||
renderedRevision: -1,
|
|
||||||
renderedTileRevision: -1
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return this.replayState_[key];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
VectorImageTile.prototype.getKey = function() {
|
|
||||||
return this.tileKeys.join('/') + '-' + this.sourceRevision_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} tileKey Key (tileCoord) of the source tile.
|
|
||||||
* @return {module:ol/VectorTile} Source tile.
|
|
||||||
*/
|
|
||||||
VectorImageTile.prototype.getTile = function(tileKey) {
|
|
||||||
return this.sourceTiles_[tileKey];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
VectorImageTile.prototype.load = function() {
|
|
||||||
// Source tiles with LOADED state - we just count them because once they are
|
|
||||||
// loaded, we're no longer listening to state changes.
|
|
||||||
let leftToLoad = 0;
|
|
||||||
// Source tiles with ERROR state - we track them because they can still have
|
|
||||||
// an ERROR state after another load attempt.
|
|
||||||
const errorSourceTiles = {};
|
|
||||||
|
|
||||||
if (this.state == TileState.IDLE) {
|
|
||||||
this.setState(TileState.LOADING);
|
|
||||||
}
|
|
||||||
if (this.state == TileState.LOADING) {
|
|
||||||
this.tileKeys.forEach(function(sourceTileKey) {
|
|
||||||
const sourceTile = this.getTile(sourceTileKey);
|
|
||||||
if (sourceTile.state == TileState.IDLE) {
|
|
||||||
sourceTile.setLoader(this.loader_);
|
|
||||||
sourceTile.load();
|
|
||||||
}
|
|
||||||
if (sourceTile.state == TileState.LOADING) {
|
|
||||||
const key = listen(sourceTile, EventType.CHANGE, function(e) {
|
|
||||||
const state = sourceTile.getState();
|
|
||||||
if (state == TileState.LOADED ||
|
|
||||||
state == TileState.ERROR) {
|
|
||||||
const uid = getUid(sourceTile);
|
|
||||||
if (state == TileState.ERROR) {
|
|
||||||
errorSourceTiles[uid] = true;
|
|
||||||
} else {
|
|
||||||
--leftToLoad;
|
|
||||||
delete errorSourceTiles[uid];
|
|
||||||
}
|
|
||||||
if (leftToLoad - Object.keys(errorSourceTiles).length == 0) {
|
|
||||||
this.finishLoading_();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
if (sourceTile && (!useLoadedOnly || sourceTile.getState() == TileState.LOADED)) {
|
||||||
this.loadListenerKeys_.push(key);
|
sourceTile.consumers++;
|
||||||
++leftToLoad;
|
this.tileKeys.push(sourceTileKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
if (useLoadedOnly && loadCount == this.tileKeys.length) {
|
||||||
|
this.finishLoading_();
|
||||||
}
|
}
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
if (leftToLoad - Object.keys(errorSourceTiles).length == 0) {
|
|
||||||
setTimeout(this.finishLoading_.bind(this), 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
if (zoom <= tileCoord[0] && this.state != TileState.LOADED) {
|
||||||
|
while (zoom > tileGrid.getMinZoom()) {
|
||||||
|
const tile = new VectorImageTile(tileCoord, state, sourceRevision,
|
||||||
|
format, tileLoadFunction, urlTileCoord, tileUrlFunction,
|
||||||
|
sourceTileGrid, tileGrid, sourceTiles, pixelRatio, projection,
|
||||||
|
tileClass, UNDEFINED, --zoom);
|
||||||
|
if (tile.state == TileState.LOADED) {
|
||||||
|
this.interimTile = tile;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
VectorImageTile.prototype.finishLoading_ = function() {
|
|
||||||
let loaded = this.tileKeys.length;
|
|
||||||
let empty = 0;
|
|
||||||
for (let i = loaded - 1; i >= 0; --i) {
|
|
||||||
const state = this.getTile(this.tileKeys[i]).getState();
|
|
||||||
if (state != TileState.LOADED) {
|
|
||||||
--loaded;
|
|
||||||
}
|
|
||||||
if (state == TileState.EMPTY) {
|
|
||||||
++empty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (loaded == this.tileKeys.length) {
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
disposeInternal() {
|
||||||
|
this.state = TileState.ABORT;
|
||||||
|
this.changed();
|
||||||
|
if (this.interimTile) {
|
||||||
|
this.interimTile.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0, ii = this.tileKeys.length; i < ii; ++i) {
|
||||||
|
const sourceTileKey = this.tileKeys[i];
|
||||||
|
const sourceTile = this.getTile(sourceTileKey);
|
||||||
|
sourceTile.consumers--;
|
||||||
|
if (sourceTile.consumers == 0) {
|
||||||
|
delete this.sourceTiles_[sourceTileKey];
|
||||||
|
sourceTile.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.tileKeys.length = 0;
|
||||||
|
this.sourceTiles_ = null;
|
||||||
this.loadListenerKeys_.forEach(unlistenByKey);
|
this.loadListenerKeys_.forEach(unlistenByKey);
|
||||||
this.loadListenerKeys_.length = 0;
|
this.loadListenerKeys_.length = 0;
|
||||||
this.setState(TileState.LOADED);
|
this.sourceTileListenerKeys_.forEach(unlistenByKey);
|
||||||
} else {
|
this.sourceTileListenerKeys_.length = 0;
|
||||||
this.setState(empty == this.tileKeys.length ? TileState.EMPTY : TileState.ERROR);
|
super.disposeInternal();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/layer/Layer} layer Layer.
|
||||||
|
* @return {CanvasRenderingContext2D} The rendering context.
|
||||||
|
*/
|
||||||
|
getContext(layer) {
|
||||||
|
const key = getUid(layer).toString();
|
||||||
|
if (!(key in this.context_)) {
|
||||||
|
this.context_[key] = createCanvasContext2D();
|
||||||
|
}
|
||||||
|
return this.context_[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Canvas for this tile.
|
||||||
|
* @param {module:ol/layer/Layer} layer Layer.
|
||||||
|
* @return {HTMLCanvasElement} Canvas.
|
||||||
|
*/
|
||||||
|
getImage(layer) {
|
||||||
|
return this.getReplayState(layer).renderedTileRevision == -1 ?
|
||||||
|
null : this.getContext(layer).canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/layer/Layer} layer Layer.
|
||||||
|
* @return {module:ol/VectorImageTile~ReplayState} The replay state.
|
||||||
|
*/
|
||||||
|
getReplayState(layer) {
|
||||||
|
const key = getUid(layer).toString();
|
||||||
|
if (!(key in this.replayState_)) {
|
||||||
|
this.replayState_[key] = {
|
||||||
|
dirty: false,
|
||||||
|
renderedRenderOrder: null,
|
||||||
|
renderedRevision: -1,
|
||||||
|
renderedTileRevision: -1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.replayState_[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
getKey() {
|
||||||
|
return this.tileKeys.join('/') + '-' + this.sourceRevision_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} tileKey Key (tileCoord) of the source tile.
|
||||||
|
* @return {module:ol/VectorTile} Source tile.
|
||||||
|
*/
|
||||||
|
getTile(tileKey) {
|
||||||
|
return this.sourceTiles_[tileKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
load() {
|
||||||
|
// Source tiles with LOADED state - we just count them because once they are
|
||||||
|
// loaded, we're no longer listening to state changes.
|
||||||
|
let leftToLoad = 0;
|
||||||
|
// Source tiles with ERROR state - we track them because they can still have
|
||||||
|
// an ERROR state after another load attempt.
|
||||||
|
const errorSourceTiles = {};
|
||||||
|
|
||||||
|
if (this.state == TileState.IDLE) {
|
||||||
|
this.setState(TileState.LOADING);
|
||||||
|
}
|
||||||
|
if (this.state == TileState.LOADING) {
|
||||||
|
this.tileKeys.forEach(function(sourceTileKey) {
|
||||||
|
const sourceTile = this.getTile(sourceTileKey);
|
||||||
|
if (sourceTile.state == TileState.IDLE) {
|
||||||
|
sourceTile.setLoader(this.loader_);
|
||||||
|
sourceTile.load();
|
||||||
|
}
|
||||||
|
if (sourceTile.state == TileState.LOADING) {
|
||||||
|
const key = listen(sourceTile, EventType.CHANGE, function(e) {
|
||||||
|
const state = sourceTile.getState();
|
||||||
|
if (state == TileState.LOADED ||
|
||||||
|
state == TileState.ERROR) {
|
||||||
|
const uid = getUid(sourceTile);
|
||||||
|
if (state == TileState.ERROR) {
|
||||||
|
errorSourceTiles[uid] = true;
|
||||||
|
} else {
|
||||||
|
--leftToLoad;
|
||||||
|
delete errorSourceTiles[uid];
|
||||||
|
}
|
||||||
|
if (leftToLoad - Object.keys(errorSourceTiles).length == 0) {
|
||||||
|
this.finishLoading_();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
this.loadListenerKeys_.push(key);
|
||||||
|
++leftToLoad;
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
if (leftToLoad - Object.keys(errorSourceTiles).length == 0) {
|
||||||
|
setTimeout(this.finishLoading_.bind(this), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
finishLoading_() {
|
||||||
|
let loaded = this.tileKeys.length;
|
||||||
|
let empty = 0;
|
||||||
|
for (let i = loaded - 1; i >= 0; --i) {
|
||||||
|
const state = this.getTile(this.tileKeys[i]).getState();
|
||||||
|
if (state != TileState.LOADED) {
|
||||||
|
--loaded;
|
||||||
|
}
|
||||||
|
if (state == TileState.EMPTY) {
|
||||||
|
++empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (loaded == this.tileKeys.length) {
|
||||||
|
this.loadListenerKeys_.forEach(unlistenByKey);
|
||||||
|
this.loadListenerKeys_.length = 0;
|
||||||
|
this.setState(TileState.LOADED);
|
||||||
|
} else {
|
||||||
|
this.setState(empty == this.tileKeys.length ? TileState.EMPTY : TileState.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default VectorImageTile;
|
export default VectorImageTile;
|
||||||
|
|
||||||
|
|||||||
@@ -1,88 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/VectorTile
|
* @module ol/VectorTile
|
||||||
*/
|
*/
|
||||||
import {getUid, inherits} from './util.js';
|
import {getUid} from './util.js';
|
||||||
import Tile from './Tile.js';
|
import Tile from './Tile.js';
|
||||||
import TileState from './TileState.js';
|
import TileState from './TileState.js';
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {function(new: module:ol/VectorTile, module:ol/tilecoord~TileCoord,
|
|
||||||
* module:ol/TileState, string, ?string, module:ol/Tile~LoadFunction)} TileClass
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Tile}
|
|
||||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
|
||||||
* @param {module:ol/TileState} state State.
|
|
||||||
* @param {string} src Data source url.
|
|
||||||
* @param {module:ol/format/Feature} format Feature format.
|
|
||||||
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
|
|
||||||
* @param {module:ol/Tile~Options=} opt_options Tile options.
|
|
||||||
*/
|
|
||||||
const VectorTile = function(tileCoord, state, src, format, tileLoadFunction, opt_options) {
|
|
||||||
|
|
||||||
Tile.call(this, tileCoord, state, opt_options);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
this.consumers = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {module:ol/extent~Extent}
|
|
||||||
*/
|
|
||||||
this.extent_ = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {module:ol/format/Feature}
|
|
||||||
*/
|
|
||||||
this.format_ = format;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Array.<module:ol/Feature>}
|
|
||||||
*/
|
|
||||||
this.features_ = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {module:ol/featureloader~FeatureLoader}
|
|
||||||
*/
|
|
||||||
this.loader_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data projection
|
|
||||||
* @private
|
|
||||||
* @type {module:ol/proj/Projection}
|
|
||||||
*/
|
|
||||||
this.projection_ = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Object.<string, module:ol/render/ReplayGroup>}
|
|
||||||
*/
|
|
||||||
this.replayGroups_ = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {module:ol/Tile~LoadFunction}
|
|
||||||
*/
|
|
||||||
this.tileLoadFunction_ = tileLoadFunction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
this.url_ = src;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(VectorTile, Tile);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {module:ol/extent~Extent}
|
* @type {module:ol/extent~Extent}
|
||||||
@@ -91,168 +13,231 @@ const DEFAULT_EXTENT = [0, 0, 4096, 4096];
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @typedef {function(new: module:ol/VectorTile, module:ol/tilecoord~TileCoord,
|
||||||
*/
|
* module:ol/TileState, string, ?string, module:ol/Tile~LoadFunction)} TileClass
|
||||||
VectorTile.prototype.disposeInternal = function() {
|
|
||||||
this.features_ = null;
|
|
||||||
this.replayGroups_ = {};
|
|
||||||
this.state = TileState.ABORT;
|
|
||||||
this.changed();
|
|
||||||
Tile.prototype.disposeInternal.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the extent of the vector tile.
|
|
||||||
* @return {module:ol/extent~Extent} The extent.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
VectorTile.prototype.getExtent = function() {
|
|
||||||
return this.extent_ || DEFAULT_EXTENT;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
class VectorTile extends Tile {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the feature format assigned for reading this tile's features.
|
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||||
* @return {module:ol/format/Feature} Feature format.
|
* @param {module:ol/TileState} state State.
|
||||||
* @api
|
* @param {string} src Data source url.
|
||||||
*/
|
* @param {module:ol/format/Feature} format Feature format.
|
||||||
VectorTile.prototype.getFormat = function() {
|
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
|
||||||
return this.format_;
|
* @param {module:ol/Tile~Options=} opt_options Tile options.
|
||||||
};
|
*/
|
||||||
|
constructor(tileCoord, state, src, format, tileLoadFunction, opt_options) {
|
||||||
|
|
||||||
|
super(tileCoord, state, opt_options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the features for this tile. Geometries will be in the projection returned
|
* @type {number}
|
||||||
* by {@link module:ol/VectorTile~VectorTile#getProjection}.
|
*/
|
||||||
* @return {Array.<module:ol/Feature|module:ol/render/Feature>} Features.
|
this.consumers = 0;
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
VectorTile.prototype.getFeatures = function() {
|
|
||||||
return this.features_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/extent~Extent}
|
||||||
|
*/
|
||||||
|
this.extent_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @private
|
||||||
*/
|
* @type {module:ol/format/Feature}
|
||||||
VectorTile.prototype.getKey = function() {
|
*/
|
||||||
return this.url_;
|
this.format_ = format;
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Array.<module:ol/Feature>}
|
||||||
|
*/
|
||||||
|
this.features_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the feature projection of features returned by
|
* @private
|
||||||
* {@link module:ol/VectorTile~VectorTile#getFeatures}.
|
* @type {module:ol/featureloader~FeatureLoader}
|
||||||
* @return {module:ol/proj/Projection} Feature projection.
|
*/
|
||||||
* @api
|
this.loader_;
|
||||||
*/
|
|
||||||
VectorTile.prototype.getProjection = function() {
|
|
||||||
return this.projection_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data projection
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/proj/Projection}
|
||||||
|
*/
|
||||||
|
this.projection_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {module:ol/layer/Layer} layer Layer.
|
* @private
|
||||||
* @param {string} key Key.
|
* @type {Object.<string, module:ol/render/ReplayGroup>}
|
||||||
* @return {module:ol/render/ReplayGroup} Replay group.
|
*/
|
||||||
*/
|
this.replayGroups_ = {};
|
||||||
VectorTile.prototype.getReplayGroup = function(layer, key) {
|
|
||||||
return this.replayGroups_[getUid(layer) + ',' + key];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/Tile~LoadFunction}
|
||||||
|
*/
|
||||||
|
this.tileLoadFunction_ = tileLoadFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.url_ = src;
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
VectorTile.prototype.load = function() {
|
|
||||||
if (this.state == TileState.IDLE) {
|
|
||||||
this.setState(TileState.LOADING);
|
|
||||||
this.tileLoadFunction_(this, this.url_);
|
|
||||||
this.loader_(null, NaN, null);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
disposeInternal() {
|
||||||
|
this.features_ = null;
|
||||||
|
this.replayGroups_ = {};
|
||||||
|
this.state = TileState.ABORT;
|
||||||
|
this.changed();
|
||||||
|
super.disposeInternal();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for successful tile load.
|
* Gets the extent of the vector tile.
|
||||||
* @param {Array.<module:ol/Feature>} features The loaded features.
|
* @return {module:ol/extent~Extent} The extent.
|
||||||
* @param {module:ol/proj/Projection} dataProjection Data projection.
|
* @api
|
||||||
* @param {module:ol/extent~Extent} extent Extent.
|
*/
|
||||||
*/
|
getExtent() {
|
||||||
VectorTile.prototype.onLoad = function(features, dataProjection, extent) {
|
return this.extent_ || DEFAULT_EXTENT;
|
||||||
this.setProjection(dataProjection);
|
}
|
||||||
this.setFeatures(features);
|
|
||||||
this.setExtent(extent);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the feature format assigned for reading this tile's features.
|
||||||
|
* @return {module:ol/format/Feature} Feature format.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getFormat() {
|
||||||
|
return this.format_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for tile load errors.
|
* Get the features for this tile. Geometries will be in the projection returned
|
||||||
*/
|
* by {@link module:ol/VectorTile~VectorTile#getProjection}.
|
||||||
VectorTile.prototype.onError = function() {
|
* @return {Array.<module:ol/Feature|module:ol/render/Feature>} Features.
|
||||||
this.setState(TileState.ERROR);
|
* @api
|
||||||
};
|
*/
|
||||||
|
getFeatures() {
|
||||||
|
return this.features_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
getKey() {
|
||||||
|
return this.url_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for use in an {@link module:ol/source/VectorTile~VectorTile}'s
|
* Get the feature projection of features returned by
|
||||||
* `tileLoadFunction`. Sets the extent of the vector tile. This is only required
|
* {@link module:ol/VectorTile~VectorTile#getFeatures}.
|
||||||
* for tiles in projections with `tile-pixels` as units. The extent should be
|
* @return {module:ol/proj/Projection} Feature projection.
|
||||||
* set to `[0, 0, tilePixelSize, tilePixelSize]`, where `tilePixelSize` is
|
* @api
|
||||||
* calculated by multiplying the tile size with the tile pixel ratio. For
|
*/
|
||||||
* sources using {@link module:ol/format/MVT~MVT} as feature format, the
|
getProjection() {
|
||||||
* {@link module:ol/format/MVT~MVT#getLastExtent} method will return the correct
|
return this.projection_;
|
||||||
* extent. The default is `[0, 0, 4096, 4096]`.
|
}
|
||||||
* @param {module:ol/extent~Extent} extent The extent.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
VectorTile.prototype.setExtent = function(extent) {
|
|
||||||
this.extent_ = extent;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/layer/Layer} layer Layer.
|
||||||
|
* @param {string} key Key.
|
||||||
|
* @return {module:ol/render/ReplayGroup} Replay group.
|
||||||
|
*/
|
||||||
|
getReplayGroup(layer, key) {
|
||||||
|
return this.replayGroups_[getUid(layer) + ',' + key];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for use in an {@link module:ol/source/VectorTile~VectorTile}'s `tileLoadFunction`.
|
* @inheritDoc
|
||||||
* Sets the features for the tile.
|
*/
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
load() {
|
||||||
* @api
|
if (this.state == TileState.IDLE) {
|
||||||
*/
|
this.setState(TileState.LOADING);
|
||||||
VectorTile.prototype.setFeatures = function(features) {
|
this.tileLoadFunction_(this, this.url_);
|
||||||
this.features_ = features;
|
this.loader_(null, NaN, null);
|
||||||
this.setState(TileState.LOADED);
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for successful tile load.
|
||||||
|
* @param {Array.<module:ol/Feature>} features The loaded features.
|
||||||
|
* @param {module:ol/proj/Projection} dataProjection Data projection.
|
||||||
|
* @param {module:ol/extent~Extent} extent Extent.
|
||||||
|
*/
|
||||||
|
onLoad(features, dataProjection, extent) {
|
||||||
|
this.setProjection(dataProjection);
|
||||||
|
this.setFeatures(features);
|
||||||
|
this.setExtent(extent);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for use in an {@link module:ol/source/VectorTile~VectorTile}'s `tileLoadFunction`.
|
* Handler for tile load errors.
|
||||||
* Sets the projection of the features that were added with
|
*/
|
||||||
* {@link module:ol/VectorTile~VectorTile#setFeatures}.
|
onError() {
|
||||||
* @param {module:ol/proj/Projection} projection Feature projection.
|
this.setState(TileState.ERROR);
|
||||||
* @api
|
}
|
||||||
*/
|
|
||||||
VectorTile.prototype.setProjection = function(projection) {
|
|
||||||
this.projection_ = projection;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function for use in an {@link module:ol/source/VectorTile~VectorTile}'s
|
||||||
|
* `tileLoadFunction`. Sets the extent of the vector tile. This is only required
|
||||||
|
* for tiles in projections with `tile-pixels` as units. The extent should be
|
||||||
|
* set to `[0, 0, tilePixelSize, tilePixelSize]`, where `tilePixelSize` is
|
||||||
|
* calculated by multiplying the tile size with the tile pixel ratio. For
|
||||||
|
* sources using {@link module:ol/format/MVT~MVT} as feature format, the
|
||||||
|
* {@link module:ol/format/MVT~MVT#getLastExtent} method will return the correct
|
||||||
|
* extent. The default is `[0, 0, 4096, 4096]`.
|
||||||
|
* @param {module:ol/extent~Extent} extent The extent.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setExtent(extent) {
|
||||||
|
this.extent_ = extent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {module:ol/layer/Layer} layer Layer.
|
* Function for use in an {@link module:ol/source/VectorTile~VectorTile}'s `tileLoadFunction`.
|
||||||
* @param {string} key Key.
|
* Sets the features for the tile.
|
||||||
* @param {module:ol/render/ReplayGroup} replayGroup Replay group.
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
*/
|
* @api
|
||||||
VectorTile.prototype.setReplayGroup = function(layer, key, replayGroup) {
|
*/
|
||||||
this.replayGroups_[getUid(layer) + ',' + key] = replayGroup;
|
setFeatures(features) {
|
||||||
};
|
this.features_ = features;
|
||||||
|
this.setState(TileState.LOADED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function for use in an {@link module:ol/source/VectorTile~VectorTile}'s `tileLoadFunction`.
|
||||||
|
* Sets the projection of the features that were added with
|
||||||
|
* {@link module:ol/VectorTile~VectorTile#setFeatures}.
|
||||||
|
* @param {module:ol/proj/Projection} projection Feature projection.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setProjection(projection) {
|
||||||
|
this.projection_ = projection;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the feature loader for reading this tile's features.
|
* @param {module:ol/layer/Layer} layer Layer.
|
||||||
* @param {module:ol/featureloader~FeatureLoader} loader Feature loader.
|
* @param {string} key Key.
|
||||||
* @api
|
* @param {module:ol/render/ReplayGroup} replayGroup Replay group.
|
||||||
*/
|
*/
|
||||||
VectorTile.prototype.setLoader = function(loader) {
|
setReplayGroup(layer, key, replayGroup) {
|
||||||
this.loader_ = loader;
|
this.replayGroups_[getUid(layer) + ',' + key] = replayGroup;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the feature loader for reading this tile's features.
|
||||||
|
* @param {module:ol/featureloader~FeatureLoader} loader Feature loader.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setLoader(loader) {
|
||||||
|
this.loader_ = loader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default VectorTile;
|
export default VectorTile;
|
||||||
|
|||||||
1809
src/ol/View.js
1809
src/ol/View.js
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/WebGLMap
|
* @module ol/WebGLMap
|
||||||
*/
|
*/
|
||||||
import {inherits} from './util.js';
|
|
||||||
import PluggableMap from './PluggableMap.js';
|
import PluggableMap from './PluggableMap.js';
|
||||||
import {defaults as defaultControls} from './control.js';
|
import {defaults as defaultControls} from './control.js';
|
||||||
import {defaults as defaultInteractions} from './interaction.js';
|
import {defaults as defaultInteractions} from './interaction.js';
|
||||||
@@ -57,38 +56,39 @@ import WebGLVectorLayerRenderer from './renderer/webgl/VectorLayer.js';
|
|||||||
* {@link module:ol/layer/Base}, so layers entered in the options or added
|
* {@link module:ol/layer/Base}, so layers entered in the options or added
|
||||||
* with `addLayer` can be groups, which can contain further groups, and so on.
|
* with `addLayer` can be groups, which can contain further groups, and so on.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/PluggableMap}
|
|
||||||
* @param {module:ol/PluggableMap~MapOptions} options Map options.
|
|
||||||
* @fires module:ol/MapBrowserEvent~MapBrowserEvent
|
* @fires module:ol/MapBrowserEvent~MapBrowserEvent
|
||||||
* @fires module:ol/MapEvent~MapEvent
|
* @fires module:ol/MapEvent~MapEvent
|
||||||
* @fires module:ol/render/Event~RenderEvent#postcompose
|
* @fires module:ol/render/Event~RenderEvent#postcompose
|
||||||
* @fires module:ol/render/Event~RenderEvent#precompose
|
* @fires module:ol/render/Event~RenderEvent#precompose
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const WebGLMap = function(options) {
|
class WebGLMap extends PluggableMap {
|
||||||
options = assign({}, options);
|
|
||||||
if (!options.controls) {
|
/**
|
||||||
options.controls = defaultControls();
|
* @param {module:ol/PluggableMap~MapOptions} options Map options.
|
||||||
}
|
*/
|
||||||
if (!options.interactions) {
|
constructor(options) {
|
||||||
options.interactions = defaultInteractions();
|
options = assign({}, options);
|
||||||
|
if (!options.controls) {
|
||||||
|
options.controls = defaultControls();
|
||||||
|
}
|
||||||
|
if (!options.interactions) {
|
||||||
|
options.interactions = defaultInteractions();
|
||||||
|
}
|
||||||
|
|
||||||
|
super(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluggableMap.call(this, options);
|
createRenderer() {
|
||||||
};
|
const renderer = new WebGLMapRenderer(this);
|
||||||
|
renderer.registerLayerRenderers([
|
||||||
|
WebGLImageLayerRenderer,
|
||||||
|
WebGLTileLayerRenderer,
|
||||||
|
WebGLVectorLayerRenderer
|
||||||
|
]);
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inherits(WebGLMap, PluggableMap);
|
|
||||||
|
|
||||||
|
|
||||||
WebGLMap.prototype.createRenderer = function() {
|
|
||||||
const renderer = new WebGLMapRenderer(this);
|
|
||||||
renderer.registerLayerRenderers([
|
|
||||||
WebGLImageLayerRenderer,
|
|
||||||
WebGLTileLayerRenderer,
|
|
||||||
WebGLVectorLayerRenderer
|
|
||||||
]);
|
|
||||||
return renderer;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default WebGLMap;
|
export default WebGLMap;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function binarySearch(haystack, needle, opt_comparator) {
|
|||||||
cmp = +comparator(haystack[mid], needle);
|
cmp = +comparator(haystack[mid], needle);
|
||||||
|
|
||||||
if (cmp < 0.0) { /* Too low. */
|
if (cmp < 0.0) { /* Too low. */
|
||||||
low = mid + 1;
|
low = mid + 1;
|
||||||
|
|
||||||
} else { /* Key found or too high */
|
} else { /* Key found or too high */
|
||||||
high = mid;
|
high = mid;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/Attribution
|
* @module ol/control/Attribution
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {equals} from '../array.js';
|
import {equals} from '../array.js';
|
||||||
import Control from '../control/Control.js';
|
import Control from '../control/Control.js';
|
||||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_COLLAPSED} from '../css.js';
|
import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_COLLAPSED} from '../css.js';
|
||||||
@@ -14,7 +13,7 @@ import {visibleAtResolution} from '../layer/Layer.js';
|
|||||||
/**
|
/**
|
||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {string} [className='ol-attribution'] CSS class name.
|
* @property {string} [className='ol-attribution'] CSS class name.
|
||||||
* @property {Element|string} [target] Specify a target if you
|
* @property {HTMLElement|string} [target] Specify a target if you
|
||||||
* want the control to be rendered outside of the map's
|
* want the control to be rendered outside of the map's
|
||||||
* viewport.
|
* viewport.
|
||||||
* @property {boolean} [collapsible=true] Specify if attributions can
|
* @property {boolean} [collapsible=true] Specify if attributions can
|
||||||
@@ -26,7 +25,7 @@ import {visibleAtResolution} from '../layer/Layer.js';
|
|||||||
* @property {string} [label='i'] Text label to use for the
|
* @property {string} [label='i'] Text label to use for the
|
||||||
* collapsed attributions button.
|
* collapsed attributions button.
|
||||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {string|Element} [collapseLabel='»'] Text label to use
|
* @property {string|HTMLElement} [collapseLabel='»'] Text label to use
|
||||||
* for the expanded attributions button.
|
* for the expanded attributions button.
|
||||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {function(module:ol/MapEvent)} [render] Function called when
|
* @property {function(module:ol/MapEvent)} [render] Function called when
|
||||||
@@ -42,168 +41,276 @@ import {visibleAtResolution} from '../layer/Layer.js';
|
|||||||
* By default it will show in the bottom right portion of the map, but this can
|
* By default it will show in the bottom right portion of the map, but this can
|
||||||
* be changed by using a css selector for `.ol-attribution`.
|
* be changed by using a css selector for `.ol-attribution`.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/control/Control}
|
|
||||||
* @param {module:ol/control/Attribution~Options=} opt_options Attribution options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Attribution = function(opt_options) {
|
class Attribution extends Control {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {module:ol/control/Attribution~Options=} opt_options Attribution options.
|
||||||
* @type {Element}
|
|
||||||
*/
|
*/
|
||||||
this.ulElement_ = document.createElement('UL');
|
constructor(opt_options) {
|
||||||
|
|
||||||
/**
|
const options = opt_options ? opt_options : {};
|
||||||
* @private
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
|
|
||||||
|
|
||||||
/**
|
super({
|
||||||
* @private
|
element: document.createElement('div'),
|
||||||
* @type {boolean}
|
render: options.render || render,
|
||||||
*/
|
target: options.target
|
||||||
this.collapsible_ = options.collapsible !== undefined ?
|
});
|
||||||
options.collapsible : true;
|
|
||||||
|
|
||||||
if (!this.collapsible_) {
|
|
||||||
this.collapsed_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const className = options.className !== undefined ? options.className : 'ol-attribution';
|
|
||||||
|
|
||||||
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Attributions';
|
|
||||||
|
|
||||||
const collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00BB';
|
|
||||||
|
|
||||||
if (typeof collapseLabel === 'string') {
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {Element}
|
* @type {HTMLElement}
|
||||||
*/
|
*/
|
||||||
this.collapseLabel_ = document.createElement('span');
|
this.ulElement_ = document.createElement('UL');
|
||||||
this.collapseLabel_.textContent = collapseLabel;
|
|
||||||
} else {
|
|
||||||
this.collapseLabel_ = collapseLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
const label = options.label !== undefined ? options.label : 'i';
|
|
||||||
|
|
||||||
if (typeof label === 'string') {
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {Element}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
this.label_ = document.createElement('span');
|
this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
|
||||||
this.label_.textContent = label;
|
|
||||||
} else {
|
/**
|
||||||
this.label_ = label;
|
* @private
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.collapsible_ = options.collapsible !== undefined ?
|
||||||
|
options.collapsible : true;
|
||||||
|
|
||||||
|
if (!this.collapsible_) {
|
||||||
|
this.collapsed_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const className = options.className !== undefined ? options.className : 'ol-attribution';
|
||||||
|
|
||||||
|
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Attributions';
|
||||||
|
|
||||||
|
const collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00BB';
|
||||||
|
|
||||||
|
if (typeof collapseLabel === 'string') {
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*/
|
||||||
|
this.collapseLabel_ = document.createElement('span');
|
||||||
|
this.collapseLabel_.textContent = collapseLabel;
|
||||||
|
} else {
|
||||||
|
this.collapseLabel_ = collapseLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
const label = options.label !== undefined ? options.label : 'i';
|
||||||
|
|
||||||
|
if (typeof label === 'string') {
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*/
|
||||||
|
this.label_ = document.createElement('span');
|
||||||
|
this.label_.textContent = label;
|
||||||
|
} else {
|
||||||
|
this.label_ = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const activeLabel = (this.collapsible_ && !this.collapsed_) ?
|
||||||
|
this.collapseLabel_ : this.label_;
|
||||||
|
const button = document.createElement('button');
|
||||||
|
button.setAttribute('type', 'button');
|
||||||
|
button.title = tipLabel;
|
||||||
|
button.appendChild(activeLabel);
|
||||||
|
|
||||||
|
listen(button, EventType.CLICK, this.handleClick_, this);
|
||||||
|
|
||||||
|
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL +
|
||||||
|
(this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') +
|
||||||
|
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||||
|
const element = this.element;
|
||||||
|
element.className = cssClasses;
|
||||||
|
element.appendChild(this.ulElement_);
|
||||||
|
element.appendChild(button);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of currently rendered resolutions.
|
||||||
|
* @type {Array.<string>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.renderedAttributions_ = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.renderedVisible_ = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const activeLabel = (this.collapsible_ && !this.collapsed_) ?
|
|
||||||
this.collapseLabel_ : this.label_;
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.setAttribute('type', 'button');
|
|
||||||
button.title = tipLabel;
|
|
||||||
button.appendChild(activeLabel);
|
|
||||||
|
|
||||||
listen(button, EventType.CLICK, this.handleClick_, this);
|
|
||||||
|
|
||||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL +
|
|
||||||
(this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') +
|
|
||||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
|
||||||
const element = document.createElement('div');
|
|
||||||
element.className = cssClasses;
|
|
||||||
element.appendChild(this.ulElement_);
|
|
||||||
element.appendChild(button);
|
|
||||||
|
|
||||||
Control.call(this, {
|
|
||||||
element: element,
|
|
||||||
render: options.render || render,
|
|
||||||
target: options.target
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of currently rendered resolutions.
|
* Get a list of visible attributions.
|
||||||
* @type {Array.<string>}
|
* @param {module:ol/PluggableMap~FrameState} frameState Frame state.
|
||||||
|
* @return {Array.<string>} Attributions.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.renderedAttributions_ = [];
|
getSourceAttributions_(frameState) {
|
||||||
|
/**
|
||||||
|
* Used to determine if an attribution already exists.
|
||||||
|
* @type {!Object.<string, boolean>}
|
||||||
|
*/
|
||||||
|
const lookup = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* A list of visible attributions.
|
||||||
* @type {boolean}
|
* @type {Array.<string>}
|
||||||
*/
|
*/
|
||||||
this.renderedVisible_ = true;
|
const visibleAttributions = [];
|
||||||
|
|
||||||
};
|
const layerStatesArray = frameState.layerStatesArray;
|
||||||
|
const resolution = frameState.viewState.resolution;
|
||||||
|
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||||
|
const layerState = layerStatesArray[i];
|
||||||
|
if (!visibleAtResolution(layerState, resolution)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
inherits(Attribution, Control);
|
const source = layerState.layer.getSource();
|
||||||
|
if (!source) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const attributionGetter = source.getAttributions();
|
||||||
|
if (!attributionGetter) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
const attributions = attributionGetter(frameState);
|
||||||
* Get a list of visible attributions.
|
if (!attributions) {
|
||||||
* @param {module:ol/PluggableMap~FrameState} frameState Frame state.
|
continue;
|
||||||
* @return {Array.<string>} Attributions.
|
}
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Attribution.prototype.getSourceAttributions_ = function(frameState) {
|
|
||||||
/**
|
|
||||||
* Used to determine if an attribution already exists.
|
|
||||||
* @type {!Object.<string, boolean>}
|
|
||||||
*/
|
|
||||||
const lookup = {};
|
|
||||||
|
|
||||||
/**
|
if (Array.isArray(attributions)) {
|
||||||
* A list of visible attributions.
|
for (let j = 0, jj = attributions.length; j < jj; ++j) {
|
||||||
* @type {Array.<string>}
|
if (!(attributions[j] in lookup)) {
|
||||||
*/
|
visibleAttributions.push(attributions[j]);
|
||||||
const visibleAttributions = [];
|
lookup[attributions[j]] = true;
|
||||||
|
}
|
||||||
const layerStatesArray = frameState.layerStatesArray;
|
}
|
||||||
const resolution = frameState.viewState.resolution;
|
} else {
|
||||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
if (!(attributions in lookup)) {
|
||||||
const layerState = layerStatesArray[i];
|
visibleAttributions.push(attributions);
|
||||||
if (!visibleAtResolution(layerState, resolution)) {
|
lookup[attributions] = true;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const source = layerState.layer.getSource();
|
|
||||||
if (!source) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const attributionGetter = source.getAttributions();
|
|
||||||
if (!attributionGetter) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const attributions = attributionGetter(frameState);
|
|
||||||
if (!attributions) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(attributions)) {
|
|
||||||
for (let j = 0, jj = attributions.length; j < jj; ++j) {
|
|
||||||
if (!(attributions[j] in lookup)) {
|
|
||||||
visibleAttributions.push(attributions[j]);
|
|
||||||
lookup[attributions[j]] = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (!(attributions in lookup)) {
|
return visibleAttributions;
|
||||||
visibleAttributions.push(attributions);
|
}
|
||||||
lookup[attributions] = true;
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param {?module:ol/PluggableMap~FrameState} frameState Frame state.
|
||||||
|
*/
|
||||||
|
updateElement_(frameState) {
|
||||||
|
if (!frameState) {
|
||||||
|
if (this.renderedVisible_) {
|
||||||
|
this.element.style.display = 'none';
|
||||||
|
this.renderedVisible_ = false;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const attributions = this.getSourceAttributions_(frameState);
|
||||||
|
|
||||||
|
const visible = attributions.length > 0;
|
||||||
|
if (this.renderedVisible_ != visible) {
|
||||||
|
this.element.style.display = visible ? '' : 'none';
|
||||||
|
this.renderedVisible_ = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (equals(attributions, this.renderedAttributions_)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeChildren(this.ulElement_);
|
||||||
|
|
||||||
|
// append the attributions
|
||||||
|
for (let i = 0, ii = attributions.length; i < ii; ++i) {
|
||||||
|
const element = document.createElement('LI');
|
||||||
|
element.innerHTML = attributions[i];
|
||||||
|
this.ulElement_.appendChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.renderedAttributions_ = attributions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event The event to handle
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleClick_(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.handleToggle_();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleToggle_() {
|
||||||
|
this.element.classList.toggle(CLASS_COLLAPSED);
|
||||||
|
if (this.collapsed_) {
|
||||||
|
replaceNode(this.collapseLabel_, this.label_);
|
||||||
|
} else {
|
||||||
|
replaceNode(this.label_, this.collapseLabel_);
|
||||||
|
}
|
||||||
|
this.collapsed_ = !this.collapsed_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return `true` if the attribution is collapsible, `false` otherwise.
|
||||||
|
* @return {boolean} True if the widget is collapsible.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getCollapsible() {
|
||||||
|
return this.collapsible_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether the attribution should be collapsible.
|
||||||
|
* @param {boolean} collapsible True if the widget is collapsible.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setCollapsible(collapsible) {
|
||||||
|
if (this.collapsible_ === collapsible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.collapsible_ = collapsible;
|
||||||
|
this.element.classList.toggle('ol-uncollapsible');
|
||||||
|
if (!collapsible && this.collapsed_) {
|
||||||
|
this.handleToggle_();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return visibleAttributions;
|
|
||||||
};
|
/**
|
||||||
|
* Collapse or expand the attribution according to the passed parameter. Will
|
||||||
|
* not do anything if the attribution isn't collapsible or if the current
|
||||||
|
* collapsed state is already the one requested.
|
||||||
|
* @param {boolean} collapsed True if the widget is collapsed.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setCollapsed(collapsed) {
|
||||||
|
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.handleToggle_();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return `true` when the attribution is currently collapsed or `false`
|
||||||
|
* otherwise.
|
||||||
|
* @return {boolean} True if the widget is collapsed.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getCollapsed() {
|
||||||
|
return this.collapsed_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -217,117 +324,4 @@ export function render(mapEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param {?module:ol/PluggableMap~FrameState} frameState Frame state.
|
|
||||||
*/
|
|
||||||
Attribution.prototype.updateElement_ = function(frameState) {
|
|
||||||
if (!frameState) {
|
|
||||||
if (this.renderedVisible_) {
|
|
||||||
this.element.style.display = 'none';
|
|
||||||
this.renderedVisible_ = false;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const attributions = this.getSourceAttributions_(frameState);
|
|
||||||
|
|
||||||
const visible = attributions.length > 0;
|
|
||||||
if (this.renderedVisible_ != visible) {
|
|
||||||
this.element.style.display = visible ? '' : 'none';
|
|
||||||
this.renderedVisible_ = visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (equals(attributions, this.renderedAttributions_)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeChildren(this.ulElement_);
|
|
||||||
|
|
||||||
// append the attributions
|
|
||||||
for (let i = 0, ii = attributions.length; i < ii; ++i) {
|
|
||||||
const element = document.createElement('LI');
|
|
||||||
element.innerHTML = attributions[i];
|
|
||||||
this.ulElement_.appendChild(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.renderedAttributions_ = attributions;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} event The event to handle
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Attribution.prototype.handleClick_ = function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.handleToggle_();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Attribution.prototype.handleToggle_ = function() {
|
|
||||||
this.element.classList.toggle(CLASS_COLLAPSED);
|
|
||||||
if (this.collapsed_) {
|
|
||||||
replaceNode(this.collapseLabel_, this.label_);
|
|
||||||
} else {
|
|
||||||
replaceNode(this.label_, this.collapseLabel_);
|
|
||||||
}
|
|
||||||
this.collapsed_ = !this.collapsed_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return `true` if the attribution is collapsible, `false` otherwise.
|
|
||||||
* @return {boolean} True if the widget is collapsible.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Attribution.prototype.getCollapsible = function() {
|
|
||||||
return this.collapsible_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether the attribution should be collapsible.
|
|
||||||
* @param {boolean} collapsible True if the widget is collapsible.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Attribution.prototype.setCollapsible = function(collapsible) {
|
|
||||||
if (this.collapsible_ === collapsible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.collapsible_ = collapsible;
|
|
||||||
this.element.classList.toggle('ol-uncollapsible');
|
|
||||||
if (!collapsible && this.collapsed_) {
|
|
||||||
this.handleToggle_();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collapse or expand the attribution according to the passed parameter. Will
|
|
||||||
* not do anything if the attribution isn't collapsible or if the current
|
|
||||||
* collapsed state is already the one requested.
|
|
||||||
* @param {boolean} collapsed True if the widget is collapsed.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Attribution.prototype.setCollapsed = function(collapsed) {
|
|
||||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.handleToggle_();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return `true` when the attribution is currently collapsed or `false`
|
|
||||||
* otherwise.
|
|
||||||
* @return {boolean} True if the widget is collapsed.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Attribution.prototype.getCollapsed = function() {
|
|
||||||
return this.collapsed_;
|
|
||||||
};
|
|
||||||
export default Attribution;
|
export default Attribution;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/Control
|
* @module ol/control/Control
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {UNDEFINED} from '../functions.js';
|
import {UNDEFINED} from '../functions.js';
|
||||||
import MapEventType from '../MapEventType.js';
|
import MapEventType from '../MapEventType.js';
|
||||||
import BaseObject from '../Object.js';
|
import BaseObject from '../Object.js';
|
||||||
@@ -11,13 +10,13 @@ import {listen, unlistenByKey} from '../events.js';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {Element} [element] The element is the control's
|
* @property {HTMLElement} [element] The element is the control's
|
||||||
* container element. This only needs to be specified if you're developing
|
* container element. This only needs to be specified if you're developing
|
||||||
* a custom control.
|
* a custom control.
|
||||||
* @property {function(module:ol/MapEvent)} [render] Function called when
|
* @property {function(module:ol/MapEvent)} [render] Function called when
|
||||||
* the control should be re-rendered. This is called in a `requestAnimationFrame`
|
* the control should be re-rendered. This is called in a `requestAnimationFrame`
|
||||||
* callback.
|
* callback.
|
||||||
* @property {Element|string} [target] Specify a target if you want
|
* @property {HTMLElement|string} [target] Specify a target if you want
|
||||||
* the control to be rendered outside of the map's viewport.
|
* the control to be rendered outside of the map's viewport.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -44,113 +43,112 @@ import {listen, unlistenByKey} from '../events.js';
|
|||||||
* You can also extend this base for your own control class. See
|
* You can also extend this base for your own control class. See
|
||||||
* examples/custom-controls for an example of how to do this.
|
* examples/custom-controls for an example of how to do this.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Object}
|
|
||||||
* @param {module:ol/control/Control~Options} options Control options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Control = function(options) {
|
class Control extends BaseObject {
|
||||||
|
|
||||||
BaseObject.call(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @param {module:ol/control/Control~Options} options Control options.
|
||||||
* @type {Element}
|
|
||||||
*/
|
*/
|
||||||
this.element = options.element ? options.element : null;
|
constructor(options) {
|
||||||
|
|
||||||
/**
|
super();
|
||||||
* @private
|
|
||||||
* @type {Element}
|
|
||||||
*/
|
|
||||||
this.target_ = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @protected
|
||||||
* @type {module:ol/PluggableMap}
|
* @type {HTMLElement}
|
||||||
*/
|
*/
|
||||||
this.map_ = null;
|
this.element = options.element ? options.element : null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @private
|
||||||
* @type {!Array.<module:ol/events~EventsKey>}
|
* @type {HTMLElement}
|
||||||
*/
|
*/
|
||||||
this.listenerKeys = [];
|
this.target_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {function(module:ol/MapEvent)}
|
* @private
|
||||||
*/
|
* @type {module:ol/PluggableMap}
|
||||||
this.render = options.render ? options.render : UNDEFINED;
|
*/
|
||||||
|
this.map_ = null;
|
||||||
|
|
||||||
if (options.target) {
|
/**
|
||||||
this.setTarget(options.target);
|
* @protected
|
||||||
}
|
* @type {!Array.<module:ol/events~EventsKey>}
|
||||||
|
*/
|
||||||
|
this.listenerKeys = [];
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @type {function(module:ol/MapEvent)}
|
||||||
|
*/
|
||||||
|
this.render = options.render ? options.render : UNDEFINED;
|
||||||
|
|
||||||
inherits(Control, BaseObject);
|
if (options.target) {
|
||||||
|
this.setTarget(options.target);
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
Control.prototype.disposeInternal = function() {
|
|
||||||
removeNode(this.element);
|
|
||||||
BaseObject.prototype.disposeInternal.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the map associated with this control.
|
|
||||||
* @return {module:ol/PluggableMap} Map.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Control.prototype.getMap = function() {
|
|
||||||
return this.map_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the control from its current map and attach it to the new map.
|
|
||||||
* Subclasses may set up event handlers to get notified about changes to
|
|
||||||
* the map here.
|
|
||||||
* @param {module:ol/PluggableMap} map Map.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Control.prototype.setMap = function(map) {
|
|
||||||
if (this.map_) {
|
|
||||||
removeNode(this.element);
|
|
||||||
}
|
|
||||||
for (let i = 0, ii = this.listenerKeys.length; i < ii; ++i) {
|
|
||||||
unlistenByKey(this.listenerKeys[i]);
|
|
||||||
}
|
|
||||||
this.listenerKeys.length = 0;
|
|
||||||
this.map_ = map;
|
|
||||||
if (this.map_) {
|
|
||||||
const target = this.target_ ?
|
|
||||||
this.target_ : map.getOverlayContainerStopEvent();
|
|
||||||
target.appendChild(this.element);
|
|
||||||
if (this.render !== UNDEFINED) {
|
|
||||||
this.listenerKeys.push(listen(map,
|
|
||||||
MapEventType.POSTRENDER, this.render, this));
|
|
||||||
}
|
}
|
||||||
map.render();
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
disposeInternal() {
|
||||||
|
removeNode(this.element);
|
||||||
|
super.disposeInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the map associated with this control.
|
||||||
|
* @return {module:ol/PluggableMap} Map.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getMap() {
|
||||||
|
return this.map_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the control from its current map and attach it to the new map.
|
||||||
|
* Subclasses may set up event handlers to get notified about changes to
|
||||||
|
* the map here.
|
||||||
|
* @param {module:ol/PluggableMap} map Map.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setMap(map) {
|
||||||
|
if (this.map_) {
|
||||||
|
removeNode(this.element);
|
||||||
|
}
|
||||||
|
for (let i = 0, ii = this.listenerKeys.length; i < ii; ++i) {
|
||||||
|
unlistenByKey(this.listenerKeys[i]);
|
||||||
|
}
|
||||||
|
this.listenerKeys.length = 0;
|
||||||
|
this.map_ = map;
|
||||||
|
if (this.map_) {
|
||||||
|
const target = this.target_ ?
|
||||||
|
this.target_ : map.getOverlayContainerStopEvent();
|
||||||
|
target.appendChild(this.element);
|
||||||
|
if (this.render !== UNDEFINED) {
|
||||||
|
this.listenerKeys.push(listen(map,
|
||||||
|
MapEventType.POSTRENDER, this.render, this));
|
||||||
|
}
|
||||||
|
map.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is used to set a target element for the control. It has no
|
||||||
|
* effect if it is called after the control has been added to the map (i.e.
|
||||||
|
* after `setMap` is called on the control). If no `target` is set in the
|
||||||
|
* options passed to the control constructor and if `setTarget` is not called
|
||||||
|
* then the control is added to the map's overlay container.
|
||||||
|
* @param {HTMLElement|string} target Target.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setTarget(target) {
|
||||||
|
this.target_ = typeof target === 'string' ?
|
||||||
|
document.getElementById(target) :
|
||||||
|
target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function is used to set a target element for the control. It has no
|
|
||||||
* effect if it is called after the control has been added to the map (i.e.
|
|
||||||
* after `setMap` is called on the control). If no `target` is set in the
|
|
||||||
* options passed to the control constructor and if `setTarget` is not called
|
|
||||||
* then the control is added to the map's overlay container.
|
|
||||||
* @param {Element|string} target Target.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Control.prototype.setTarget = function(target) {
|
|
||||||
this.target_ = typeof target === 'string' ?
|
|
||||||
document.getElementById(target) :
|
|
||||||
target;
|
|
||||||
};
|
|
||||||
export default Control;
|
export default Control;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/FullScreen
|
* @module ol/control/FullScreen
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import Control from '../control/Control.js';
|
import Control from '../control/Control.js';
|
||||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_UNSUPPORTED} from '../css.js';
|
import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_UNSUPPORTED} from '../css.js';
|
||||||
import {replaceNode} from '../dom.js';
|
import {replaceNode} from '../dom.js';
|
||||||
@@ -35,16 +34,16 @@ const getChangeType = (function() {
|
|||||||
/**
|
/**
|
||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {string} [className='ol-full-screen'] CSS class name.
|
* @property {string} [className='ol-full-screen'] CSS class name.
|
||||||
* @property {string|Element} [label='\u2922'] Text label to use for the button.
|
* @property {string|HTMLElement} [label='\u2922'] Text label to use for the button.
|
||||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {string|Element} [labelActive='\u00d7'] Text label to use for the
|
* @property {string|HTMLElement} [labelActive='\u00d7'] Text label to use for the
|
||||||
* button when full-screen is active.
|
* button when full-screen is active.
|
||||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {string} [tipLabel='Toggle full-screen'] Text label to use for the button tip.
|
* @property {string} [tipLabel='Toggle full-screen'] Text label to use for the button tip.
|
||||||
* @property {boolean} [keys=false] Full keyboard access.
|
* @property {boolean} [keys=false] Full keyboard access.
|
||||||
* @property {Element|string} [target] Specify a target if you want the
|
* @property {HTMLElement|string} [target] Specify a target if you want the
|
||||||
* control to be rendered outside of the map's viewport.
|
* control to be rendered outside of the map's viewport.
|
||||||
* @property {Element|string} [source] The element to be displayed
|
* @property {HTMLElement|string} [source] The element to be displayed
|
||||||
* fullscreen. When not provided, the element containing the map viewport will
|
* fullscreen. When not provided, the element containing the map viewport will
|
||||||
* be displayed fullscreen.
|
* be displayed fullscreen.
|
||||||
*/
|
*/
|
||||||
@@ -61,154 +60,151 @@ const getChangeType = (function() {
|
|||||||
* The [Fullscreen API](http://www.w3.org/TR/fullscreen/) is used to
|
* The [Fullscreen API](http://www.w3.org/TR/fullscreen/) is used to
|
||||||
* toggle the map in full screen mode.
|
* toggle the map in full screen mode.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/control/Control}
|
|
||||||
* @param {module:ol/control/FullScreen~Options=} opt_options Options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const FullScreen = function(opt_options) {
|
class FullScreen extends Control {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {module:ol/control/FullScreen~Options=} opt_options Options.
|
||||||
* @type {string}
|
|
||||||
*/
|
*/
|
||||||
this.cssClassName_ = options.className !== undefined ? options.className :
|
constructor(opt_options) {
|
||||||
'ol-full-screen';
|
|
||||||
|
|
||||||
const label = options.label !== undefined ? options.label : '\u2922';
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
/**
|
super({
|
||||||
* @private
|
element: document.createElement('div'),
|
||||||
* @type {Element}
|
target: options.target
|
||||||
*/
|
});
|
||||||
this.labelNode_ = typeof label === 'string' ?
|
|
||||||
document.createTextNode(label) : label;
|
|
||||||
|
|
||||||
const labelActive = options.labelActive !== undefined ? options.labelActive : '\u00d7';
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.cssClassName_ = options.className !== undefined ? options.className :
|
||||||
|
'ol-full-screen';
|
||||||
|
|
||||||
/**
|
const label = options.label !== undefined ? options.label : '\u2922';
|
||||||
* @private
|
|
||||||
* @type {Element}
|
|
||||||
*/
|
|
||||||
this.labelActiveNode_ = typeof labelActive === 'string' ?
|
|
||||||
document.createTextNode(labelActive) : labelActive;
|
|
||||||
|
|
||||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
/**
|
||||||
const button = document.createElement('button');
|
* @private
|
||||||
button.className = this.cssClassName_ + '-' + isFullScreen();
|
* @type {HTMLElement}
|
||||||
button.setAttribute('type', 'button');
|
*/
|
||||||
button.title = tipLabel;
|
this.labelNode_ = typeof label === 'string' ?
|
||||||
button.appendChild(this.labelNode_);
|
document.createTextNode(label) : label;
|
||||||
|
|
||||||
listen(button, EventType.CLICK,
|
const labelActive = options.labelActive !== undefined ? options.labelActive : '\u00d7';
|
||||||
this.handleClick_, this);
|
|
||||||
|
|
||||||
const cssClasses = this.cssClassName_ + ' ' + CLASS_UNSELECTABLE +
|
/**
|
||||||
' ' + CLASS_CONTROL + ' ' +
|
* @private
|
||||||
(!isFullScreenSupported() ? CLASS_UNSUPPORTED : '');
|
* @type {HTMLElement}
|
||||||
const element = document.createElement('div');
|
*/
|
||||||
element.className = cssClasses;
|
this.labelActiveNode_ = typeof labelActive === 'string' ?
|
||||||
element.appendChild(button);
|
document.createTextNode(labelActive) : labelActive;
|
||||||
|
|
||||||
Control.call(this, {
|
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||||
element: element,
|
const button = document.createElement('button');
|
||||||
target: options.target
|
button.className = this.cssClassName_ + '-' + isFullScreen();
|
||||||
});
|
button.setAttribute('type', 'button');
|
||||||
|
button.title = tipLabel;
|
||||||
|
button.appendChild(this.labelNode_);
|
||||||
|
|
||||||
/**
|
listen(button, EventType.CLICK,
|
||||||
* @private
|
this.handleClick_, this);
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
this.keys_ = options.keys !== undefined ? options.keys : false;
|
|
||||||
|
|
||||||
/**
|
const cssClasses = this.cssClassName_ + ' ' + CLASS_UNSELECTABLE +
|
||||||
* @private
|
' ' + CLASS_CONTROL + ' ' +
|
||||||
* @type {Element|string|undefined}
|
(!isFullScreenSupported() ? CLASS_UNSUPPORTED : '');
|
||||||
*/
|
const element = this.element;
|
||||||
this.source_ = options.source;
|
element.className = cssClasses;
|
||||||
|
element.appendChild(button);
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.keys_ = options.keys !== undefined ? options.keys : false;
|
||||||
|
|
||||||
inherits(FullScreen, Control);
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {HTMLElement|string|undefined}
|
||||||
|
*/
|
||||||
|
this.source_ = options.source;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} event The event to handle
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
FullScreen.prototype.handleClick_ = function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.handleFullScreen_();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
FullScreen.prototype.handleFullScreen_ = function() {
|
|
||||||
if (!isFullScreenSupported()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const map = this.getMap();
|
|
||||||
if (!map) {
|
/**
|
||||||
return;
|
* @param {MouseEvent} event The event to handle
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleClick_(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.handleFullScreen_();
|
||||||
}
|
}
|
||||||
if (isFullScreen()) {
|
|
||||||
exitFullScreen();
|
/**
|
||||||
} else {
|
* @private
|
||||||
let element;
|
*/
|
||||||
if (this.source_) {
|
handleFullScreen_() {
|
||||||
element = typeof this.source_ === 'string' ?
|
if (!isFullScreenSupported()) {
|
||||||
document.getElementById(this.source_) :
|
return;
|
||||||
this.source_;
|
|
||||||
} else {
|
|
||||||
element = map.getTargetElement();
|
|
||||||
}
|
}
|
||||||
if (this.keys_) {
|
const map = this.getMap();
|
||||||
requestFullScreenWithKeys(element);
|
if (!map) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isFullScreen()) {
|
||||||
|
exitFullScreen();
|
||||||
} else {
|
} else {
|
||||||
requestFullScreen(element);
|
let element;
|
||||||
|
if (this.source_) {
|
||||||
|
element = typeof this.source_ === 'string' ?
|
||||||
|
document.getElementById(this.source_) :
|
||||||
|
this.source_;
|
||||||
|
} else {
|
||||||
|
element = map.getTargetElement();
|
||||||
|
}
|
||||||
|
if (this.keys_) {
|
||||||
|
requestFullScreenWithKeys(element);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
requestFullScreen(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @private
|
||||||
* @private
|
*/
|
||||||
*/
|
handleFullScreenChange_() {
|
||||||
FullScreen.prototype.handleFullScreenChange_ = function() {
|
const button = this.element.firstElementChild;
|
||||||
const button = this.element.firstElementChild;
|
const map = this.getMap();
|
||||||
const map = this.getMap();
|
if (isFullScreen()) {
|
||||||
if (isFullScreen()) {
|
button.className = this.cssClassName_ + '-true';
|
||||||
button.className = this.cssClassName_ + '-true';
|
replaceNode(this.labelActiveNode_, this.labelNode_);
|
||||||
replaceNode(this.labelActiveNode_, this.labelNode_);
|
} else {
|
||||||
} else {
|
button.className = this.cssClassName_ + '-false';
|
||||||
button.className = this.cssClassName_ + '-false';
|
replaceNode(this.labelNode_, this.labelActiveNode_);
|
||||||
replaceNode(this.labelNode_, this.labelActiveNode_);
|
}
|
||||||
|
if (map) {
|
||||||
|
map.updateSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (map) {
|
|
||||||
map.updateSize();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @inheritDoc
|
||||||
* @inheritDoc
|
* @api
|
||||||
* @api
|
*/
|
||||||
*/
|
setMap(map) {
|
||||||
FullScreen.prototype.setMap = function(map) {
|
super.setMap(map);
|
||||||
Control.prototype.setMap.call(this, map);
|
if (map) {
|
||||||
if (map) {
|
this.listenerKeys.push(listen(document,
|
||||||
this.listenerKeys.push(listen(document,
|
getChangeType(),
|
||||||
getChangeType(),
|
this.handleFullScreenChange_, this)
|
||||||
this.handleFullScreenChange_, this)
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {boolean} Fullscreen is supported by the current platform.
|
* @return {boolean} Fullscreen is supported by the current platform.
|
||||||
@@ -235,7 +231,7 @@ function isFullScreen() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Request to fullscreen an element.
|
* Request to fullscreen an element.
|
||||||
* @param {Element} element Element to request fullscreen
|
* @param {HTMLElement} element Element to request fullscreen
|
||||||
*/
|
*/
|
||||||
function requestFullScreen(element) {
|
function requestFullScreen(element) {
|
||||||
if (element.requestFullscreen) {
|
if (element.requestFullscreen) {
|
||||||
@@ -251,7 +247,7 @@ function requestFullScreen(element) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Request to fullscreen an element with keyboard input.
|
* Request to fullscreen an element with keyboard input.
|
||||||
* @param {Element} element Element to request fullscreen
|
* @param {HTMLElement} element Element to request fullscreen
|
||||||
*/
|
*/
|
||||||
function requestFullScreenWithKeys(element) {
|
function requestFullScreenWithKeys(element) {
|
||||||
if (element.mozRequestFullScreenWithKeys) {
|
if (element.mozRequestFullScreenWithKeys) {
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/MousePosition
|
* @module ol/control/MousePosition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {listen} from '../events.js';
|
import {listen} from '../events.js';
|
||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import {getChangeEventType} from '../Object.js';
|
import {getChangeEventType} from '../Object.js';
|
||||||
@@ -46,75 +44,203 @@ const COORDINATE_FORMAT = 'coordinateFormat';
|
|||||||
* By default the control is shown in the top right corner of the map, but this
|
* By default the control is shown in the top right corner of the map, but this
|
||||||
* can be changed by using the css selector `.ol-mouse-position`.
|
* can be changed by using the css selector `.ol-mouse-position`.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/control/Control}
|
|
||||||
* @param {module:ol/control/MousePosition~Options=} opt_options Mouse position
|
|
||||||
* options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const MousePosition = function(opt_options) {
|
class MousePosition extends Control {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
/**
|
||||||
|
* @param {module:ol/control/MousePosition~Options=} opt_options Mouse position options.
|
||||||
|
*/
|
||||||
|
constructor(opt_options) {
|
||||||
|
|
||||||
const element = document.createElement('DIV');
|
const options = opt_options ? opt_options : {};
|
||||||
element.className = options.className !== undefined ? options.className : 'ol-mouse-position';
|
|
||||||
|
|
||||||
Control.call(this, {
|
const element = document.createElement('DIV');
|
||||||
element: element,
|
element.className = options.className !== undefined ? options.className : 'ol-mouse-position';
|
||||||
render: options.render || render,
|
|
||||||
target: options.target
|
|
||||||
});
|
|
||||||
|
|
||||||
listen(this,
|
super({
|
||||||
getChangeEventType(PROJECTION),
|
element: element,
|
||||||
this.handleProjectionChanged_, this);
|
render: options.render || render,
|
||||||
|
target: options.target
|
||||||
|
});
|
||||||
|
|
||||||
|
listen(this,
|
||||||
|
getChangeEventType(PROJECTION),
|
||||||
|
this.handleProjectionChanged_, this);
|
||||||
|
|
||||||
|
if (options.coordinateFormat) {
|
||||||
|
this.setCoordinateFormat(options.coordinateFormat);
|
||||||
|
}
|
||||||
|
if (options.projection) {
|
||||||
|
this.setProjection(options.projection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.undefinedHTML_ = 'undefinedHTML' in options ? options.undefinedHTML : ' ';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.renderOnMouseOut_ = !!this.undefinedHTML_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.renderedHTML_ = element.innerHTML;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/proj/Projection}
|
||||||
|
*/
|
||||||
|
this.mapProjection_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {?module:ol/proj~TransformFunction}
|
||||||
|
*/
|
||||||
|
this.transform_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/pixel~Pixel}
|
||||||
|
*/
|
||||||
|
this.lastMouseMovePixel_ = null;
|
||||||
|
|
||||||
if (options.coordinateFormat) {
|
|
||||||
this.setCoordinateFormat(options.coordinateFormat);
|
|
||||||
}
|
|
||||||
if (options.projection) {
|
|
||||||
this.setProjection(options.projection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {string}
|
|
||||||
*/
|
*/
|
||||||
this.undefinedHTML_ = 'undefinedHTML' in options ? options.undefinedHTML : ' ';
|
handleProjectionChanged_() {
|
||||||
|
this.transform_ = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* Return the coordinate format type used to render the current position or
|
||||||
* @type {boolean}
|
* undefined.
|
||||||
|
* @return {module:ol/coordinate~CoordinateFormat|undefined} The format to render the current
|
||||||
|
* position in.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
this.renderOnMouseOut_ = !!this.undefinedHTML_;
|
getCoordinateFormat() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/coordinate~CoordinateFormat|undefined} */ (this.get(COORDINATE_FORMAT))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* Return the projection that is used to report the mouse position.
|
||||||
* @type {string}
|
* @return {module:ol/proj/Projection|undefined} The projection to report mouse
|
||||||
|
* position in.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
this.renderedHTML_ = element.innerHTML;
|
getProjection() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/proj/Projection|undefined} */ (this.get(PROJECTION))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {Event} event Browser event.
|
||||||
* @type {module:ol/proj/Projection}
|
* @protected
|
||||||
*/
|
*/
|
||||||
this.mapProjection_ = null;
|
handleMouseMove(event) {
|
||||||
|
const map = this.getMap();
|
||||||
|
this.lastMouseMovePixel_ = map.getEventPixel(event);
|
||||||
|
this.updateHTML_(this.lastMouseMovePixel_);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {Event} event Browser event.
|
||||||
* @type {?module:ol/proj~TransformFunction}
|
* @protected
|
||||||
*/
|
*/
|
||||||
this.transform_ = null;
|
handleMouseOut(event) {
|
||||||
|
this.updateHTML_(null);
|
||||||
|
this.lastMouseMovePixel_ = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @inheritDoc
|
||||||
* @type {module:ol~Pixel}
|
* @api
|
||||||
*/
|
*/
|
||||||
this.lastMouseMovePixel_ = null;
|
setMap(map) {
|
||||||
|
super.setMap(map);
|
||||||
|
if (map) {
|
||||||
|
const viewport = map.getViewport();
|
||||||
|
this.listenerKeys.push(
|
||||||
|
listen(viewport, EventType.MOUSEMOVE, this.handleMouseMove, this)
|
||||||
|
);
|
||||||
|
if (this.renderOnMouseOut_) {
|
||||||
|
this.listenerKeys.push(
|
||||||
|
listen(viewport, EventType.MOUSEOUT, this.handleMouseOut, this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* Set the coordinate format type used to render the current position.
|
||||||
|
* @param {module:ol/coordinate~CoordinateFormat} format The format to render the current
|
||||||
|
* position in.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setCoordinateFormat(format) {
|
||||||
|
this.set(COORDINATE_FORMAT, format);
|
||||||
|
}
|
||||||
|
|
||||||
inherits(MousePosition, Control);
|
/**
|
||||||
|
* Set the projection that is used to report the mouse position.
|
||||||
|
* @param {module:ol/proj~ProjectionLike} projection The projection to report mouse
|
||||||
|
* position in.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setProjection(projection) {
|
||||||
|
this.set(PROJECTION, getProjection(projection));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {?module:ol/pixel~Pixel} pixel Pixel.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
updateHTML_(pixel) {
|
||||||
|
let html = this.undefinedHTML_;
|
||||||
|
if (pixel && this.mapProjection_) {
|
||||||
|
if (!this.transform_) {
|
||||||
|
const projection = this.getProjection();
|
||||||
|
if (projection) {
|
||||||
|
this.transform_ = getTransformFromProjections(
|
||||||
|
this.mapProjection_, projection);
|
||||||
|
} else {
|
||||||
|
this.transform_ = identityTransform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const map = this.getMap();
|
||||||
|
const coordinate = map.getCoordinateFromPixel(pixel);
|
||||||
|
if (coordinate) {
|
||||||
|
this.transform_(coordinate, coordinate);
|
||||||
|
const coordinateFormat = this.getCoordinateFormat();
|
||||||
|
if (coordinateFormat) {
|
||||||
|
html = coordinateFormat(coordinate);
|
||||||
|
} else {
|
||||||
|
html = coordinate.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.renderedHTML_ || html !== this.renderedHTML_) {
|
||||||
|
this.element.innerHTML = html;
|
||||||
|
this.renderedHTML_ = html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,141 +263,4 @@ export function render(mapEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.handleProjectionChanged_ = function() {
|
|
||||||
this.transform_ = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the coordinate format type used to render the current position or
|
|
||||||
* undefined.
|
|
||||||
* @return {module:ol/coordinate~CoordinateFormat|undefined} The format to render the current
|
|
||||||
* position in.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.getCoordinateFormat = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/coordinate~CoordinateFormat|undefined} */ (this.get(COORDINATE_FORMAT))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the projection that is used to report the mouse position.
|
|
||||||
* @return {module:ol/proj/Projection|undefined} The projection to report mouse
|
|
||||||
* position in.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.getProjection = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/proj/Projection|undefined} */ (this.get(PROJECTION))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} event Browser event.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.handleMouseMove = function(event) {
|
|
||||||
const map = this.getMap();
|
|
||||||
this.lastMouseMovePixel_ = map.getEventPixel(event);
|
|
||||||
this.updateHTML_(this.lastMouseMovePixel_);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} event Browser event.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.handleMouseOut = function(event) {
|
|
||||||
this.updateHTML_(null);
|
|
||||||
this.lastMouseMovePixel_ = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.setMap = function(map) {
|
|
||||||
Control.prototype.setMap.call(this, map);
|
|
||||||
if (map) {
|
|
||||||
const viewport = map.getViewport();
|
|
||||||
this.listenerKeys.push(
|
|
||||||
listen(viewport, EventType.MOUSEMOVE, this.handleMouseMove, this)
|
|
||||||
);
|
|
||||||
if (this.renderOnMouseOut_) {
|
|
||||||
this.listenerKeys.push(
|
|
||||||
listen(viewport, EventType.MOUSEOUT, this.handleMouseOut, this)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the coordinate format type used to render the current position.
|
|
||||||
* @param {module:ol/coordinate~CoordinateFormat} format The format to render the current
|
|
||||||
* position in.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.setCoordinateFormat = function(format) {
|
|
||||||
this.set(COORDINATE_FORMAT, format);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the projection that is used to report the mouse position.
|
|
||||||
* @param {module:ol/proj~ProjectionLike} projection The projection to report mouse
|
|
||||||
* position in.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.setProjection = function(projection) {
|
|
||||||
this.set(PROJECTION, getProjection(projection));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {?module:ol~Pixel} pixel Pixel.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MousePosition.prototype.updateHTML_ = function(pixel) {
|
|
||||||
let html = this.undefinedHTML_;
|
|
||||||
if (pixel && this.mapProjection_) {
|
|
||||||
if (!this.transform_) {
|
|
||||||
const projection = this.getProjection();
|
|
||||||
if (projection) {
|
|
||||||
this.transform_ = getTransformFromProjections(
|
|
||||||
this.mapProjection_, projection);
|
|
||||||
} else {
|
|
||||||
this.transform_ = identityTransform;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const map = this.getMap();
|
|
||||||
const coordinate = map.getCoordinateFromPixel(pixel);
|
|
||||||
if (coordinate) {
|
|
||||||
this.transform_(coordinate, coordinate);
|
|
||||||
const coordinateFormat = this.getCoordinateFormat();
|
|
||||||
if (coordinateFormat) {
|
|
||||||
html = coordinateFormat(coordinate);
|
|
||||||
} else {
|
|
||||||
html = coordinate.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this.renderedHTML_ || html !== this.renderedHTML_) {
|
|
||||||
this.element.innerHTML = html;
|
|
||||||
this.renderedHTML_ = html;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default MousePosition;
|
export default MousePosition;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/Rotate
|
* @module ol/control/Rotate
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Control from '../control/Control.js';
|
import Control from '../control/Control.js';
|
||||||
import {CLASS_CONTROL, CLASS_HIDDEN, CLASS_UNSELECTABLE} from '../css.js';
|
import {CLASS_CONTROL, CLASS_HIDDEN, CLASS_UNSELECTABLE} from '../css.js';
|
||||||
import {easeOut} from '../easing.js';
|
import {easeOut} from '../easing.js';
|
||||||
import {listen} from '../events.js';
|
import {listen} from '../events.js';
|
||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import {inherits} from '../util.js';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {string} [className='ol-rotate'] CSS class name.
|
* @property {string} [className='ol-rotate'] CSS class name.
|
||||||
* @property {string|Element} [label='⇧'] Text label to use for the rotate button.
|
* @property {string|HTMLElement} [label='⇧'] Text label to use for the rotate button.
|
||||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {string} [tipLabel='Reset rotation'] Text label to use for the rotate tip.
|
* @property {string} [tipLabel='Reset rotation'] Text label to use for the rotate tip.
|
||||||
* @property {number} [duration=250] Animation duration in milliseconds.
|
* @property {number} [duration=250] Animation duration in milliseconds.
|
||||||
@@ -22,7 +20,7 @@ import {inherits} from '../util.js';
|
|||||||
* be re-rendered. This is called in a `requestAnimationFrame` callback.
|
* be re-rendered. This is called in a `requestAnimationFrame` callback.
|
||||||
* @property {function()} [resetNorth] Function called when the control is clicked.
|
* @property {function()} [resetNorth] Function called when the control is clicked.
|
||||||
* This will override the default `resetNorth`.
|
* This will override the default `resetNorth`.
|
||||||
* @property {Element|string} [target] Specify a target if you want the control to be
|
* @property {HTMLElement|string} [target] Specify a target if you want the control to be
|
||||||
* rendered outside of the map's viewport.
|
* rendered outside of the map's viewport.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -33,122 +31,120 @@ import {inherits} from '../util.js';
|
|||||||
* To style this control use css selector `.ol-rotate`. A `.ol-hidden` css
|
* To style this control use css selector `.ol-rotate`. A `.ol-hidden` css
|
||||||
* selector is added to the button when the rotation is 0.
|
* selector is added to the button when the rotation is 0.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/control/Control}
|
|
||||||
* @param {module:ol/control/Rotate~Options=} opt_options Rotate options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Rotate = function(opt_options) {
|
class Rotate extends Control {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
const className = options.className !== undefined ? options.className : 'ol-rotate';
|
|
||||||
|
|
||||||
const label = options.label !== undefined ? options.label : '\u21E7';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Element}
|
* @param {module:ol/control/Rotate~Options=} opt_options Rotate options.
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
this.label_ = null;
|
constructor(opt_options) {
|
||||||
|
|
||||||
if (typeof label === 'string') {
|
const options = opt_options ? opt_options : {};
|
||||||
this.label_ = document.createElement('span');
|
|
||||||
this.label_.className = 'ol-compass';
|
|
||||||
this.label_.textContent = label;
|
|
||||||
} else {
|
|
||||||
this.label_ = label;
|
|
||||||
this.label_.classList.add('ol-compass');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Reset rotation';
|
super({
|
||||||
|
element: document.createElement('div'),
|
||||||
|
render: options.render || render,
|
||||||
|
target: options.target
|
||||||
|
});
|
||||||
|
|
||||||
const button = document.createElement('button');
|
const className = options.className !== undefined ? options.className : 'ol-rotate';
|
||||||
button.className = className + '-reset';
|
|
||||||
button.setAttribute('type', 'button');
|
|
||||||
button.title = tipLabel;
|
|
||||||
button.appendChild(this.label_);
|
|
||||||
|
|
||||||
listen(button, EventType.CLICK,
|
const label = options.label !== undefined ? options.label : '\u21E7';
|
||||||
Rotate.prototype.handleClick_, this);
|
|
||||||
|
|
||||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
/**
|
||||||
const element = document.createElement('div');
|
* @type {HTMLElement}
|
||||||
element.className = cssClasses;
|
* @private
|
||||||
element.appendChild(button);
|
*/
|
||||||
|
this.label_ = null;
|
||||||
|
|
||||||
this.callResetNorth_ = options.resetNorth ? options.resetNorth : undefined;
|
if (typeof label === 'string') {
|
||||||
|
this.label_ = document.createElement('span');
|
||||||
Control.call(this, {
|
this.label_.className = 'ol-compass';
|
||||||
element: element,
|
this.label_.textContent = label;
|
||||||
render: options.render || render,
|
|
||||||
target: options.target
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {boolean}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.autoHide_ = options.autoHide !== undefined ? options.autoHide : true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {number|undefined}
|
|
||||||
*/
|
|
||||||
this.rotation_ = undefined;
|
|
||||||
|
|
||||||
if (this.autoHide_) {
|
|
||||||
this.element.classList.add(CLASS_HIDDEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(Rotate, Control);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} event The event to handle
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Rotate.prototype.handleClick_ = function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
if (this.callResetNorth_ !== undefined) {
|
|
||||||
this.callResetNorth_();
|
|
||||||
} else {
|
|
||||||
this.resetNorth_();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Rotate.prototype.resetNorth_ = function() {
|
|
||||||
const map = this.getMap();
|
|
||||||
const view = map.getView();
|
|
||||||
if (!view) {
|
|
||||||
// the map does not have a view, so we can't act
|
|
||||||
// upon it
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (view.getRotation() !== undefined) {
|
|
||||||
if (this.duration_ > 0) {
|
|
||||||
view.animate({
|
|
||||||
rotation: 0,
|
|
||||||
duration: this.duration_,
|
|
||||||
easing: easeOut
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
view.setRotation(0);
|
this.label_ = label;
|
||||||
|
this.label_.classList.add('ol-compass');
|
||||||
|
}
|
||||||
|
|
||||||
|
const tipLabel = options.tipLabel ? options.tipLabel : 'Reset rotation';
|
||||||
|
|
||||||
|
const button = document.createElement('button');
|
||||||
|
button.className = className + '-reset';
|
||||||
|
button.setAttribute('type', 'button');
|
||||||
|
button.title = tipLabel;
|
||||||
|
button.appendChild(this.label_);
|
||||||
|
|
||||||
|
listen(button, EventType.CLICK, this.handleClick_, this);
|
||||||
|
|
||||||
|
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||||
|
const element = this.element;
|
||||||
|
element.className = cssClasses;
|
||||||
|
element.appendChild(button);
|
||||||
|
|
||||||
|
this.callResetNorth_ = options.resetNorth ? options.resetNorth : undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.autoHide_ = options.autoHide !== undefined ? options.autoHide : true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number|undefined}
|
||||||
|
*/
|
||||||
|
this.rotation_ = undefined;
|
||||||
|
|
||||||
|
if (this.autoHide_) {
|
||||||
|
this.element.classList.add(CLASS_HIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event The event to handle
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleClick_(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (this.callResetNorth_ !== undefined) {
|
||||||
|
this.callResetNorth_();
|
||||||
|
} else {
|
||||||
|
this.resetNorth_();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
resetNorth_() {
|
||||||
|
const map = this.getMap();
|
||||||
|
const view = map.getView();
|
||||||
|
if (!view) {
|
||||||
|
// the map does not have a view, so we can't act
|
||||||
|
// upon it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (view.getRotation() !== undefined) {
|
||||||
|
if (this.duration_ > 0) {
|
||||||
|
view.animate({
|
||||||
|
rotation: 0,
|
||||||
|
duration: this.duration_,
|
||||||
|
easing: easeOut
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
view.setRotation(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/ScaleLine
|
* @module ol/control/ScaleLine
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {getChangeEventType} from '../Object.js';
|
import {getChangeEventType} from '../Object.js';
|
||||||
import {assert} from '../asserts.js';
|
import {assert} from '../asserts.js';
|
||||||
import Control from '../control/Control.js';
|
import Control from '../control/Control.js';
|
||||||
@@ -43,7 +42,7 @@ const LEADING_DIGITS = [1, 2, 5];
|
|||||||
* @property {number} [minWidth=64] Minimum width in pixels.
|
* @property {number} [minWidth=64] Minimum width in pixels.
|
||||||
* @property {function(module:ol/MapEvent)} [render] Function called when the control
|
* @property {function(module:ol/MapEvent)} [render] Function called when the control
|
||||||
* should be re-rendered. This is called in a `requestAnimationFrame` callback.
|
* should be re-rendered. This is called in a `requestAnimationFrame` callback.
|
||||||
* @property {Element|string} [target] Specify a target if you want the control
|
* @property {HTMLElement|string} [target] Specify a target if you want the control
|
||||||
* to be rendered outside of the map's viewport.
|
* to be rendered outside of the map's viewport.
|
||||||
* @property {module:ol/control/ScaleLine~Units|string} [units='metric'] Units.
|
* @property {module:ol/control/ScaleLine~Units|string} [units='metric'] Units.
|
||||||
*/
|
*/
|
||||||
@@ -59,92 +58,226 @@ const LEADING_DIGITS = [1, 2, 5];
|
|||||||
* By default the scale line will show in the bottom left portion of the map,
|
* By default the scale line will show in the bottom left portion of the map,
|
||||||
* but this can be changed by using the css selector `.ol-scale-line`.
|
* but this can be changed by using the css selector `.ol-scale-line`.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/control/Control}
|
|
||||||
* @param {module:ol/control/ScaleLine~Options=} opt_options Scale line options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const ScaleLine = function(opt_options) {
|
class ScaleLine extends Control {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
/**
|
||||||
|
* @param {module:ol/control/ScaleLine~Options=} opt_options Scale line options.
|
||||||
|
*/
|
||||||
|
constructor(opt_options) {
|
||||||
|
|
||||||
const className = options.className !== undefined ? options.className : 'ol-scale-line';
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
const className = options.className !== undefined ? options.className : 'ol-scale-line';
|
||||||
|
|
||||||
|
super({
|
||||||
|
element: document.createElement('DIV'),
|
||||||
|
render: options.render || render,
|
||||||
|
target: options.target
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*/
|
||||||
|
this.innerElement_ = document.createElement('DIV');
|
||||||
|
this.innerElement_.className = className + '-inner';
|
||||||
|
|
||||||
|
this.element.className = className + ' ' + CLASS_UNSELECTABLE;
|
||||||
|
this.element.appendChild(this.innerElement_);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {?module:ol/View~State}
|
||||||
|
*/
|
||||||
|
this.viewState_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.minWidth_ = options.minWidth !== undefined ? options.minWidth : 64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.renderedVisible_ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number|undefined}
|
||||||
|
*/
|
||||||
|
this.renderedWidth_ = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.renderedHTML_ = '';
|
||||||
|
|
||||||
|
listen(
|
||||||
|
this, getChangeEventType(UNITS_PROP),
|
||||||
|
this.handleUnitsChanged_, this);
|
||||||
|
|
||||||
|
this.setUnits(/** @type {module:ol/control/ScaleLine~Units} */ (options.units) ||
|
||||||
|
Units.METRIC);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the units to use in the scale line.
|
||||||
|
* @return {module:ol/control/ScaleLine~Units|undefined} The units
|
||||||
|
* to use in the scale line.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getUnits() {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/control/ScaleLine~Units|undefined} */ (this.get(UNITS_PROP))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {Element}
|
|
||||||
*/
|
*/
|
||||||
this.innerElement_ = document.createElement('DIV');
|
handleUnitsChanged_() {
|
||||||
this.innerElement_.className = className + '-inner';
|
this.updateElement_();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the units to use in the scale line.
|
||||||
|
* @param {module:ol/control/ScaleLine~Units} units The units to use in the scale line.
|
||||||
|
* @observable
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setUnits(units) {
|
||||||
|
this.set(UNITS_PROP, units);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {Element}
|
|
||||||
*/
|
*/
|
||||||
this.element_ = document.createElement('DIV');
|
updateElement_() {
|
||||||
this.element_.className = className + ' ' + CLASS_UNSELECTABLE;
|
const viewState = this.viewState_;
|
||||||
this.element_.appendChild(this.innerElement_);
|
|
||||||
|
|
||||||
/**
|
if (!viewState) {
|
||||||
* @private
|
if (this.renderedVisible_) {
|
||||||
* @type {?module:ol/View~State}
|
this.element.style.display = 'none';
|
||||||
*/
|
this.renderedVisible_ = false;
|
||||||
this.viewState_ = null;
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
const center = viewState.center;
|
||||||
* @private
|
const projection = viewState.projection;
|
||||||
* @type {number}
|
const units = this.getUnits();
|
||||||
*/
|
const pointResolutionUnits = units == Units.DEGREES ?
|
||||||
this.minWidth_ = options.minWidth !== undefined ? options.minWidth : 64;
|
ProjUnits.DEGREES :
|
||||||
|
ProjUnits.METERS;
|
||||||
|
let pointResolution =
|
||||||
|
getPointResolution(projection, viewState.resolution, center, pointResolutionUnits);
|
||||||
|
if (projection.getUnits() != ProjUnits.DEGREES && projection.getMetersPerUnit()
|
||||||
|
&& pointResolutionUnits == ProjUnits.METERS) {
|
||||||
|
pointResolution *= projection.getMetersPerUnit();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
let nominalCount = this.minWidth_ * pointResolution;
|
||||||
* @private
|
let suffix = '';
|
||||||
* @type {boolean}
|
if (units == Units.DEGREES) {
|
||||||
*/
|
const metersPerDegree = METERS_PER_UNIT[ProjUnits.DEGREES];
|
||||||
this.renderedVisible_ = false;
|
if (projection.getUnits() == ProjUnits.DEGREES) {
|
||||||
|
nominalCount *= metersPerDegree;
|
||||||
|
} else {
|
||||||
|
pointResolution /= metersPerDegree;
|
||||||
|
}
|
||||||
|
if (nominalCount < metersPerDegree / 60) {
|
||||||
|
suffix = '\u2033'; // seconds
|
||||||
|
pointResolution *= 3600;
|
||||||
|
} else if (nominalCount < metersPerDegree) {
|
||||||
|
suffix = '\u2032'; // minutes
|
||||||
|
pointResolution *= 60;
|
||||||
|
} else {
|
||||||
|
suffix = '\u00b0'; // degrees
|
||||||
|
}
|
||||||
|
} else if (units == Units.IMPERIAL) {
|
||||||
|
if (nominalCount < 0.9144) {
|
||||||
|
suffix = 'in';
|
||||||
|
pointResolution /= 0.0254;
|
||||||
|
} else if (nominalCount < 1609.344) {
|
||||||
|
suffix = 'ft';
|
||||||
|
pointResolution /= 0.3048;
|
||||||
|
} else {
|
||||||
|
suffix = 'mi';
|
||||||
|
pointResolution /= 1609.344;
|
||||||
|
}
|
||||||
|
} else if (units == Units.NAUTICAL) {
|
||||||
|
pointResolution /= 1852;
|
||||||
|
suffix = 'nm';
|
||||||
|
} else if (units == Units.METRIC) {
|
||||||
|
if (nominalCount < 0.001) {
|
||||||
|
suffix = 'μm';
|
||||||
|
pointResolution *= 1000000;
|
||||||
|
} else if (nominalCount < 1) {
|
||||||
|
suffix = 'mm';
|
||||||
|
pointResolution *= 1000;
|
||||||
|
} else if (nominalCount < 1000) {
|
||||||
|
suffix = 'm';
|
||||||
|
} else {
|
||||||
|
suffix = 'km';
|
||||||
|
pointResolution /= 1000;
|
||||||
|
}
|
||||||
|
} else if (units == Units.US) {
|
||||||
|
if (nominalCount < 0.9144) {
|
||||||
|
suffix = 'in';
|
||||||
|
pointResolution *= 39.37;
|
||||||
|
} else if (nominalCount < 1609.344) {
|
||||||
|
suffix = 'ft';
|
||||||
|
pointResolution /= 0.30480061;
|
||||||
|
} else {
|
||||||
|
suffix = 'mi';
|
||||||
|
pointResolution /= 1609.3472;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(false, 33); // Invalid units
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
let i = 3 * Math.floor(
|
||||||
* @private
|
Math.log(this.minWidth_ * pointResolution) / Math.log(10));
|
||||||
* @type {number|undefined}
|
let count, width;
|
||||||
*/
|
while (true) {
|
||||||
this.renderedWidth_ = undefined;
|
count = LEADING_DIGITS[((i % 3) + 3) % 3] *
|
||||||
|
Math.pow(10, Math.floor(i / 3));
|
||||||
|
width = Math.round(count / pointResolution);
|
||||||
|
if (isNaN(width)) {
|
||||||
|
this.element.style.display = 'none';
|
||||||
|
this.renderedVisible_ = false;
|
||||||
|
return;
|
||||||
|
} else if (width >= this.minWidth_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
const html = count + ' ' + suffix;
|
||||||
* @private
|
if (this.renderedHTML_ != html) {
|
||||||
* @type {string}
|
this.innerElement_.innerHTML = html;
|
||||||
*/
|
this.renderedHTML_ = html;
|
||||||
this.renderedHTML_ = '';
|
}
|
||||||
|
|
||||||
Control.call(this, {
|
if (this.renderedWidth_ != width) {
|
||||||
element: this.element_,
|
this.innerElement_.style.width = width + 'px';
|
||||||
render: options.render || render,
|
this.renderedWidth_ = width;
|
||||||
target: options.target
|
}
|
||||||
});
|
|
||||||
|
|
||||||
listen(
|
if (!this.renderedVisible_) {
|
||||||
this, getChangeEventType(UNITS_PROP),
|
this.element.style.display = '';
|
||||||
this.handleUnitsChanged_, this);
|
this.renderedVisible_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
this.setUnits(/** @type {module:ol/control/ScaleLine~Units} */ (options.units) ||
|
}
|
||||||
Units.METRIC);
|
}
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(ScaleLine, Control);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the units to use in the scale line.
|
|
||||||
* @return {module:ol/control/ScaleLine~Units|undefined} The units
|
|
||||||
* to use in the scale line.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
ScaleLine.prototype.getUnits = function() {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/control/ScaleLine~Units|undefined} */ (this.get(UNITS_PROP))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -164,145 +297,4 @@ export function render(mapEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ScaleLine.prototype.handleUnitsChanged_ = function() {
|
|
||||||
this.updateElement_();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the units to use in the scale line.
|
|
||||||
* @param {module:ol/control/ScaleLine~Units} units The units to use in the scale line.
|
|
||||||
* @observable
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
ScaleLine.prototype.setUnits = function(units) {
|
|
||||||
this.set(UNITS_PROP, units);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ScaleLine.prototype.updateElement_ = function() {
|
|
||||||
const viewState = this.viewState_;
|
|
||||||
|
|
||||||
if (!viewState) {
|
|
||||||
if (this.renderedVisible_) {
|
|
||||||
this.element_.style.display = 'none';
|
|
||||||
this.renderedVisible_ = false;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const center = viewState.center;
|
|
||||||
const projection = viewState.projection;
|
|
||||||
const units = this.getUnits();
|
|
||||||
const pointResolutionUnits = units == Units.DEGREES ?
|
|
||||||
ProjUnits.DEGREES :
|
|
||||||
ProjUnits.METERS;
|
|
||||||
let pointResolution =
|
|
||||||
getPointResolution(projection, viewState.resolution, center, pointResolutionUnits);
|
|
||||||
if (projection.getUnits() != ProjUnits.DEGREES && projection.getMetersPerUnit()
|
|
||||||
&& pointResolutionUnits == ProjUnits.METERS) {
|
|
||||||
pointResolution *= projection.getMetersPerUnit();
|
|
||||||
}
|
|
||||||
|
|
||||||
let nominalCount = this.minWidth_ * pointResolution;
|
|
||||||
let suffix = '';
|
|
||||||
if (units == Units.DEGREES) {
|
|
||||||
const metersPerDegree = METERS_PER_UNIT[ProjUnits.DEGREES];
|
|
||||||
if (projection.getUnits() == ProjUnits.DEGREES) {
|
|
||||||
nominalCount *= metersPerDegree;
|
|
||||||
} else {
|
|
||||||
pointResolution /= metersPerDegree;
|
|
||||||
}
|
|
||||||
if (nominalCount < metersPerDegree / 60) {
|
|
||||||
suffix = '\u2033'; // seconds
|
|
||||||
pointResolution *= 3600;
|
|
||||||
} else if (nominalCount < metersPerDegree) {
|
|
||||||
suffix = '\u2032'; // minutes
|
|
||||||
pointResolution *= 60;
|
|
||||||
} else {
|
|
||||||
suffix = '\u00b0'; // degrees
|
|
||||||
}
|
|
||||||
} else if (units == Units.IMPERIAL) {
|
|
||||||
if (nominalCount < 0.9144) {
|
|
||||||
suffix = 'in';
|
|
||||||
pointResolution /= 0.0254;
|
|
||||||
} else if (nominalCount < 1609.344) {
|
|
||||||
suffix = 'ft';
|
|
||||||
pointResolution /= 0.3048;
|
|
||||||
} else {
|
|
||||||
suffix = 'mi';
|
|
||||||
pointResolution /= 1609.344;
|
|
||||||
}
|
|
||||||
} else if (units == Units.NAUTICAL) {
|
|
||||||
pointResolution /= 1852;
|
|
||||||
suffix = 'nm';
|
|
||||||
} else if (units == Units.METRIC) {
|
|
||||||
if (nominalCount < 0.001) {
|
|
||||||
suffix = 'μm';
|
|
||||||
pointResolution *= 1000000;
|
|
||||||
} else if (nominalCount < 1) {
|
|
||||||
suffix = 'mm';
|
|
||||||
pointResolution *= 1000;
|
|
||||||
} else if (nominalCount < 1000) {
|
|
||||||
suffix = 'm';
|
|
||||||
} else {
|
|
||||||
suffix = 'km';
|
|
||||||
pointResolution /= 1000;
|
|
||||||
}
|
|
||||||
} else if (units == Units.US) {
|
|
||||||
if (nominalCount < 0.9144) {
|
|
||||||
suffix = 'in';
|
|
||||||
pointResolution *= 39.37;
|
|
||||||
} else if (nominalCount < 1609.344) {
|
|
||||||
suffix = 'ft';
|
|
||||||
pointResolution /= 0.30480061;
|
|
||||||
} else {
|
|
||||||
suffix = 'mi';
|
|
||||||
pointResolution /= 1609.3472;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(false, 33); // Invalid units
|
|
||||||
}
|
|
||||||
|
|
||||||
let i = 3 * Math.floor(
|
|
||||||
Math.log(this.minWidth_ * pointResolution) / Math.log(10));
|
|
||||||
let count, width;
|
|
||||||
while (true) {
|
|
||||||
count = LEADING_DIGITS[((i % 3) + 3) % 3] *
|
|
||||||
Math.pow(10, Math.floor(i / 3));
|
|
||||||
width = Math.round(count / pointResolution);
|
|
||||||
if (isNaN(width)) {
|
|
||||||
this.element_.style.display = 'none';
|
|
||||||
this.renderedVisible_ = false;
|
|
||||||
return;
|
|
||||||
} else if (width >= this.minWidth_) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
const html = count + ' ' + suffix;
|
|
||||||
if (this.renderedHTML_ != html) {
|
|
||||||
this.innerElement_.innerHTML = html;
|
|
||||||
this.renderedHTML_ = html;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.renderedWidth_ != width) {
|
|
||||||
this.innerElement_.style.width = width + 'px';
|
|
||||||
this.renderedWidth_ = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.renderedVisible_) {
|
|
||||||
this.element_.style.display = '';
|
|
||||||
this.renderedVisible_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ScaleLine;
|
export default ScaleLine;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/Zoom
|
* @module ol/control/Zoom
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {listen} from '../events.js';
|
import {listen} from '../events.js';
|
||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import Control from '../control/Control.js';
|
import Control from '../control/Control.js';
|
||||||
@@ -13,14 +12,14 @@ import {easeOut} from '../easing.js';
|
|||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {number} [duration=250] Animation duration in milliseconds.
|
* @property {number} [duration=250] Animation duration in milliseconds.
|
||||||
* @property {string} [className='ol-zoom'] CSS class name.
|
* @property {string} [className='ol-zoom'] CSS class name.
|
||||||
* @property {string|Element} [zoomInLabel='+'] Text label to use for the zoom-in
|
* @property {string|HTMLElement} [zoomInLabel='+'] Text label to use for the zoom-in
|
||||||
* button. Instead of text, also an element (e.g. a `span` element) can be used.
|
* button. Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {string|Element} [zoomOutLabel='-'] Text label to use for the zoom-out button.
|
* @property {string|HTMLElement} [zoomOutLabel='-'] Text label to use for the zoom-out button.
|
||||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {string} [zoomInTipLabel='Zoom in'] Text label to use for the button tip.
|
* @property {string} [zoomInTipLabel='Zoom in'] Text label to use for the button tip.
|
||||||
* @property {string} [zoomOutTipLabel='Zoom out'] Text label to use for the button tip.
|
* @property {string} [zoomOutTipLabel='Zoom out'] Text label to use for the button tip.
|
||||||
* @property {number} [delta=1] The zoom delta applied on each click.
|
* @property {number} [delta=1] The zoom delta applied on each click.
|
||||||
* @property {Element|string} [target] Specify a target if you want the control to be
|
* @property {HTMLElement|string} [target] Specify a target if you want the control to be
|
||||||
* rendered outside of the map's viewport.
|
* rendered outside of the map's viewport.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -31,109 +30,108 @@ import {easeOut} from '../easing.js';
|
|||||||
* This control is one of the default controls of a map. To style this control
|
* This control is one of the default controls of a map. To style this control
|
||||||
* use css selectors `.ol-zoom-in` and `.ol-zoom-out`.
|
* use css selectors `.ol-zoom-in` and `.ol-zoom-out`.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/control/Control}
|
|
||||||
* @param {module:ol/control/Zoom~Options=} opt_options Zoom options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Zoom = function(opt_options) {
|
class Zoom extends Control {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
const className = options.className !== undefined ? options.className : 'ol-zoom';
|
|
||||||
|
|
||||||
const delta = options.delta !== undefined ? options.delta : 1;
|
|
||||||
|
|
||||||
const zoomInLabel = options.zoomInLabel !== undefined ? options.zoomInLabel : '+';
|
|
||||||
const zoomOutLabel = options.zoomOutLabel !== undefined ? options.zoomOutLabel : '\u2212';
|
|
||||||
|
|
||||||
const zoomInTipLabel = options.zoomInTipLabel !== undefined ?
|
|
||||||
options.zoomInTipLabel : 'Zoom in';
|
|
||||||
const zoomOutTipLabel = options.zoomOutTipLabel !== undefined ?
|
|
||||||
options.zoomOutTipLabel : 'Zoom out';
|
|
||||||
|
|
||||||
const inElement = document.createElement('button');
|
|
||||||
inElement.className = className + '-in';
|
|
||||||
inElement.setAttribute('type', 'button');
|
|
||||||
inElement.title = zoomInTipLabel;
|
|
||||||
inElement.appendChild(
|
|
||||||
typeof zoomInLabel === 'string' ? document.createTextNode(zoomInLabel) : zoomInLabel
|
|
||||||
);
|
|
||||||
|
|
||||||
listen(inElement, EventType.CLICK,
|
|
||||||
Zoom.prototype.handleClick_.bind(this, delta));
|
|
||||||
|
|
||||||
const outElement = document.createElement('button');
|
|
||||||
outElement.className = className + '-out';
|
|
||||||
outElement.setAttribute('type', 'button');
|
|
||||||
outElement.title = zoomOutTipLabel;
|
|
||||||
outElement.appendChild(
|
|
||||||
typeof zoomOutLabel === 'string' ? document.createTextNode(zoomOutLabel) : zoomOutLabel
|
|
||||||
);
|
|
||||||
|
|
||||||
listen(outElement, EventType.CLICK,
|
|
||||||
Zoom.prototype.handleClick_.bind(this, -delta));
|
|
||||||
|
|
||||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
|
||||||
const element = document.createElement('div');
|
|
||||||
element.className = cssClasses;
|
|
||||||
element.appendChild(inElement);
|
|
||||||
element.appendChild(outElement);
|
|
||||||
|
|
||||||
Control.call(this, {
|
|
||||||
element: element,
|
|
||||||
target: options.target
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* @param {module:ol/control/Zoom~Options=} opt_options Zoom options.
|
||||||
|
*/
|
||||||
|
constructor(opt_options) {
|
||||||
|
|
||||||
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
super({
|
||||||
|
element: document.createElement('div'),
|
||||||
|
target: options.target
|
||||||
|
});
|
||||||
|
|
||||||
|
const className = options.className !== undefined ? options.className : 'ol-zoom';
|
||||||
|
|
||||||
|
const delta = options.delta !== undefined ? options.delta : 1;
|
||||||
|
|
||||||
|
const zoomInLabel = options.zoomInLabel !== undefined ? options.zoomInLabel : '+';
|
||||||
|
const zoomOutLabel = options.zoomOutLabel !== undefined ? options.zoomOutLabel : '\u2212';
|
||||||
|
|
||||||
|
const zoomInTipLabel = options.zoomInTipLabel !== undefined ?
|
||||||
|
options.zoomInTipLabel : 'Zoom in';
|
||||||
|
const zoomOutTipLabel = options.zoomOutTipLabel !== undefined ?
|
||||||
|
options.zoomOutTipLabel : 'Zoom out';
|
||||||
|
|
||||||
|
const inElement = document.createElement('button');
|
||||||
|
inElement.className = className + '-in';
|
||||||
|
inElement.setAttribute('type', 'button');
|
||||||
|
inElement.title = zoomInTipLabel;
|
||||||
|
inElement.appendChild(
|
||||||
|
typeof zoomInLabel === 'string' ? document.createTextNode(zoomInLabel) : zoomInLabel
|
||||||
|
);
|
||||||
|
|
||||||
|
listen(inElement, EventType.CLICK, this.handleClick_.bind(this, delta));
|
||||||
|
|
||||||
|
const outElement = document.createElement('button');
|
||||||
|
outElement.className = className + '-out';
|
||||||
|
outElement.setAttribute('type', 'button');
|
||||||
|
outElement.title = zoomOutTipLabel;
|
||||||
|
outElement.appendChild(
|
||||||
|
typeof zoomOutLabel === 'string' ? document.createTextNode(zoomOutLabel) : zoomOutLabel
|
||||||
|
);
|
||||||
|
|
||||||
|
listen(outElement, EventType.CLICK, this.handleClick_.bind(this, -delta));
|
||||||
|
|
||||||
|
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||||
|
const element = this.element;
|
||||||
|
element.className = cssClasses;
|
||||||
|
element.appendChild(inElement);
|
||||||
|
element.appendChild(outElement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} delta Zoom delta.
|
||||||
|
* @param {MouseEvent} event The event to handle
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
handleClick_(delta, event) {
|
||||||
|
event.preventDefault();
|
||||||
};
|
this.zoomByDelta_(delta);
|
||||||
|
|
||||||
inherits(Zoom, Control);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} delta Zoom delta.
|
|
||||||
* @param {Event} event The event to handle
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Zoom.prototype.handleClick_ = function(delta, event) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.zoomByDelta_(delta);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} delta Zoom delta.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
Zoom.prototype.zoomByDelta_ = function(delta) {
|
|
||||||
const map = this.getMap();
|
|
||||||
const view = map.getView();
|
|
||||||
if (!view) {
|
|
||||||
// the map does not have a view, so we can't act
|
|
||||||
// upon it
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const currentResolution = view.getResolution();
|
|
||||||
if (currentResolution) {
|
/**
|
||||||
const newResolution = view.constrainResolution(currentResolution, delta);
|
* @param {number} delta Zoom delta.
|
||||||
if (this.duration_ > 0) {
|
* @private
|
||||||
if (view.getAnimating()) {
|
*/
|
||||||
view.cancelAnimations();
|
zoomByDelta_(delta) {
|
||||||
|
const map = this.getMap();
|
||||||
|
const view = map.getView();
|
||||||
|
if (!view) {
|
||||||
|
// the map does not have a view, so we can't act
|
||||||
|
// upon it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const currentResolution = view.getResolution();
|
||||||
|
if (currentResolution) {
|
||||||
|
const newResolution = view.constrainResolution(currentResolution, delta);
|
||||||
|
if (this.duration_ > 0) {
|
||||||
|
if (view.getAnimating()) {
|
||||||
|
view.cancelAnimations();
|
||||||
|
}
|
||||||
|
view.animate({
|
||||||
|
resolution: newResolution,
|
||||||
|
duration: this.duration_,
|
||||||
|
easing: easeOut
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
view.setResolution(newResolution);
|
||||||
}
|
}
|
||||||
view.animate({
|
|
||||||
resolution: newResolution,
|
|
||||||
duration: this.duration_,
|
|
||||||
easing: easeOut
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
view.setResolution(newResolution);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
export default Zoom;
|
export default Zoom;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/ZoomSlider
|
* @module ol/control/ZoomSlider
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import ViewHint from '../ViewHint.js';
|
import ViewHint from '../ViewHint.js';
|
||||||
import Control from '../control/Control.js';
|
import Control from '../control/Control.js';
|
||||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||||
@@ -42,167 +41,305 @@ const Direction = {
|
|||||||
*
|
*
|
||||||
* map.addControl(new ZoomSlider());
|
* map.addControl(new ZoomSlider());
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/control/Control}
|
|
||||||
* @param {module:ol/control/ZoomSlider~Options=} opt_options Zoom slider options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const ZoomSlider = function(opt_options) {
|
class ZoomSlider extends Control {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will hold the current resolution of the view.
|
* @param {module:ol/control/ZoomSlider~Options=} opt_options Zoom slider options.
|
||||||
*
|
|
||||||
* @type {number|undefined}
|
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
this.currentResolution_ = undefined;
|
constructor(opt_options) {
|
||||||
|
|
||||||
/**
|
const options = opt_options ? opt_options : {};
|
||||||
* The direction of the slider. Will be determined from actual display of the
|
|
||||||
* container and defaults to Direction.VERTICAL.
|
|
||||||
*
|
|
||||||
* @type {Direction}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.direction_ = Direction.VERTICAL;
|
|
||||||
|
|
||||||
/**
|
super({
|
||||||
* @type {boolean}
|
element: document.createElement('div'),
|
||||||
* @private
|
render: options.render || render
|
||||||
*/
|
});
|
||||||
this.dragging_;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* Will hold the current resolution of the view.
|
||||||
* @private
|
*
|
||||||
*/
|
* @type {number|undefined}
|
||||||
this.heightLimit_ = 0;
|
* @private
|
||||||
|
*/
|
||||||
|
this.currentResolution_ = undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* The direction of the slider. Will be determined from actual display of the
|
||||||
* @private
|
* container and defaults to Direction.VERTICAL.
|
||||||
*/
|
*
|
||||||
this.widthLimit_ = 0;
|
* @type {Direction}
|
||||||
|
* @private
|
||||||
/**
|
*/
|
||||||
* @type {number|undefined}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.previousX_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number|undefined}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.previousY_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The calculated thumb size (border box plus margins). Set when initSlider_
|
|
||||||
* is called.
|
|
||||||
* @type {module:ol/size~Size}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.thumbSize_ = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the slider is initialized.
|
|
||||||
* @type {boolean}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.sliderInitialized_ = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.duration_ = options.duration !== undefined ? options.duration : 200;
|
|
||||||
|
|
||||||
const className = options.className !== undefined ? options.className : 'ol-zoomslider';
|
|
||||||
const thumbElement = document.createElement('button');
|
|
||||||
thumbElement.setAttribute('type', 'button');
|
|
||||||
thumbElement.className = className + '-thumb ' + CLASS_UNSELECTABLE;
|
|
||||||
const containerElement = document.createElement('div');
|
|
||||||
containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
|
||||||
containerElement.appendChild(thumbElement);
|
|
||||||
/**
|
|
||||||
* @type {module:ol/pointer/PointerEventHandler}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.dragger_ = new PointerEventHandler(containerElement);
|
|
||||||
|
|
||||||
listen(this.dragger_, PointerEventType.POINTERDOWN,
|
|
||||||
this.handleDraggerStart_, this);
|
|
||||||
listen(this.dragger_, PointerEventType.POINTERMOVE,
|
|
||||||
this.handleDraggerDrag_, this);
|
|
||||||
listen(this.dragger_, PointerEventType.POINTERUP,
|
|
||||||
this.handleDraggerEnd_, this);
|
|
||||||
|
|
||||||
listen(containerElement, EventType.CLICK, this.handleContainerClick_, this);
|
|
||||||
listen(thumbElement, EventType.CLICK, stopPropagation);
|
|
||||||
|
|
||||||
Control.call(this, {
|
|
||||||
element: containerElement,
|
|
||||||
render: options.render || render
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(ZoomSlider, Control);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.disposeInternal = function() {
|
|
||||||
this.dragger_.dispose();
|
|
||||||
Control.prototype.disposeInternal.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.setMap = function(map) {
|
|
||||||
Control.prototype.setMap.call(this, map);
|
|
||||||
if (map) {
|
|
||||||
map.render();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the slider element. This will determine and set this controls
|
|
||||||
* direction_ and also constrain the dragging of the thumb to always be within
|
|
||||||
* the bounds of the container.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.initSlider_ = function() {
|
|
||||||
const container = this.element;
|
|
||||||
const containerSize = {
|
|
||||||
width: container.offsetWidth, height: container.offsetHeight
|
|
||||||
};
|
|
||||||
|
|
||||||
const thumb = container.firstElementChild;
|
|
||||||
const computedStyle = getComputedStyle(thumb);
|
|
||||||
const thumbWidth = thumb.offsetWidth +
|
|
||||||
parseFloat(computedStyle['marginRight']) +
|
|
||||||
parseFloat(computedStyle['marginLeft']);
|
|
||||||
const thumbHeight = thumb.offsetHeight +
|
|
||||||
parseFloat(computedStyle['marginTop']) +
|
|
||||||
parseFloat(computedStyle['marginBottom']);
|
|
||||||
this.thumbSize_ = [thumbWidth, thumbHeight];
|
|
||||||
|
|
||||||
if (containerSize.width > containerSize.height) {
|
|
||||||
this.direction_ = Direction.HORIZONTAL;
|
|
||||||
this.widthLimit_ = containerSize.width - thumbWidth;
|
|
||||||
} else {
|
|
||||||
this.direction_ = Direction.VERTICAL;
|
this.direction_ = Direction.VERTICAL;
|
||||||
this.heightLimit_ = containerSize.height - thumbHeight;
|
|
||||||
|
/**
|
||||||
|
* @type {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.dragging_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.heightLimit_ = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.widthLimit_ = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.previousX_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.previousY_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The calculated thumb size (border box plus margins). Set when initSlider_
|
||||||
|
* is called.
|
||||||
|
* @type {module:ol/size~Size}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.thumbSize_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the slider is initialized.
|
||||||
|
* @type {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.sliderInitialized_ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.duration_ = options.duration !== undefined ? options.duration : 200;
|
||||||
|
|
||||||
|
const className = options.className !== undefined ? options.className : 'ol-zoomslider';
|
||||||
|
const thumbElement = document.createElement('button');
|
||||||
|
thumbElement.setAttribute('type', 'button');
|
||||||
|
thumbElement.className = className + '-thumb ' + CLASS_UNSELECTABLE;
|
||||||
|
const containerElement = this.element;
|
||||||
|
containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||||
|
containerElement.appendChild(thumbElement);
|
||||||
|
/**
|
||||||
|
* @type {module:ol/pointer/PointerEventHandler}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.dragger_ = new PointerEventHandler(containerElement);
|
||||||
|
|
||||||
|
listen(this.dragger_, PointerEventType.POINTERDOWN,
|
||||||
|
this.handleDraggerStart_, this);
|
||||||
|
listen(this.dragger_, PointerEventType.POINTERMOVE,
|
||||||
|
this.handleDraggerDrag_, this);
|
||||||
|
listen(this.dragger_, PointerEventType.POINTERUP,
|
||||||
|
this.handleDraggerEnd_, this);
|
||||||
|
|
||||||
|
listen(containerElement, EventType.CLICK, this.handleContainerClick_, this);
|
||||||
|
listen(thumbElement, EventType.CLICK, stopPropagation);
|
||||||
}
|
}
|
||||||
this.sliderInitialized_ = true;
|
|
||||||
};
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
disposeInternal() {
|
||||||
|
this.dragger_.dispose();
|
||||||
|
super.disposeInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
setMap(map) {
|
||||||
|
super.setMap(map);
|
||||||
|
if (map) {
|
||||||
|
map.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the slider element. This will determine and set this controls
|
||||||
|
* direction_ and also constrain the dragging of the thumb to always be within
|
||||||
|
* the bounds of the container.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
initSlider_() {
|
||||||
|
const container = this.element;
|
||||||
|
const containerSize = {
|
||||||
|
width: container.offsetWidth, height: container.offsetHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
const thumb = /** @type {HTMLElement} */ (container.firstElementChild);
|
||||||
|
const computedStyle = getComputedStyle(thumb);
|
||||||
|
const thumbWidth = thumb.offsetWidth +
|
||||||
|
parseFloat(computedStyle['marginRight']) +
|
||||||
|
parseFloat(computedStyle['marginLeft']);
|
||||||
|
const thumbHeight = thumb.offsetHeight +
|
||||||
|
parseFloat(computedStyle['marginTop']) +
|
||||||
|
parseFloat(computedStyle['marginBottom']);
|
||||||
|
this.thumbSize_ = [thumbWidth, thumbHeight];
|
||||||
|
|
||||||
|
if (containerSize.width > containerSize.height) {
|
||||||
|
this.direction_ = Direction.HORIZONTAL;
|
||||||
|
this.widthLimit_ = containerSize.width - thumbWidth;
|
||||||
|
} else {
|
||||||
|
this.direction_ = Direction.VERTICAL;
|
||||||
|
this.heightLimit_ = containerSize.height - thumbHeight;
|
||||||
|
}
|
||||||
|
this.sliderInitialized_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event The browser event to handle.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleContainerClick_(event) {
|
||||||
|
const view = this.getMap().getView();
|
||||||
|
|
||||||
|
const relativePosition = this.getRelativePosition_(
|
||||||
|
event.offsetX - this.thumbSize_[0] / 2,
|
||||||
|
event.offsetY - this.thumbSize_[1] / 2);
|
||||||
|
|
||||||
|
const resolution = this.getResolutionForPosition_(relativePosition);
|
||||||
|
|
||||||
|
view.animate({
|
||||||
|
resolution: view.constrainResolution(resolution),
|
||||||
|
duration: this.duration_,
|
||||||
|
easing: easeOut
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle dragger start events.
|
||||||
|
* @param {module:ol/pointer/PointerEvent} event The drag event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleDraggerStart_(event) {
|
||||||
|
if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
|
||||||
|
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
|
||||||
|
this.previousX_ = event.clientX;
|
||||||
|
this.previousY_ = event.clientY;
|
||||||
|
this.dragging_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle dragger drag events.
|
||||||
|
*
|
||||||
|
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleDraggerDrag_(event) {
|
||||||
|
if (this.dragging_) {
|
||||||
|
const element = /** @type {HTMLElement} */ (this.element.firstElementChild);
|
||||||
|
const deltaX = event.clientX - this.previousX_ + parseInt(element.style.left, 10);
|
||||||
|
const deltaY = event.clientY - this.previousY_ + parseInt(element.style.top, 10);
|
||||||
|
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
|
||||||
|
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
|
||||||
|
this.getMap().getView().setResolution(this.currentResolution_);
|
||||||
|
this.setThumbPosition_(this.currentResolution_);
|
||||||
|
this.previousX_ = event.clientX;
|
||||||
|
this.previousY_ = event.clientY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle dragger end events.
|
||||||
|
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleDraggerEnd_(event) {
|
||||||
|
if (this.dragging_) {
|
||||||
|
const view = this.getMap().getView();
|
||||||
|
view.setHint(ViewHint.INTERACTING, -1);
|
||||||
|
|
||||||
|
view.animate({
|
||||||
|
resolution: view.constrainResolution(this.currentResolution_),
|
||||||
|
duration: this.duration_,
|
||||||
|
easing: easeOut
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dragging_ = false;
|
||||||
|
this.previousX_ = undefined;
|
||||||
|
this.previousY_ = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Positions the thumb inside its container according to the given resolution.
|
||||||
|
*
|
||||||
|
* @param {number} res The res.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
setThumbPosition_(res) {
|
||||||
|
const position = this.getPositionForResolution_(res);
|
||||||
|
const thumb = /** @type {HTMLElement} */ (this.element.firstElementChild);
|
||||||
|
|
||||||
|
if (this.direction_ == Direction.HORIZONTAL) {
|
||||||
|
thumb.style.left = this.widthLimit_ * position + 'px';
|
||||||
|
} else {
|
||||||
|
thumb.style.top = this.heightLimit_ * position + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the relative position of the thumb given x and y offsets. The
|
||||||
|
* relative position scales from 0 to 1. The x and y offsets are assumed to be
|
||||||
|
* in pixel units within the dragger limits.
|
||||||
|
*
|
||||||
|
* @param {number} x Pixel position relative to the left of the slider.
|
||||||
|
* @param {number} y Pixel position relative to the top of the slider.
|
||||||
|
* @return {number} The relative position of the thumb.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getRelativePosition_(x, y) {
|
||||||
|
let amount;
|
||||||
|
if (this.direction_ === Direction.HORIZONTAL) {
|
||||||
|
amount = x / this.widthLimit_;
|
||||||
|
} else {
|
||||||
|
amount = y / this.heightLimit_;
|
||||||
|
}
|
||||||
|
return clamp(amount, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the corresponding resolution of the thumb given its relative
|
||||||
|
* position (where 0 is the minimum and 1 is the maximum).
|
||||||
|
*
|
||||||
|
* @param {number} position The relative position of the thumb.
|
||||||
|
* @return {number} The corresponding resolution.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getResolutionForPosition_(position) {
|
||||||
|
const fn = this.getMap().getView().getResolutionForValueFunction();
|
||||||
|
return fn(1 - position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the relative position of the slider for the given resolution. A
|
||||||
|
* relative position of 0 corresponds to the minimum view resolution. A
|
||||||
|
* relative position of 1 corresponds to the maximum view resolution.
|
||||||
|
*
|
||||||
|
* @param {number} res The resolution.
|
||||||
|
* @return {number} The relative position value (between 0 and 1).
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getPositionForResolution_(res) {
|
||||||
|
const fn = this.getMap().getView().getValueForResolutionFunction();
|
||||||
|
return 1 - fn(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,151 +363,4 @@ export function render(mapEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} event The browser event to handle.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.handleContainerClick_ = function(event) {
|
|
||||||
const view = this.getMap().getView();
|
|
||||||
|
|
||||||
const relativePosition = this.getRelativePosition_(
|
|
||||||
event.offsetX - this.thumbSize_[0] / 2,
|
|
||||||
event.offsetY - this.thumbSize_[1] / 2);
|
|
||||||
|
|
||||||
const resolution = this.getResolutionForPosition_(relativePosition);
|
|
||||||
|
|
||||||
view.animate({
|
|
||||||
resolution: view.constrainResolution(resolution),
|
|
||||||
duration: this.duration_,
|
|
||||||
easing: easeOut
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle dragger start events.
|
|
||||||
* @param {module:ol/pointer/PointerEvent} event The drag event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.handleDraggerStart_ = function(event) {
|
|
||||||
if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
|
|
||||||
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
|
|
||||||
this.previousX_ = event.clientX;
|
|
||||||
this.previousY_ = event.clientY;
|
|
||||||
this.dragging_ = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle dragger drag events.
|
|
||||||
*
|
|
||||||
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.handleDraggerDrag_ = function(event) {
|
|
||||||
if (this.dragging_) {
|
|
||||||
const element = this.element.firstElementChild;
|
|
||||||
const deltaX = event.clientX - this.previousX_ + parseInt(element.style.left, 10);
|
|
||||||
const deltaY = event.clientY - this.previousY_ + parseInt(element.style.top, 10);
|
|
||||||
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
|
|
||||||
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
|
|
||||||
this.getMap().getView().setResolution(this.currentResolution_);
|
|
||||||
this.setThumbPosition_(this.currentResolution_);
|
|
||||||
this.previousX_ = event.clientX;
|
|
||||||
this.previousY_ = event.clientY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle dragger end events.
|
|
||||||
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.handleDraggerEnd_ = function(event) {
|
|
||||||
if (this.dragging_) {
|
|
||||||
const view = this.getMap().getView();
|
|
||||||
view.setHint(ViewHint.INTERACTING, -1);
|
|
||||||
|
|
||||||
view.animate({
|
|
||||||
resolution: view.constrainResolution(this.currentResolution_),
|
|
||||||
duration: this.duration_,
|
|
||||||
easing: easeOut
|
|
||||||
});
|
|
||||||
|
|
||||||
this.dragging_ = false;
|
|
||||||
this.previousX_ = undefined;
|
|
||||||
this.previousY_ = undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Positions the thumb inside its container according to the given resolution.
|
|
||||||
*
|
|
||||||
* @param {number} res The res.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.setThumbPosition_ = function(res) {
|
|
||||||
const position = this.getPositionForResolution_(res);
|
|
||||||
const thumb = this.element.firstElementChild;
|
|
||||||
|
|
||||||
if (this.direction_ == Direction.HORIZONTAL) {
|
|
||||||
thumb.style.left = this.widthLimit_ * position + 'px';
|
|
||||||
} else {
|
|
||||||
thumb.style.top = this.heightLimit_ * position + 'px';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the relative position of the thumb given x and y offsets. The
|
|
||||||
* relative position scales from 0 to 1. The x and y offsets are assumed to be
|
|
||||||
* in pixel units within the dragger limits.
|
|
||||||
*
|
|
||||||
* @param {number} x Pixel position relative to the left of the slider.
|
|
||||||
* @param {number} y Pixel position relative to the top of the slider.
|
|
||||||
* @return {number} The relative position of the thumb.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.getRelativePosition_ = function(x, y) {
|
|
||||||
let amount;
|
|
||||||
if (this.direction_ === Direction.HORIZONTAL) {
|
|
||||||
amount = x / this.widthLimit_;
|
|
||||||
} else {
|
|
||||||
amount = y / this.heightLimit_;
|
|
||||||
}
|
|
||||||
return clamp(amount, 0, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the corresponding resolution of the thumb given its relative
|
|
||||||
* position (where 0 is the minimum and 1 is the maximum).
|
|
||||||
*
|
|
||||||
* @param {number} position The relative position of the thumb.
|
|
||||||
* @return {number} The corresponding resolution.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.getResolutionForPosition_ = function(position) {
|
|
||||||
const fn = this.getMap().getView().getResolutionForValueFunction();
|
|
||||||
return fn(1 - position);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the relative position of the slider for the given resolution. A
|
|
||||||
* relative position of 0 corresponds to the minimum view resolution. A
|
|
||||||
* relative position of 1 corresponds to the maximum view resolution.
|
|
||||||
*
|
|
||||||
* @param {number} res The resolution.
|
|
||||||
* @return {number} The relative position value (between 0 and 1).
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomSlider.prototype.getPositionForResolution_ = function(res) {
|
|
||||||
const fn = this.getMap().getView().getValueForResolutionFunction();
|
|
||||||
return 1 - fn(res);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ZoomSlider;
|
export default ZoomSlider;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/ZoomToExtent
|
* @module ol/control/ZoomToExtent
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {listen} from '../events.js';
|
import {listen} from '../events.js';
|
||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import Control from '../control/Control.js';
|
import Control from '../control/Control.js';
|
||||||
@@ -11,9 +10,9 @@ import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
|||||||
/**
|
/**
|
||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {string} [className='ol-zoom-extent'] Class name.
|
* @property {string} [className='ol-zoom-extent'] Class name.
|
||||||
* @property {Element|string} [target] Specify a target if you want the control
|
* @property {HTMLElement|string} [target] Specify a target if you want the control
|
||||||
* to be rendered outside of the map's viewport.
|
* to be rendered outside of the map's viewport.
|
||||||
* @property {string|Element} [label='E'] Text label to use for the button.
|
* @property {string|HTMLElement} [label='E'] Text label to use for the button.
|
||||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {string} [tipLabel='Fit to extent'] Text label to use for the button tip.
|
* @property {string} [tipLabel='Fit to extent'] Text label to use for the button tip.
|
||||||
* @property {module:ol/extent~Extent} [extent] The extent to zoom to. If undefined the validity
|
* @property {module:ol/extent~Extent} [extent] The extent to zoom to. If undefined the validity
|
||||||
@@ -26,64 +25,64 @@ import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
|||||||
* A button control which, when pressed, changes the map view to a specific
|
* A button control which, when pressed, changes the map view to a specific
|
||||||
* extent. To style this control use the css selector `.ol-zoom-extent`.
|
* extent. To style this control use the css selector `.ol-zoom-extent`.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/control/Control}
|
|
||||||
* @param {module:ol/control/ZoomToExtent~Options=} opt_options Options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const ZoomToExtent = function(opt_options) {
|
class ZoomToExtent extends Control {
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/control/ZoomToExtent~Options=} opt_options Options.
|
||||||
|
*/
|
||||||
|
constructor(opt_options) {
|
||||||
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
super({
|
||||||
|
element: document.createElement('div'),
|
||||||
|
target: options.target
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {module:ol/extent~Extent}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.extent = options.extent ? options.extent : null;
|
||||||
|
|
||||||
|
const className = options.className !== undefined ? options.className : 'ol-zoom-extent';
|
||||||
|
|
||||||
|
const label = options.label !== undefined ? options.label : 'E';
|
||||||
|
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Fit to extent';
|
||||||
|
const button = document.createElement('button');
|
||||||
|
button.setAttribute('type', 'button');
|
||||||
|
button.title = tipLabel;
|
||||||
|
button.appendChild(
|
||||||
|
typeof label === 'string' ? document.createTextNode(label) : label
|
||||||
|
);
|
||||||
|
|
||||||
|
listen(button, EventType.CLICK, this.handleClick_, this);
|
||||||
|
|
||||||
|
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||||
|
const element = this.element;
|
||||||
|
element.className = cssClasses;
|
||||||
|
element.appendChild(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event The event to handle
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleClick_(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.handleZoomToExtent();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {module:ol/extent~Extent}
|
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
this.extent = options.extent ? options.extent : null;
|
handleZoomToExtent() {
|
||||||
|
const map = this.getMap();
|
||||||
|
const view = map.getView();
|
||||||
|
const extent = !this.extent ? view.getProjection().getExtent() : this.extent;
|
||||||
|
view.fit(extent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const className = options.className !== undefined ? options.className : 'ol-zoom-extent';
|
|
||||||
|
|
||||||
const label = options.label !== undefined ? options.label : 'E';
|
|
||||||
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Fit to extent';
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.setAttribute('type', 'button');
|
|
||||||
button.title = tipLabel;
|
|
||||||
button.appendChild(
|
|
||||||
typeof label === 'string' ? document.createTextNode(label) : label
|
|
||||||
);
|
|
||||||
|
|
||||||
listen(button, EventType.CLICK, this.handleClick_, this);
|
|
||||||
|
|
||||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
|
||||||
const element = document.createElement('div');
|
|
||||||
element.className = cssClasses;
|
|
||||||
element.appendChild(button);
|
|
||||||
|
|
||||||
Control.call(this, {
|
|
||||||
element: element,
|
|
||||||
target: options.target
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(ZoomToExtent, Control);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} event The event to handle
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ZoomToExtent.prototype.handleClick_ = function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.handleZoomToExtent();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
ZoomToExtent.prototype.handleZoomToExtent = function() {
|
|
||||||
const map = this.getMap();
|
|
||||||
const view = map.getView();
|
|
||||||
const extent = !this.extent ? view.getProjection().getExtent() : this.extent;
|
|
||||||
view.fit(extent);
|
|
||||||
};
|
|
||||||
export default ZoomToExtent;
|
export default ZoomToExtent;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export function createCanvasContext2D(opt_width, opt_height) {
|
|||||||
* Get the current computed width for the given element including margin,
|
* Get the current computed width for the given element including margin,
|
||||||
* padding and border.
|
* padding and border.
|
||||||
* Equivalent to jQuery's `$(el).outerWidth(true)`.
|
* Equivalent to jQuery's `$(el).outerWidth(true)`.
|
||||||
* @param {!Element} element Element.
|
* @param {!HTMLElement} element Element.
|
||||||
* @return {number} The width.
|
* @return {number} The width.
|
||||||
*/
|
*/
|
||||||
export function outerWidth(element) {
|
export function outerWidth(element) {
|
||||||
@@ -41,7 +41,7 @@ export function outerWidth(element) {
|
|||||||
* Get the current computed height for the given element including margin,
|
* Get the current computed height for the given element including margin,
|
||||||
* padding and border.
|
* padding and border.
|
||||||
* Equivalent to jQuery's `$(el).outerHeight(true)`.
|
* Equivalent to jQuery's `$(el).outerHeight(true)`.
|
||||||
* @param {!Element} element Element.
|
* @param {!HTMLElement} element Element.
|
||||||
* @return {number} The height.
|
* @return {number} The height.
|
||||||
*/
|
*/
|
||||||
export function outerHeight(element) {
|
export function outerHeight(element) {
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ function removeListeners(target, type) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an event listener on an event target. Inspired by
|
* Registers an event listener on an event target. Inspired by
|
||||||
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
|
* https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html
|
||||||
*
|
*
|
||||||
* This function efficiently binds a `listener` to a `this` object, and returns
|
* This function efficiently binds a `listener` to a `this` object, and returns
|
||||||
* a key for use with {@link module:ol/events~unlistenByKey}.
|
* a key for use with {@link module:ol/events~unlistenByKey}.
|
||||||
@@ -170,7 +170,7 @@ export function listen(target, type, listener, opt_this, opt_once) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a one-off event listener on an event target. Inspired by
|
* Registers a one-off event listener on an event target. Inspired by
|
||||||
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
|
* https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html
|
||||||
*
|
*
|
||||||
* This function efficiently binds a `listener` as self-unregistering listener
|
* This function efficiently binds a `listener` as self-unregistering listener
|
||||||
* to a `this` object, and returns a key for use with
|
* to a `this` object, and returns a key for use with
|
||||||
@@ -195,7 +195,7 @@ export function listenOnce(target, type, listener, opt_this) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters an event listener on an event target. Inspired by
|
* Unregisters an event listener on an event target. Inspired by
|
||||||
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
|
* https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html
|
||||||
*
|
*
|
||||||
* To return a listener, this function needs to be called with the exact same
|
* To return a listener, this function needs to be called with the exact same
|
||||||
* arguments that were used for a previous {@link module:ol/events~listen} call.
|
* arguments that were used for a previous {@link module:ol/events~listen} call.
|
||||||
@@ -219,7 +219,7 @@ export function unlisten(target, type, listener, opt_this) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters event listeners on an event target. Inspired by
|
* Unregisters event listeners on an event target. Inspired by
|
||||||
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
|
* https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html
|
||||||
*
|
*
|
||||||
* The argument passed to this function is the key returned from
|
* The argument passed to this function is the key returned from
|
||||||
* {@link module:ol/events~listen} or {@link module:ol/events~listenOnce}.
|
* {@link module:ol/events~listen} or {@link module:ol/events~listenOnce}.
|
||||||
@@ -246,7 +246,7 @@ export function unlistenByKey(key) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters all event listeners on an event target. Inspired by
|
* Unregisters all event listeners on an event target. Inspired by
|
||||||
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
|
* https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html
|
||||||
*
|
*
|
||||||
* @param {module:ol/events/EventTarget~EventTargetLike} target Target.
|
* @param {module:ol/events/EventTarget~EventTargetLike} target Target.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,58 +1,63 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/events/Event
|
* @module ol/events/Event
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Stripped down implementation of the W3C DOM Level 2 Event interface.
|
* Stripped down implementation of the W3C DOM Level 2 Event interface.
|
||||||
* @see {@link https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface}
|
* See https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface.
|
||||||
*
|
*
|
||||||
* This implementation only provides `type` and `target` properties, and
|
* This implementation only provides `type` and `target` properties, and
|
||||||
* `stopPropagation` and `preventDefault` methods. It is meant as base class
|
* `stopPropagation` and `preventDefault` methods. It is meant as base class
|
||||||
* for higher level events defined in the library, and works with
|
* for higher level events defined in the library, and works with
|
||||||
* {@link module:ol/events/EventTarget~EventTarget}.
|
* {@link module:ol/events/EventTarget~EventTarget}.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {string} type Type.
|
|
||||||
*/
|
*/
|
||||||
const Event = function(type) {
|
class Event {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {boolean}
|
* @param {string} type Type.
|
||||||
*/
|
*/
|
||||||
this.propagationStopped;
|
constructor(type) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event type.
|
* @type {boolean}
|
||||||
* @type {string}
|
*/
|
||||||
* @api
|
this.propagationStopped;
|
||||||
*/
|
|
||||||
this.type = type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event target.
|
* The event type.
|
||||||
* @type {Object}
|
* @type {string}
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
this.target = null;
|
this.type = type;
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* The event target.
|
||||||
|
* @type {Object}
|
||||||
/**
|
* @api
|
||||||
* Stop event propagation.
|
*/
|
||||||
* @function
|
this.target = null;
|
||||||
* @api
|
}
|
||||||
*/
|
|
||||||
Event.prototype.preventDefault =
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop event propagation.
|
* Stop event propagation.
|
||||||
* @function
|
* @function
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
Event.prototype.stopPropagation = function() {
|
preventDefault() {
|
||||||
this.propagationStopped = true;
|
this.propagationStopped = true;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop event propagation.
|
||||||
|
* @function
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
stopPropagation() {
|
||||||
|
this.propagationStopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/events/EventTarget
|
* @module ol/events/EventTarget
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import Disposable from '../Disposable.js';
|
import Disposable from '../Disposable.js';
|
||||||
import {unlistenAll} from '../events.js';
|
import {unlistenAll} from '../events.js';
|
||||||
import {UNDEFINED} from '../functions.js';
|
import {UNDEFINED} from '../functions.js';
|
||||||
@@ -16,7 +15,7 @@ import Event from '../events/Event.js';
|
|||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* A simplified implementation of the W3C DOM Level 2 EventTarget interface.
|
* A simplified implementation of the W3C DOM Level 2 EventTarget interface.
|
||||||
* @see {@link https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget}
|
* See https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget.
|
||||||
*
|
*
|
||||||
* There are two important simplifications compared to the specification:
|
* There are two important simplifications compared to the specification:
|
||||||
*
|
*
|
||||||
@@ -27,141 +26,140 @@ import Event from '../events/Event.js';
|
|||||||
* `stopPropagation` or `preventDefault` on an event object, it means that no
|
* `stopPropagation` or `preventDefault` on an event object, it means that no
|
||||||
* more listeners after this one will be called. Same as when the listener
|
* more listeners after this one will be called. Same as when the listener
|
||||||
* returns false.
|
* returns false.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/Disposable}
|
|
||||||
*/
|
*/
|
||||||
const EventTarget = function() {
|
class EventTarget extends Disposable {
|
||||||
|
constructor() {
|
||||||
|
|
||||||
Disposable.call(this);
|
super();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {!Object.<string, number>}
|
* @type {!Object.<string, number>}
|
||||||
*/
|
*/
|
||||||
this.pendingRemovals_ = {};
|
this.pendingRemovals_ = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {!Object.<string, number>}
|
* @type {!Object.<string, number>}
|
||||||
*/
|
*/
|
||||||
this.dispatching_ = {};
|
this.dispatching_ = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {!Object.<string, Array.<module:ol/events~ListenerFunction>>}
|
* @type {!Object.<string, Array.<module:ol/events~ListenerFunction>>}
|
||||||
*/
|
*/
|
||||||
this.listeners_ = {};
|
this.listeners_ = {};
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(EventTarget, Disposable);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} type Type.
|
|
||||||
* @param {module:ol/events~ListenerFunction} listener Listener.
|
|
||||||
*/
|
|
||||||
EventTarget.prototype.addEventListener = function(type, listener) {
|
|
||||||
let listeners = this.listeners_[type];
|
|
||||||
if (!listeners) {
|
|
||||||
listeners = this.listeners_[type] = [];
|
|
||||||
}
|
}
|
||||||
if (listeners.indexOf(listener) === -1) {
|
|
||||||
listeners.push(listener);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @param {string} type Type.
|
||||||
* @param {{type: string,
|
* @param {module:ol/events~ListenerFunction} listener Listener.
|
||||||
* target: (EventTarget|module:ol/events/EventTarget|undefined)}|module:ol/events/Event|
|
*/
|
||||||
* string} event Event or event type.
|
addEventListener(type, listener) {
|
||||||
* @return {boolean|undefined} `false` if anyone called preventDefault on the
|
let listeners = this.listeners_[type];
|
||||||
* event object or if any of the listeners returned false.
|
if (!listeners) {
|
||||||
*/
|
listeners = this.listeners_[type] = [];
|
||||||
EventTarget.prototype.dispatchEvent = function(event) {
|
|
||||||
const evt = typeof event === 'string' ? new Event(event) : event;
|
|
||||||
const type = evt.type;
|
|
||||||
evt.target = this;
|
|
||||||
const listeners = this.listeners_[type];
|
|
||||||
let propagate;
|
|
||||||
if (listeners) {
|
|
||||||
if (!(type in this.dispatching_)) {
|
|
||||||
this.dispatching_[type] = 0;
|
|
||||||
this.pendingRemovals_[type] = 0;
|
|
||||||
}
|
}
|
||||||
++this.dispatching_[type];
|
if (listeners.indexOf(listener) === -1) {
|
||||||
for (let i = 0, ii = listeners.length; i < ii; ++i) {
|
listeners.push(listener);
|
||||||
if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
|
}
|
||||||
propagate = false;
|
}
|
||||||
break;
|
|
||||||
|
/**
|
||||||
|
* Dispatches an event and calls all listeners listening for events
|
||||||
|
* of this type. The event parameter can either be a string or an
|
||||||
|
* Object with a `type` property.
|
||||||
|
*
|
||||||
|
* @param {{type: string,
|
||||||
|
* target: (EventTarget|module:ol/events/EventTarget|undefined)}|
|
||||||
|
* module:ol/events/Event|string} event Event object.
|
||||||
|
* @return {boolean|undefined} `false` if anyone called preventDefault on the
|
||||||
|
* event object or if any of the listeners returned false.
|
||||||
|
* @function
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
dispatchEvent(event) {
|
||||||
|
const evt = typeof event === 'string' ? new Event(event) : event;
|
||||||
|
const type = evt.type;
|
||||||
|
evt.target = this;
|
||||||
|
const listeners = this.listeners_[type];
|
||||||
|
let propagate;
|
||||||
|
if (listeners) {
|
||||||
|
if (!(type in this.dispatching_)) {
|
||||||
|
this.dispatching_[type] = 0;
|
||||||
|
this.pendingRemovals_[type] = 0;
|
||||||
}
|
}
|
||||||
}
|
++this.dispatching_[type];
|
||||||
--this.dispatching_[type];
|
for (let i = 0, ii = listeners.length; i < ii; ++i) {
|
||||||
if (this.dispatching_[type] === 0) {
|
if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
|
||||||
let pendingRemovals = this.pendingRemovals_[type];
|
propagate = false;
|
||||||
delete this.pendingRemovals_[type];
|
break;
|
||||||
while (pendingRemovals--) {
|
}
|
||||||
this.removeEventListener(type, UNDEFINED);
|
|
||||||
}
|
}
|
||||||
delete this.dispatching_[type];
|
--this.dispatching_[type];
|
||||||
|
if (this.dispatching_[type] === 0) {
|
||||||
|
let pendingRemovals = this.pendingRemovals_[type];
|
||||||
|
delete this.pendingRemovals_[type];
|
||||||
|
while (pendingRemovals--) {
|
||||||
|
this.removeEventListener(type, UNDEFINED);
|
||||||
|
}
|
||||||
|
delete this.dispatching_[type];
|
||||||
|
}
|
||||||
|
return propagate;
|
||||||
}
|
}
|
||||||
return propagate;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
disposeInternal() {
|
||||||
|
unlistenAll(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* Get the listeners for a specified event type. Listeners are returned in the
|
||||||
*/
|
* order that they will be called in.
|
||||||
EventTarget.prototype.disposeInternal = function() {
|
*
|
||||||
unlistenAll(this);
|
* @param {string} type Type.
|
||||||
};
|
* @return {Array.<module:ol/events~ListenerFunction>} Listeners.
|
||||||
|
*/
|
||||||
|
getListeners(type) {
|
||||||
|
return this.listeners_[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string=} opt_type Type. If not provided,
|
||||||
|
* `true` will be returned if this EventTarget has any listeners.
|
||||||
|
* @return {boolean} Has listeners.
|
||||||
|
*/
|
||||||
|
hasListener(opt_type) {
|
||||||
|
return opt_type ?
|
||||||
|
opt_type in this.listeners_ :
|
||||||
|
Object.keys(this.listeners_).length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the listeners for a specified event type. Listeners are returned in the
|
* @param {string} type Type.
|
||||||
* order that they will be called in.
|
* @param {module:ol/events~ListenerFunction} listener Listener.
|
||||||
*
|
*/
|
||||||
* @param {string} type Type.
|
removeEventListener(type, listener) {
|
||||||
* @return {Array.<module:ol/events~ListenerFunction>} Listeners.
|
const listeners = this.listeners_[type];
|
||||||
*/
|
if (listeners) {
|
||||||
EventTarget.prototype.getListeners = function(type) {
|
const index = listeners.indexOf(listener);
|
||||||
return this.listeners_[type];
|
if (type in this.pendingRemovals_) {
|
||||||
};
|
// make listener a no-op, and remove later in #dispatchEvent()
|
||||||
|
listeners[index] = UNDEFINED;
|
||||||
|
++this.pendingRemovals_[type];
|
||||||
/**
|
} else {
|
||||||
* @param {string=} opt_type Type. If not provided,
|
listeners.splice(index, 1);
|
||||||
* `true` will be returned if this EventTarget has any listeners.
|
if (listeners.length === 0) {
|
||||||
* @return {boolean} Has listeners.
|
delete this.listeners_[type];
|
||||||
*/
|
}
|
||||||
EventTarget.prototype.hasListener = function(opt_type) {
|
|
||||||
return opt_type ?
|
|
||||||
opt_type in this.listeners_ :
|
|
||||||
Object.keys(this.listeners_).length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} type Type.
|
|
||||||
* @param {module:ol/events~ListenerFunction} listener Listener.
|
|
||||||
*/
|
|
||||||
EventTarget.prototype.removeEventListener = function(type, listener) {
|
|
||||||
const listeners = this.listeners_[type];
|
|
||||||
if (listeners) {
|
|
||||||
const index = listeners.indexOf(listener);
|
|
||||||
if (type in this.pendingRemovals_) {
|
|
||||||
// make listener a no-op, and remove later in #dispatchEvent()
|
|
||||||
listeners[index] = UNDEFINED;
|
|
||||||
++this.pendingRemovals_[type];
|
|
||||||
} else {
|
|
||||||
listeners.splice(index, 1);
|
|
||||||
if (listeners.length === 0) {
|
|
||||||
delete this.listeners_[type];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
export default EventTarget;
|
export default EventTarget;
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ export const mouseOnly = function(mapBrowserEvent) {
|
|||||||
/**
|
/**
|
||||||
* Return `true` if the event originates from a primary pointer in
|
* Return `true` if the event originates from a primary pointer in
|
||||||
* contact with the surface or if the left mouse button is pressed.
|
* contact with the surface or if the left mouse button is pressed.
|
||||||
* @see http://www.w3.org/TR/pointerevents/#button-states
|
* See http://www.w3.org/TR/pointerevents/#button-states.
|
||||||
*
|
*
|
||||||
* @param {module:ol/MapBrowserEvent} mapBrowserEvent Map browser event.
|
* @param {module:ol/MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||||
* @return {boolean} True if the event originates from a primary pointer.
|
* @return {boolean} True if the event originates from a primary pointer.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/EsriJSON
|
* @module ol/format/EsriJSON
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
import {assert} from '../asserts.js';
|
import {assert} from '../asserts.js';
|
||||||
import {containsExtent} from '../extent.js';
|
import {containsExtent} from '../extent.js';
|
||||||
@@ -58,27 +57,154 @@ GEOMETRY_WRITERS[GeometryType.MULTI_POLYGON] = writeMultiPolygonGeometry;
|
|||||||
* @classdesc
|
* @classdesc
|
||||||
* Feature format for reading and writing data in the EsriJSON format.
|
* Feature format for reading and writing data in the EsriJSON format.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/JSONFeature}
|
|
||||||
* @param {module:ol/format/EsriJSON~Options=} opt_options Options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const EsriJSON = function(opt_options) {
|
class EsriJSON extends JSONFeature {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
JSONFeature.call(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the geometry attribute for features.
|
* @param {module:ol/format/EsriJSON~Options=} opt_options Options.
|
||||||
* @type {string|undefined}
|
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
this.geometryName_ = options.geometryName;
|
constructor(opt_options) {
|
||||||
|
|
||||||
};
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
inherits(EsriJSON, JSONFeature);
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the geometry attribute for features.
|
||||||
|
* @type {string|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.geometryName_ = options.geometryName;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeatureFromObject(object, opt_options) {
|
||||||
|
const esriJSONFeature = /** @type {EsriJSONFeature} */ (object);
|
||||||
|
const geometry = readGeometry(esriJSONFeature.geometry, opt_options);
|
||||||
|
const feature = new Feature();
|
||||||
|
if (this.geometryName_) {
|
||||||
|
feature.setGeometryName(this.geometryName_);
|
||||||
|
}
|
||||||
|
feature.setGeometry(geometry);
|
||||||
|
if (opt_options && opt_options.idField &&
|
||||||
|
esriJSONFeature.attributes[opt_options.idField]) {
|
||||||
|
feature.setId(/** @type {number} */(esriJSONFeature.attributes[opt_options.idField]));
|
||||||
|
}
|
||||||
|
if (esriJSONFeature.attributes) {
|
||||||
|
feature.setProperties(esriJSONFeature.attributes);
|
||||||
|
}
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeaturesFromObject(object, opt_options) {
|
||||||
|
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
|
||||||
|
const options = opt_options ? opt_options : {};
|
||||||
|
if (esriJSONObject.features) {
|
||||||
|
const esriJSONFeatureCollection = /** @type {EsriJSONFeatureCollection} */ (object);
|
||||||
|
/** @type {Array.<module:ol/Feature>} */
|
||||||
|
const features = [];
|
||||||
|
const esriJSONFeatures = esriJSONFeatureCollection.features;
|
||||||
|
options.idField = object.objectIdFieldName;
|
||||||
|
for (let i = 0, ii = esriJSONFeatures.length; i < ii; ++i) {
|
||||||
|
features.push(this.readFeatureFromObject(esriJSONFeatures[i], options));
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
} else {
|
||||||
|
return [this.readFeatureFromObject(object, options)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readGeometryFromObject(object, opt_options) {
|
||||||
|
return readGeometry(/** @type {EsriJSONGeometry} */(object), opt_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readProjectionFromObject(object) {
|
||||||
|
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
|
||||||
|
if (esriJSONObject.spatialReference && esriJSONObject.spatialReference.wkid) {
|
||||||
|
const crs = esriJSONObject.spatialReference.wkid;
|
||||||
|
return getProjection('EPSG:' + crs);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a geometry as a EsriJSON object.
|
||||||
|
*
|
||||||
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {EsriJSONGeometry} Object.
|
||||||
|
* @override
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeGeometryObject(geometry, opt_options) {
|
||||||
|
return writeGeometry(geometry, this.adaptOptions(opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a feature as a esriJSON Feature object.
|
||||||
|
*
|
||||||
|
* @param {module:ol/Feature} feature Feature.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {Object} Object.
|
||||||
|
* @override
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeatureObject(feature, opt_options) {
|
||||||
|
opt_options = this.adaptOptions(opt_options);
|
||||||
|
const object = {};
|
||||||
|
const geometry = feature.getGeometry();
|
||||||
|
if (geometry) {
|
||||||
|
object['geometry'] = writeGeometry(geometry, opt_options);
|
||||||
|
if (opt_options && opt_options.featureProjection) {
|
||||||
|
object['geometry']['spatialReference'] = /** @type {EsriJSONCRS} */({
|
||||||
|
wkid: getProjection(opt_options.featureProjection).getCode().split(':').pop()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const properties = feature.getProperties();
|
||||||
|
delete properties[feature.getGeometryName()];
|
||||||
|
if (!isEmpty(properties)) {
|
||||||
|
object['attributes'] = properties;
|
||||||
|
} else {
|
||||||
|
object['attributes'] = {};
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode an array of features as a EsriJSON object.
|
||||||
|
*
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {Object} EsriJSON Object.
|
||||||
|
* @override
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeaturesObject(features, opt_options) {
|
||||||
|
opt_options = this.adaptOptions(opt_options);
|
||||||
|
const objects = [];
|
||||||
|
for (let i = 0, ii = features.length; i < ii; ++i) {
|
||||||
|
objects.push(this.writeFeatureObject(features[i], opt_options));
|
||||||
|
}
|
||||||
|
return /** @type {EsriJSONFeatureCollection} */ ({
|
||||||
|
'features': objects
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -413,121 +539,6 @@ function writeMultiPolygonGeometry(geometry, opt_options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a feature from a EsriJSON Feature source. Only works for Feature,
|
|
||||||
* use `readFeatures` to read FeatureCollection source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.readFeature;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all features from a EsriJSON source. Works with both Feature and
|
|
||||||
* FeatureCollection sources.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.readFeatureFromObject = function(object, opt_options) {
|
|
||||||
const esriJSONFeature = /** @type {EsriJSONFeature} */ (object);
|
|
||||||
const geometry = readGeometry(esriJSONFeature.geometry, opt_options);
|
|
||||||
const feature = new Feature();
|
|
||||||
if (this.geometryName_) {
|
|
||||||
feature.setGeometryName(this.geometryName_);
|
|
||||||
}
|
|
||||||
feature.setGeometry(geometry);
|
|
||||||
if (opt_options && opt_options.idField &&
|
|
||||||
esriJSONFeature.attributes[opt_options.idField]) {
|
|
||||||
feature.setId(/** @type {number} */(esriJSONFeature.attributes[opt_options.idField]));
|
|
||||||
}
|
|
||||||
if (esriJSONFeature.attributes) {
|
|
||||||
feature.setProperties(esriJSONFeature.attributes);
|
|
||||||
}
|
|
||||||
return feature;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.readFeaturesFromObject = function(object, opt_options) {
|
|
||||||
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
if (esriJSONObject.features) {
|
|
||||||
const esriJSONFeatureCollection = /** @type {EsriJSONFeatureCollection} */ (object);
|
|
||||||
/** @type {Array.<module:ol/Feature>} */
|
|
||||||
const features = [];
|
|
||||||
const esriJSONFeatures = esriJSONFeatureCollection.features;
|
|
||||||
options.idField = object.objectIdFieldName;
|
|
||||||
for (let i = 0, ii = esriJSONFeatures.length; i < ii; ++i) {
|
|
||||||
features.push(this.readFeatureFromObject(esriJSONFeatures[i], options));
|
|
||||||
}
|
|
||||||
return features;
|
|
||||||
} else {
|
|
||||||
return [this.readFeatureFromObject(object, options)];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a geometry from a EsriJSON source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/geom/Geometry} Geometry.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.readGeometry;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.readGeometryFromObject = function(object, opt_options) {
|
|
||||||
return readGeometry(/** @type {EsriJSONGeometry} */(object), opt_options);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from a EsriJSON source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.readProjection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.readProjectionFromObject = function(object) {
|
|
||||||
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
|
|
||||||
if (esriJSONObject.spatialReference && esriJSONObject.spatialReference.wkid) {
|
|
||||||
const crs = esriJSONObject.spatialReference.wkid;
|
|
||||||
return getProjection('EPSG:' + crs);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
@@ -540,106 +551,4 @@ function writeGeometry(geometry, opt_options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a geometry as a EsriJSON string.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} EsriJSON.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.writeGeometry;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a geometry as a EsriJSON object.
|
|
||||||
*
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {EsriJSONGeometry} Object.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.writeGeometryObject = function(geometry, opt_options) {
|
|
||||||
return writeGeometry(geometry, this.adaptOptions(opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a feature as a EsriJSON Feature string.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {module:ol/Feature} feature Feature.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} EsriJSON.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.writeFeature;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a feature as a esriJSON Feature object.
|
|
||||||
*
|
|
||||||
* @param {module:ol/Feature} feature Feature.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {Object} Object.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.writeFeatureObject = function(feature, opt_options) {
|
|
||||||
opt_options = this.adaptOptions(opt_options);
|
|
||||||
const object = {};
|
|
||||||
const geometry = feature.getGeometry();
|
|
||||||
if (geometry) {
|
|
||||||
object['geometry'] = writeGeometry(geometry, opt_options);
|
|
||||||
if (opt_options && opt_options.featureProjection) {
|
|
||||||
object['geometry']['spatialReference'] = /** @type {EsriJSONCRS} */({
|
|
||||||
wkid: getProjection(opt_options.featureProjection).getCode().split(':').pop()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const properties = feature.getProperties();
|
|
||||||
delete properties[feature.getGeometryName()];
|
|
||||||
if (!isEmpty(properties)) {
|
|
||||||
object['attributes'] = properties;
|
|
||||||
} else {
|
|
||||||
object['attributes'] = {};
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode an array of features as EsriJSON.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} EsriJSON.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.writeFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode an array of features as a EsriJSON object.
|
|
||||||
*
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {Object} EsriJSON Object.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
EsriJSON.prototype.writeFeaturesObject = function(features, opt_options) {
|
|
||||||
opt_options = this.adaptOptions(opt_options);
|
|
||||||
const objects = [];
|
|
||||||
for (let i = 0, ii = features.length; i < ii; ++i) {
|
|
||||||
objects.push(this.writeFeatureObject(features[i], opt_options));
|
|
||||||
}
|
|
||||||
return /** @type {EsriJSONFeatureCollection} */ ({
|
|
||||||
'features': objects
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EsriJSON;
|
export default EsriJSON;
|
||||||
|
|||||||
@@ -56,154 +56,144 @@ import {get as getProjection, equivalent as equivalentProjection, transformExten
|
|||||||
* {@link module:ol/Feature~Feature} objects from a variety of commonly used geospatial
|
* {@link module:ol/Feature~Feature} objects from a variety of commonly used geospatial
|
||||||
* file formats. See the documentation for each format for more details.
|
* file formats. See the documentation for each format for more details.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const FeatureFormat = function() {
|
class FeatureFormat {
|
||||||
|
constructor() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {module:ol/proj/Projection}
|
* @type {module:ol/proj/Projection}
|
||||||
*/
|
*/
|
||||||
this.dataProjection = null;
|
this.dataProjection = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {module:ol/proj/Projection}
|
* @type {module:ol/proj/Projection}
|
||||||
*/
|
*/
|
||||||
this.defaultFeatureProjection = null;
|
this.defaultFeatureProjection = null;
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the data projection to the read options.
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
|
||||||
* @return {module:ol/format/Feature~ReadOptions|undefined} Options.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
FeatureFormat.prototype.getReadOptions = function(source, opt_options) {
|
|
||||||
let options;
|
|
||||||
if (opt_options) {
|
|
||||||
options = {
|
|
||||||
dataProjection: opt_options.dataProjection ?
|
|
||||||
opt_options.dataProjection : this.readProjection(source),
|
|
||||||
featureProjection: opt_options.featureProjection
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return this.adaptOptions(options);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the data projection to the read options.
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
||||||
|
* @return {module:ol/format/Feature~ReadOptions|undefined} Options.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
getReadOptions(source, opt_options) {
|
||||||
|
let options;
|
||||||
|
if (opt_options) {
|
||||||
|
options = {
|
||||||
|
dataProjection: opt_options.dataProjection ?
|
||||||
|
opt_options.dataProjection : this.readProjection(source),
|
||||||
|
featureProjection: opt_options.featureProjection
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.adaptOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the `dataProjection` on the options, if no `dataProjection`
|
* Sets the `dataProjection` on the options, if no `dataProjection`
|
||||||
* is set.
|
* is set.
|
||||||
* @param {module:ol/format/Feature~WriteOptions|module:ol/format/Feature~ReadOptions|undefined} options
|
* @param {module:ol/format/Feature~WriteOptions|module:ol/format/Feature~ReadOptions|undefined} options
|
||||||
* Options.
|
* Options.
|
||||||
* @protected
|
* @protected
|
||||||
* @return {module:ol/format/Feature~WriteOptions|module:ol/format/Feature~ReadOptions|undefined}
|
* @return {module:ol/format/Feature~WriteOptions|module:ol/format/Feature~ReadOptions|undefined}
|
||||||
* Updated options.
|
* Updated options.
|
||||||
*/
|
*/
|
||||||
FeatureFormat.prototype.adaptOptions = function(options) {
|
adaptOptions(options) {
|
||||||
return assign({
|
return assign({
|
||||||
dataProjection: this.dataProjection,
|
dataProjection: this.dataProjection,
|
||||||
featureProjection: this.defaultFeatureProjection
|
featureProjection: this.defaultFeatureProjection
|
||||||
}, options);
|
}, options);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the extent from the source of the last {@link readFeatures} call.
|
||||||
|
* @return {module:ol/extent~Extent} Tile extent.
|
||||||
|
*/
|
||||||
|
getLastExtent() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the extent from the source of the last {@link readFeatures} call.
|
* @abstract
|
||||||
* @return {module:ol/extent~Extent} Tile extent.
|
* @return {module:ol/format/FormatType} Format.
|
||||||
*/
|
*/
|
||||||
FeatureFormat.prototype.getLastExtent = function() {
|
getType() {}
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a single feature from a source.
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {module:ol/Feature} Feature.
|
||||||
|
*/
|
||||||
|
readFeature(source, opt_options) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract
|
* Read all features from a source.
|
||||||
* @return {module:ol/format/FormatType} Format.
|
*
|
||||||
*/
|
* @abstract
|
||||||
FeatureFormat.prototype.getType = function() {};
|
* @param {Document|Node|ArrayBuffer|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
*/
|
||||||
|
readFeatures(source, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a single geometry from a source.
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {module:ol/geom/Geometry} Geometry.
|
||||||
|
*/
|
||||||
|
readGeometry(source, opt_options) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a single feature from a source.
|
* Read the projection from a source.
|
||||||
*
|
*
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {Document|Node|Object|string} source Source.
|
* @param {Document|Node|Object|string} source Source.
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
* @return {module:ol/proj/Projection} Projection.
|
||||||
* @return {module:ol/Feature} Feature.
|
*/
|
||||||
*/
|
readProjection(source) {}
|
||||||
FeatureFormat.prototype.readFeature = function(source, opt_options) {};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a feature in this format.
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @param {module:ol/Feature} feature Feature.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {string} Result.
|
||||||
|
*/
|
||||||
|
writeFeature(feature, opt_options) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read all features from a source.
|
* Encode an array of features in this format.
|
||||||
*
|
*
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {Document|Node|ArrayBuffer|Object|string} source Source.
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
* @return {string} Result.
|
||||||
*/
|
*/
|
||||||
FeatureFormat.prototype.readFeatures = function(source, opt_options) {};
|
writeFeatures(features, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* Write a single geometry in this format.
|
||||||
* Read a single geometry from a source.
|
*
|
||||||
*
|
* @abstract
|
||||||
* @abstract
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
* @param {Document|Node|Object|string} source Source.
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
* @return {string} Result.
|
||||||
* @return {module:ol/geom/Geometry} Geometry.
|
*/
|
||||||
*/
|
writeGeometry(geometry, opt_options) {}
|
||||||
FeatureFormat.prototype.readGeometry = function(source, opt_options) {};
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from a source.
|
|
||||||
*
|
|
||||||
* @abstract
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
*/
|
|
||||||
FeatureFormat.prototype.readProjection = function(source) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a feature in this format.
|
|
||||||
*
|
|
||||||
* @abstract
|
|
||||||
* @param {module:ol/Feature} feature Feature.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} Result.
|
|
||||||
*/
|
|
||||||
FeatureFormat.prototype.writeFeature = function(feature, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode an array of features in this format.
|
|
||||||
*
|
|
||||||
* @abstract
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} Result.
|
|
||||||
*/
|
|
||||||
FeatureFormat.prototype.writeFeatures = function(features, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a single geometry in this format.
|
|
||||||
*
|
|
||||||
* @abstract
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} Result.
|
|
||||||
*/
|
|
||||||
FeatureFormat.prototype.writeGeometry = function(geometry, opt_options) {};
|
|
||||||
|
|
||||||
export default FeatureFormat;
|
export default FeatureFormat;
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,8 @@ import GML3 from '../format/GML3.js';
|
|||||||
* version 3.1.1.
|
* version 3.1.1.
|
||||||
* Currently only supports GML 3.1.1 Simple Features profile.
|
* Currently only supports GML 3.1.1 Simple Features profile.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @param {module:ol/format/GMLBase~Options=} opt_options
|
* @param {module:ol/format/GMLBase~Options=} opt_options
|
||||||
* Optional configuration object.
|
* Optional configuration object.
|
||||||
* @extends {module:ol/format/GMLBase}
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const GML = GML3;
|
const GML = GML3;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,6 @@
|
|||||||
// FIXME Envelopes should not be treated as geometries! readEnvelope_ is part
|
// FIXME Envelopes should not be treated as geometries! readEnvelope_ is part
|
||||||
// of GEOMETRY_PARSERS_ and methods using GEOMETRY_PARSERS_ do not expect
|
// of GEOMETRY_PARSERS_ and methods using GEOMETRY_PARSERS_ do not expect
|
||||||
// envelopes/extents, only geometries!
|
// envelopes/extents, only geometries!
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {extend} from '../array.js';
|
import {extend} from '../array.js';
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
import {transformWithOptions} from '../format/Feature.js';
|
import {transformWithOptions} from '../format/Feature.js';
|
||||||
@@ -29,6 +28,20 @@ import {getAllTextContent, getAttributeNS, makeArrayPusher, makeReplacer, parseN
|
|||||||
export const GMLNS = 'http://www.opengis.net/gml';
|
export const GMLNS = 'http://www.opengis.net/gml';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A regular expression that matches if a string only contains whitespace
|
||||||
|
* characters. It will e.g. match `''`, `' '`, `'\n'` etc. The non-breaking
|
||||||
|
* space (0xa0) is explicitly included as IE doesn't include it in its
|
||||||
|
* definition of `\s`.
|
||||||
|
*
|
||||||
|
* Information from `goog.string.isEmptyOrWhitespace`: https://github.com/google/closure-library/blob/e877b1e/closure/goog/string/string.js#L156-L160
|
||||||
|
*
|
||||||
|
* @const
|
||||||
|
* @type {RegExp}
|
||||||
|
*/
|
||||||
|
const ONLY_WHITESPACE_RE = /^[\s\xa0]*$/;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {Object.<string, string>|string} [featureNS] Feature
|
* @property {Object.<string, string>|string} [featureNS] Feature
|
||||||
@@ -69,407 +82,392 @@ export const GMLNS = 'http://www.opengis.net/gml';
|
|||||||
* This class cannot be instantiated, it contains only base content that
|
* This class cannot be instantiated, it contains only base content that
|
||||||
* is shared with versioned format classes GML2 and GML3.
|
* is shared with versioned format classes GML2 and GML3.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {module:ol/format/GMLBase~Options=} opt_options
|
|
||||||
* Optional configuration object.
|
|
||||||
* @extends {module:ol/format/XMLFeature}
|
|
||||||
*/
|
*/
|
||||||
const GMLBase = function(opt_options) {
|
class GMLBase extends XMLFeature {
|
||||||
const options = /** @type {module:ol/format/GMLBase~Options} */ (opt_options ? opt_options : {});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @param {module:ol/format/GMLBase~Options=} opt_options Optional configuration object.
|
||||||
* @type {Array.<string>|string|undefined}
|
|
||||||
*/
|
*/
|
||||||
this.featureType = options.featureType;
|
constructor(opt_options) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const options = /** @type {module:ol/format/GMLBase~Options} */ (opt_options ? opt_options : {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {Array.<string>|string|undefined}
|
||||||
|
*/
|
||||||
|
this.featureType = options.featureType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {Object.<string, string>|string|undefined}
|
||||||
|
*/
|
||||||
|
this.featureNS = options.featureNS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.srsName = options.srsName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.schemaLocation = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Object.<string, Object.<string, Object>>}
|
||||||
|
*/
|
||||||
|
this.FEATURE_COLLECTION_PARSERS = {};
|
||||||
|
this.FEATURE_COLLECTION_PARSERS[GMLNS] = {
|
||||||
|
'featureMember': makeReplacer(this.readFeaturesInternal),
|
||||||
|
'featureMembers': makeReplacer(this.readFeaturesInternal)
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @param {Node} node Node.
|
||||||
* @type {Object.<string, string>|string|undefined}
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {Array.<module:ol/Feature> | undefined} Features.
|
||||||
*/
|
*/
|
||||||
this.featureNS = options.featureNS;
|
readFeaturesInternal(node, objectStack) {
|
||||||
|
const localName = node.localName;
|
||||||
/**
|
let features = null;
|
||||||
* @protected
|
if (localName == 'FeatureCollection') {
|
||||||
* @type {string}
|
if (node.namespaceURI === 'http://www.opengis.net/wfs') {
|
||||||
*/
|
features = pushParseAndPop([],
|
||||||
this.srsName = options.srsName;
|
this.FEATURE_COLLECTION_PARSERS, node,
|
||||||
|
objectStack, this);
|
||||||
/**
|
} else {
|
||||||
* @protected
|
features = pushParseAndPop(null,
|
||||||
* @type {string}
|
this.FEATURE_COLLECTION_PARSERS, node,
|
||||||
*/
|
objectStack, this);
|
||||||
this.schemaLocation = '';
|
}
|
||||||
|
} else if (localName == 'featureMembers' || localName == 'featureMember') {
|
||||||
/**
|
const context = objectStack[0];
|
||||||
* @type {Object.<string, Object.<string, Object>>}
|
let featureType = context['featureType'];
|
||||||
*/
|
let featureNS = context['featureNS'];
|
||||||
this.FEATURE_COLLECTION_PARSERS = {};
|
const prefix = 'p';
|
||||||
this.FEATURE_COLLECTION_PARSERS[GMLNS] = {
|
const defaultPrefix = 'p0';
|
||||||
'featureMember': makeReplacer(GMLBase.prototype.readFeaturesInternal),
|
if (!featureType && node.childNodes) {
|
||||||
'featureMembers': makeReplacer(GMLBase.prototype.readFeaturesInternal)
|
featureType = [], featureNS = {};
|
||||||
};
|
for (let i = 0, ii = node.childNodes.length; i < ii; ++i) {
|
||||||
|
const child = node.childNodes[i];
|
||||||
XMLFeature.call(this);
|
if (child.nodeType === 1) {
|
||||||
};
|
const ft = child.nodeName.split(':').pop();
|
||||||
|
if (featureType.indexOf(ft) === -1) {
|
||||||
inherits(GMLBase, XMLFeature);
|
let key = '';
|
||||||
|
let count = 0;
|
||||||
|
const uri = child.namespaceURI;
|
||||||
/**
|
for (const candidate in featureNS) {
|
||||||
* A regular expression that matches if a string only contains whitespace
|
if (featureNS[candidate] === uri) {
|
||||||
* characters. It will e.g. match `''`, `' '`, `'\n'` etc. The non-breaking
|
key = candidate;
|
||||||
* space (0xa0) is explicitly included as IE doesn't include it in its
|
break;
|
||||||
* definition of `\s`.
|
}
|
||||||
*
|
++count;
|
||||||
* Information from `goog.string.isEmptyOrWhitespace`: https://github.com/google/closure-library/blob/e877b1e/closure/goog/string/string.js#L156-L160
|
|
||||||
*
|
|
||||||
* @const
|
|
||||||
* @type {RegExp}
|
|
||||||
*/
|
|
||||||
const ONLY_WHITESPACE_RE = /^[\s\xa0]*$/;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {Array.<module:ol/Feature> | undefined} Features.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readFeaturesInternal = function(node, objectStack) {
|
|
||||||
const localName = node.localName;
|
|
||||||
let features = null;
|
|
||||||
if (localName == 'FeatureCollection') {
|
|
||||||
if (node.namespaceURI === 'http://www.opengis.net/wfs') {
|
|
||||||
features = pushParseAndPop([],
|
|
||||||
this.FEATURE_COLLECTION_PARSERS, node,
|
|
||||||
objectStack, this);
|
|
||||||
} else {
|
|
||||||
features = pushParseAndPop(null,
|
|
||||||
this.FEATURE_COLLECTION_PARSERS, node,
|
|
||||||
objectStack, this);
|
|
||||||
}
|
|
||||||
} else if (localName == 'featureMembers' || localName == 'featureMember') {
|
|
||||||
const context = objectStack[0];
|
|
||||||
let featureType = context['featureType'];
|
|
||||||
let featureNS = context['featureNS'];
|
|
||||||
const prefix = 'p';
|
|
||||||
const defaultPrefix = 'p0';
|
|
||||||
if (!featureType && node.childNodes) {
|
|
||||||
featureType = [], featureNS = {};
|
|
||||||
for (let i = 0, ii = node.childNodes.length; i < ii; ++i) {
|
|
||||||
const child = node.childNodes[i];
|
|
||||||
if (child.nodeType === 1) {
|
|
||||||
const ft = child.nodeName.split(':').pop();
|
|
||||||
if (featureType.indexOf(ft) === -1) {
|
|
||||||
let key = '';
|
|
||||||
let count = 0;
|
|
||||||
const uri = child.namespaceURI;
|
|
||||||
for (const candidate in featureNS) {
|
|
||||||
if (featureNS[candidate] === uri) {
|
|
||||||
key = candidate;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
++count;
|
if (!key) {
|
||||||
|
key = prefix + count;
|
||||||
|
featureNS[key] = uri;
|
||||||
|
}
|
||||||
|
featureType.push(key + ':' + ft);
|
||||||
}
|
}
|
||||||
if (!key) {
|
|
||||||
key = prefix + count;
|
|
||||||
featureNS[key] = uri;
|
|
||||||
}
|
|
||||||
featureType.push(key + ':' + ft);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (localName != 'featureMember') {
|
||||||
if (localName != 'featureMember') {
|
// recheck featureType for each featureMember
|
||||||
// recheck featureType for each featureMember
|
context['featureType'] = featureType;
|
||||||
context['featureType'] = featureType;
|
context['featureNS'] = featureNS;
|
||||||
context['featureNS'] = featureNS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (typeof featureNS === 'string') {
|
|
||||||
const ns = featureNS;
|
|
||||||
featureNS = {};
|
|
||||||
featureNS[defaultPrefix] = ns;
|
|
||||||
}
|
|
||||||
const parsersNS = {};
|
|
||||||
const featureTypes = Array.isArray(featureType) ? featureType : [featureType];
|
|
||||||
for (const p in featureNS) {
|
|
||||||
const parsers = {};
|
|
||||||
for (let i = 0, ii = featureTypes.length; i < ii; ++i) {
|
|
||||||
const featurePrefix = featureTypes[i].indexOf(':') === -1 ?
|
|
||||||
defaultPrefix : featureTypes[i].split(':')[0];
|
|
||||||
if (featurePrefix === p) {
|
|
||||||
parsers[featureTypes[i].split(':').pop()] =
|
|
||||||
(localName == 'featureMembers') ?
|
|
||||||
makeArrayPusher(this.readFeatureElement, this) :
|
|
||||||
makeReplacer(this.readFeatureElement, this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parsersNS[featureNS[p]] = parsers;
|
if (typeof featureNS === 'string') {
|
||||||
}
|
const ns = featureNS;
|
||||||
if (localName == 'featureMember') {
|
featureNS = {};
|
||||||
features = pushParseAndPop(undefined, parsersNS, node, objectStack);
|
featureNS[defaultPrefix] = ns;
|
||||||
} else {
|
|
||||||
features = pushParseAndPop([], parsersNS, node, objectStack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (features === null) {
|
|
||||||
features = [];
|
|
||||||
}
|
|
||||||
return features;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {module:ol/geom/Geometry|undefined} Geometry.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readGeometryElement = function(node, objectStack) {
|
|
||||||
const context = /** @type {Object} */ (objectStack[0]);
|
|
||||||
context['srsName'] = node.firstElementChild.getAttribute('srsName');
|
|
||||||
context['srsDimension'] = node.firstElementChild.getAttribute('srsDimension');
|
|
||||||
/** @type {module:ol/geom/Geometry} */
|
|
||||||
const geometry = pushParseAndPop(null, this.GEOMETRY_PARSERS_, node, objectStack, this);
|
|
||||||
if (geometry) {
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/geom/Geometry} */ (transformWithOptions(geometry, false, context))
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readFeatureElement = function(node, objectStack) {
|
|
||||||
let n;
|
|
||||||
const fid = node.getAttribute('fid') || getAttributeNS(node, GMLNS, 'id');
|
|
||||||
const values = {};
|
|
||||||
let geometryName;
|
|
||||||
for (n = node.firstElementChild; n; n = n.nextElementSibling) {
|
|
||||||
const localName = n.localName;
|
|
||||||
// Assume attribute elements have one child node and that the child
|
|
||||||
// is a text or CDATA node (to be treated as text).
|
|
||||||
// Otherwise assume it is a geometry node.
|
|
||||||
if (n.childNodes.length === 0 ||
|
|
||||||
(n.childNodes.length === 1 &&
|
|
||||||
(n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) {
|
|
||||||
let value = getAllTextContent(n, false);
|
|
||||||
if (ONLY_WHITESPACE_RE.test(value)) {
|
|
||||||
value = undefined;
|
|
||||||
}
|
}
|
||||||
values[localName] = value;
|
const parsersNS = {};
|
||||||
} else {
|
const featureTypes = Array.isArray(featureType) ? featureType : [featureType];
|
||||||
// boundedBy is an extent and must not be considered as a geometry
|
for (const p in featureNS) {
|
||||||
if (localName !== 'boundedBy') {
|
const parsers = {};
|
||||||
geometryName = localName;
|
for (let i = 0, ii = featureTypes.length; i < ii; ++i) {
|
||||||
|
const featurePrefix = featureTypes[i].indexOf(':') === -1 ?
|
||||||
|
defaultPrefix : featureTypes[i].split(':')[0];
|
||||||
|
if (featurePrefix === p) {
|
||||||
|
parsers[featureTypes[i].split(':').pop()] =
|
||||||
|
(localName == 'featureMembers') ?
|
||||||
|
makeArrayPusher(this.readFeatureElement, this) :
|
||||||
|
makeReplacer(this.readFeatureElement, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsersNS[featureNS[p]] = parsers;
|
||||||
}
|
}
|
||||||
values[localName] = this.readGeometryElement(n, objectStack);
|
if (localName == 'featureMember') {
|
||||||
|
features = pushParseAndPop(undefined, parsersNS, node, objectStack);
|
||||||
|
} else {
|
||||||
|
features = pushParseAndPop([], parsersNS, node, objectStack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (features === null) {
|
||||||
|
features = [];
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {module:ol/geom/Geometry|undefined} Geometry.
|
||||||
|
*/
|
||||||
|
readGeometryElement(node, objectStack) {
|
||||||
|
const context = /** @type {Object} */ (objectStack[0]);
|
||||||
|
context['srsName'] = node.firstElementChild.getAttribute('srsName');
|
||||||
|
context['srsDimension'] = node.firstElementChild.getAttribute('srsDimension');
|
||||||
|
/** @type {module:ol/geom/Geometry} */
|
||||||
|
const geometry = pushParseAndPop(null, this.GEOMETRY_PARSERS_, node, objectStack, this);
|
||||||
|
if (geometry) {
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/geom/Geometry} */ (transformWithOptions(geometry, false, context))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const feature = new Feature(values);
|
|
||||||
if (geometryName) {
|
|
||||||
feature.setGeometryName(geometryName);
|
|
||||||
}
|
|
||||||
if (fid) {
|
|
||||||
feature.setId(fid);
|
|
||||||
}
|
|
||||||
return feature;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @param {Node} node Node.
|
||||||
* @param {Node} node Node.
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
* @return {module:ol/Feature} Feature.
|
||||||
* @return {module:ol/geom/Point|undefined} Point.
|
*/
|
||||||
*/
|
readFeatureElement(node, objectStack) {
|
||||||
GMLBase.prototype.readPoint = function(node, objectStack) {
|
let n;
|
||||||
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
|
const fid = node.getAttribute('fid') || getAttributeNS(node, GMLNS, 'id');
|
||||||
if (flatCoordinates) {
|
const values = {};
|
||||||
const point = new Point(null);
|
let geometryName;
|
||||||
point.setFlatCoordinates(GeometryLayout.XYZ, flatCoordinates);
|
for (n = node.firstElementChild; n; n = n.nextElementSibling) {
|
||||||
return point;
|
const localName = n.localName;
|
||||||
}
|
// Assume attribute elements have one child node and that the child
|
||||||
};
|
// is a text or CDATA node (to be treated as text).
|
||||||
|
// Otherwise assume it is a geometry node.
|
||||||
|
if (n.childNodes.length === 0 ||
|
||||||
/**
|
(n.childNodes.length === 1 &&
|
||||||
* @param {Node} node Node.
|
(n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) {
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
let value = getAllTextContent(n, false);
|
||||||
* @return {module:ol/geom/MultiPoint|undefined} MultiPoint.
|
if (ONLY_WHITESPACE_RE.test(value)) {
|
||||||
*/
|
value = undefined;
|
||||||
GMLBase.prototype.readMultiPoint = function(node, objectStack) {
|
}
|
||||||
/** @type {Array.<Array.<number>>} */
|
values[localName] = value;
|
||||||
const coordinates = pushParseAndPop([],
|
} else {
|
||||||
this.MULTIPOINT_PARSERS_, node, objectStack, this);
|
// boundedBy is an extent and must not be considered as a geometry
|
||||||
if (coordinates) {
|
if (localName !== 'boundedBy') {
|
||||||
return new MultiPoint(coordinates);
|
geometryName = localName;
|
||||||
} else {
|
}
|
||||||
return undefined;
|
values[localName] = this.readGeometryElement(n, objectStack);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {module:ol/geom/MultiLineString|undefined} MultiLineString.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readMultiLineString = function(node, objectStack) {
|
|
||||||
/** @type {Array.<module:ol/geom/LineString>} */
|
|
||||||
const lineStrings = pushParseAndPop([],
|
|
||||||
this.MULTILINESTRING_PARSERS_, node, objectStack, this);
|
|
||||||
if (lineStrings) {
|
|
||||||
const multiLineString = new MultiLineString(null);
|
|
||||||
multiLineString.setLineStrings(lineStrings);
|
|
||||||
return multiLineString;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {module:ol/geom/MultiPolygon|undefined} MultiPolygon.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readMultiPolygon = function(node, objectStack) {
|
|
||||||
/** @type {Array.<module:ol/geom/Polygon>} */
|
|
||||||
const polygons = pushParseAndPop([], this.MULTIPOLYGON_PARSERS_, node, objectStack, this);
|
|
||||||
if (polygons) {
|
|
||||||
const multiPolygon = new MultiPolygon(null);
|
|
||||||
multiPolygon.setPolygons(polygons);
|
|
||||||
return multiPolygon;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.pointMemberParser_ = function(node, objectStack) {
|
|
||||||
parseNode(this.POINTMEMBER_PARSERS_, node, objectStack, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.lineStringMemberParser_ = function(node, objectStack) {
|
|
||||||
parseNode(this.LINESTRINGMEMBER_PARSERS_, node, objectStack, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.polygonMemberParser_ = function(node, objectStack) {
|
|
||||||
parseNode(this.POLYGONMEMBER_PARSERS_, node, objectStack, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {module:ol/geom/LineString|undefined} LineString.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readLineString = function(node, objectStack) {
|
|
||||||
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
|
|
||||||
if (flatCoordinates) {
|
|
||||||
const lineString = new LineString(null);
|
|
||||||
lineString.setFlatCoordinates(GeometryLayout.XYZ, flatCoordinates);
|
|
||||||
return lineString;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @private
|
|
||||||
* @return {Array.<number>|undefined} LinearRing flat coordinates.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readFlatLinearRing_ = function(node, objectStack) {
|
|
||||||
const ring = pushParseAndPop(null,
|
|
||||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
|
|
||||||
objectStack, this);
|
|
||||||
if (ring) {
|
|
||||||
return ring;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {module:ol/geom/LinearRing|undefined} LinearRing.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readLinearRing = function(node, objectStack) {
|
|
||||||
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
|
|
||||||
if (flatCoordinates) {
|
|
||||||
const ring = new LinearRing(null);
|
|
||||||
ring.setFlatCoordinates(GeometryLayout.XYZ, flatCoordinates);
|
|
||||||
return ring;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {module:ol/geom/Polygon|undefined} Polygon.
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readPolygon = function(node, objectStack) {
|
|
||||||
/** @type {Array.<Array.<number>>} */
|
|
||||||
const flatLinearRings = pushParseAndPop([null],
|
|
||||||
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
|
|
||||||
if (flatLinearRings && flatLinearRings[0]) {
|
|
||||||
const polygon = new Polygon(null);
|
|
||||||
const flatCoordinates = flatLinearRings[0];
|
|
||||||
const ends = [flatCoordinates.length];
|
|
||||||
let i, ii;
|
|
||||||
for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
|
|
||||||
extend(flatCoordinates, flatLinearRings[i]);
|
|
||||||
ends.push(flatCoordinates.length);
|
|
||||||
}
|
}
|
||||||
polygon.setFlatCoordinates(GeometryLayout.XYZ, flatCoordinates, ends);
|
const feature = new Feature(values);
|
||||||
return polygon;
|
if (geometryName) {
|
||||||
} else {
|
feature.setGeometryName(geometryName);
|
||||||
return undefined;
|
}
|
||||||
|
if (fid) {
|
||||||
|
feature.setId(fid);
|
||||||
|
}
|
||||||
|
return feature;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {module:ol/geom/Point|undefined} Point.
|
||||||
|
*/
|
||||||
|
readPoint(node, objectStack) {
|
||||||
|
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
|
||||||
|
if (flatCoordinates) {
|
||||||
|
return new Point(flatCoordinates, GeometryLayout.XYZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
* @private
|
* @return {module:ol/geom/MultiPoint|undefined} MultiPoint.
|
||||||
* @return {Array.<number>} Flat coordinates.
|
*/
|
||||||
*/
|
readMultiPoint(node, objectStack) {
|
||||||
GMLBase.prototype.readFlatCoordinatesFromNode_ = function(node, objectStack) {
|
/** @type {Array.<Array.<number>>} */
|
||||||
return pushParseAndPop(null, this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node, objectStack, this);
|
const coordinates = pushParseAndPop([],
|
||||||
};
|
this.MULTIPOINT_PARSERS_, node, objectStack, this);
|
||||||
|
if (coordinates) {
|
||||||
|
return new MultiPoint(coordinates);
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {module:ol/geom/MultiLineString|undefined} MultiLineString.
|
||||||
|
*/
|
||||||
|
readMultiLineString(node, objectStack) {
|
||||||
|
/** @type {Array.<module:ol/geom/LineString>} */
|
||||||
|
const lineStrings = pushParseAndPop([],
|
||||||
|
this.MULTILINESTRING_PARSERS_, node, objectStack, this);
|
||||||
|
if (lineStrings) {
|
||||||
|
return new MultiLineString(lineStrings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {module:ol/geom/MultiPolygon|undefined} MultiPolygon.
|
||||||
|
*/
|
||||||
|
readMultiPolygon(node, objectStack) {
|
||||||
|
/** @type {Array.<module:ol/geom/Polygon>} */
|
||||||
|
const polygons = pushParseAndPop([], this.MULTIPOLYGON_PARSERS_, node, objectStack, this);
|
||||||
|
if (polygons) {
|
||||||
|
return new MultiPolygon(polygons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
pointMemberParser_(node, objectStack) {
|
||||||
|
parseNode(this.POINTMEMBER_PARSERS_, node, objectStack, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
lineStringMemberParser_(node, objectStack) {
|
||||||
|
parseNode(this.LINESTRINGMEMBER_PARSERS_, node, objectStack, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
polygonMemberParser_(node, objectStack) {
|
||||||
|
parseNode(this.POLYGONMEMBER_PARSERS_, node, objectStack, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {module:ol/geom/LineString|undefined} LineString.
|
||||||
|
*/
|
||||||
|
readLineString(node, objectStack) {
|
||||||
|
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
|
||||||
|
if (flatCoordinates) {
|
||||||
|
const lineString = new LineString(flatCoordinates, GeometryLayout.XYZ);
|
||||||
|
return lineString;
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @private
|
||||||
|
* @return {Array.<number>|undefined} LinearRing flat coordinates.
|
||||||
|
*/
|
||||||
|
readFlatLinearRing_(node, objectStack) {
|
||||||
|
const ring = pushParseAndPop(null,
|
||||||
|
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
|
||||||
|
objectStack, this);
|
||||||
|
if (ring) {
|
||||||
|
return ring;
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {module:ol/geom/LinearRing|undefined} LinearRing.
|
||||||
|
*/
|
||||||
|
readLinearRing(node, objectStack) {
|
||||||
|
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
|
||||||
|
if (flatCoordinates) {
|
||||||
|
return new LinearRing(flatCoordinates, GeometryLayout.XYZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {module:ol/geom/Polygon|undefined} Polygon.
|
||||||
|
*/
|
||||||
|
readPolygon(node, objectStack) {
|
||||||
|
/** @type {Array.<Array.<number>>} */
|
||||||
|
const flatLinearRings = pushParseAndPop([null],
|
||||||
|
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
|
||||||
|
if (flatLinearRings && flatLinearRings[0]) {
|
||||||
|
const flatCoordinates = flatLinearRings[0];
|
||||||
|
const ends = [flatCoordinates.length];
|
||||||
|
let i, ii;
|
||||||
|
for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
|
||||||
|
extend(flatCoordinates, flatLinearRings[i]);
|
||||||
|
ends.push(flatCoordinates.length);
|
||||||
|
}
|
||||||
|
return new Polygon(flatCoordinates, GeometryLayout.XYZ, ends);
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @private
|
||||||
|
* @return {Array.<number>} Flat coordinates.
|
||||||
|
*/
|
||||||
|
readFlatCoordinatesFromNode_(node, objectStack) {
|
||||||
|
return pushParseAndPop(null, this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node, objectStack, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readGeometryFromNode(node, opt_options) {
|
||||||
|
const geometry = this.readGeometryElement(node,
|
||||||
|
[this.getReadOptions(node, opt_options ? opt_options : {})]);
|
||||||
|
return geometry ? geometry : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeaturesFromNode(node, opt_options) {
|
||||||
|
const options = {
|
||||||
|
featureType: this.featureType,
|
||||||
|
featureNS: this.featureNS
|
||||||
|
};
|
||||||
|
if (opt_options) {
|
||||||
|
assign(options, this.getReadOptions(node, opt_options));
|
||||||
|
}
|
||||||
|
const features = this.readFeaturesInternal(node, [options]);
|
||||||
|
return features || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readProjectionFromNode(node) {
|
||||||
|
return getProjection(this.srsName ? this.srsName : node.firstElementChild.getAttribute('srsName'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
@@ -557,49 +555,4 @@ GMLBase.prototype.RING_PARSERS = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readGeometryFromNode = function(node, opt_options) {
|
|
||||||
const geometry = this.readGeometryElement(node,
|
|
||||||
[this.getReadOptions(node, opt_options ? opt_options : {})]);
|
|
||||||
return geometry ? geometry : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all features from a GML FeatureCollection.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readFeaturesFromNode = function(node, opt_options) {
|
|
||||||
const options = {
|
|
||||||
featureType: this.featureType,
|
|
||||||
featureNS: this.featureNS
|
|
||||||
};
|
|
||||||
if (opt_options) {
|
|
||||||
assign(options, this.getReadOptions(node, opt_options));
|
|
||||||
}
|
|
||||||
const features = this.readFeaturesInternal(node, [options]);
|
|
||||||
return features || [];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GMLBase.prototype.readProjectionFromNode = function(node) {
|
|
||||||
return getProjection(this.srsName ? this.srsName : node.firstElementChild.getAttribute('srsName'));
|
|
||||||
};
|
|
||||||
export default GMLBase;
|
export default GMLBase;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/GPX
|
* @module ol/format/GPX
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
import {includes} from '../array.js';
|
import {includes} from '../array.js';
|
||||||
import {transformWithOptions} from '../format/Feature.js';
|
import {transformWithOptions} from '../format/Feature.js';
|
||||||
@@ -18,52 +17,6 @@ import {createElementNS, makeArrayPusher, makeArraySerializer, makeChildAppender
|
|||||||
XML_SCHEMA_INSTANCE_URI} from '../xml.js';
|
XML_SCHEMA_INSTANCE_URI} from '../xml.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Options
|
|
||||||
* @property {function(module:ol/Feature, Node)} [readExtensions] Callback function
|
|
||||||
* to process `extensions` nodes. To prevent memory leaks, this callback function must
|
|
||||||
* not store any references to the node. Note that the `extensions`
|
|
||||||
* node is not allowed in GPX 1.0. Moreover, only `extensions`
|
|
||||||
* nodes from `wpt`, `rte` and `trk` can be processed, as those are
|
|
||||||
* directly mapped to a feature.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} LayoutOptions
|
|
||||||
* @property {boolean} [hasZ]
|
|
||||||
* @property {boolean} [hasM]
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @classdesc
|
|
||||||
* Feature format for reading and writing data in the GPX format.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/XMLFeature}
|
|
||||||
* @param {module:ol/format/GPX~Options=} opt_options Options.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
const GPX = function(opt_options) {
|
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
XMLFeature.call(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
this.dataProjection = getProjection('EPSG:4326');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {function(module:ol/Feature, Node)|undefined}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.readExtensions_ = options.readExtensions;
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(GPX, XMLFeature);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {Array.<null|string>}
|
* @type {Array.<null|string>}
|
||||||
@@ -117,6 +70,159 @@ const LINK_PARSERS = makeStructureNS(
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {Object.<string, Object.<string, module:ol/xml~Serializer>>}
|
||||||
|
*/
|
||||||
|
const GPX_SERIALIZERS = makeStructureNS(
|
||||||
|
NAMESPACE_URIS, {
|
||||||
|
'rte': makeChildAppender(writeRte),
|
||||||
|
'trk': makeChildAppender(writeTrk),
|
||||||
|
'wpt': makeChildAppender(writeWpt)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Options
|
||||||
|
* @property {function(module:ol/Feature, Node)} [readExtensions] Callback function
|
||||||
|
* to process `extensions` nodes. To prevent memory leaks, this callback function must
|
||||||
|
* not store any references to the node. Note that the `extensions`
|
||||||
|
* node is not allowed in GPX 1.0. Moreover, only `extensions`
|
||||||
|
* nodes from `wpt`, `rte` and `trk` can be processed, as those are
|
||||||
|
* directly mapped to a feature.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} LayoutOptions
|
||||||
|
* @property {boolean} [hasZ]
|
||||||
|
* @property {boolean} [hasM]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* Feature format for reading and writing data in the GPX format.
|
||||||
|
*
|
||||||
|
* Note that {@link module:ol/format/GPX~GPX#readFeature} only reads the first
|
||||||
|
* feature of the source.
|
||||||
|
*
|
||||||
|
* When reading, routes (`<rte>`) are converted into LineString geometries, and
|
||||||
|
* tracks (`<trk>`) into MultiLineString. Any properties on route and track
|
||||||
|
* waypoints are ignored.
|
||||||
|
*
|
||||||
|
* When writing, LineString geometries are output as routes (`<rte>`), and
|
||||||
|
* MultiLineString as tracks (`<trk>`).
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
class GPX extends XMLFeature {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/format/GPX~Options=} opt_options Options.
|
||||||
|
*/
|
||||||
|
constructor(opt_options) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
this.dataProjection = getProjection('EPSG:4326');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {function(module:ol/Feature, Node)|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.readExtensions_ = options.readExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array.<module:ol/Feature>} features List of features.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleReadExtensions_(features) {
|
||||||
|
if (!features) {
|
||||||
|
features = [];
|
||||||
|
}
|
||||||
|
for (let i = 0, ii = features.length; i < ii; ++i) {
|
||||||
|
const feature = features[i];
|
||||||
|
if (this.readExtensions_) {
|
||||||
|
const extensionsNode = feature.get('extensionsNode_') || null;
|
||||||
|
this.readExtensions_(feature, extensionsNode);
|
||||||
|
}
|
||||||
|
feature.set('extensionsNode_', undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeatureFromNode(node, opt_options) {
|
||||||
|
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const featureReader = FEATURE_READER[node.localName];
|
||||||
|
if (!featureReader) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const feature = featureReader(node, [this.getReadOptions(node, opt_options)]);
|
||||||
|
if (!feature) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.handleReadExtensions_([feature]);
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeaturesFromNode(node, opt_options) {
|
||||||
|
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (node.localName == 'gpx') {
|
||||||
|
/** @type {Array.<module:ol/Feature>} */
|
||||||
|
const features = pushParseAndPop([], GPX_PARSERS,
|
||||||
|
node, [this.getReadOptions(node, opt_options)]);
|
||||||
|
if (features) {
|
||||||
|
this.handleReadExtensions_(features);
|
||||||
|
return features;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode an array of features in the GPX format as an XML node.
|
||||||
|
* LineString geometries are output as routes (`<rte>`), and MultiLineString
|
||||||
|
* as tracks (`<trk>`).
|
||||||
|
*
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
|
||||||
|
* @return {Node} Node.
|
||||||
|
* @override
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeaturesNode(features, opt_options) {
|
||||||
|
opt_options = this.adaptOptions(opt_options);
|
||||||
|
//FIXME Serialize metadata
|
||||||
|
const gpx = createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
|
||||||
|
const xmlnsUri = 'http://www.w3.org/2000/xmlns/';
|
||||||
|
gpx.setAttributeNS(xmlnsUri, 'xmlns:xsi', XML_SCHEMA_INSTANCE_URI);
|
||||||
|
gpx.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', SCHEMA_LOCATION);
|
||||||
|
gpx.setAttribute('version', '1.1');
|
||||||
|
gpx.setAttribute('creator', 'OpenLayers');
|
||||||
|
|
||||||
|
pushSerializeAndPop(/** @type {module:ol/xml~NodeStackItem} */
|
||||||
|
({node: gpx}), GPX_SERIALIZERS, GPX_NODE_FACTORY, features, [opt_options]);
|
||||||
|
return gpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
||||||
@@ -380,18 +486,6 @@ function GPX_NODE_FACTORY(value, objectStack, opt_nodeName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @const
|
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Serializer>>}
|
|
||||||
*/
|
|
||||||
const GPX_SERIALIZERS = makeStructureNS(
|
|
||||||
NAMESPACE_URIS, {
|
|
||||||
'rte': makeChildAppender(writeRte),
|
|
||||||
'trk': makeChildAppender(writeTrk),
|
|
||||||
'wpt': makeChildAppender(writeWpt)
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||||
* @param {module:ol/format/GPX~LayoutOptions} layoutOptions Layout options.
|
* @param {module:ol/format/GPX~LayoutOptions} layoutOptions Layout options.
|
||||||
@@ -553,8 +647,7 @@ function readRte(node, objectStack) {
|
|||||||
const layoutOptions = /** @type {module:ol/format/GPX~LayoutOptions} */ (values['layoutOptions']);
|
const layoutOptions = /** @type {module:ol/format/GPX~LayoutOptions} */ (values['layoutOptions']);
|
||||||
delete values['layoutOptions'];
|
delete values['layoutOptions'];
|
||||||
const layout = applyLayoutOptions(layoutOptions, flatCoordinates);
|
const layout = applyLayoutOptions(layoutOptions, flatCoordinates);
|
||||||
const geometry = new LineString(null);
|
const geometry = new LineString(flatCoordinates, layout);
|
||||||
geometry.setFlatCoordinates(layout, flatCoordinates);
|
|
||||||
transformWithOptions(geometry, false, options);
|
transformWithOptions(geometry, false, options);
|
||||||
const feature = new Feature(geometry);
|
const feature = new Feature(geometry);
|
||||||
feature.setProperties(values);
|
feature.setProperties(values);
|
||||||
@@ -585,8 +678,7 @@ function readTrk(node, objectStack) {
|
|||||||
const layoutOptions = /** @type {module:ol/format/GPX~LayoutOptions} */ (values['layoutOptions']);
|
const layoutOptions = /** @type {module:ol/format/GPX~LayoutOptions} */ (values['layoutOptions']);
|
||||||
delete values['layoutOptions'];
|
delete values['layoutOptions'];
|
||||||
const layout = applyLayoutOptions(layoutOptions, flatCoordinates, ends);
|
const layout = applyLayoutOptions(layoutOptions, flatCoordinates, ends);
|
||||||
const geometry = new MultiLineString(null);
|
const geometry = new MultiLineString(flatCoordinates, layout, ends);
|
||||||
geometry.setFlatCoordinates(layout, flatCoordinates, ends);
|
|
||||||
transformWithOptions(geometry, false, options);
|
transformWithOptions(geometry, false, options);
|
||||||
const feature = new Feature(geometry);
|
const feature = new Feature(geometry);
|
||||||
feature.setProperties(values);
|
feature.setProperties(values);
|
||||||
@@ -616,106 +708,6 @@ function readWpt(node, objectStack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Array.<module:ol/Feature>} features List of features.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
GPX.prototype.handleReadExtensions_ = function(features) {
|
|
||||||
if (!features) {
|
|
||||||
features = [];
|
|
||||||
}
|
|
||||||
for (let i = 0, ii = features.length; i < ii; ++i) {
|
|
||||||
const feature = features[i];
|
|
||||||
if (this.readExtensions_) {
|
|
||||||
const extensionsNode = feature.get('extensionsNode_') || null;
|
|
||||||
this.readExtensions_(feature, extensionsNode);
|
|
||||||
}
|
|
||||||
feature.set('extensionsNode_', undefined);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the first feature from a GPX source.
|
|
||||||
* Routes (`<rte>`) are converted into LineString geometries, and tracks (`<trk>`)
|
|
||||||
* into MultiLineString. Any properties on route and track waypoints are ignored.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GPX.prototype.readFeature;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GPX.prototype.readFeatureFromNode = function(node, opt_options) {
|
|
||||||
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const featureReader = FEATURE_READER[node.localName];
|
|
||||||
if (!featureReader) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const feature = featureReader(node, [this.getReadOptions(node, opt_options)]);
|
|
||||||
if (!feature) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
this.handleReadExtensions_([feature]);
|
|
||||||
return feature;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all features from a GPX source.
|
|
||||||
* Routes (`<rte>`) are converted into LineString geometries, and tracks (`<trk>`)
|
|
||||||
* into MultiLineString. Any properties on route and track waypoints are ignored.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GPX.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GPX.prototype.readFeaturesFromNode = function(node, opt_options) {
|
|
||||||
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
if (node.localName == 'gpx') {
|
|
||||||
/** @type {Array.<module:ol/Feature>} */
|
|
||||||
const features = pushParseAndPop([], GPX_PARSERS,
|
|
||||||
node, [this.getReadOptions(node, opt_options)]);
|
|
||||||
if (features) {
|
|
||||||
this.handleReadExtensions_(features);
|
|
||||||
return features;
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from a GPX source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GPX.prototype.readProjection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {string} value Value for the link's `href` attribute.
|
* @param {string} value Value for the link's `href` attribute.
|
||||||
@@ -862,43 +854,4 @@ function writeWpt(node, feature, objectStack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode an array of features in the GPX format.
|
|
||||||
* LineString geometries are output as routes (`<rte>`), and MultiLineString
|
|
||||||
* as tracks (`<trk>`).
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} Result.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GPX.prototype.writeFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode an array of features in the GPX format as an XML node.
|
|
||||||
* LineString geometries are output as routes (`<rte>`), and MultiLineString
|
|
||||||
* as tracks (`<trk>`).
|
|
||||||
*
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
|
|
||||||
* @return {Node} Node.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GPX.prototype.writeFeaturesNode = function(features, opt_options) {
|
|
||||||
opt_options = this.adaptOptions(opt_options);
|
|
||||||
//FIXME Serialize metadata
|
|
||||||
const gpx = createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
|
|
||||||
const xmlnsUri = 'http://www.w3.org/2000/xmlns/';
|
|
||||||
gpx.setAttributeNS(xmlnsUri, 'xmlns:xsi', XML_SCHEMA_INSTANCE_URI);
|
|
||||||
gpx.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', SCHEMA_LOCATION);
|
|
||||||
gpx.setAttribute('version', '1.1');
|
|
||||||
gpx.setAttribute('creator', 'OpenLayers');
|
|
||||||
|
|
||||||
pushSerializeAndPop(/** @type {module:ol/xml~NodeStackItem} */
|
|
||||||
({node: gpx}), GPX_SERIALIZERS, GPX_NODE_FACTORY, features, [opt_options]);
|
|
||||||
return gpx;
|
|
||||||
};
|
|
||||||
export default GPX;
|
export default GPX;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
// TODO: serialize dataProjection as crs member when writing
|
// TODO: serialize dataProjection as crs member when writing
|
||||||
// see https://github.com/openlayers/openlayers/issues/2078
|
// see https://github.com/openlayers/openlayers/issues/2078
|
||||||
|
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {assert} from '../asserts.js';
|
import {assert} from '../asserts.js';
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
import {transformWithOptions} from '../format/Feature.js';
|
import {transformWithOptions} from '../format/Feature.js';
|
||||||
@@ -37,45 +36,197 @@ import {get as getProjection} from '../proj.js';
|
|||||||
* @classdesc
|
* @classdesc
|
||||||
* Feature format for reading and writing data in the GeoJSON format.
|
* Feature format for reading and writing data in the GeoJSON format.
|
||||||
*
|
*
|
||||||
* @constructor
|
* @api
|
||||||
* @extends {module:ol/format/JSONFeature}
|
|
||||||
* @param {module:ol/format/GeoJSON~Options=} opt_options Options.
|
|
||||||
* @api
|
|
||||||
*/
|
*/
|
||||||
const GeoJSON = function(opt_options) {
|
class GeoJSON extends JSONFeature {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
/**
|
||||||
|
* @param {module:ol/format/GeoJSON~Options=} opt_options Options.
|
||||||
|
*/
|
||||||
|
constructor(opt_options) {
|
||||||
|
|
||||||
JSONFeature.call(this);
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
this.dataProjection = getProjection(
|
||||||
|
options.dataProjection ?
|
||||||
|
options.dataProjection : 'EPSG:4326');
|
||||||
|
|
||||||
|
if (options.featureProjection) {
|
||||||
|
this.defaultFeatureProjection = getProjection(options.featureProjection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the geometry attribute for features.
|
||||||
|
* @type {string|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.geometryName_ = options.geometryName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look for the geometry name in the feature GeoJSON
|
||||||
|
* @type {boolean|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.extractGeometryName_ = options.extractGeometryName;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
this.dataProjection = getProjection(
|
readFeatureFromObject(object, opt_options) {
|
||||||
options.dataProjection ?
|
/**
|
||||||
options.dataProjection : 'EPSG:4326');
|
* @type {GeoJSONFeature}
|
||||||
|
*/
|
||||||
|
let geoJSONFeature = null;
|
||||||
|
if (object.type === 'Feature') {
|
||||||
|
geoJSONFeature = /** @type {GeoJSONFeature} */ (object);
|
||||||
|
} else {
|
||||||
|
geoJSONFeature = /** @type {GeoJSONFeature} */ ({
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: /** @type {GeoJSONGeometry|GeoJSONGeometryCollection} */ (object)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (options.featureProjection) {
|
const geometry = readGeometry(geoJSONFeature.geometry, opt_options);
|
||||||
this.defaultFeatureProjection = getProjection(options.featureProjection);
|
const feature = new Feature();
|
||||||
|
if (this.geometryName_) {
|
||||||
|
feature.setGeometryName(this.geometryName_);
|
||||||
|
} else if (this.extractGeometryName_ && geoJSONFeature.geometry_name !== undefined) {
|
||||||
|
feature.setGeometryName(geoJSONFeature.geometry_name);
|
||||||
|
}
|
||||||
|
feature.setGeometry(geometry);
|
||||||
|
if (geoJSONFeature.id !== undefined) {
|
||||||
|
feature.setId(geoJSONFeature.id);
|
||||||
|
}
|
||||||
|
if (geoJSONFeature.properties) {
|
||||||
|
feature.setProperties(geoJSONFeature.properties);
|
||||||
|
}
|
||||||
|
return feature;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the geometry attribute for features.
|
* @inheritDoc
|
||||||
* @type {string|undefined}
|
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
this.geometryName_ = options.geometryName;
|
readFeaturesFromObject(object, opt_options) {
|
||||||
|
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
|
||||||
|
/** @type {Array.<module:ol/Feature>} */
|
||||||
|
let features = null;
|
||||||
|
if (geoJSONObject.type === 'FeatureCollection') {
|
||||||
|
const geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */ (object);
|
||||||
|
features = [];
|
||||||
|
const geoJSONFeatures = geoJSONFeatureCollection.features;
|
||||||
|
for (let i = 0, ii = geoJSONFeatures.length; i < ii; ++i) {
|
||||||
|
features.push(this.readFeatureFromObject(geoJSONFeatures[i], opt_options));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
features = [this.readFeatureFromObject(object, opt_options)];
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look for the geometry name in the feature GeoJSON
|
* @inheritDoc
|
||||||
* @type {boolean|undefined}
|
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
this.extractGeometryName_ = options.extractGeometryName;
|
readGeometryFromObject(object, opt_options) {
|
||||||
|
return readGeometry(/** @type {GeoJSONGeometry} */ (object), opt_options);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readProjectionFromObject(object) {
|
||||||
|
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
|
||||||
|
const crs = geoJSONObject.crs;
|
||||||
|
let projection;
|
||||||
|
if (crs) {
|
||||||
|
if (crs.type == 'name') {
|
||||||
|
projection = getProjection(crs.properties.name);
|
||||||
|
} else {
|
||||||
|
assert(false, 36); // Unknown SRS type
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
projection = this.dataProjection;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
/** @type {module:ol/proj/Projection} */ (projection)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
inherits(GeoJSON, JSONFeature);
|
/**
|
||||||
|
* Encode a feature as a GeoJSON Feature object.
|
||||||
|
*
|
||||||
|
* @param {module:ol/Feature} feature Feature.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {GeoJSONFeature} Object.
|
||||||
|
* @override
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeatureObject(feature, opt_options) {
|
||||||
|
opt_options = this.adaptOptions(opt_options);
|
||||||
|
|
||||||
|
const object = /** @type {GeoJSONFeature} */ ({
|
||||||
|
'type': 'Feature'
|
||||||
|
});
|
||||||
|
const id = feature.getId();
|
||||||
|
if (id !== undefined) {
|
||||||
|
object.id = id;
|
||||||
|
}
|
||||||
|
const geometry = feature.getGeometry();
|
||||||
|
if (geometry) {
|
||||||
|
object.geometry = writeGeometry(geometry, opt_options);
|
||||||
|
} else {
|
||||||
|
object.geometry = null;
|
||||||
|
}
|
||||||
|
const properties = feature.getProperties();
|
||||||
|
delete properties[feature.getGeometryName()];
|
||||||
|
if (!isEmpty(properties)) {
|
||||||
|
object.properties = properties;
|
||||||
|
} else {
|
||||||
|
object.properties = null;
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode an array of features as a GeoJSON object.
|
||||||
|
*
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {GeoJSONFeatureCollection} GeoJSON Object.
|
||||||
|
* @override
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeaturesObject(features, opt_options) {
|
||||||
|
opt_options = this.adaptOptions(opt_options);
|
||||||
|
const objects = [];
|
||||||
|
for (let i = 0, ii = features.length; i < ii; ++i) {
|
||||||
|
objects.push(this.writeFeatureObject(features[i], opt_options));
|
||||||
|
}
|
||||||
|
return /** @type {GeoJSONFeatureCollection} */ ({
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: objects
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a geometry as a GeoJSON object.
|
||||||
|
*
|
||||||
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {GeoJSONGeometry|GeoJSONGeometryCollection} Object.
|
||||||
|
* @override
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeGeometryObject(geometry, opt_options) {
|
||||||
|
return writeGeometry(geometry, this.adaptOptions(opt_options));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -325,249 +476,4 @@ function writePolygonGeometry(geometry, opt_options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a feature from a GeoJSON Feature source. Only works for Feature or
|
|
||||||
* geometry types. Use {@link module:ol/format/GeoJSON#readFeatures} to read
|
|
||||||
* FeatureCollection source. If feature at source has an id, it will be used
|
|
||||||
* as Feature id by calling {@link module:ol/Feature#setId} internally.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.readFeature;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all features from a GeoJSON source. Works for all GeoJSON types.
|
|
||||||
* If the source includes only geometries, features will be created with those
|
|
||||||
* geometries.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.readFeatureFromObject = function(object, opt_options) {
|
|
||||||
/**
|
|
||||||
* @type {GeoJSONFeature}
|
|
||||||
*/
|
|
||||||
let geoJSONFeature = null;
|
|
||||||
if (object.type === 'Feature') {
|
|
||||||
geoJSONFeature = /** @type {GeoJSONFeature} */ (object);
|
|
||||||
} else {
|
|
||||||
geoJSONFeature = /** @type {GeoJSONFeature} */ ({
|
|
||||||
type: 'Feature',
|
|
||||||
geometry: /** @type {GeoJSONGeometry|GeoJSONGeometryCollection} */ (object)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const geometry = readGeometry(geoJSONFeature.geometry, opt_options);
|
|
||||||
const feature = new Feature();
|
|
||||||
if (this.geometryName_) {
|
|
||||||
feature.setGeometryName(this.geometryName_);
|
|
||||||
} else if (this.extractGeometryName_ && geoJSONFeature.geometry_name !== undefined) {
|
|
||||||
feature.setGeometryName(geoJSONFeature.geometry_name);
|
|
||||||
}
|
|
||||||
feature.setGeometry(geometry);
|
|
||||||
if (geoJSONFeature.id !== undefined) {
|
|
||||||
feature.setId(geoJSONFeature.id);
|
|
||||||
}
|
|
||||||
if (geoJSONFeature.properties) {
|
|
||||||
feature.setProperties(geoJSONFeature.properties);
|
|
||||||
}
|
|
||||||
return feature;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.readFeaturesFromObject = function(object, opt_options) {
|
|
||||||
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
|
|
||||||
/** @type {Array.<module:ol/Feature>} */
|
|
||||||
let features = null;
|
|
||||||
if (geoJSONObject.type === 'FeatureCollection') {
|
|
||||||
const geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */ (object);
|
|
||||||
features = [];
|
|
||||||
const geoJSONFeatures = geoJSONFeatureCollection.features;
|
|
||||||
for (let i = 0, ii = geoJSONFeatures.length; i < ii; ++i) {
|
|
||||||
features.push(this.readFeatureFromObject(geoJSONFeatures[i], opt_options));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
features = [this.readFeatureFromObject(object, opt_options)];
|
|
||||||
}
|
|
||||||
return features;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a geometry from a GeoJSON source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/geom/Geometry} Geometry.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.readGeometry;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.readGeometryFromObject = function(object, opt_options) {
|
|
||||||
return readGeometry(/** @type {GeoJSONGeometry} */ (object), opt_options);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from a GeoJSON source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.readProjection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.readProjectionFromObject = function(object) {
|
|
||||||
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
|
|
||||||
const crs = geoJSONObject.crs;
|
|
||||||
let projection;
|
|
||||||
if (crs) {
|
|
||||||
if (crs.type == 'name') {
|
|
||||||
projection = getProjection(crs.properties.name);
|
|
||||||
} else {
|
|
||||||
assert(false, 36); // Unknown SRS type
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
projection = this.dataProjection;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/proj/Projection} */ (projection)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a feature as a GeoJSON Feature string.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {module:ol/Feature} feature Feature.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} GeoJSON.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.writeFeature;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a feature as a GeoJSON Feature object.
|
|
||||||
*
|
|
||||||
* @param {module:ol/Feature} feature Feature.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {GeoJSONFeature} Object.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.writeFeatureObject = function(feature, opt_options) {
|
|
||||||
opt_options = this.adaptOptions(opt_options);
|
|
||||||
|
|
||||||
const object = /** @type {GeoJSONFeature} */ ({
|
|
||||||
'type': 'Feature'
|
|
||||||
});
|
|
||||||
const id = feature.getId();
|
|
||||||
if (id !== undefined) {
|
|
||||||
object.id = id;
|
|
||||||
}
|
|
||||||
const geometry = feature.getGeometry();
|
|
||||||
if (geometry) {
|
|
||||||
object.geometry = writeGeometry(geometry, opt_options);
|
|
||||||
} else {
|
|
||||||
object.geometry = null;
|
|
||||||
}
|
|
||||||
const properties = feature.getProperties();
|
|
||||||
delete properties[feature.getGeometryName()];
|
|
||||||
if (!isEmpty(properties)) {
|
|
||||||
object.properties = properties;
|
|
||||||
} else {
|
|
||||||
object.properties = null;
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode an array of features as GeoJSON.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} GeoJSON.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.writeFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode an array of features as a GeoJSON object.
|
|
||||||
*
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {GeoJSONFeatureCollection} GeoJSON Object.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.writeFeaturesObject = function(features, opt_options) {
|
|
||||||
opt_options = this.adaptOptions(opt_options);
|
|
||||||
const objects = [];
|
|
||||||
for (let i = 0, ii = features.length; i < ii; ++i) {
|
|
||||||
objects.push(this.writeFeatureObject(features[i], opt_options));
|
|
||||||
}
|
|
||||||
return /** @type {GeoJSONFeatureCollection} */ ({
|
|
||||||
type: 'FeatureCollection',
|
|
||||||
features: objects
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a geometry as a GeoJSON string.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} GeoJSON.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.writeGeometry;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a geometry as a GeoJSON object.
|
|
||||||
*
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {GeoJSONGeometry|GeoJSONGeometryCollection} Object.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
GeoJSON.prototype.writeGeometryObject = function(geometry, opt_options) {
|
|
||||||
return writeGeometry(geometry, this.adaptOptions(opt_options));
|
|
||||||
};
|
|
||||||
export default GeoJSON;
|
export default GeoJSON;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/IGC
|
* @module ol/format/IGC
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
import {transformWithOptions} from '../format/Feature.js';
|
import {transformWithOptions} from '../format/Feature.js';
|
||||||
import TextFeature from '../format/TextFeature.js';
|
import TextFeature from '../format/TextFeature.js';
|
||||||
@@ -19,44 +18,6 @@ const IGCZ = {
|
|||||||
NONE: 'none'
|
NONE: 'none'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Options
|
|
||||||
* @property {IGCZ|string} [altitudeMode='none'] Altitude mode. Possible
|
|
||||||
* values are `'barometric'`, `'gps'`, and `'none'`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @classdesc
|
|
||||||
* Feature format for `*.igc` flight recording files.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/TextFeature}
|
|
||||||
* @param {module:ol/format/IGC~Options=} opt_options Options.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
const IGC = function(opt_options) {
|
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
TextFeature.call(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
this.dataProjection = getProjection('EPSG:4326');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {IGCZ}
|
|
||||||
*/
|
|
||||||
this.altitudeMode_ = options.altitudeMode ? options.altitudeMode : IGCZ.NONE;
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(IGC, TextFeature);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {RegExp}
|
* @type {RegExp}
|
||||||
@@ -89,155 +50,154 @@ const NEWLINE_RE = /\r\n|\r|\n/;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the feature from the IGC source.
|
* @typedef {Object} Options
|
||||||
*
|
* @property {IGCZ|string} [altitudeMode='none'] Altitude mode. Possible
|
||||||
* @function
|
* values are `'barometric'`, `'gps'`, and `'none'`.
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
* @api
|
|
||||||
*/
|
*/
|
||||||
IGC.prototype.readFeature;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @classdesc
|
||||||
|
* Feature format for `*.igc` flight recording files.
|
||||||
|
*
|
||||||
|
* As IGC sources contain a single feature,
|
||||||
|
* {@link module:ol/format/IGC~IGC#readFeatures} will return the feature in an
|
||||||
|
* array
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
IGC.prototype.readFeatureFromText = function(text, opt_options) {
|
class IGC extends TextFeature {
|
||||||
const altitudeMode = this.altitudeMode_;
|
|
||||||
const lines = text.split(NEWLINE_RE);
|
/**
|
||||||
/** @type {Object.<string, string>} */
|
* @param {module:ol/format/IGC~Options=} opt_options Options.
|
||||||
const properties = {};
|
*/
|
||||||
const flatCoordinates = [];
|
constructor(opt_options) {
|
||||||
let year = 2000;
|
super();
|
||||||
let month = 0;
|
|
||||||
let day = 1;
|
const options = opt_options ? opt_options : {};
|
||||||
let lastDateTime = -1;
|
|
||||||
let i, ii;
|
/**
|
||||||
for (i = 0, ii = lines.length; i < ii; ++i) {
|
* @inheritDoc
|
||||||
const line = lines[i];
|
*/
|
||||||
let m;
|
this.dataProjection = getProjection('EPSG:4326');
|
||||||
if (line.charAt(0) == 'B') {
|
|
||||||
m = B_RECORD_RE.exec(line);
|
/**
|
||||||
if (m) {
|
* @private
|
||||||
const hour = parseInt(m[1], 10);
|
* @type {IGCZ}
|
||||||
const minute = parseInt(m[2], 10);
|
*/
|
||||||
const second = parseInt(m[3], 10);
|
this.altitudeMode_ = options.altitudeMode ? options.altitudeMode : IGCZ.NONE;
|
||||||
let y = parseInt(m[4], 10) + parseInt(m[5], 10) / 60000;
|
}
|
||||||
if (m[6] == 'S') {
|
|
||||||
y = -y;
|
/**
|
||||||
}
|
* @inheritDoc
|
||||||
let x = parseInt(m[7], 10) + parseInt(m[8], 10) / 60000;
|
*/
|
||||||
if (m[9] == 'W') {
|
readFeatureFromText(text, opt_options) {
|
||||||
x = -x;
|
const altitudeMode = this.altitudeMode_;
|
||||||
}
|
const lines = text.split(NEWLINE_RE);
|
||||||
flatCoordinates.push(x, y);
|
/** @type {Object.<string, string>} */
|
||||||
if (altitudeMode != IGCZ.NONE) {
|
const properties = {};
|
||||||
let z;
|
const flatCoordinates = [];
|
||||||
if (altitudeMode == IGCZ.GPS) {
|
let year = 2000;
|
||||||
z = parseInt(m[11], 10);
|
let month = 0;
|
||||||
} else if (altitudeMode == IGCZ.BAROMETRIC) {
|
let day = 1;
|
||||||
z = parseInt(m[12], 10);
|
let lastDateTime = -1;
|
||||||
} else {
|
let i, ii;
|
||||||
z = 0;
|
for (i = 0, ii = lines.length; i < ii; ++i) {
|
||||||
}
|
const line = lines[i];
|
||||||
flatCoordinates.push(z);
|
let m;
|
||||||
}
|
if (line.charAt(0) == 'B') {
|
||||||
let dateTime = Date.UTC(year, month, day, hour, minute, second);
|
m = B_RECORD_RE.exec(line);
|
||||||
// Detect UTC midnight wrap around.
|
|
||||||
if (dateTime < lastDateTime) {
|
|
||||||
dateTime = Date.UTC(year, month, day + 1, hour, minute, second);
|
|
||||||
}
|
|
||||||
flatCoordinates.push(dateTime / 1000);
|
|
||||||
lastDateTime = dateTime;
|
|
||||||
}
|
|
||||||
} else if (line.charAt(0) == 'H') {
|
|
||||||
m = HFDTE_RECORD_RE.exec(line);
|
|
||||||
if (m) {
|
|
||||||
day = parseInt(m[1], 10);
|
|
||||||
month = parseInt(m[2], 10) - 1;
|
|
||||||
year = 2000 + parseInt(m[3], 10);
|
|
||||||
} else {
|
|
||||||
m = H_RECORD_RE.exec(line);
|
|
||||||
if (m) {
|
if (m) {
|
||||||
properties[m[1]] = m[2].trim();
|
const hour = parseInt(m[1], 10);
|
||||||
|
const minute = parseInt(m[2], 10);
|
||||||
|
const second = parseInt(m[3], 10);
|
||||||
|
let y = parseInt(m[4], 10) + parseInt(m[5], 10) / 60000;
|
||||||
|
if (m[6] == 'S') {
|
||||||
|
y = -y;
|
||||||
|
}
|
||||||
|
let x = parseInt(m[7], 10) + parseInt(m[8], 10) / 60000;
|
||||||
|
if (m[9] == 'W') {
|
||||||
|
x = -x;
|
||||||
|
}
|
||||||
|
flatCoordinates.push(x, y);
|
||||||
|
if (altitudeMode != IGCZ.NONE) {
|
||||||
|
let z;
|
||||||
|
if (altitudeMode == IGCZ.GPS) {
|
||||||
|
z = parseInt(m[11], 10);
|
||||||
|
} else if (altitudeMode == IGCZ.BAROMETRIC) {
|
||||||
|
z = parseInt(m[12], 10);
|
||||||
|
} else {
|
||||||
|
z = 0;
|
||||||
|
}
|
||||||
|
flatCoordinates.push(z);
|
||||||
|
}
|
||||||
|
let dateTime = Date.UTC(year, month, day, hour, minute, second);
|
||||||
|
// Detect UTC midnight wrap around.
|
||||||
|
if (dateTime < lastDateTime) {
|
||||||
|
dateTime = Date.UTC(year, month, day + 1, hour, minute, second);
|
||||||
|
}
|
||||||
|
flatCoordinates.push(dateTime / 1000);
|
||||||
|
lastDateTime = dateTime;
|
||||||
|
}
|
||||||
|
} else if (line.charAt(0) == 'H') {
|
||||||
|
m = HFDTE_RECORD_RE.exec(line);
|
||||||
|
if (m) {
|
||||||
|
day = parseInt(m[1], 10);
|
||||||
|
month = parseInt(m[2], 10) - 1;
|
||||||
|
year = 2000 + parseInt(m[3], 10);
|
||||||
|
} else {
|
||||||
|
m = H_RECORD_RE.exec(line);
|
||||||
|
if (m) {
|
||||||
|
properties[m[1]] = m[2].trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (flatCoordinates.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const layout = altitudeMode == IGCZ.NONE ? GeometryLayout.XYM : GeometryLayout.XYZM;
|
||||||
|
const lineString = new LineString(flatCoordinates, layout);
|
||||||
|
const feature = new Feature(transformWithOptions(lineString, false, opt_options));
|
||||||
|
feature.setProperties(properties);
|
||||||
|
return feature;
|
||||||
}
|
}
|
||||||
if (flatCoordinates.length === 0) {
|
|
||||||
return null;
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeaturesFromText(text, opt_options) {
|
||||||
|
const feature = this.readFeatureFromText(text, opt_options);
|
||||||
|
if (feature) {
|
||||||
|
return [feature];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const lineString = new LineString(null);
|
|
||||||
const layout = altitudeMode == IGCZ.NONE ? GeometryLayout.XYM : GeometryLayout.XYZM;
|
|
||||||
lineString.setFlatCoordinates(layout, flatCoordinates);
|
|
||||||
const feature = new Feature(transformWithOptions(lineString, false, opt_options));
|
|
||||||
feature.setProperties(properties);
|
|
||||||
return feature;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeatureText(feature, opt_options) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the feature from the source. As IGC sources contain a single
|
* Not implemented.
|
||||||
* feature, this will return the feature in an array.
|
* @inheritDoc
|
||||||
*
|
*/
|
||||||
* @function
|
writeFeaturesText(features, opt_options) {}
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
IGC.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeGeometryText(geometry, opt_options) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* Not implemented.
|
||||||
*/
|
* @inheritDoc
|
||||||
IGC.prototype.readFeaturesFromText = function(text, opt_options) {
|
*/
|
||||||
const feature = this.readFeatureFromText(text, opt_options);
|
readGeometryFromText(text, opt_options) {}
|
||||||
if (feature) {
|
}
|
||||||
return [feature];
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from the IGC source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
IGC.prototype.readProjection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
IGC.prototype.writeFeatureText = function(feature, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
IGC.prototype.writeFeaturesText = function(features, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
IGC.prototype.writeGeometryText = function(geometry, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
IGC.prototype.readGeometryFromText = function(text, opt_options) {};
|
|
||||||
export default IGC;
|
export default IGC;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/JSONFeature
|
* @module ol/format/JSONFeature
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import FeatureFormat from '../format/Feature.js';
|
import FeatureFormat from '../format/Feature.js';
|
||||||
import FormatType from '../format/FormatType.js';
|
import FormatType from '../format/FormatType.js';
|
||||||
|
|
||||||
@@ -11,15 +10,167 @@ import FormatType from '../format/FormatType.js';
|
|||||||
* instantiated in apps.
|
* instantiated in apps.
|
||||||
* Base class for JSON feature formats.
|
* Base class for JSON feature formats.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @extends {module:ol/format/Feature}
|
|
||||||
*/
|
*/
|
||||||
const JSONFeature = function() {
|
class JSONFeature extends FeatureFormat {
|
||||||
FeatureFormat.call(this);
|
constructor() {
|
||||||
};
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
inherits(JSONFeature, FeatureFormat);
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
getType() {
|
||||||
|
return FormatType.JSON;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a feature. Only works for a single feature. Use `readFeatures` to
|
||||||
|
* read a feature collection.
|
||||||
|
*
|
||||||
|
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {module:ol/Feature} Feature.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readFeature(source, opt_options) {
|
||||||
|
return this.readFeatureFromObject(
|
||||||
|
getObject(source), this.getReadOptions(source, opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read all features. Works with both a single feature and a feature
|
||||||
|
* collection.
|
||||||
|
*
|
||||||
|
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readFeatures(source, opt_options) {
|
||||||
|
return this.readFeaturesFromObject(
|
||||||
|
getObject(source), this.getReadOptions(source, opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {Object} object Object.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/Feature} Feature.
|
||||||
|
*/
|
||||||
|
readFeatureFromObject(object, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {Object} object Object.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @protected
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
*/
|
||||||
|
readFeaturesFromObject(object, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a geometry.
|
||||||
|
*
|
||||||
|
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {module:ol/geom/Geometry} Geometry.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readGeometry(source, opt_options) {
|
||||||
|
return this.readGeometryFromObject(
|
||||||
|
getObject(source), this.getReadOptions(source, opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {Object} object Object.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/geom/Geometry} Geometry.
|
||||||
|
*/
|
||||||
|
readGeometryFromObject(object, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the projection.
|
||||||
|
*
|
||||||
|
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||||
|
* @return {module:ol/proj/Projection} Projection.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readProjection(source) {
|
||||||
|
return this.readProjectionFromObject(getObject(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {Object} object Object.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/proj/Projection} Projection.
|
||||||
|
*/
|
||||||
|
readProjectionFromObject(object) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a feature as string.
|
||||||
|
*
|
||||||
|
* @param {module:ol/Feature} feature Feature.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {string} Encoded feature.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeature(feature, opt_options) {
|
||||||
|
return JSON.stringify(this.writeFeatureObject(feature, opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {module:ol/Feature} feature Feature.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {Object} Object.
|
||||||
|
*/
|
||||||
|
writeFeatureObject(feature, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode an array of features as string.
|
||||||
|
*
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {string} Encoded features.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeatures(features, opt_options) {
|
||||||
|
return JSON.stringify(this.writeFeaturesObject(features, opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {Object} Object.
|
||||||
|
*/
|
||||||
|
writeFeaturesObject(features, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a geometry as string.
|
||||||
|
*
|
||||||
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {string} Encoded geometry.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeGeometry(geometry, opt_options) {
|
||||||
|
return JSON.stringify(this.writeGeometryObject(geometry, opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {Object} Object.
|
||||||
|
*/
|
||||||
|
writeGeometryObject(geometry, opt_options) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,135 +189,4 @@ function getObject(source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.getType = function() {
|
|
||||||
return FormatType.JSON;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.readFeature = function(source, opt_options) {
|
|
||||||
return this.readFeatureFromObject(
|
|
||||||
getObject(source), this.getReadOptions(source, opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.readFeatures = function(source, opt_options) {
|
|
||||||
return this.readFeaturesFromObject(
|
|
||||||
getObject(source), this.getReadOptions(source, opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {Object} object Object.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.readFeatureFromObject = function(object, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {Object} object Object.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @protected
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.readFeaturesFromObject = function(object, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.readGeometry = function(source, opt_options) {
|
|
||||||
return this.readGeometryFromObject(
|
|
||||||
getObject(source), this.getReadOptions(source, opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {Object} object Object.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/geom/Geometry} Geometry.
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.readGeometryFromObject = function(object, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.readProjection = function(source) {
|
|
||||||
return this.readProjectionFromObject(getObject(source));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {Object} object Object.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.readProjectionFromObject = function(object) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.writeFeature = function(feature, opt_options) {
|
|
||||||
return JSON.stringify(this.writeFeatureObject(feature, opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {module:ol/Feature} feature Feature.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {Object} Object.
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.writeFeatureObject = function(feature, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.writeFeatures = function(features, opt_options) {
|
|
||||||
return JSON.stringify(this.writeFeaturesObject(features, opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {Object} Object.
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.writeFeaturesObject = function(features, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.writeGeometry = function(geometry, opt_options) {
|
|
||||||
return JSON.stringify(this.writeGeometryObject(geometry, opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {Object} Object.
|
|
||||||
*/
|
|
||||||
JSONFeature.prototype.writeGeometryObject = function(geometry, opt_options) {};
|
|
||||||
export default JSONFeature;
|
export default JSONFeature;
|
||||||
|
|||||||
1225
src/ol/format/KML.js
1225
src/ol/format/KML.js
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
//FIXME Implement projection handling
|
//FIXME Implement projection handling
|
||||||
|
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {assert} from '../asserts.js';
|
import {assert} from '../asserts.js';
|
||||||
import PBF from 'pbf';
|
import PBF from 'pbf';
|
||||||
import FeatureFormat, {transformWithOptions} from '../format/Feature.js';
|
import FeatureFormat, {transformWithOptions} from '../format/Feature.js';
|
||||||
@@ -42,61 +41,282 @@ import RenderFeature from '../render/Feature.js';
|
|||||||
* @classdesc
|
* @classdesc
|
||||||
* Feature format for reading data in the Mapbox MVT format.
|
* Feature format for reading data in the Mapbox MVT format.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/Feature}
|
|
||||||
* @param {module:ol/format/MVT~Options=} opt_options Options.
|
* @param {module:ol/format/MVT~Options=} opt_options Options.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const MVT = function(opt_options) {
|
class MVT extends FeatureFormat {
|
||||||
|
|
||||||
FeatureFormat.call(this);
|
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {module:ol/proj/Projection}
|
* @param {module:ol/format/MVT~Options=} opt_options Options.
|
||||||
*/
|
*/
|
||||||
this.dataProjection = new Projection({
|
constructor(opt_options) {
|
||||||
code: '',
|
super();
|
||||||
units: Units.TILE_PIXELS
|
|
||||||
});
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {module:ol/proj/Projection}
|
||||||
|
*/
|
||||||
|
this.dataProjection = new Projection({
|
||||||
|
code: '',
|
||||||
|
units: Units.TILE_PIXELS
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {function((module:ol/geom/Geometry|Object.<string,*>)=)|
|
||||||
|
* function(module:ol/geom/GeometryType,Array.<number>,
|
||||||
|
* (Array.<number>|Array.<Array.<number>>),Object.<string,*>,number)}
|
||||||
|
*/
|
||||||
|
this.featureClass_ = options.featureClass ?
|
||||||
|
options.featureClass : RenderFeature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string|undefined}
|
||||||
|
*/
|
||||||
|
this.geometryName_ = options.geometryName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.layerName_ = options.layerName ? options.layerName : 'layer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Array.<string>}
|
||||||
|
*/
|
||||||
|
this.layers_ = options.layers ? options.layers : null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/extent~Extent}
|
||||||
|
*/
|
||||||
|
this.extent_ = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the raw geometry from the pbf offset stored in a raw feature's geometry
|
||||||
|
* property.
|
||||||
|
* @suppress {missingProperties}
|
||||||
|
* @param {Object} pbf PBF.
|
||||||
|
* @param {Object} feature Raw feature.
|
||||||
|
* @param {Array.<number>} flatCoordinates Array to store flat coordinates in.
|
||||||
|
* @param {Array.<number>} ends Array to store ends in.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
readRawGeometry_(pbf, feature, flatCoordinates, ends) {
|
||||||
|
pbf.pos = feature.geometry;
|
||||||
|
|
||||||
|
const end = pbf.readVarint() + pbf.pos;
|
||||||
|
let cmd = 1;
|
||||||
|
let length = 0;
|
||||||
|
let x = 0;
|
||||||
|
let y = 0;
|
||||||
|
let coordsLen = 0;
|
||||||
|
let currentEnd = 0;
|
||||||
|
|
||||||
|
while (pbf.pos < end) {
|
||||||
|
if (!length) {
|
||||||
|
const cmdLen = pbf.readVarint();
|
||||||
|
cmd = cmdLen & 0x7;
|
||||||
|
length = cmdLen >> 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
length--;
|
||||||
|
|
||||||
|
if (cmd === 1 || cmd === 2) {
|
||||||
|
x += pbf.readSVarint();
|
||||||
|
y += pbf.readSVarint();
|
||||||
|
|
||||||
|
if (cmd === 1) { // moveTo
|
||||||
|
if (coordsLen > currentEnd) {
|
||||||
|
ends.push(coordsLen);
|
||||||
|
currentEnd = coordsLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flatCoordinates.push(x, y);
|
||||||
|
coordsLen += 2;
|
||||||
|
|
||||||
|
} else if (cmd === 7) {
|
||||||
|
|
||||||
|
if (coordsLen > currentEnd) {
|
||||||
|
// close polygon
|
||||||
|
flatCoordinates.push(
|
||||||
|
flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]);
|
||||||
|
coordsLen += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
assert(false, 59); // Invalid command found in the PBF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coordsLen > currentEnd) {
|
||||||
|
ends.push(coordsLen);
|
||||||
|
currentEnd = coordsLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {function((module:ol/geom/Geometry|Object.<string,*>)=)|
|
* @param {Object} pbf PBF
|
||||||
* function(module:ol/geom/GeometryType,Array.<number>,
|
* @param {Object} rawFeature Raw Mapbox feature.
|
||||||
* (Array.<number>|Array.<Array.<number>>),Object.<string,*>,number)}
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {module:ol/Feature|module:ol/render/Feature} Feature.
|
||||||
*/
|
*/
|
||||||
this.featureClass_ = options.featureClass ?
|
createFeature_(pbf, rawFeature, opt_options) {
|
||||||
options.featureClass : RenderFeature;
|
const type = rawFeature.type;
|
||||||
|
if (type === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let feature;
|
||||||
|
const id = rawFeature.id;
|
||||||
|
const values = rawFeature.properties;
|
||||||
|
values[this.layerName_] = rawFeature.layer.name;
|
||||||
|
|
||||||
|
const flatCoordinates = [];
|
||||||
|
const ends = [];
|
||||||
|
this.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);
|
||||||
|
|
||||||
|
const geometryType = getGeometryType(type, ends.length);
|
||||||
|
|
||||||
|
if (this.featureClass_ === RenderFeature) {
|
||||||
|
feature = new this.featureClass_(geometryType, flatCoordinates, ends, values, id);
|
||||||
|
} else {
|
||||||
|
let geom;
|
||||||
|
if (geometryType == GeometryType.POLYGON) {
|
||||||
|
const endss = [];
|
||||||
|
let offset = 0;
|
||||||
|
let prevEndIndex = 0;
|
||||||
|
for (let i = 0, ii = ends.length; i < ii; ++i) {
|
||||||
|
const end = ends[i];
|
||||||
|
if (!linearRingIsClockwise(flatCoordinates, offset, end, 2)) {
|
||||||
|
endss.push(ends.slice(prevEndIndex, i));
|
||||||
|
prevEndIndex = i;
|
||||||
|
}
|
||||||
|
offset = end;
|
||||||
|
}
|
||||||
|
if (endss.length > 1) {
|
||||||
|
geom = new MultiPolygon(flatCoordinates, GeometryLayout.XY, endss);
|
||||||
|
} else {
|
||||||
|
geom = new Polygon(flatCoordinates, GeometryLayout.XY, ends);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
geom = geometryType === GeometryType.POINT ? new Point(flatCoordinates, GeometryLayout.XY) :
|
||||||
|
geometryType === GeometryType.LINE_STRING ? new LineString(flatCoordinates, GeometryLayout.XY) :
|
||||||
|
geometryType === GeometryType.POLYGON ? new Polygon(flatCoordinates, GeometryLayout.XY, ends) :
|
||||||
|
geometryType === GeometryType.MULTI_POINT ? new MultiPoint(flatCoordinates, GeometryLayout.XY) :
|
||||||
|
geometryType === GeometryType.MULTI_LINE_STRING ? new MultiLineString(flatCoordinates, GeometryLayout.XY, ends) :
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
feature = new this.featureClass_();
|
||||||
|
if (this.geometryName_) {
|
||||||
|
feature.setGeometryName(this.geometryName_);
|
||||||
|
}
|
||||||
|
const geometry = transformWithOptions(geom, false, this.adaptOptions(opt_options));
|
||||||
|
feature.setGeometry(geometry);
|
||||||
|
feature.setId(id);
|
||||||
|
feature.setProperties(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @inheritDoc
|
||||||
* @type {string|undefined}
|
* @api
|
||||||
*/
|
*/
|
||||||
this.geometryName_ = options.geometryName;
|
getLastExtent() {
|
||||||
|
return this.extent_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @inheritDoc
|
||||||
* @type {string}
|
|
||||||
*/
|
*/
|
||||||
this.layerName_ = options.layerName ? options.layerName : 'layer';
|
getType() {
|
||||||
|
return FormatType.ARRAY_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @inheritDoc
|
||||||
* @type {Array.<string>}
|
* @api
|
||||||
*/
|
*/
|
||||||
this.layers_ = options.layers ? options.layers : null;
|
readFeatures(source, opt_options) {
|
||||||
|
const layers = this.layers_;
|
||||||
|
|
||||||
|
const pbf = new PBF(/** @type {ArrayBuffer} */ (source));
|
||||||
|
const pbfLayers = pbf.readFields(layersPBFReader, {});
|
||||||
|
/** @type {Array.<module:ol/Feature|module:ol/render/Feature>} */
|
||||||
|
const features = [];
|
||||||
|
for (const name in pbfLayers) {
|
||||||
|
if (layers && layers.indexOf(name) == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const pbfLayer = pbfLayers[name];
|
||||||
|
|
||||||
|
for (let i = 0, ii = pbfLayer.length; i < ii; ++i) {
|
||||||
|
const rawFeature = readRawFeature(pbf, pbfLayer, i);
|
||||||
|
features.push(this.createFeature_(pbf, rawFeature));
|
||||||
|
}
|
||||||
|
this.extent_ = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @inheritDoc
|
||||||
* @type {module:ol/extent~Extent}
|
* @api
|
||||||
*/
|
*/
|
||||||
this.extent_ = null;
|
readProjection(source) {
|
||||||
|
return this.dataProjection;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* Sets the layers that features will be read from.
|
||||||
|
* @param {Array.<string>} layers Layers.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
setLayers(layers) {
|
||||||
|
this.layers_ = layers;
|
||||||
|
}
|
||||||
|
|
||||||
inherits(MVT, FeatureFormat);
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
readFeature() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
readGeometry() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
writeFeature() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
writeGeometry() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
writeFeatures() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -201,72 +421,6 @@ function readRawFeature(pbf, layer, i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the raw geometry from the pbf offset stored in a raw feature's geometry
|
|
||||||
* property.
|
|
||||||
* @suppress {missingProperties}
|
|
||||||
* @param {Object} pbf PBF.
|
|
||||||
* @param {Object} feature Raw feature.
|
|
||||||
* @param {Array.<number>} flatCoordinates Array to store flat coordinates in.
|
|
||||||
* @param {Array.<number>} ends Array to store ends in.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
MVT.prototype.readRawGeometry_ = function(pbf, feature, flatCoordinates, ends) {
|
|
||||||
pbf.pos = feature.geometry;
|
|
||||||
|
|
||||||
const end = pbf.readVarint() + pbf.pos;
|
|
||||||
let cmd = 1;
|
|
||||||
let length = 0;
|
|
||||||
let x = 0;
|
|
||||||
let y = 0;
|
|
||||||
let coordsLen = 0;
|
|
||||||
let currentEnd = 0;
|
|
||||||
|
|
||||||
while (pbf.pos < end) {
|
|
||||||
if (!length) {
|
|
||||||
const cmdLen = pbf.readVarint();
|
|
||||||
cmd = cmdLen & 0x7;
|
|
||||||
length = cmdLen >> 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
length--;
|
|
||||||
|
|
||||||
if (cmd === 1 || cmd === 2) {
|
|
||||||
x += pbf.readSVarint();
|
|
||||||
y += pbf.readSVarint();
|
|
||||||
|
|
||||||
if (cmd === 1) { // moveTo
|
|
||||||
if (coordsLen > currentEnd) {
|
|
||||||
ends.push(coordsLen);
|
|
||||||
currentEnd = coordsLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flatCoordinates.push(x, y);
|
|
||||||
coordsLen += 2;
|
|
||||||
|
|
||||||
} else if (cmd === 7) {
|
|
||||||
|
|
||||||
if (coordsLen > currentEnd) {
|
|
||||||
// close polygon
|
|
||||||
flatCoordinates.push(
|
|
||||||
flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]);
|
|
||||||
coordsLen += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
assert(false, 59); // Invalid command found in the PBF
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (coordsLen > currentEnd) {
|
|
||||||
ends.push(coordsLen);
|
|
||||||
currentEnd = coordsLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @suppress {missingProperties}
|
* @suppress {missingProperties}
|
||||||
* @param {number} type The raw feature's geometry type
|
* @param {number} type The raw feature's geometry type
|
||||||
@@ -292,170 +446,4 @@ function getGeometryType(type, numEnds) {
|
|||||||
return geometryType;
|
return geometryType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param {Object} pbf PBF
|
|
||||||
* @param {Object} rawFeature Raw Mapbox feature.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/Feature|module:ol/render/Feature} Feature.
|
|
||||||
*/
|
|
||||||
MVT.prototype.createFeature_ = function(pbf, rawFeature, opt_options) {
|
|
||||||
const type = rawFeature.type;
|
|
||||||
if (type === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let feature;
|
|
||||||
const id = rawFeature.id;
|
|
||||||
const values = rawFeature.properties;
|
|
||||||
values[this.layerName_] = rawFeature.layer.name;
|
|
||||||
|
|
||||||
const flatCoordinates = [];
|
|
||||||
let ends = [];
|
|
||||||
this.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);
|
|
||||||
|
|
||||||
const geometryType = getGeometryType(type, ends.length);
|
|
||||||
|
|
||||||
if (this.featureClass_ === RenderFeature) {
|
|
||||||
feature = new this.featureClass_(geometryType, flatCoordinates, ends, values, id);
|
|
||||||
} else {
|
|
||||||
let geom;
|
|
||||||
if (geometryType == GeometryType.POLYGON) {
|
|
||||||
const endss = [];
|
|
||||||
let offset = 0;
|
|
||||||
let prevEndIndex = 0;
|
|
||||||
for (let i = 0, ii = ends.length; i < ii; ++i) {
|
|
||||||
const end = ends[i];
|
|
||||||
if (!linearRingIsClockwise(flatCoordinates, offset, end, 2)) {
|
|
||||||
endss.push(ends.slice(prevEndIndex, i));
|
|
||||||
prevEndIndex = i;
|
|
||||||
}
|
|
||||||
offset = end;
|
|
||||||
}
|
|
||||||
if (endss.length > 1) {
|
|
||||||
ends = endss;
|
|
||||||
geom = new MultiPolygon(null);
|
|
||||||
} else {
|
|
||||||
geom = new Polygon(null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
geom = geometryType === GeometryType.POINT ? new Point(null) :
|
|
||||||
geometryType === GeometryType.LINE_STRING ? new LineString(null) :
|
|
||||||
geometryType === GeometryType.POLYGON ? new Polygon(null) :
|
|
||||||
geometryType === GeometryType.MULTI_POINT ? new MultiPoint (null) :
|
|
||||||
geometryType === GeometryType.MULTI_LINE_STRING ? new MultiLineString(null) :
|
|
||||||
null;
|
|
||||||
}
|
|
||||||
geom.setFlatCoordinates(GeometryLayout.XY, flatCoordinates, ends);
|
|
||||||
feature = new this.featureClass_();
|
|
||||||
if (this.geometryName_) {
|
|
||||||
feature.setGeometryName(this.geometryName_);
|
|
||||||
}
|
|
||||||
const geometry = transformWithOptions(geom, false, this.adaptOptions(opt_options));
|
|
||||||
feature.setGeometry(geometry);
|
|
||||||
feature.setId(id);
|
|
||||||
feature.setProperties(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
return feature;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MVT.prototype.getLastExtent = function() {
|
|
||||||
return this.extent_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
MVT.prototype.getType = function() {
|
|
||||||
return FormatType.ARRAY_BUFFER;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MVT.prototype.readFeatures = function(source, opt_options) {
|
|
||||||
const layers = this.layers_;
|
|
||||||
|
|
||||||
const pbf = new PBF(/** @type {ArrayBuffer} */ (source));
|
|
||||||
const pbfLayers = pbf.readFields(layersPBFReader, {});
|
|
||||||
/** @type {Array.<module:ol/Feature|module:ol/render/Feature>} */
|
|
||||||
const features = [];
|
|
||||||
for (const name in pbfLayers) {
|
|
||||||
if (layers && layers.indexOf(name) == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const pbfLayer = pbfLayers[name];
|
|
||||||
|
|
||||||
for (let i = 0, ii = pbfLayer.length; i < ii; ++i) {
|
|
||||||
const rawFeature = readRawFeature(pbf, pbfLayer, i);
|
|
||||||
features.push(this.createFeature_(pbf, rawFeature));
|
|
||||||
}
|
|
||||||
this.extent_ = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return features;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MVT.prototype.readProjection = function(source) {
|
|
||||||
return this.dataProjection;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the layers that features will be read from.
|
|
||||||
* @param {Array.<string>} layers Layers.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
MVT.prototype.setLayers = function(layers) {
|
|
||||||
this.layers_ = layers;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
MVT.prototype.readFeature = function() {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
MVT.prototype.readGeometry = function() {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
MVT.prototype.writeFeature = function() {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
MVT.prototype.writeGeometry = function() {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
MVT.prototype.writeFeatures = function() {};
|
|
||||||
export default MVT;
|
export default MVT;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* @module ol/format/OSMXML
|
* @module ol/format/OSMXML
|
||||||
*/
|
*/
|
||||||
// FIXME add typedef for stack state objects
|
// FIXME add typedef for stack state objects
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {extend} from '../array.js';
|
import {extend} from '../array.js';
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
import {transformWithOptions} from '../format/Feature.js';
|
import {transformWithOptions} from '../format/Feature.js';
|
||||||
@@ -15,26 +14,6 @@ import {isEmpty} from '../obj.js';
|
|||||||
import {get as getProjection} from '../proj.js';
|
import {get as getProjection} from '../proj.js';
|
||||||
import {pushParseAndPop, makeStructureNS} from '../xml.js';
|
import {pushParseAndPop, makeStructureNS} from '../xml.js';
|
||||||
|
|
||||||
/**
|
|
||||||
* @classdesc
|
|
||||||
* Feature format for reading data in the
|
|
||||||
* [OSMXML format](http://wiki.openstreetmap.org/wiki/OSM_XML).
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/XMLFeature}
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
const OSMXML = function() {
|
|
||||||
XMLFeature.call(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
this.dataProjection = getProjection('EPSG:4326');
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(OSMXML, XMLFeature);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
@@ -65,6 +44,83 @@ const PARSERS = makeStructureNS(
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* Feature format for reading data in the
|
||||||
|
* [OSMXML format](http://wiki.openstreetmap.org/wiki/OSM_XML).
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
class OSMXML extends XMLFeature {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
this.dataProjection = getProjection('EPSG:4326');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeaturesFromNode(node, opt_options) {
|
||||||
|
const options = this.getReadOptions(node, opt_options);
|
||||||
|
if (node.localName == 'osm') {
|
||||||
|
const state = pushParseAndPop({
|
||||||
|
nodes: {},
|
||||||
|
ways: [],
|
||||||
|
features: []
|
||||||
|
}, PARSERS, node, [options]);
|
||||||
|
// parse nodes in ways
|
||||||
|
for (let j = 0; j < state.ways.length; j++) {
|
||||||
|
const values = /** @type {Object} */ (state.ways[j]);
|
||||||
|
/** @type {Array.<number>} */
|
||||||
|
const flatCoordinates = [];
|
||||||
|
for (let i = 0, ii = values.ndrefs.length; i < ii; i++) {
|
||||||
|
const point = state.nodes[values.ndrefs[i]];
|
||||||
|
extend(flatCoordinates, point);
|
||||||
|
}
|
||||||
|
let geometry;
|
||||||
|
if (values.ndrefs[0] == values.ndrefs[values.ndrefs.length - 1]) {
|
||||||
|
// closed way
|
||||||
|
geometry = new Polygon(flatCoordinates, GeometryLayout.XY, [flatCoordinates.length]);
|
||||||
|
} else {
|
||||||
|
geometry = new LineString(flatCoordinates, GeometryLayout.XY);
|
||||||
|
}
|
||||||
|
transformWithOptions(geometry, false, options);
|
||||||
|
const feature = new Feature(geometry);
|
||||||
|
feature.setId(values.id);
|
||||||
|
feature.setProperties(values.tags);
|
||||||
|
state.features.push(feature);
|
||||||
|
}
|
||||||
|
if (state.features) {
|
||||||
|
return state.features;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeatureNode(feature, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeaturesNode(features, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeGeometryNode(geometry, opt_options) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
||||||
@@ -140,90 +196,4 @@ function readTag(node, objectStack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all features from an OSM source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
OSMXML.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
OSMXML.prototype.readFeaturesFromNode = function(node, opt_options) {
|
|
||||||
const options = this.getReadOptions(node, opt_options);
|
|
||||||
if (node.localName == 'osm') {
|
|
||||||
const state = pushParseAndPop({
|
|
||||||
nodes: {},
|
|
||||||
ways: [],
|
|
||||||
features: []
|
|
||||||
}, PARSERS, node, [options]);
|
|
||||||
// parse nodes in ways
|
|
||||||
for (let j = 0; j < state.ways.length; j++) {
|
|
||||||
const values = /** @type {Object} */ (state.ways[j]);
|
|
||||||
/** @type {Array.<number>} */
|
|
||||||
const flatCoordinates = [];
|
|
||||||
for (let i = 0, ii = values.ndrefs.length; i < ii; i++) {
|
|
||||||
const point = state.nodes[values.ndrefs[i]];
|
|
||||||
extend(flatCoordinates, point);
|
|
||||||
}
|
|
||||||
let geometry;
|
|
||||||
if (values.ndrefs[0] == values.ndrefs[values.ndrefs.length - 1]) {
|
|
||||||
// closed way
|
|
||||||
geometry = new Polygon(null);
|
|
||||||
geometry.setFlatCoordinates(GeometryLayout.XY, flatCoordinates,
|
|
||||||
[flatCoordinates.length]);
|
|
||||||
} else {
|
|
||||||
geometry = new LineString(null);
|
|
||||||
geometry.setFlatCoordinates(GeometryLayout.XY, flatCoordinates);
|
|
||||||
}
|
|
||||||
transformWithOptions(geometry, false, options);
|
|
||||||
const feature = new Feature(geometry);
|
|
||||||
feature.setId(values.id);
|
|
||||||
feature.setProperties(values.tags);
|
|
||||||
state.features.push(feature);
|
|
||||||
}
|
|
||||||
if (state.features) {
|
|
||||||
return state.features;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from an OSM source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
OSMXML.prototype.readProjection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
OSMXML.prototype.writeFeatureNode = function(feature, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
OSMXML.prototype.writeFeaturesNode = function(features, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
OSMXML.prototype.writeGeometryNode = function(geometry, opt_options) {};
|
|
||||||
export default OSMXML;
|
export default OSMXML;
|
||||||
|
|||||||
@@ -1,22 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/OWS
|
* @module ol/format/OWS
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {readHref} from '../format/XLink.js';
|
import {readHref} from '../format/XLink.js';
|
||||||
import XML from '../format/XML.js';
|
import XML from '../format/XML.js';
|
||||||
import {readString} from '../format/xsd.js';
|
import {readString} from '../format/xsd.js';
|
||||||
import {makeObjectPropertyPusher, makeObjectPropertySetter, makeStructureNS, pushParseAndPop} from '../xml.js';
|
import {makeObjectPropertyPusher, makeObjectPropertySetter, makeStructureNS, pushParseAndPop} from '../xml.js';
|
||||||
|
|
||||||
/**
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/XML}
|
|
||||||
*/
|
|
||||||
const OWS = function() {
|
|
||||||
XML.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(OWS, XML);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
@@ -37,6 +26,34 @@ const PARSERS = makeStructureNS(
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
class OWS extends XML {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFromDocument(doc) {
|
||||||
|
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||||
|
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||||
|
return this.readFromNode(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFromNode(node) {
|
||||||
|
const owsObject = pushParseAndPop({},
|
||||||
|
PARSERS, node, []);
|
||||||
|
return owsObject ? owsObject : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
||||||
@@ -187,29 +204,6 @@ const SERVICE_PROVIDER_PARSERS =
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
OWS.prototype.readFromDocument = function(doc) {
|
|
||||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
|
||||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
|
||||||
return this.readFromNode(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
OWS.prototype.readFromNode = function(node) {
|
|
||||||
const owsObject = pushParseAndPop({},
|
|
||||||
PARSERS, node, []);
|
|
||||||
return owsObject ? owsObject : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/Polyline
|
* @module ol/format/Polyline
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {assert} from '../asserts.js';
|
import {assert} from '../asserts.js';
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
import {transformWithOptions} from '../format/Feature.js';
|
import {transformWithOptions} from '../format/Feature.js';
|
||||||
@@ -27,37 +26,111 @@ import {get as getProjection} from '../proj.js';
|
|||||||
* Feature format for reading and writing data in the Encoded
|
* Feature format for reading and writing data in the Encoded
|
||||||
* Polyline Algorithm Format.
|
* Polyline Algorithm Format.
|
||||||
*
|
*
|
||||||
* @constructor
|
* When reading features, the coordinates are assumed to be in two dimensions
|
||||||
* @extends {module:ol/format/TextFeature}
|
* and in [latitude, longitude] order.
|
||||||
* @param {module:ol/format/Polyline~Options=} opt_options Optional configuration object.
|
*
|
||||||
|
* As Polyline sources contain a single feature,
|
||||||
|
* {@link module:ol/format/Polyline~Polyline#readFeatures} will return the
|
||||||
|
* feature in an array.
|
||||||
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Polyline = function(opt_options) {
|
class Polyline extends TextFeature {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
/**
|
||||||
|
* @param {module:ol/format/Polyline~Options=} opt_options Optional configuration object.
|
||||||
|
*/
|
||||||
|
constructor(opt_options) {
|
||||||
|
super();
|
||||||
|
|
||||||
TextFeature.call(this);
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
this.dataProjection = getProjection('EPSG:4326');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.factor_ = options.factor ? options.factor : 1e5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {module:ol/geom/GeometryLayout}
|
||||||
|
*/
|
||||||
|
this.geometryLayout_ = options.geometryLayout ?
|
||||||
|
options.geometryLayout : GeometryLayout.XY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
this.dataProjection = getProjection('EPSG:4326');
|
readFeatureFromText(text, opt_options) {
|
||||||
|
const geometry = this.readGeometryFromText(text, opt_options);
|
||||||
|
return new Feature(geometry);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @inheritDoc
|
||||||
* @type {number}
|
|
||||||
*/
|
*/
|
||||||
this.factor_ = options.factor ? options.factor : 1e5;
|
readFeaturesFromText(text, opt_options) {
|
||||||
|
const feature = this.readFeatureFromText(text, opt_options);
|
||||||
|
return [feature];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @inheritDoc
|
||||||
* @type {module:ol/geom/GeometryLayout}
|
|
||||||
*/
|
*/
|
||||||
this.geometryLayout_ = options.geometryLayout ?
|
readGeometryFromText(text, opt_options) {
|
||||||
options.geometryLayout : GeometryLayout.XY;
|
const stride = getStrideForLayout(this.geometryLayout_);
|
||||||
};
|
const flatCoordinates = decodeDeltas(text, stride, this.factor_);
|
||||||
|
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
|
||||||
|
const coordinates = inflateCoordinates(flatCoordinates, 0, flatCoordinates.length, stride);
|
||||||
|
|
||||||
inherits(Polyline, TextFeature);
|
return (
|
||||||
|
/** @type {module:ol/geom/Geometry} */ (transformWithOptions(
|
||||||
|
new LineString(coordinates, this.geometryLayout_),
|
||||||
|
false,
|
||||||
|
this.adaptOptions(opt_options)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeatureText(feature, opt_options) {
|
||||||
|
const geometry = feature.getGeometry();
|
||||||
|
if (geometry) {
|
||||||
|
return this.writeGeometryText(geometry, opt_options);
|
||||||
|
} else {
|
||||||
|
assert(false, 40); // Expected `feature` to have a geometry
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeaturesText(features, opt_options) {
|
||||||
|
return this.writeFeatureText(features[0], opt_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeGeometryText(geometry, opt_options) {
|
||||||
|
geometry = /** @type {module:ol/geom/LineString} */
|
||||||
|
(transformWithOptions(geometry, true, this.adaptOptions(opt_options)));
|
||||||
|
const flatCoordinates = geometry.getFlatCoordinates();
|
||||||
|
const stride = geometry.getStride();
|
||||||
|
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
|
||||||
|
return encodeDeltas(flatCoordinates, stride, this.factor_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -264,135 +337,4 @@ export function encodeUnsignedInteger(num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the feature from the Polyline source. The coordinates are assumed to be
|
|
||||||
* in two dimensions and in latitude, longitude order.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Polyline.prototype.readFeature;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
Polyline.prototype.readFeatureFromText = function(text, opt_options) {
|
|
||||||
const geometry = this.readGeometryFromText(text, opt_options);
|
|
||||||
return new Feature(geometry);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the feature from the source. As Polyline sources contain a single
|
|
||||||
* feature, this will return the feature in an array.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Polyline.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
Polyline.prototype.readFeaturesFromText = function(text, opt_options) {
|
|
||||||
const feature = this.readFeatureFromText(text, opt_options);
|
|
||||||
return [feature];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the geometry from the source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {module:ol/geom/Geometry} Geometry.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Polyline.prototype.readGeometry;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
Polyline.prototype.readGeometryFromText = function(text, opt_options) {
|
|
||||||
const stride = getStrideForLayout(this.geometryLayout_);
|
|
||||||
const flatCoordinates = decodeDeltas(text, stride, this.factor_);
|
|
||||||
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
|
|
||||||
const coordinates = inflateCoordinates(flatCoordinates, 0, flatCoordinates.length, stride);
|
|
||||||
|
|
||||||
return (
|
|
||||||
/** @type {module:ol/geom/Geometry} */ (transformWithOptions(
|
|
||||||
new LineString(coordinates, this.geometryLayout_),
|
|
||||||
false,
|
|
||||||
this.adaptOptions(opt_options)
|
|
||||||
))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from a Polyline source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Polyline.prototype.readProjection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
Polyline.prototype.writeFeatureText = function(feature, opt_options) {
|
|
||||||
const geometry = feature.getGeometry();
|
|
||||||
if (geometry) {
|
|
||||||
return this.writeGeometryText(geometry, opt_options);
|
|
||||||
} else {
|
|
||||||
assert(false, 40); // Expected `feature` to have a geometry
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
Polyline.prototype.writeFeaturesText = function(features, opt_options) {
|
|
||||||
return this.writeFeatureText(features[0], opt_options);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a single geometry in Polyline format.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @return {string} Geometry.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
Polyline.prototype.writeGeometry;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
Polyline.prototype.writeGeometryText = function(geometry, opt_options) {
|
|
||||||
geometry = /** @type {module:ol/geom/LineString} */
|
|
||||||
(transformWithOptions(geometry, true, this.adaptOptions(opt_options)));
|
|
||||||
const flatCoordinates = geometry.getFlatCoordinates();
|
|
||||||
const stride = geometry.getStride();
|
|
||||||
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
|
|
||||||
return encodeDeltas(flatCoordinates, stride, this.factor_);
|
|
||||||
};
|
|
||||||
export default Polyline;
|
export default Polyline;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/TextFeature
|
* @module ol/format/TextFeature
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import FeatureFormat from '../format/Feature.js';
|
import FeatureFormat from '../format/Feature.js';
|
||||||
import FormatType from '../format/FormatType.js';
|
import FormatType from '../format/FormatType.js';
|
||||||
|
|
||||||
@@ -11,15 +10,169 @@ import FormatType from '../format/FormatType.js';
|
|||||||
* instantiated in apps.
|
* instantiated in apps.
|
||||||
* Base class for text feature formats.
|
* Base class for text feature formats.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @extends {module:ol/format/Feature}
|
|
||||||
*/
|
*/
|
||||||
const TextFeature = function() {
|
class TextFeature extends FeatureFormat {
|
||||||
FeatureFormat.call(this);
|
constructor() {
|
||||||
};
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
inherits(TextFeature, FeatureFormat);
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
getType() {
|
||||||
|
return FormatType.TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the feature from the source.
|
||||||
|
*
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {module:ol/Feature} Feature.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readFeature(source, opt_options) {
|
||||||
|
return this.readFeatureFromText(getText(source), this.adaptOptions(opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {string} text Text.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/Feature} Feature.
|
||||||
|
*/
|
||||||
|
readFeatureFromText(text, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the features from the source.
|
||||||
|
*
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readFeatures(source, opt_options) {
|
||||||
|
return this.readFeaturesFromText(getText(source), this.adaptOptions(opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {string} text Text.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @protected
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
*/
|
||||||
|
readFeaturesFromText(text, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the geometry from the source.
|
||||||
|
*
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @return {module:ol/geom/Geometry} Geometry.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readGeometry(source, opt_options) {
|
||||||
|
return this.readGeometryFromText(getText(source), this.adaptOptions(opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {string} text Text.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/geom/Geometry} Geometry.
|
||||||
|
*/
|
||||||
|
readGeometryFromText(text, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the projection from the source.
|
||||||
|
*
|
||||||
|
* @function
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @return {module:ol/proj/Projection} Projection.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readProjection(source) {
|
||||||
|
return this.readProjectionFromText(getText(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} text Text.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/proj/Projection} Projection.
|
||||||
|
*/
|
||||||
|
readProjectionFromText(text) {
|
||||||
|
return this.dataProjection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a feature as a string.
|
||||||
|
*
|
||||||
|
* @function
|
||||||
|
* @param {module:ol/Feature} feature Feature.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {string} Encoded feature.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeature(feature, opt_options) {
|
||||||
|
return this.writeFeatureText(feature, this.adaptOptions(opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {module:ol/Feature} feature Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @protected
|
||||||
|
* @return {string} Text.
|
||||||
|
*/
|
||||||
|
writeFeatureText(feature, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode an array of features as string.
|
||||||
|
*
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {string} Encoded features.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeatures(features, opt_options) {
|
||||||
|
return this.writeFeaturesText(features, this.adaptOptions(opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @protected
|
||||||
|
* @return {string} Text.
|
||||||
|
*/
|
||||||
|
writeFeaturesText(features, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a single geometry.
|
||||||
|
*
|
||||||
|
* @function
|
||||||
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {string} Geometry.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeGeometry(geometry, opt_options) {
|
||||||
|
return this.writeGeometryText(geometry, this.adaptOptions(opt_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @protected
|
||||||
|
* @return {string} Text.
|
||||||
|
*/
|
||||||
|
writeGeometryText(geometry, opt_options) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,136 +188,4 @@ function getText(source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.getType = function() {
|
|
||||||
return FormatType.TEXT;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.readFeature = function(source, opt_options) {
|
|
||||||
return this.readFeatureFromText(getText(source), this.adaptOptions(opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {string} text Text.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.readFeatureFromText = function(text, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.readFeatures = function(source, opt_options) {
|
|
||||||
return this.readFeaturesFromText(getText(source), this.adaptOptions(opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {string} text Text.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @protected
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.readFeaturesFromText = function(text, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.readGeometry = function(source, opt_options) {
|
|
||||||
return this.readGeometryFromText(getText(source), this.adaptOptions(opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {string} text Text.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/geom/Geometry} Geometry.
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.readGeometryFromText = function(text, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.readProjection = function(source) {
|
|
||||||
return this.readProjectionFromText(getText(source));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} text Text.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.readProjectionFromText = function(text) {
|
|
||||||
return this.dataProjection;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.writeFeature = function(feature, opt_options) {
|
|
||||||
return this.writeFeatureText(feature, this.adaptOptions(opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {module:ol/Feature} feature Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @protected
|
|
||||||
* @return {string} Text.
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.writeFeatureText = function(feature, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.writeFeatures = function(features, opt_options) {
|
|
||||||
return this.writeFeaturesText(features, this.adaptOptions(opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @protected
|
|
||||||
* @return {string} Text.
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.writeFeaturesText = function(features, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.writeGeometry = function(geometry, opt_options) {
|
|
||||||
return this.writeGeometryText(geometry, this.adaptOptions(opt_options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
|
||||||
* @protected
|
|
||||||
* @return {string} Text.
|
|
||||||
*/
|
|
||||||
TextFeature.prototype.writeGeometryText = function(geometry, opt_options) {};
|
|
||||||
export default TextFeature;
|
export default TextFeature;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/TopoJSON
|
* @module ol/format/TopoJSON
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
import {transformWithOptions} from '../format/Feature.js';
|
import {transformWithOptions} from '../format/Feature.js';
|
||||||
import JSONFeature from '../format/JSONFeature.js';
|
import JSONFeature from '../format/JSONFeature.js';
|
||||||
@@ -43,39 +42,117 @@ import {get as getProjection} from '../proj.js';
|
|||||||
* @classdesc
|
* @classdesc
|
||||||
* Feature format for reading data in the TopoJSON format.
|
* Feature format for reading data in the TopoJSON format.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/JSONFeature}
|
|
||||||
* @param {module:ol/format/TopoJSON~Options=} opt_options Options.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const TopoJSON = function(opt_options) {
|
class TopoJSON extends JSONFeature {
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
JSONFeature.call(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {module:ol/format/TopoJSON~Options=} opt_options Options.
|
||||||
* @type {string|undefined}
|
|
||||||
*/
|
*/
|
||||||
this.layerName_ = options.layerName;
|
constructor(opt_options) {
|
||||||
|
super();
|
||||||
|
|
||||||
/**
|
const options = opt_options ? opt_options : {};
|
||||||
* @private
|
|
||||||
* @type {Array.<string>}
|
/**
|
||||||
*/
|
* @private
|
||||||
this.layers_ = options.layers ? options.layers : null;
|
* @type {string|undefined}
|
||||||
|
*/
|
||||||
|
this.layerName_ = options.layerName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Array.<string>}
|
||||||
|
*/
|
||||||
|
this.layers_ = options.layers ? options.layers : null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
this.dataProjection = getProjection(
|
||||||
|
options.dataProjection ?
|
||||||
|
options.dataProjection : 'EPSG:4326');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
this.dataProjection = getProjection(
|
readFeaturesFromObject(object, opt_options) {
|
||||||
options.dataProjection ?
|
if (object.type == 'Topology') {
|
||||||
options.dataProjection : 'EPSG:4326');
|
const topoJSONTopology = /** @type {TopoJSONTopology} */ (object);
|
||||||
|
let transform, scale = null, translate = null;
|
||||||
|
if (topoJSONTopology.transform) {
|
||||||
|
transform = topoJSONTopology.transform;
|
||||||
|
scale = transform.scale;
|
||||||
|
translate = transform.translate;
|
||||||
|
}
|
||||||
|
const arcs = topoJSONTopology.arcs;
|
||||||
|
if (transform) {
|
||||||
|
transformArcs(arcs, scale, translate);
|
||||||
|
}
|
||||||
|
/** @type {Array.<module:ol/Feature>} */
|
||||||
|
const features = [];
|
||||||
|
const topoJSONFeatures = topoJSONTopology.objects;
|
||||||
|
const property = this.layerName_;
|
||||||
|
let feature;
|
||||||
|
for (const objectName in topoJSONFeatures) {
|
||||||
|
if (this.layers_ && this.layers_.indexOf(objectName) == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (topoJSONFeatures[objectName].type === 'GeometryCollection') {
|
||||||
|
feature = /** @type {TopoJSONGeometryCollection} */ (topoJSONFeatures[objectName]);
|
||||||
|
features.push.apply(features, readFeaturesFromGeometryCollection(
|
||||||
|
feature, arcs, scale, translate, property, objectName, opt_options));
|
||||||
|
} else {
|
||||||
|
feature = /** @type {TopoJSONGeometry} */ (topoJSONFeatures[objectName]);
|
||||||
|
features.push(readFeatureFromGeometry(
|
||||||
|
feature, arcs, scale, translate, property, objectName, opt_options));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readProjectionFromObject(object) {
|
||||||
|
return this.dataProjection;
|
||||||
|
}
|
||||||
|
|
||||||
inherits(TopoJSON, JSONFeature);
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeatureObject(feature, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeaturesObject(features, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeGeometryObject(geometry, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
readGeometryFromObject() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
readFeatureFromObject() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -298,59 +375,6 @@ function readFeatureFromGeometry(object, arcs, scale, translate, property, name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all features from a TopoJSON source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.readFeaturesFromObject = function(object, opt_options) {
|
|
||||||
if (object.type == 'Topology') {
|
|
||||||
const topoJSONTopology = /** @type {TopoJSONTopology} */ (object);
|
|
||||||
let transform, scale = null, translate = null;
|
|
||||||
if (topoJSONTopology.transform) {
|
|
||||||
transform = topoJSONTopology.transform;
|
|
||||||
scale = transform.scale;
|
|
||||||
translate = transform.translate;
|
|
||||||
}
|
|
||||||
const arcs = topoJSONTopology.arcs;
|
|
||||||
if (transform) {
|
|
||||||
transformArcs(arcs, scale, translate);
|
|
||||||
}
|
|
||||||
/** @type {Array.<module:ol/Feature>} */
|
|
||||||
const features = [];
|
|
||||||
const topoJSONFeatures = topoJSONTopology.objects;
|
|
||||||
const property = this.layerName_;
|
|
||||||
let feature;
|
|
||||||
for (const objectName in topoJSONFeatures) {
|
|
||||||
if (this.layers_ && this.layers_.indexOf(objectName) == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (topoJSONFeatures[objectName].type === 'GeometryCollection') {
|
|
||||||
feature = /** @type {TopoJSONGeometryCollection} */ (topoJSONFeatures[objectName]);
|
|
||||||
features.push.apply(features, readFeaturesFromGeometryCollection(
|
|
||||||
feature, arcs, scale, translate, property, objectName, opt_options));
|
|
||||||
} else {
|
|
||||||
feature = /** @type {TopoJSONGeometry} */ (topoJSONFeatures[objectName]);
|
|
||||||
features.push(readFeatureFromGeometry(
|
|
||||||
feature, arcs, scale, translate, property, objectName, opt_options));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return features;
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a linear transform to array of arcs. The provided array of arcs is
|
* Apply a linear transform to array of arcs. The provided array of arcs is
|
||||||
* modified in place.
|
* modified in place.
|
||||||
@@ -401,56 +425,4 @@ function transformVertex(vertex, scale, translate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from a TopoJSON source.
|
|
||||||
*
|
|
||||||
* @param {Document|Node|Object|string} object Source.
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
* @override
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.readProjection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.readProjectionFromObject = function(object) {
|
|
||||||
return this.dataProjection;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.writeFeatureObject = function(feature, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.writeFeaturesObject = function(features, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.writeGeometryObject = function(geometry, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.readGeometryFromObject = function() {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
TopoJSON.prototype.readFeatureFromObject = function() {};
|
|
||||||
export default TopoJSON;
|
export default TopoJSON;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/WFS
|
* @module ol/format/WFS
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {assert} from '../asserts.js';
|
import {assert} from '../asserts.js';
|
||||||
import GML2 from '../format/GML2.js';
|
import GML2 from '../format/GML2.js';
|
||||||
import GML3 from '../format/GML3.js';
|
import GML3 from '../format/GML3.js';
|
||||||
@@ -17,6 +16,69 @@ import {createElementNS, isDocument, isNode, makeArrayPusher, makeChildAppender,
|
|||||||
pushParseAndPop, pushSerializeAndPop, XML_SCHEMA_INSTANCE_URI} from '../xml.js';
|
pushParseAndPop, pushSerializeAndPop, XML_SCHEMA_INSTANCE_URI} from '../xml.js';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
||||||
|
*/
|
||||||
|
const FEATURE_COLLECTION_PARSERS = {
|
||||||
|
'http://www.opengis.net/gml': {
|
||||||
|
'boundedBy': makeObjectPropertySetter(
|
||||||
|
GMLBase.prototype.readGeometryElement, 'bounds')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
||||||
|
*/
|
||||||
|
const TRANSACTION_SUMMARY_PARSERS = {
|
||||||
|
'http://www.opengis.net/wfs': {
|
||||||
|
'totalInserted': makeObjectPropertySetter(readNonNegativeInteger),
|
||||||
|
'totalUpdated': makeObjectPropertySetter(readNonNegativeInteger),
|
||||||
|
'totalDeleted': makeObjectPropertySetter(readNonNegativeInteger)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
||||||
|
*/
|
||||||
|
const TRANSACTION_RESPONSE_PARSERS = {
|
||||||
|
'http://www.opengis.net/wfs': {
|
||||||
|
'TransactionSummary': makeObjectPropertySetter(
|
||||||
|
readTransactionSummary, 'transactionSummary'),
|
||||||
|
'InsertResults': makeObjectPropertySetter(
|
||||||
|
readInsertResults, 'insertIds')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Object.<string, Object.<string, module:ol/xml~Serializer>>}
|
||||||
|
*/
|
||||||
|
const QUERY_SERIALIZERS = {
|
||||||
|
'http://www.opengis.net/wfs': {
|
||||||
|
'PropertyName': makeChildAppender(writeStringTextNode)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Object.<string, Object.<string, module:ol/xml~Serializer>>}
|
||||||
|
*/
|
||||||
|
const TRANSACTION_SERIALIZERS = {
|
||||||
|
'http://www.opengis.net/wfs': {
|
||||||
|
'Insert': makeChildAppender(writeFeature),
|
||||||
|
'Update': makeChildAppender(writeUpdate),
|
||||||
|
'Delete': makeChildAppender(writeDelete),
|
||||||
|
'Property': makeChildAppender(writeProperty),
|
||||||
|
'Native': makeChildAppender(writeNative)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {Object.<string, string>|string} [featureNS] The namespace URI used for features.
|
* @property {Object.<string, string>|string} [featureNS] The namespace URI used for features.
|
||||||
@@ -138,197 +200,340 @@ const DEFAULT_VERSION = '1.1.0';
|
|||||||
* as option if you want to read a WFS that contains GML2 (WFS 1.0.0).
|
* as option if you want to read a WFS that contains GML2 (WFS 1.0.0).
|
||||||
* Also see {@link module:ol/format/GMLBase~GMLBase} which is used by this format.
|
* Also see {@link module:ol/format/GMLBase~GMLBase} which is used by this format.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @param {module:ol/format/WFS~Options=} opt_options Optional configuration object.
|
|
||||||
* @extends {module:ol/format/XMLFeature}
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const WFS = function(opt_options) {
|
class WFS extends XMLFeature {
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @param {module:ol/format/WFS~Options=} opt_options Optional configuration object.
|
||||||
* @type {Array.<string>|string|undefined}
|
|
||||||
*/
|
*/
|
||||||
this.featureType_ = options.featureType;
|
constructor(opt_options) {
|
||||||
|
super();
|
||||||
|
|
||||||
/**
|
const options = opt_options ? opt_options : {};
|
||||||
* @private
|
|
||||||
* @type {Object.<string, string>|string|undefined}
|
|
||||||
*/
|
|
||||||
this.featureNS_ = options.featureNS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {module:ol/format/GMLBase}
|
* @type {Array.<string>|string|undefined}
|
||||||
*/
|
*/
|
||||||
this.gmlFormat_ = options.gmlFormat ?
|
this.featureType_ = options.featureType;
|
||||||
options.gmlFormat : new GML3();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {string}
|
* @type {Object.<string, string>|string|undefined}
|
||||||
*/
|
*/
|
||||||
this.schemaLocation_ = options.schemaLocation ?
|
this.featureNS_ = options.featureNS;
|
||||||
options.schemaLocation : SCHEMA_LOCATIONS[DEFAULT_VERSION];
|
|
||||||
|
|
||||||
XMLFeature.call(this);
|
/**
|
||||||
};
|
* @private
|
||||||
|
* @type {module:ol/format/GMLBase}
|
||||||
|
*/
|
||||||
|
this.gmlFormat_ = options.gmlFormat ?
|
||||||
|
options.gmlFormat : new GML3();
|
||||||
|
|
||||||
inherits(WFS, XMLFeature);
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
/**
|
*/
|
||||||
* @return {Array.<string>|string|undefined} featureType
|
this.schemaLocation_ = options.schemaLocation ?
|
||||||
*/
|
options.schemaLocation : SCHEMA_LOCATIONS[DEFAULT_VERSION];
|
||||||
WFS.prototype.getFeatureType = function() {
|
|
||||||
return this.featureType_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Array.<string>|string|undefined} featureType Feature type(s) to parse.
|
|
||||||
*/
|
|
||||||
WFS.prototype.setFeatureType = function(featureType) {
|
|
||||||
this.featureType_ = featureType;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all features from a WFS FeatureCollection.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
WFS.prototype.readFeatures;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WFS.prototype.readFeaturesFromNode = function(node, opt_options) {
|
|
||||||
const context = /** @type {module:ol/xml~NodeStackItem} */ ({
|
|
||||||
'featureType': this.featureType_,
|
|
||||||
'featureNS': this.featureNS_
|
|
||||||
});
|
|
||||||
assign(context, this.getReadOptions(node, opt_options ? opt_options : {}));
|
|
||||||
const objectStack = [context];
|
|
||||||
this.gmlFormat_.FEATURE_COLLECTION_PARSERS[GMLNS][
|
|
||||||
'featureMember'] =
|
|
||||||
makeArrayPusher(GMLBase.prototype.readFeaturesInternal);
|
|
||||||
let features = pushParseAndPop([],
|
|
||||||
this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node,
|
|
||||||
objectStack, this.gmlFormat_);
|
|
||||||
if (!features) {
|
|
||||||
features = [];
|
|
||||||
}
|
}
|
||||||
return features;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @return {Array.<string>|string|undefined} featureType
|
||||||
* Read transaction response of the source.
|
*/
|
||||||
*
|
getFeatureType() {
|
||||||
* @param {Document|Node|Object|string} source Source.
|
return this.featureType_;
|
||||||
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
WFS.prototype.readTransactionResponse = function(source) {
|
|
||||||
if (isDocument(source)) {
|
|
||||||
return this.readTransactionResponseFromDocument(
|
|
||||||
/** @type {Document} */ (source));
|
|
||||||
} else if (isNode(source)) {
|
|
||||||
return this.readTransactionResponseFromNode(/** @type {Node} */ (source));
|
|
||||||
} else if (typeof source === 'string') {
|
|
||||||
const doc = parse(source);
|
|
||||||
return this.readTransactionResponseFromDocument(doc);
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @param {Array.<string>|string|undefined} featureType Feature type(s) to parse.
|
||||||
* Read feature collection metadata of the source.
|
*/
|
||||||
*
|
setFeatureType(featureType) {
|
||||||
* @param {Document|Node|Object|string} source Source.
|
this.featureType_ = featureType;
|
||||||
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
|
|
||||||
* FeatureCollection metadata.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
WFS.prototype.readFeatureCollectionMetadata = function(source) {
|
|
||||||
if (isDocument(source)) {
|
|
||||||
return this.readFeatureCollectionMetadataFromDocument(
|
|
||||||
/** @type {Document} */ (source));
|
|
||||||
} else if (isNode(source)) {
|
|
||||||
return this.readFeatureCollectionMetadataFromNode(
|
|
||||||
/** @type {Node} */ (source));
|
|
||||||
} else if (typeof source === 'string') {
|
|
||||||
const doc = parse(source);
|
|
||||||
return this.readFeatureCollectionMetadataFromDocument(doc);
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeaturesFromNode(node, opt_options) {
|
||||||
|
const context = /** @type {module:ol/xml~NodeStackItem} */ ({
|
||||||
|
'featureType': this.featureType_,
|
||||||
|
'featureNS': this.featureNS_
|
||||||
|
});
|
||||||
|
assign(context, this.getReadOptions(node, opt_options ? opt_options : {}));
|
||||||
|
const objectStack = [context];
|
||||||
|
this.gmlFormat_.FEATURE_COLLECTION_PARSERS[GMLNS][
|
||||||
|
'featureMember'] =
|
||||||
|
makeArrayPusher(GMLBase.prototype.readFeaturesInternal);
|
||||||
|
let features = pushParseAndPop([],
|
||||||
|
this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node,
|
||||||
|
objectStack, this.gmlFormat_);
|
||||||
|
if (!features) {
|
||||||
|
features = [];
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Document} doc Document.
|
* Read transaction response of the source.
|
||||||
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
|
*
|
||||||
* FeatureCollection metadata.
|
* @param {Document|Node|Object|string} source Source.
|
||||||
*/
|
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
|
||||||
WFS.prototype.readFeatureCollectionMetadataFromDocument = function(doc) {
|
* @api
|
||||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
*/
|
||||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
readTransactionResponse(source) {
|
||||||
return this.readFeatureCollectionMetadataFromNode(n);
|
if (isDocument(source)) {
|
||||||
|
return this.readTransactionResponseFromDocument(
|
||||||
|
/** @type {Document} */ (source));
|
||||||
|
} else if (isNode(source)) {
|
||||||
|
return this.readTransactionResponseFromNode(/** @type {Node} */ (source));
|
||||||
|
} else if (typeof source === 'string') {
|
||||||
|
const doc = parse(source);
|
||||||
|
return this.readTransactionResponseFromDocument(doc);
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* Read feature collection metadata of the source.
|
||||||
* @const
|
*
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
* @param {Document|Node|Object|string} source Source.
|
||||||
*/
|
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
|
||||||
const FEATURE_COLLECTION_PARSERS = {
|
* FeatureCollection metadata.
|
||||||
'http://www.opengis.net/gml': {
|
* @api
|
||||||
'boundedBy': makeObjectPropertySetter(
|
*/
|
||||||
GMLBase.prototype.readGeometryElement, 'bounds')
|
readFeatureCollectionMetadata(source) {
|
||||||
|
if (isDocument(source)) {
|
||||||
|
return this.readFeatureCollectionMetadataFromDocument(
|
||||||
|
/** @type {Document} */ (source));
|
||||||
|
} else if (isNode(source)) {
|
||||||
|
return this.readFeatureCollectionMetadataFromNode(
|
||||||
|
/** @type {Node} */ (source));
|
||||||
|
} else if (typeof source === 'string') {
|
||||||
|
const doc = parse(source);
|
||||||
|
return this.readFeatureCollectionMetadataFromDocument(doc);
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @param {Document} doc Document.
|
||||||
* @param {Node} node Node.
|
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
|
||||||
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
|
* FeatureCollection metadata.
|
||||||
* FeatureCollection metadata.
|
*/
|
||||||
*/
|
readFeatureCollectionMetadataFromDocument(doc) {
|
||||||
WFS.prototype.readFeatureCollectionMetadataFromNode = function(node) {
|
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||||
const result = {};
|
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||||
const value = readNonNegativeIntegerString(
|
return this.readFeatureCollectionMetadataFromNode(n);
|
||||||
node.getAttribute('numberOfFeatures'));
|
}
|
||||||
result['numberOfFeatures'] = value;
|
}
|
||||||
return pushParseAndPop(
|
return undefined;
|
||||||
/** @type {module:ol/format/WFS~FeatureCollectionMetadata} */ (result),
|
|
||||||
FEATURE_COLLECTION_PARSERS, node, [], this.gmlFormat_);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @const
|
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
|
||||||
*/
|
|
||||||
const TRANSACTION_SUMMARY_PARSERS = {
|
|
||||||
'http://www.opengis.net/wfs': {
|
|
||||||
'totalInserted': makeObjectPropertySetter(readNonNegativeInteger),
|
|
||||||
'totalUpdated': makeObjectPropertySetter(readNonNegativeInteger),
|
|
||||||
'totalDeleted': makeObjectPropertySetter(readNonNegativeInteger)
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
|
||||||
|
* FeatureCollection metadata.
|
||||||
|
*/
|
||||||
|
readFeatureCollectionMetadataFromNode(node) {
|
||||||
|
const result = {};
|
||||||
|
const value = readNonNegativeIntegerString(
|
||||||
|
node.getAttribute('numberOfFeatures'));
|
||||||
|
result['numberOfFeatures'] = value;
|
||||||
|
return pushParseAndPop(
|
||||||
|
/** @type {module:ol/format/WFS~FeatureCollectionMetadata} */ (result),
|
||||||
|
FEATURE_COLLECTION_PARSERS, node, [], this.gmlFormat_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Document} doc Document.
|
||||||
|
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
|
||||||
|
*/
|
||||||
|
readTransactionResponseFromDocument(doc) {
|
||||||
|
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||||
|
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||||
|
return this.readTransactionResponseFromNode(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
|
||||||
|
*/
|
||||||
|
readTransactionResponseFromNode(node) {
|
||||||
|
return pushParseAndPop(
|
||||||
|
/** @type {module:ol/format/WFS~TransactionResponse} */({}),
|
||||||
|
TRANSACTION_RESPONSE_PARSERS, node, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode format as WFS `GetFeature` and return the Node.
|
||||||
|
*
|
||||||
|
* @param {module:ol/format/WFS~WriteGetFeatureOptions} options Options.
|
||||||
|
* @return {Node} Result.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeGetFeature(options) {
|
||||||
|
const node = createElementNS(WFSNS, 'GetFeature');
|
||||||
|
node.setAttribute('service', 'WFS');
|
||||||
|
node.setAttribute('version', '1.1.0');
|
||||||
|
let filter;
|
||||||
|
if (options) {
|
||||||
|
if (options.handle) {
|
||||||
|
node.setAttribute('handle', options.handle);
|
||||||
|
}
|
||||||
|
if (options.outputFormat) {
|
||||||
|
node.setAttribute('outputFormat', options.outputFormat);
|
||||||
|
}
|
||||||
|
if (options.maxFeatures !== undefined) {
|
||||||
|
node.setAttribute('maxFeatures', options.maxFeatures);
|
||||||
|
}
|
||||||
|
if (options.resultType) {
|
||||||
|
node.setAttribute('resultType', options.resultType);
|
||||||
|
}
|
||||||
|
if (options.startIndex !== undefined) {
|
||||||
|
node.setAttribute('startIndex', options.startIndex);
|
||||||
|
}
|
||||||
|
if (options.count !== undefined) {
|
||||||
|
node.setAttribute('count', options.count);
|
||||||
|
}
|
||||||
|
filter = options.filter;
|
||||||
|
if (options.bbox) {
|
||||||
|
assert(options.geometryName,
|
||||||
|
12); // `options.geometryName` must also be provided when `options.bbox` is set
|
||||||
|
const bbox = bboxFilter(
|
||||||
|
/** @type {string} */ (options.geometryName), options.bbox, options.srsName);
|
||||||
|
if (filter) {
|
||||||
|
// if bbox and filter are both set, combine the two into a single filter
|
||||||
|
filter = andFilter(filter, bbox);
|
||||||
|
} else {
|
||||||
|
filter = bbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', this.schemaLocation_);
|
||||||
|
/** @type {module:ol/xml~NodeStackItem} */
|
||||||
|
const context = {
|
||||||
|
node: node,
|
||||||
|
'srsName': options.srsName,
|
||||||
|
'featureNS': options.featureNS ? options.featureNS : this.featureNS_,
|
||||||
|
'featurePrefix': options.featurePrefix,
|
||||||
|
'geometryName': options.geometryName,
|
||||||
|
'filter': filter,
|
||||||
|
'propertyNames': options.propertyNames ? options.propertyNames : []
|
||||||
|
};
|
||||||
|
assert(Array.isArray(options.featureTypes),
|
||||||
|
11); // `options.featureTypes` should be an Array
|
||||||
|
writeGetFeature(node, /** @type {!Array.<string>} */ (options.featureTypes), [context]);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode format as WFS `Transaction` and return the Node.
|
||||||
|
*
|
||||||
|
* @param {Array.<module:ol/Feature>} inserts The features to insert.
|
||||||
|
* @param {Array.<module:ol/Feature>} updates The features to update.
|
||||||
|
* @param {Array.<module:ol/Feature>} deletes The features to delete.
|
||||||
|
* @param {module:ol/format/WFS~WriteTransactionOptions} options Write options.
|
||||||
|
* @return {Node} Result.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeTransaction(inserts, updates, deletes, options) {
|
||||||
|
const objectStack = [];
|
||||||
|
const node = createElementNS(WFSNS, 'Transaction');
|
||||||
|
const version = options.version ? options.version : DEFAULT_VERSION;
|
||||||
|
const gmlVersion = version === '1.0.0' ? 2 : 3;
|
||||||
|
node.setAttribute('service', 'WFS');
|
||||||
|
node.setAttribute('version', version);
|
||||||
|
let baseObj;
|
||||||
|
/** @type {module:ol/xml~NodeStackItem} */
|
||||||
|
let obj;
|
||||||
|
if (options) {
|
||||||
|
baseObj = options.gmlOptions ? options.gmlOptions : {};
|
||||||
|
if (options.handle) {
|
||||||
|
node.setAttribute('handle', options.handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const schemaLocation = SCHEMA_LOCATIONS[version];
|
||||||
|
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', schemaLocation);
|
||||||
|
const featurePrefix = options.featurePrefix ? options.featurePrefix : FEATURE_PREFIX;
|
||||||
|
if (inserts) {
|
||||||
|
obj = {node: node, 'featureNS': options.featureNS,
|
||||||
|
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
||||||
|
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
|
||||||
|
assign(obj, baseObj);
|
||||||
|
pushSerializeAndPop(obj,
|
||||||
|
TRANSACTION_SERIALIZERS,
|
||||||
|
makeSimpleNodeFactory('Insert'), inserts,
|
||||||
|
objectStack);
|
||||||
|
}
|
||||||
|
if (updates) {
|
||||||
|
obj = {node: node, 'featureNS': options.featureNS,
|
||||||
|
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
||||||
|
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
|
||||||
|
assign(obj, baseObj);
|
||||||
|
pushSerializeAndPop(obj,
|
||||||
|
TRANSACTION_SERIALIZERS,
|
||||||
|
makeSimpleNodeFactory('Update'), updates,
|
||||||
|
objectStack);
|
||||||
|
}
|
||||||
|
if (deletes) {
|
||||||
|
pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
|
||||||
|
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
||||||
|
'gmlVersion': gmlVersion, 'srsName': options.srsName},
|
||||||
|
TRANSACTION_SERIALIZERS,
|
||||||
|
makeSimpleNodeFactory('Delete'), deletes,
|
||||||
|
objectStack);
|
||||||
|
}
|
||||||
|
if (options.nativeElements) {
|
||||||
|
pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
|
||||||
|
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
||||||
|
'gmlVersion': gmlVersion, 'srsName': options.srsName},
|
||||||
|
TRANSACTION_SERIALIZERS,
|
||||||
|
makeSimpleNodeFactory('Native'), options.nativeElements,
|
||||||
|
objectStack);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readProjectionFromDocument(doc) {
|
||||||
|
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||||
|
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||||
|
return this.readProjectionFromNode(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readProjectionFromNode(node) {
|
||||||
|
if (node.firstElementChild &&
|
||||||
|
node.firstElementChild.firstElementChild) {
|
||||||
|
node = node.firstElementChild.firstElementChild;
|
||||||
|
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
|
||||||
|
if (!(n.childNodes.length === 0 ||
|
||||||
|
(n.childNodes.length === 1 &&
|
||||||
|
n.firstChild.nodeType === 3))) {
|
||||||
|
const objectStack = [{}];
|
||||||
|
this.gmlFormat_.readGeometryElement(n, objectStack);
|
||||||
|
return getProjection(objectStack.pop().srsName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -386,55 +591,6 @@ function readInsertResults(node, objectStack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @const
|
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
|
||||||
*/
|
|
||||||
const TRANSACTION_RESPONSE_PARSERS = {
|
|
||||||
'http://www.opengis.net/wfs': {
|
|
||||||
'TransactionSummary': makeObjectPropertySetter(
|
|
||||||
readTransactionSummary, 'transactionSummary'),
|
|
||||||
'InsertResults': makeObjectPropertySetter(
|
|
||||||
readInsertResults, 'insertIds')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Document} doc Document.
|
|
||||||
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
|
|
||||||
*/
|
|
||||||
WFS.prototype.readTransactionResponseFromDocument = function(doc) {
|
|
||||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
|
||||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
|
||||||
return this.readTransactionResponseFromNode(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
|
|
||||||
*/
|
|
||||||
WFS.prototype.readTransactionResponseFromNode = function(node) {
|
|
||||||
return pushParseAndPop(
|
|
||||||
/** @type {module:ol/format/WFS~TransactionResponse} */({}),
|
|
||||||
TRANSACTION_RESPONSE_PARSERS, node, []);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Serializer>>}
|
|
||||||
*/
|
|
||||||
const QUERY_SERIALIZERS = {
|
|
||||||
'http://www.opengis.net/wfs': {
|
|
||||||
'PropertyName': makeChildAppender(writeStringTextNode)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {module:ol/Feature} feature Feature.
|
* @param {module:ol/Feature} feature Feature.
|
||||||
@@ -507,20 +663,6 @@ function writeDelete(node, feature, objectStack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Serializer>>}
|
|
||||||
*/
|
|
||||||
const TRANSACTION_SERIALIZERS = {
|
|
||||||
'http://www.opengis.net/wfs': {
|
|
||||||
'Insert': makeChildAppender(writeFeature),
|
|
||||||
'Update': makeChildAppender(writeUpdate),
|
|
||||||
'Delete': makeChildAppender(writeDelete),
|
|
||||||
'Property': makeChildAppender(writeProperty),
|
|
||||||
'Native': makeChildAppender(writeNative)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {module:ol/Feature} feature Feature.
|
* @param {module:ol/Feature} feature Feature.
|
||||||
@@ -942,180 +1084,4 @@ function writeGetFeature(node, featureTypes, objectStack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode format as WFS `GetFeature` and return the Node.
|
|
||||||
*
|
|
||||||
* @param {module:ol/format/WFS~WriteGetFeatureOptions} options Options.
|
|
||||||
* @return {Node} Result.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
WFS.prototype.writeGetFeature = function(options) {
|
|
||||||
const node = createElementNS(WFSNS, 'GetFeature');
|
|
||||||
node.setAttribute('service', 'WFS');
|
|
||||||
node.setAttribute('version', '1.1.0');
|
|
||||||
let filter;
|
|
||||||
if (options) {
|
|
||||||
if (options.handle) {
|
|
||||||
node.setAttribute('handle', options.handle);
|
|
||||||
}
|
|
||||||
if (options.outputFormat) {
|
|
||||||
node.setAttribute('outputFormat', options.outputFormat);
|
|
||||||
}
|
|
||||||
if (options.maxFeatures !== undefined) {
|
|
||||||
node.setAttribute('maxFeatures', options.maxFeatures);
|
|
||||||
}
|
|
||||||
if (options.resultType) {
|
|
||||||
node.setAttribute('resultType', options.resultType);
|
|
||||||
}
|
|
||||||
if (options.startIndex !== undefined) {
|
|
||||||
node.setAttribute('startIndex', options.startIndex);
|
|
||||||
}
|
|
||||||
if (options.count !== undefined) {
|
|
||||||
node.setAttribute('count', options.count);
|
|
||||||
}
|
|
||||||
filter = options.filter;
|
|
||||||
if (options.bbox) {
|
|
||||||
assert(options.geometryName,
|
|
||||||
12); // `options.geometryName` must also be provided when `options.bbox` is set
|
|
||||||
const bbox = bboxFilter(
|
|
||||||
/** @type {string} */ (options.geometryName), options.bbox, options.srsName);
|
|
||||||
if (filter) {
|
|
||||||
// if bbox and filter are both set, combine the two into a single filter
|
|
||||||
filter = andFilter(filter, bbox);
|
|
||||||
} else {
|
|
||||||
filter = bbox;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', this.schemaLocation_);
|
|
||||||
/** @type {module:ol/xml~NodeStackItem} */
|
|
||||||
const context = {
|
|
||||||
node: node,
|
|
||||||
'srsName': options.srsName,
|
|
||||||
'featureNS': options.featureNS ? options.featureNS : this.featureNS_,
|
|
||||||
'featurePrefix': options.featurePrefix,
|
|
||||||
'geometryName': options.geometryName,
|
|
||||||
'filter': filter,
|
|
||||||
'propertyNames': options.propertyNames ? options.propertyNames : []
|
|
||||||
};
|
|
||||||
assert(Array.isArray(options.featureTypes),
|
|
||||||
11); // `options.featureTypes` should be an Array
|
|
||||||
writeGetFeature(node, /** @type {!Array.<string>} */ (options.featureTypes), [context]);
|
|
||||||
return node;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode format as WFS `Transaction` and return the Node.
|
|
||||||
*
|
|
||||||
* @param {Array.<module:ol/Feature>} inserts The features to insert.
|
|
||||||
* @param {Array.<module:ol/Feature>} updates The features to update.
|
|
||||||
* @param {Array.<module:ol/Feature>} deletes The features to delete.
|
|
||||||
* @param {module:ol/format/WFS~WriteTransactionOptions} options Write options.
|
|
||||||
* @return {Node} Result.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
WFS.prototype.writeTransaction = function(inserts, updates, deletes, options) {
|
|
||||||
const objectStack = [];
|
|
||||||
const node = createElementNS(WFSNS, 'Transaction');
|
|
||||||
const version = options.version ? options.version : DEFAULT_VERSION;
|
|
||||||
const gmlVersion = version === '1.0.0' ? 2 : 3;
|
|
||||||
node.setAttribute('service', 'WFS');
|
|
||||||
node.setAttribute('version', version);
|
|
||||||
let baseObj;
|
|
||||||
/** @type {module:ol/xml~NodeStackItem} */
|
|
||||||
let obj;
|
|
||||||
if (options) {
|
|
||||||
baseObj = options.gmlOptions ? options.gmlOptions : {};
|
|
||||||
if (options.handle) {
|
|
||||||
node.setAttribute('handle', options.handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const schemaLocation = SCHEMA_LOCATIONS[version];
|
|
||||||
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', schemaLocation);
|
|
||||||
const featurePrefix = options.featurePrefix ? options.featurePrefix : FEATURE_PREFIX;
|
|
||||||
if (inserts) {
|
|
||||||
obj = {node: node, 'featureNS': options.featureNS,
|
|
||||||
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
|
||||||
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
|
|
||||||
assign(obj, baseObj);
|
|
||||||
pushSerializeAndPop(obj,
|
|
||||||
TRANSACTION_SERIALIZERS,
|
|
||||||
makeSimpleNodeFactory('Insert'), inserts,
|
|
||||||
objectStack);
|
|
||||||
}
|
|
||||||
if (updates) {
|
|
||||||
obj = {node: node, 'featureNS': options.featureNS,
|
|
||||||
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
|
||||||
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
|
|
||||||
assign(obj, baseObj);
|
|
||||||
pushSerializeAndPop(obj,
|
|
||||||
TRANSACTION_SERIALIZERS,
|
|
||||||
makeSimpleNodeFactory('Update'), updates,
|
|
||||||
objectStack);
|
|
||||||
}
|
|
||||||
if (deletes) {
|
|
||||||
pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
|
|
||||||
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
|
||||||
'gmlVersion': gmlVersion, 'srsName': options.srsName},
|
|
||||||
TRANSACTION_SERIALIZERS,
|
|
||||||
makeSimpleNodeFactory('Delete'), deletes,
|
|
||||||
objectStack);
|
|
||||||
}
|
|
||||||
if (options.nativeElements) {
|
|
||||||
pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
|
|
||||||
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
|
||||||
'gmlVersion': gmlVersion, 'srsName': options.srsName},
|
|
||||||
TRANSACTION_SERIALIZERS,
|
|
||||||
makeSimpleNodeFactory('Native'), options.nativeElements,
|
|
||||||
objectStack);
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the projection from a WFS source.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @return {?module:ol/proj/Projection} Projection.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
WFS.prototype.readProjection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WFS.prototype.readProjectionFromDocument = function(doc) {
|
|
||||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
|
||||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
|
||||||
return this.readProjectionFromNode(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WFS.prototype.readProjectionFromNode = function(node) {
|
|
||||||
if (node.firstElementChild &&
|
|
||||||
node.firstElementChild.firstElementChild) {
|
|
||||||
node = node.firstElementChild.firstElementChild;
|
|
||||||
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
|
|
||||||
if (!(n.childNodes.length === 0 ||
|
|
||||||
(n.childNodes.length === 1 &&
|
|
||||||
n.firstChild.nodeType === 3))) {
|
|
||||||
const objectStack = [{}];
|
|
||||||
this.gmlFormat_.readGeometryElement(n, objectStack);
|
|
||||||
return getProjection(objectStack.pop().srsName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
export default WFS;
|
export default WFS;
|
||||||
|
|||||||
1219
src/ol/format/WKT.js
1219
src/ol/format/WKT.js
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/WMSCapabilities
|
* @module ol/format/WMSCapabilities
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {readHref} from '../format/XLink.js';
|
import {readHref} from '../format/XLink.js';
|
||||||
import XML from '../format/XML.js';
|
import XML from '../format/XML.js';
|
||||||
import {readDecimalString, readString, readNonNegativeInteger, readDecimal, readBooleanString, readNonNegativeIntegerString} from '../format/xsd.js';
|
import {readDecimalString, readString, readNonNegativeInteger, readDecimal, readBooleanString, readNonNegativeIntegerString} from '../format/xsd.js';
|
||||||
@@ -9,27 +8,6 @@ import {makeArrayPusher, makeObjectPropertyPusher, makeObjectPropertySetter,
|
|||||||
makeStructureNS, pushParseAndPop} from '../xml.js';
|
makeStructureNS, pushParseAndPop} from '../xml.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @classdesc
|
|
||||||
* Format for reading WMS capabilities data
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/XML}
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
const WMSCapabilities = function() {
|
|
||||||
|
|
||||||
XML.call(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {string|undefined}
|
|
||||||
*/
|
|
||||||
this.version = undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(WMSCapabilities, XML);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {Array.<null|string>}
|
* @type {Array.<null|string>}
|
||||||
@@ -63,6 +41,47 @@ const CAPABILITY_PARSERS = makeStructureNS(
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* Format for reading WMS capabilities data
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
class WMSCapabilities extends XML {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string|undefined}
|
||||||
|
*/
|
||||||
|
this.version = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFromDocument(doc) {
|
||||||
|
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||||
|
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||||
|
return this.readFromNode(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFromNode(node) {
|
||||||
|
this.version = node.getAttribute('version').trim();
|
||||||
|
const wmsCapabilityObject = pushParseAndPop({
|
||||||
|
'version': this.version
|
||||||
|
}, PARSERS, node, []);
|
||||||
|
return wmsCapabilityObject ? wmsCapabilityObject : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
||||||
@@ -266,42 +285,6 @@ const KEYWORDLIST_PARSERS = makeStructureNS(
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a WMS capabilities document.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|string} source The XML source.
|
|
||||||
* @return {Object} An object representing the WMS capabilities.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
WMSCapabilities.prototype.read;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WMSCapabilities.prototype.readFromDocument = function(doc) {
|
|
||||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
|
||||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
|
||||||
return this.readFromNode(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WMSCapabilities.prototype.readFromNode = function(node) {
|
|
||||||
this.version = node.getAttribute('version').trim();
|
|
||||||
const wmsCapabilityObject = pushParseAndPop({
|
|
||||||
'version': this.version
|
|
||||||
}, PARSERS, node, []);
|
|
||||||
return wmsCapabilityObject ? wmsCapabilityObject : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/WMSGetFeatureInfo
|
* @module ol/format/WMSGetFeatureInfo
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {extend, includes} from '../array.js';
|
import {extend, includes} from '../array.js';
|
||||||
import GML2 from '../format/GML2.js';
|
import GML2 from '../format/GML2.js';
|
||||||
import XMLFeature from '../format/XMLFeature.js';
|
import XMLFeature from '../format/XMLFeature.js';
|
||||||
@@ -15,46 +14,6 @@ import {makeArrayPusher, makeStructureNS, pushParseAndPop} from '../xml.js';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @classdesc
|
|
||||||
* Format for reading WMSGetFeatureInfo format. It uses
|
|
||||||
* {@link module:ol/format/GML2~GML2} to read features.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/XMLFeature}
|
|
||||||
* @param {module:ol/format/WMSGetFeatureInfo~Options=} opt_options Options.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
const WMSGetFeatureInfo = function(opt_options) {
|
|
||||||
|
|
||||||
const options = opt_options ? opt_options : {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
this.featureNS_ = 'http://mapserver.gis.umn.edu/mapserver';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {module:ol/format/GML2}
|
|
||||||
*/
|
|
||||||
this.gmlFormat_ = new GML2();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Array.<string>}
|
|
||||||
*/
|
|
||||||
this.layers_ = options.layers ? options.layers : null;
|
|
||||||
|
|
||||||
XMLFeature.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(WMSGetFeatureInfo, XMLFeature);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@@ -70,122 +29,145 @@ const layerIdentifier = '_layer';
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {Array.<string>} layers
|
* @classdesc
|
||||||
*/
|
* Format for reading WMSGetFeatureInfo format. It uses
|
||||||
WMSGetFeatureInfo.prototype.getLayers = function() {
|
* {@link module:ol/format/GML2~GML2} to read features.
|
||||||
return this.layers_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Array.<string>} layers Layers to parse.
|
|
||||||
*/
|
|
||||||
WMSGetFeatureInfo.prototype.setLayers = function(layers) {
|
|
||||||
this.layers_ = layers;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
WMSGetFeatureInfo.prototype.readFeatures_ = function(node, objectStack) {
|
|
||||||
node.setAttribute('namespaceURI', this.featureNS_);
|
|
||||||
const localName = node.localName;
|
|
||||||
/** @type {Array.<module:ol/Feature>} */
|
|
||||||
let features = [];
|
|
||||||
if (node.childNodes.length === 0) {
|
|
||||||
return features;
|
|
||||||
}
|
|
||||||
if (localName == 'msGMLOutput') {
|
|
||||||
for (let i = 0, ii = node.childNodes.length; i < ii; i++) {
|
|
||||||
const layer = node.childNodes[i];
|
|
||||||
if (layer.nodeType !== Node.ELEMENT_NODE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const context = objectStack[0];
|
|
||||||
|
|
||||||
const toRemove = layerIdentifier;
|
|
||||||
const layerName = layer.localName.replace(toRemove, '');
|
|
||||||
|
|
||||||
if (this.layers_ && !includes(this.layers_, layerName)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const featureType = layerName +
|
|
||||||
featureIdentifier;
|
|
||||||
|
|
||||||
context['featureType'] = featureType;
|
|
||||||
context['featureNS'] = this.featureNS_;
|
|
||||||
|
|
||||||
const parsers = {};
|
|
||||||
parsers[featureType] = makeArrayPusher(
|
|
||||||
this.gmlFormat_.readFeatureElement, this.gmlFormat_);
|
|
||||||
const parsersNS = makeStructureNS(
|
|
||||||
[context['featureNS'], null], parsers);
|
|
||||||
layer.setAttribute('namespaceURI', this.featureNS_);
|
|
||||||
const layerFeatures = pushParseAndPop(
|
|
||||||
[], parsersNS, layer, objectStack, this.gmlFormat_);
|
|
||||||
if (layerFeatures) {
|
|
||||||
extend(features, layerFeatures);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (localName == 'FeatureCollection') {
|
|
||||||
const gmlFeatures = pushParseAndPop([],
|
|
||||||
this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node,
|
|
||||||
[{}], this.gmlFormat_);
|
|
||||||
if (gmlFeatures) {
|
|
||||||
features = gmlFeatures;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return features;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all features from a WMSGetFeatureInfo response.
|
|
||||||
*
|
*
|
||||||
* @function
|
|
||||||
* @param {Document|Node|Object|string} source Source.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
WMSGetFeatureInfo.prototype.readFeatures;
|
class WMSGetFeatureInfo extends XMLFeature {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/format/WMSGetFeatureInfo~Options=} opt_options Options.
|
||||||
|
*/
|
||||||
|
constructor(opt_options) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.featureNS_ = 'http://mapserver.gis.umn.edu/mapserver';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @private
|
||||||
*/
|
* @type {module:ol/format/GML2}
|
||||||
WMSGetFeatureInfo.prototype.readFeaturesFromNode = function(node, opt_options) {
|
*/
|
||||||
const options = {};
|
this.gmlFormat_ = new GML2();
|
||||||
if (opt_options) {
|
|
||||||
assign(options, this.getReadOptions(node, opt_options));
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Array.<string>}
|
||||||
|
*/
|
||||||
|
this.layers_ = options.layers ? options.layers : null;
|
||||||
}
|
}
|
||||||
return this.readFeatures_(node, [options]);
|
|
||||||
};
|
/**
|
||||||
|
* @return {Array.<string>} layers
|
||||||
|
*/
|
||||||
|
getLayers() {
|
||||||
|
return this.layers_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array.<string>} layers Layers to parse.
|
||||||
|
*/
|
||||||
|
setLayers(layers) {
|
||||||
|
this.layers_ = layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
readFeatures_(node, objectStack) {
|
||||||
|
node.setAttribute('namespaceURI', this.featureNS_);
|
||||||
|
const localName = node.localName;
|
||||||
|
/** @type {Array.<module:ol/Feature>} */
|
||||||
|
let features = [];
|
||||||
|
if (node.childNodes.length === 0) {
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
if (localName == 'msGMLOutput') {
|
||||||
|
for (let i = 0, ii = node.childNodes.length; i < ii; i++) {
|
||||||
|
const layer = node.childNodes[i];
|
||||||
|
if (layer.nodeType !== Node.ELEMENT_NODE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const context = objectStack[0];
|
||||||
|
|
||||||
|
const toRemove = layerIdentifier;
|
||||||
|
const layerName = layer.localName.replace(toRemove, '');
|
||||||
|
|
||||||
|
if (this.layers_ && !includes(this.layers_, layerName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const featureType = layerName +
|
||||||
|
featureIdentifier;
|
||||||
|
|
||||||
|
context['featureType'] = featureType;
|
||||||
|
context['featureNS'] = this.featureNS_;
|
||||||
|
|
||||||
|
const parsers = {};
|
||||||
|
parsers[featureType] = makeArrayPusher(
|
||||||
|
this.gmlFormat_.readFeatureElement, this.gmlFormat_);
|
||||||
|
const parsersNS = makeStructureNS(
|
||||||
|
[context['featureNS'], null], parsers);
|
||||||
|
layer.setAttribute('namespaceURI', this.featureNS_);
|
||||||
|
const layerFeatures = pushParseAndPop(
|
||||||
|
[], parsersNS, layer, objectStack, this.gmlFormat_);
|
||||||
|
if (layerFeatures) {
|
||||||
|
extend(features, layerFeatures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (localName == 'FeatureCollection') {
|
||||||
|
const gmlFeatures = pushParseAndPop([],
|
||||||
|
this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node,
|
||||||
|
[{}], this.gmlFormat_);
|
||||||
|
if (gmlFeatures) {
|
||||||
|
features = gmlFeatures;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFeaturesFromNode(node, opt_options) {
|
||||||
|
const options = {};
|
||||||
|
if (opt_options) {
|
||||||
|
assign(options, this.getReadOptions(node, opt_options));
|
||||||
|
}
|
||||||
|
return this.readFeatures_(node, [options]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeatureNode(feature, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeaturesNode(features, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not implemented.
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeGeometryNode(geometry, opt_options) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WMSGetFeatureInfo.prototype.writeFeatureNode = function(feature, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WMSGetFeatureInfo.prototype.writeFeaturesNode = function(features, opt_options) {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not implemented.
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WMSGetFeatureInfo.prototype.writeGeometryNode = function(geometry, opt_options) {};
|
|
||||||
export default WMSGetFeatureInfo;
|
export default WMSGetFeatureInfo;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/WMTSCapabilities
|
* @module ol/format/WMTSCapabilities
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {boundingExtent} from '../extent.js';
|
import {boundingExtent} from '../extent.js';
|
||||||
import OWS from '../format/OWS.js';
|
import OWS from '../format/OWS.js';
|
||||||
import {readHref} from '../format/XLink.js';
|
import {readHref} from '../format/XLink.js';
|
||||||
@@ -10,26 +9,6 @@ import {readString, readNonNegativeInteger, readDecimal} from '../format/xsd.js'
|
|||||||
import {pushParseAndPop, makeStructureNS,
|
import {pushParseAndPop, makeStructureNS,
|
||||||
makeObjectPropertySetter, makeObjectPropertyPusher, makeArrayPusher} from '../xml.js';
|
makeObjectPropertySetter, makeObjectPropertyPusher, makeArrayPusher} from '../xml.js';
|
||||||
|
|
||||||
/**
|
|
||||||
* @classdesc
|
|
||||||
* Format for reading WMTS capabilities data.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @extends {module:ol/format/XML}
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
const WMTSCapabilities = function() {
|
|
||||||
XML.call(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {module:ol/format/OWS}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.owsParser_ = new OWS();
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(WMTSCapabilities, XML);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
@@ -61,6 +40,51 @@ const PARSERS = makeStructureNS(
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* Format for reading WMTS capabilities data.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
class WMTSCapabilities extends XML {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {module:ol/format/OWS}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.owsParser_ = new OWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFromDocument(doc) {
|
||||||
|
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||||
|
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||||
|
return this.readFromNode(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readFromNode(node) {
|
||||||
|
const version = node.getAttribute('version').trim();
|
||||||
|
let WMTSCapabilityObject = this.owsParser_.readFromNode(node);
|
||||||
|
if (!WMTSCapabilityObject) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
WMTSCapabilityObject['version'] = version;
|
||||||
|
WMTSCapabilityObject = pushParseAndPop(WMTSCapabilityObject, PARSERS, node, []);
|
||||||
|
return WMTSCapabilityObject ? WMTSCapabilityObject : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
|
||||||
@@ -193,45 +217,6 @@ const TM_PARSERS = makeStructureNS(
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a WMTS capabilities document.
|
|
||||||
*
|
|
||||||
* @function
|
|
||||||
* @param {Document|Node|string} source The XML source.
|
|
||||||
* @return {Object} An object representing the WMTS capabilities.
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
WMTSCapabilities.prototype.read;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WMTSCapabilities.prototype.readFromDocument = function(doc) {
|
|
||||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
|
||||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
|
||||||
return this.readFromNode(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
WMTSCapabilities.prototype.readFromNode = function(node) {
|
|
||||||
const version = node.getAttribute('version').trim();
|
|
||||||
let WMTSCapabilityObject = this.owsParser_.readFromNode(node);
|
|
||||||
if (!WMTSCapabilityObject) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
WMTSCapabilityObject['version'] = version;
|
|
||||||
WMTSCapabilityObject = pushParseAndPop(WMTSCapabilityObject, PARSERS, node, []);
|
|
||||||
return WMTSCapabilityObject ? WMTSCapabilityObject : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {Array.<*>} objectStack Object stack.
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const NAMESPACE_URI = 'http://www.w3.org/1999/xlink';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @return {boolean|undefined} Boolean.
|
* @return {string|undefined} href.
|
||||||
*/
|
*/
|
||||||
export function readHref(node) {
|
export function readHref(node) {
|
||||||
return node.getAttributeNS(NAMESPACE_URI, 'href');
|
return node.getAttributeNS(NAMESPACE_URI, 'href');
|
||||||
|
|||||||
@@ -7,44 +7,42 @@ import {isDocument, isNode, parse} from '../xml.js';
|
|||||||
* @classdesc
|
* @classdesc
|
||||||
* Generic format for reading non-feature XML data
|
* Generic format for reading non-feature XML data
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @struct
|
|
||||||
*/
|
*/
|
||||||
const XML = function() {
|
class XML {
|
||||||
};
|
/**
|
||||||
|
* Read the source document.
|
||||||
|
*
|
||||||
/**
|
* @param {Document|Node|string} source The XML source.
|
||||||
* @param {Document|Node|string} source Source.
|
* @return {Object} An object representing the source.
|
||||||
* @return {Object} The parsed result.
|
* @api
|
||||||
*/
|
*/
|
||||||
XML.prototype.read = function(source) {
|
read(source) {
|
||||||
if (isDocument(source)) {
|
if (isDocument(source)) {
|
||||||
return this.readFromDocument(/** @type {Document} */ (source));
|
return this.readFromDocument(/** @type {Document} */ (source));
|
||||||
} else if (isNode(source)) {
|
} else if (isNode(source)) {
|
||||||
return this.readFromNode(/** @type {Node} */ (source));
|
return this.readFromNode(/** @type {Node} */ (source));
|
||||||
} else if (typeof source === 'string') {
|
} else if (typeof source === 'string') {
|
||||||
const doc = parse(source);
|
const doc = parse(source);
|
||||||
return this.readFromDocument(doc);
|
return this.readFromDocument(doc);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {Document} doc Document.
|
||||||
|
* @return {Object} Object
|
||||||
|
*/
|
||||||
|
readFromDocument(doc) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {Document} doc Document.
|
* @param {Node} node Node.
|
||||||
* @return {Object} Object
|
* @return {Object} Object
|
||||||
*/
|
*/
|
||||||
XML.prototype.readFromDocument = function(doc) {};
|
readFromNode(node) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @return {Object} Object
|
|
||||||
*/
|
|
||||||
XML.prototype.readFromNode = function(node) {};
|
|
||||||
export default XML;
|
export default XML;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/XMLFeature
|
* @module ol/format/XMLFeature
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../util.js';
|
|
||||||
import {extend} from '../array.js';
|
import {extend} from '../array.js';
|
||||||
import FeatureFormat from '../format/Feature.js';
|
import FeatureFormat from '../format/Feature.js';
|
||||||
import FormatType from '../format/FormatType.js';
|
import FormatType from '../format/FormatType.js';
|
||||||
@@ -13,251 +12,251 @@ import {isDocument, isNode, parse} from '../xml.js';
|
|||||||
* instantiated in apps.
|
* instantiated in apps.
|
||||||
* Base class for XML feature formats.
|
* Base class for XML feature formats.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @extends {module:ol/format/Feature}
|
|
||||||
*/
|
*/
|
||||||
const XMLFeature = function() {
|
class XMLFeature extends FeatureFormat {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {XMLSerializer}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.xmlSerializer_ = new XMLSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {XMLSerializer}
|
* @inheritDoc
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
this.xmlSerializer_ = new XMLSerializer();
|
getType() {
|
||||||
|
return FormatType.XML;
|
||||||
FeatureFormat.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(XMLFeature, FeatureFormat);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.getType = function() {
|
|
||||||
return FormatType.XML;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readFeature = function(source, opt_options) {
|
|
||||||
if (isDocument(source)) {
|
|
||||||
return this.readFeatureFromDocument(/** @type {Document} */ (source), opt_options);
|
|
||||||
} else if (isNode(source)) {
|
|
||||||
return this.readFeatureFromNode(/** @type {Node} */ (source), opt_options);
|
|
||||||
} else if (typeof source === 'string') {
|
|
||||||
const doc = parse(source);
|
|
||||||
return this.readFeatureFromDocument(doc, opt_options);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* Read a single feature.
|
||||||
* @param {Document} doc Document.
|
*
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
* @param {Document|Node|Object|string} source Source.
|
||||||
* @return {module:ol/Feature} Feature.
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
|
||||||
*/
|
* @return {module:ol/Feature} Feature.
|
||||||
XMLFeature.prototype.readFeatureFromDocument = function(doc, opt_options) {
|
* @api
|
||||||
const features = this.readFeaturesFromDocument(doc, opt_options);
|
*/
|
||||||
if (features.length > 0) {
|
readFeature(source, opt_options) {
|
||||||
return features[0];
|
if (isDocument(source)) {
|
||||||
} else {
|
return this.readFeatureFromDocument(/** @type {Document} */ (source), opt_options);
|
||||||
return null;
|
} else if (isNode(source)) {
|
||||||
}
|
return this.readFeatureFromNode(/** @type {Node} */ (source), opt_options);
|
||||||
};
|
} else if (typeof source === 'string') {
|
||||||
|
const doc = parse(source);
|
||||||
|
return this.readFeatureFromDocument(doc, opt_options);
|
||||||
/**
|
} else {
|
||||||
* @param {Node} node Node.
|
return null;
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
|
||||||
* @return {module:ol/Feature} Feature.
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readFeatureFromNode = function(node, opt_options) {
|
|
||||||
return null; // not implemented
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readFeatures = function(source, opt_options) {
|
|
||||||
if (isDocument(source)) {
|
|
||||||
return this.readFeaturesFromDocument(
|
|
||||||
/** @type {Document} */ (source), opt_options);
|
|
||||||
} else if (isNode(source)) {
|
|
||||||
return this.readFeaturesFromNode(/** @type {Node} */ (source), opt_options);
|
|
||||||
} else if (typeof source === 'string') {
|
|
||||||
const doc = parse(source);
|
|
||||||
return this.readFeaturesFromDocument(doc, opt_options);
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Document} doc Document.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
|
||||||
* @protected
|
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readFeaturesFromDocument = function(doc, opt_options) {
|
|
||||||
/** @type {Array.<module:ol/Feature>} */
|
|
||||||
const features = [];
|
|
||||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
|
||||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
|
||||||
extend(features, this.readFeaturesFromNode(n, opt_options));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return features;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @param {Document} doc Document.
|
||||||
* @abstract
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
||||||
* @param {Node} node Node.
|
* @return {module:ol/Feature} Feature.
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
*/
|
||||||
* @protected
|
readFeatureFromDocument(doc, opt_options) {
|
||||||
* @return {Array.<module:ol/Feature>} Features.
|
const features = this.readFeaturesFromDocument(doc, opt_options);
|
||||||
*/
|
if (features.length > 0) {
|
||||||
XMLFeature.prototype.readFeaturesFromNode = function(node, opt_options) {};
|
return features[0];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
/**
|
}
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readGeometry = function(source, opt_options) {
|
|
||||||
if (isDocument(source)) {
|
|
||||||
return this.readGeometryFromDocument(
|
|
||||||
/** @type {Document} */ (source), opt_options);
|
|
||||||
} else if (isNode(source)) {
|
|
||||||
return this.readGeometryFromNode(/** @type {Node} */ (source), opt_options);
|
|
||||||
} else if (typeof source === 'string') {
|
|
||||||
const doc = parse(source);
|
|
||||||
return this.readGeometryFromDocument(doc, opt_options);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* @param {Node} node Node.
|
||||||
* @param {Document} doc Document.
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
* @return {module:ol/Feature} Feature.
|
||||||
* @protected
|
*/
|
||||||
* @return {module:ol/geom/Geometry} Geometry.
|
readFeatureFromNode(node, opt_options) {
|
||||||
*/
|
return null; // not implemented
|
||||||
XMLFeature.prototype.readGeometryFromDocument = function(doc, opt_options) {
|
|
||||||
return null; // not implemented
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/geom/Geometry} Geometry.
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readGeometryFromNode = function(node, opt_options) {
|
|
||||||
return null; // not implemented
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readProjection = function(source) {
|
|
||||||
if (isDocument(source)) {
|
|
||||||
return this.readProjectionFromDocument(/** @type {Document} */ (source));
|
|
||||||
} else if (isNode(source)) {
|
|
||||||
return this.readProjectionFromNode(/** @type {Node} */ (source));
|
|
||||||
} else if (typeof source === 'string') {
|
|
||||||
const doc = parse(source);
|
|
||||||
return this.readProjectionFromDocument(doc);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* Read all features from a feature collection.
|
||||||
|
*
|
||||||
|
* @function
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readFeatures(source, opt_options) {
|
||||||
|
if (isDocument(source)) {
|
||||||
|
return this.readFeaturesFromDocument(
|
||||||
|
/** @type {Document} */ (source), opt_options);
|
||||||
|
} else if (isNode(source)) {
|
||||||
|
return this.readFeaturesFromNode(/** @type {Node} */ (source), opt_options);
|
||||||
|
} else if (typeof source === 'string') {
|
||||||
|
const doc = parse(source);
|
||||||
|
return this.readFeaturesFromDocument(doc, opt_options);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Document} doc Document.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
||||||
|
* @protected
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
*/
|
||||||
|
readFeaturesFromDocument(doc, opt_options) {
|
||||||
|
/** @type {Array.<module:ol/Feature>} */
|
||||||
|
const features = [];
|
||||||
|
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||||
|
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||||
|
extend(features, this.readFeaturesFromNode(n, opt_options));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
||||||
|
* @protected
|
||||||
|
* @return {Array.<module:ol/Feature>} Features.
|
||||||
|
*/
|
||||||
|
readFeaturesFromNode(node, opt_options) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
readGeometry(source, opt_options) {
|
||||||
|
if (isDocument(source)) {
|
||||||
|
return this.readGeometryFromDocument(
|
||||||
|
/** @type {Document} */ (source), opt_options);
|
||||||
|
} else if (isNode(source)) {
|
||||||
|
return this.readGeometryFromNode(/** @type {Node} */ (source), opt_options);
|
||||||
|
} else if (typeof source === 'string') {
|
||||||
|
const doc = parse(source);
|
||||||
|
return this.readGeometryFromDocument(doc, opt_options);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Document} doc Document.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/geom/Geometry} Geometry.
|
||||||
|
*/
|
||||||
|
readGeometryFromDocument(doc, opt_options) {
|
||||||
|
return null; // not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/geom/Geometry} Geometry.
|
||||||
|
*/
|
||||||
|
readGeometryFromNode(node, opt_options) {
|
||||||
|
return null; // not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the projection from the source.
|
||||||
|
*
|
||||||
|
* @param {Document|Node|Object|string} source Source.
|
||||||
|
* @return {module:ol/proj/Projection} Projection.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
readProjection(source) {
|
||||||
|
if (isDocument(source)) {
|
||||||
|
return this.readProjectionFromDocument(/** @type {Document} */ (source));
|
||||||
|
} else if (isNode(source)) {
|
||||||
|
return this.readProjectionFromNode(/** @type {Node} */ (source));
|
||||||
|
} else if (typeof source === 'string') {
|
||||||
|
const doc = parse(source);
|
||||||
|
return this.readProjectionFromDocument(doc);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Document} doc Document.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/proj/Projection} Projection.
|
||||||
|
*/
|
||||||
|
readProjectionFromDocument(doc) {
|
||||||
|
return this.dataProjection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @protected
|
||||||
|
* @return {module:ol/proj/Projection} Projection.
|
||||||
|
*/
|
||||||
|
readProjectionFromNode(node) {
|
||||||
|
return this.dataProjection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeFeature(feature, opt_options) {
|
||||||
|
const node = this.writeFeatureNode(feature, opt_options);
|
||||||
|
return this.xmlSerializer_.serializeToString(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/Feature} feature Feature.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
|
||||||
|
* @protected
|
||||||
|
* @return {Node} Node.
|
||||||
|
*/
|
||||||
|
writeFeatureNode(feature, opt_options) {
|
||||||
|
return null; // not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode an array of features as string.
|
||||||
|
*
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
|
||||||
|
* @return {string} Result.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
writeFeatures(features, opt_options) {
|
||||||
|
const node = this.writeFeaturesNode(features, opt_options);
|
||||||
|
return this.xmlSerializer_.serializeToString(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array.<module:ol/Feature>} features Features.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
|
||||||
|
* @return {Node} Node.
|
||||||
|
*/
|
||||||
|
writeFeaturesNode(features, opt_options) {
|
||||||
|
return null; // not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
writeGeometry(geometry, opt_options) {
|
||||||
|
const node = this.writeGeometryNode(geometry, opt_options);
|
||||||
|
return this.xmlSerializer_.serializeToString(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {module:ol/geom/Geometry} geometry Geometry.
|
||||||
|
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
|
||||||
|
* @return {Node} Node.
|
||||||
|
*/
|
||||||
|
writeGeometryNode(geometry, opt_options) {
|
||||||
|
return null; // not implemented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Document} doc Document.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readProjectionFromDocument = function(doc) {
|
|
||||||
return this.dataProjection;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Node} node Node.
|
|
||||||
* @protected
|
|
||||||
* @return {module:ol/proj/Projection} Projection.
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.readProjectionFromNode = function(node) {
|
|
||||||
return this.dataProjection;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.writeFeature = function(feature, opt_options) {
|
|
||||||
const node = this.writeFeatureNode(feature, opt_options);
|
|
||||||
return this.xmlSerializer_.serializeToString(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/Feature} feature Feature.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
|
|
||||||
* @protected
|
|
||||||
* @return {Node} Node.
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.writeFeatureNode = function(feature, opt_options) {
|
|
||||||
return null; // not implemented
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.writeFeatures = function(features, opt_options) {
|
|
||||||
const node = this.writeFeaturesNode(features, opt_options);
|
|
||||||
return this.xmlSerializer_.serializeToString(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Array.<module:ol/Feature>} features Features.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
|
|
||||||
* @return {Node} Node.
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.writeFeaturesNode = function(features, opt_options) {
|
|
||||||
return null; // not implemented
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.writeGeometry = function(geometry, opt_options) {
|
|
||||||
const node = this.writeGeometryNode(geometry, opt_options);
|
|
||||||
return this.xmlSerializer_.serializeToString(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
|
|
||||||
* @return {Node} Node.
|
|
||||||
*/
|
|
||||||
XMLFeature.prototype.writeGeometryNode = function(geometry, opt_options) {
|
|
||||||
return null; // not implemented
|
|
||||||
};
|
|
||||||
export default XMLFeature;
|
export default XMLFeature;
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/filter/And
|
* @module ol/format/filter/And
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../../util.js';
|
|
||||||
import LogicalNary from '../filter/LogicalNary.js';
|
import LogicalNary from '../filter/LogicalNary.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Represents a logical `<And>` operator between two or more filter conditions.
|
* Represents a logical `<And>` operator between two or more filter conditions.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {...module:ol/format/filter/Filter} conditions Conditions.
|
|
||||||
* @extends {module:ol/format/filter/LogicalNary}
|
|
||||||
*/
|
*/
|
||||||
const And = function(conditions) {
|
class And extends LogicalNary {
|
||||||
const params = ['And'].concat(Array.prototype.slice.call(arguments));
|
|
||||||
LogicalNary.apply(this, params);
|
|
||||||
};
|
|
||||||
|
|
||||||
inherits(And, LogicalNary);
|
/**
|
||||||
|
* @param {...module:ol/format/filter/Filter} conditions Conditions.
|
||||||
|
*/
|
||||||
|
constructor(conditions) {
|
||||||
|
const params = ['And'].concat(Array.prototype.slice.call(arguments));
|
||||||
|
super(...params);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export default And;
|
export default And;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/filter/Bbox
|
* @module ol/format/filter/Bbox
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../../util.js';
|
|
||||||
import Filter from '../filter/Filter.js';
|
import Filter from '../filter/Filter.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,34 +8,36 @@ import Filter from '../filter/Filter.js';
|
|||||||
* Represents a `<BBOX>` operator to test whether a geometry-valued property
|
* Represents a `<BBOX>` operator to test whether a geometry-valued property
|
||||||
* intersects a fixed bounding box
|
* intersects a fixed bounding box
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @param {!string} geometryName Geometry name to use.
|
|
||||||
* @param {!module:ol/extent~Extent} extent Extent.
|
|
||||||
* @param {string=} opt_srsName SRS name. No srsName attribute will be
|
|
||||||
* set on geometries when this is not provided.
|
|
||||||
* @extends {module:ol/format/filter/Filter}
|
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
const Bbox = function(geometryName, extent, opt_srsName) {
|
class Bbox extends Filter {
|
||||||
|
|
||||||
Filter.call(this, 'BBOX');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {!string}
|
* @param {!string} geometryName Geometry name to use.
|
||||||
|
* @param {!module:ol/extent~Extent} extent Extent.
|
||||||
|
* @param {string=} opt_srsName SRS name. No srsName attribute will be set
|
||||||
|
* on geometries when this is not provided.
|
||||||
*/
|
*/
|
||||||
this.geometryName = geometryName;
|
constructor(geometryName, extent, opt_srsName) {
|
||||||
|
|
||||||
/**
|
super('BBOX');
|
||||||
* @type {module:ol/extent~Extent}
|
|
||||||
*/
|
|
||||||
this.extent = extent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {string|undefined}
|
* @type {!string}
|
||||||
*/
|
*/
|
||||||
this.srsName = opt_srsName;
|
this.geometryName = geometryName;
|
||||||
};
|
|
||||||
|
|
||||||
inherits(Bbox, Filter);
|
/**
|
||||||
|
* @type {module:ol/extent~Extent}
|
||||||
|
*/
|
||||||
|
this.extent = extent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string|undefined}
|
||||||
|
*/
|
||||||
|
this.srsName = opt_srsName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export default Bbox;
|
export default Bbox;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/filter/Comparison
|
* @module ol/format/filter/Comparison
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../../util.js';
|
|
||||||
import Filter from '../filter/Filter.js';
|
import Filter from '../filter/Filter.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,22 +8,24 @@ import Filter from '../filter/Filter.js';
|
|||||||
* Abstract class; normally only used for creating subclasses and not instantiated in apps.
|
* Abstract class; normally only used for creating subclasses and not instantiated in apps.
|
||||||
* Base class for WFS GetFeature property comparison filters.
|
* Base class for WFS GetFeature property comparison filters.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {!string} tagName The XML tag name for this filter.
|
|
||||||
* @param {!string} propertyName Name of the context property to compare.
|
|
||||||
* @extends {module:ol/format/filter/Filter}
|
|
||||||
*/
|
*/
|
||||||
const Comparison = function(tagName, propertyName) {
|
class Comparison extends Filter {
|
||||||
|
|
||||||
Filter.call(this, tagName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {!string}
|
* @param {!string} tagName The XML tag name for this filter.
|
||||||
|
* @param {!string} propertyName Name of the context property to compare.
|
||||||
*/
|
*/
|
||||||
this.propertyName = propertyName;
|
constructor(tagName, propertyName) {
|
||||||
};
|
|
||||||
|
|
||||||
inherits(Comparison, Filter);
|
super(tagName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {!string}
|
||||||
|
*/
|
||||||
|
this.propertyName = propertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export default Comparison;
|
export default Comparison;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/filter/ComparisonBinary
|
* @module ol/format/filter/ComparisonBinary
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../../util.js';
|
|
||||||
import Comparison from '../filter/Comparison.js';
|
import Comparison from '../filter/Comparison.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,28 +8,31 @@ import Comparison from '../filter/Comparison.js';
|
|||||||
* Abstract class; normally only used for creating subclasses and not instantiated in apps.
|
* Abstract class; normally only used for creating subclasses and not instantiated in apps.
|
||||||
* Base class for WFS GetFeature property binary comparison filters.
|
* Base class for WFS GetFeature property binary comparison filters.
|
||||||
*
|
*
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {!string} tagName The XML tag name for this filter.
|
|
||||||
* @param {!string} propertyName Name of the context property to compare.
|
|
||||||
* @param {!(string|number)} expression The value to compare.
|
|
||||||
* @param {boolean=} opt_matchCase Case-sensitive?
|
|
||||||
* @extends {module:ol/format/filter/Comparison}
|
|
||||||
*/
|
*/
|
||||||
const ComparisonBinary = function(tagName, propertyName, expression, opt_matchCase) {
|
class ComparisonBinary extends Comparison {
|
||||||
|
|
||||||
Comparison.call(this, tagName, propertyName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {!(string|number)}
|
* @param {!string} tagName The XML tag name for this filter.
|
||||||
|
* @param {!string} propertyName Name of the context property to compare.
|
||||||
|
* @param {!(string|number)} expression The value to compare.
|
||||||
|
* @param {boolean=} opt_matchCase Case-sensitive?
|
||||||
*/
|
*/
|
||||||
this.expression = expression;
|
constructor(tagName, propertyName, expression, opt_matchCase) {
|
||||||
|
|
||||||
/**
|
super(tagName, propertyName);
|
||||||
* @type {boolean|undefined}
|
|
||||||
*/
|
/**
|
||||||
this.matchCase = opt_matchCase;
|
* @type {!(string|number)}
|
||||||
};
|
*/
|
||||||
|
this.expression = expression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {boolean|undefined}
|
||||||
|
*/
|
||||||
|
this.matchCase = opt_matchCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
inherits(ComparisonBinary, Comparison);
|
|
||||||
export default ComparisonBinary;
|
export default ComparisonBinary;
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/filter/Contains
|
* @module ol/format/filter/Contains
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../../util.js';
|
|
||||||
import Spatial from '../filter/Spatial.js';
|
import Spatial from '../filter/Spatial.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Represents a `<Contains>` operator to test whether a geometry-valued property
|
* Represents a `<Contains>` operator to test whether a geometry-valued property
|
||||||
* contains a given geometry.
|
* contains a given geometry.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {!string} geometryName Geometry name to use.
|
|
||||||
* @param {!module:ol/geom/Geometry} geometry Geometry.
|
|
||||||
* @param {string=} opt_srsName SRS name. No srsName attribute will be
|
|
||||||
* set on geometries when this is not provided.
|
|
||||||
* @extends {module:ol/format/filter/Spatial}
|
|
||||||
* @api
|
|
||||||
*/
|
*/
|
||||||
const Contains = function(geometryName, geometry, opt_srsName) {
|
class Contains extends Spatial {
|
||||||
|
|
||||||
Spatial.call(this, 'Contains', geometryName, geometry, opt_srsName);
|
/**
|
||||||
|
* @param {!string} geometryName Geometry name to use.
|
||||||
|
* @param {!module:ol/geom/Geometry} geometry Geometry.
|
||||||
|
* @param {string=} opt_srsName SRS name. No srsName attribute will be
|
||||||
|
* set on geometries when this is not provided.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
constructor(geometryName, geometry, opt_srsName) {
|
||||||
|
|
||||||
};
|
super('Contains', geometryName, geometry, opt_srsName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
inherits(Contains, Spatial);
|
|
||||||
export default Contains;
|
export default Contains;
|
||||||
|
|||||||
@@ -1,33 +1,34 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/filter/During
|
* @module ol/format/filter/During
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../../util.js';
|
|
||||||
import Comparison from '../filter/Comparison.js';
|
import Comparison from '../filter/Comparison.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Represents a `<During>` comparison operator.
|
* Represents a `<During>` comparison operator.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {!string} propertyName Name of the context property to compare.
|
|
||||||
* @param {!string} begin The begin date in ISO-8601 format.
|
|
||||||
* @param {!string} end The end date in ISO-8601 format.
|
|
||||||
* @extends {module:ol/format/filter/Comparison}
|
|
||||||
* @api
|
|
||||||
*/
|
*/
|
||||||
const During = function(propertyName, begin, end) {
|
class During extends Comparison {
|
||||||
Comparison.call(this, 'During', propertyName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {!string}
|
* @param {!string} propertyName Name of the context property to compare.
|
||||||
|
* @param {!string} begin The begin date in ISO-8601 format.
|
||||||
|
* @param {!string} end The end date in ISO-8601 format.
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
this.begin = begin;
|
constructor(propertyName, begin, end) {
|
||||||
|
super('During', propertyName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {!string}
|
* @type {!string}
|
||||||
*/
|
*/
|
||||||
this.end = end;
|
this.begin = begin;
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @type {!string}
|
||||||
|
*/
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
inherits(During, Comparison);
|
|
||||||
export default During;
|
export default During;
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/filter/EqualTo
|
* @module ol/format/filter/EqualTo
|
||||||
*/
|
*/
|
||||||
import {inherits} from '../../util.js';
|
|
||||||
import ComparisonBinary from '../filter/ComparisonBinary.js';
|
import ComparisonBinary from '../filter/ComparisonBinary.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Represents a `<PropertyIsEqualTo>` comparison operator.
|
* Represents a `<PropertyIsEqualTo>` comparison operator.
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {!string} propertyName Name of the context property to compare.
|
|
||||||
* @param {!(string|number)} expression The value to compare.
|
|
||||||
* @param {boolean=} opt_matchCase Case-sensitive?
|
|
||||||
* @extends {module:ol/format/filter/ComparisonBinary}
|
|
||||||
* @api
|
|
||||||
*/
|
*/
|
||||||
const EqualTo = function(propertyName, expression, opt_matchCase) {
|
class EqualTo extends ComparisonBinary {
|
||||||
ComparisonBinary.call(this, 'PropertyIsEqualTo', propertyName, expression, opt_matchCase);
|
|
||||||
};
|
/**
|
||||||
|
* @param {!string} propertyName Name of the context property to compare.
|
||||||
|
* @param {!(string|number)} expression The value to compare.
|
||||||
|
* @param {boolean=} opt_matchCase Case-sensitive?
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
constructor(propertyName, expression, opt_matchCase) {
|
||||||
|
super('PropertyIsEqualTo', propertyName, expression, opt_matchCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
inherits(EqualTo, ComparisonBinary);
|
|
||||||
export default EqualTo;
|
export default EqualTo;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user