Compare commits
227 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47b53ded6d | ||
|
|
3c8aeb7287 | ||
|
|
7b899fa767 | ||
|
|
f695cb012a | ||
|
|
929ce05f81 | ||
|
|
81b7a77954 | ||
|
|
91045b0ad1 | ||
|
|
b11f6abb3c | ||
|
|
571f3f30a4 | ||
|
|
85ddded15c | ||
|
|
d3c8880b22 | ||
|
|
54d3bbd625 | ||
|
|
405a8db075 | ||
|
|
27e58be43d | ||
|
|
cee34fa51b | ||
|
|
16aa548383 | ||
|
|
860fdabd76 | ||
|
|
761aa0ea5c | ||
|
|
d493d0a820 | ||
|
|
d6e35edac5 | ||
|
|
2143eebd30 | ||
|
|
64225776d4 | ||
|
|
355c3c7b58 | ||
|
|
e792a121f4 | ||
|
|
3364dbb46e | ||
|
|
23610efe30 | ||
|
|
75bf3e1ccf | ||
|
|
f2f5cd2630 | ||
|
|
6f6698dd6a | ||
|
|
4320b07c5d | ||
|
|
25603d7cf1 | ||
|
|
935eb63876 | ||
|
|
6111b91cca | ||
|
|
7a34d22b37 | ||
|
|
c3f51c676a | ||
|
|
968c8aa34e | ||
|
|
b001a48567 | ||
|
|
bf9156cbeb | ||
|
|
bafd8548d1 | ||
|
|
e3ead5df06 | ||
|
|
22ca08179d | ||
|
|
c8df907ff2 | ||
|
|
c0950dee11 | ||
|
|
da3d8952da | ||
|
|
95e43c852d | ||
|
|
d4d3555a88 | ||
|
|
ef9a1a25b1 | ||
|
|
44fdfaa630 | ||
|
|
112473afee | ||
|
|
5e505f200a | ||
|
|
5e4474ca8c | ||
|
|
d3f766c748 | ||
|
|
2b1acc6216 | ||
|
|
c008de1a88 | ||
|
|
e6a38d8211 | ||
|
|
e6f4054d3b | ||
|
|
fe636a0e98 | ||
|
|
76d36d4b20 | ||
|
|
abb5fef043 | ||
|
|
0c486c522a | ||
|
|
af3c38052e | ||
|
|
f1ff39cc8b | ||
|
|
643c2e6f21 | ||
|
|
d5aa0d9a8e | ||
|
|
793b27e9f5 | ||
|
|
9d28549b2b | ||
|
|
ef90f5a097 | ||
|
|
c50d775330 | ||
|
|
6da6cef760 | ||
|
|
1d94d71a5b | ||
|
|
65fee5b7ac | ||
|
|
5267776627 | ||
|
|
a721ce03c9 | ||
|
|
23e2fcefef | ||
|
|
d17d470d48 | ||
|
|
c6dedbc40b | ||
|
|
de107c5502 | ||
|
|
6740ca9ee8 | ||
|
|
2c82ca86f0 | ||
|
|
b7ad9160ef | ||
|
|
acc97a53eb | ||
|
|
7634c0c2c4 | ||
|
|
49cc39c4dd | ||
|
|
3595c2cce7 | ||
|
|
80c4809aee | ||
|
|
10b4aa1bab | ||
|
|
8f7cbc5ed6 | ||
|
|
7094f65ef7 | ||
|
|
ac8e62818f | ||
|
|
c89fb3ccfe | ||
|
|
223d5ab60d | ||
|
|
2142b538ac | ||
|
|
5149889bd2 | ||
|
|
b57cdb730c | ||
|
|
8600d46a0e | ||
|
|
7509425aa4 | ||
|
|
c9ab9bc711 | ||
|
|
cd6ac857b9 | ||
|
|
7b35557cee | ||
|
|
4549d2f7a8 | ||
|
|
7780d77ade | ||
|
|
bfaac061c8 | ||
|
|
afce912f11 | ||
|
|
a705c6fe11 | ||
|
|
26e146b1d8 | ||
|
|
a62bbd6650 | ||
|
|
38fa805f03 | ||
|
|
1d3f8b5d7d | ||
|
|
c53aa7e8d5 | ||
|
|
109cd6f3a6 | ||
|
|
4f703efd23 | ||
|
|
a157fff318 | ||
|
|
84ed12ec46 | ||
|
|
5fb692a876 | ||
|
|
06908775e8 | ||
|
|
da66a37182 | ||
|
|
96eaf2de06 | ||
|
|
86d9d691e4 | ||
|
|
c69ba6a3dd | ||
|
|
2adf3befb8 | ||
|
|
f81e36d8e0 | ||
|
|
f7d62f054c | ||
|
|
c0b6eefd8f | ||
|
|
a09fa923a5 | ||
|
|
7c207d47bb | ||
|
|
eac5d652cf | ||
|
|
4d3e903670 | ||
|
|
e7cd691362 | ||
|
|
74759142d9 | ||
|
|
3021d3a6a7 | ||
|
|
cfafe90235 | ||
|
|
ccaca9fc52 | ||
|
|
3f918f4e8d | ||
|
|
5871d64c9d | ||
|
|
d1f19b8e0d | ||
|
|
3f214f6ac4 | ||
|
|
0159d20d6d | ||
|
|
ce20380078 | ||
|
|
f9e5c9c596 | ||
|
|
7d04ef3e2d | ||
|
|
ced3633d80 | ||
|
|
e62b2e4479 | ||
|
|
8cf57941ac | ||
|
|
dd132c9fad | ||
|
|
1cdfc709ae | ||
|
|
1b01efc08b | ||
|
|
28450cbb5a | ||
|
|
1c341e288c | ||
|
|
3f23deb09a | ||
|
|
ceafa88dc8 | ||
|
|
54186d7893 | ||
|
|
9a0c0e2f2b | ||
|
|
c6d1778202 | ||
|
|
e532727713 | ||
|
|
edc16b9739 | ||
|
|
59871274ca | ||
|
|
039b54de48 | ||
|
|
5993b45c63 | ||
|
|
5c5364bbb7 | ||
|
|
6411c9267b | ||
|
|
f85fcf30a2 | ||
|
|
b5e0ae6f8c | ||
|
|
e6f5c2a008 | ||
|
|
31cfa0d952 | ||
|
|
a753d282cc | ||
|
|
e3a8dc89de | ||
|
|
18aa9b5091 | ||
|
|
84e051d19b | ||
|
|
af319c259b | ||
|
|
0af5642569 | ||
|
|
d6118f31e4 | ||
|
|
7463a58066 | ||
|
|
f645a9e1e4 | ||
|
|
a9591f8b99 | ||
|
|
43d9ebe51d | ||
|
|
aa90c97ba3 | ||
|
|
874c4aef21 | ||
|
|
2249c82ac2 | ||
|
|
a2c9a0796c | ||
|
|
d6bb13b54b | ||
|
|
d628f6b098 | ||
|
|
e2da56afa1 | ||
|
|
f74e4c95ff | ||
|
|
b8cb1fe795 | ||
|
|
1e8968d97a | ||
|
|
9c480d77f5 | ||
|
|
0e943f5832 | ||
|
|
e99f43af8d | ||
|
|
2bcb10c973 | ||
|
|
9301fff6cb | ||
|
|
83c33a03c6 | ||
|
|
e848acd806 | ||
|
|
72cc824502 | ||
|
|
4b3aac32c3 | ||
|
|
acab0ebd57 | ||
|
|
6a4d1c9b89 | ||
|
|
698b62af98 | ||
|
|
817370a65b | ||
|
|
07d5211e30 | ||
|
|
3fcecc98e6 | ||
|
|
6ed677a3f0 | ||
|
|
dd16bb984c | ||
|
|
f672c1792b | ||
|
|
0286564e8a | ||
|
|
96e75ab17f | ||
|
|
a6dddfa282 | ||
|
|
5a2a7d30e6 | ||
|
|
d5ea855108 | ||
|
|
d8a495b639 | ||
|
|
4aa3ef59d5 | ||
|
|
7451e176ef | ||
|
|
872d869ded | ||
|
|
d48e818390 | ||
|
|
fad3cf9672 | ||
|
|
9acd65270a | ||
|
|
57e1dda5f1 | ||
|
|
53d5d8c1d9 | ||
|
|
54da473991 | ||
|
|
f186ed3deb | ||
|
|
973cc6fd89 | ||
|
|
36b521a00e | ||
|
|
7065722fa6 | ||
|
|
10b54a9f3f | ||
|
|
e3bc0bca3e | ||
|
|
b903cee7dd | ||
|
|
282fdafad7 | ||
|
|
ab9100450b |
@@ -1,8 +1,13 @@
|
||||
language: python
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
env:
|
||||
- DISPLAY=:99.0
|
||||
|
||||
before_install:
|
||||
- "sudo pip install -r requirements.txt"
|
||||
- "pip install -r requirements.txt"
|
||||
- "npm install -g npm && npm install"
|
||||
|
||||
before_script:
|
||||
|
||||
3
Makefile
3
Makefile
@@ -19,7 +19,8 @@ BUILD_HOSTED := build/hosted/$(BRANCH)
|
||||
BUILD_HOSTED_EXAMPLES := $(addprefix $(BUILD_HOSTED)/,$(EXAMPLES))
|
||||
BUILD_HOSTED_EXAMPLES_JS := $(addprefix $(BUILD_HOSTED)/,$(EXAMPLES_JS))
|
||||
|
||||
CHECK_EXAMPLE_TIMESTAMPS = $(patsubst examples/%.html,build/timestamps/check-%-timestamp,$(EXAMPLES_HTML))
|
||||
UNPHANTOMABLE_EXAMPLES = examples/shaded-relief.html examples/raster.html examples/region-growing.html
|
||||
CHECK_EXAMPLE_TIMESTAMPS = $(patsubst examples/%.html,build/timestamps/check-%-timestamp,$(filter-out $(UNPHANTOMABLE_EXAMPLES),$(EXAMPLES_HTML)))
|
||||
|
||||
TASKS_JS := $(shell find tasks -name '*.js')
|
||||
|
||||
|
||||
@@ -1,5 +1,110 @@
|
||||
## Upgrade notes
|
||||
|
||||
### v3.8.0
|
||||
|
||||
There should be nothing special required when upgrading from v3.7.0 to v3.8.0.
|
||||
|
||||
### v3.7.0
|
||||
|
||||
#### Removal of `ol.FeatureOverlay`
|
||||
|
||||
Instead of an `ol.FeatureOverlay`, we now use an `ol.layer.Vector` with an
|
||||
`ol.source.Vector`. If you previously had:
|
||||
```js
|
||||
var featureOverlay = new ol.FeatureOverlay({
|
||||
map: map,
|
||||
style: overlayStyle
|
||||
});
|
||||
featureOverlay.addFeature(feature);
|
||||
featureOverlay.removeFeature(feature);
|
||||
var collection = featureOverlay.getFeatures();
|
||||
```
|
||||
you will have to change this to:
|
||||
```js
|
||||
var collection = new ol.Collection();
|
||||
var featureOverlay = new ol.layer.Vector({
|
||||
map: map,
|
||||
source: new ol.source.Vector({
|
||||
features: collection,
|
||||
useSpatialIndex: false // optional, might improve performance
|
||||
}),
|
||||
style: overlayStyle,
|
||||
updateWhileAnimating: true, // optional, for instant visual feedback
|
||||
updateWhileInteracting: true // optional, for instant visual feedback
|
||||
});
|
||||
featureOverlay.getSource().addFeature(feature);
|
||||
featureOverlay.getSource().removeFeature(feature);
|
||||
```
|
||||
|
||||
With the removal of `ol.FeatureOverlay`, `zIndex` symbolizer properties of overlays are no longer stacked per map, but per layer/overlay. If you previously had multiple feature overlays where you controlled the rendering order of features by using `zIndex` symbolizer properties, you can now achieve the same rendering order only if all overlay features are on the same layer.
|
||||
|
||||
Note that `ol.FeatureOverlay#getFeatures()` returned an `{ol.Collection.<ol.Feature>}`, whereas `ol.source.Vector#getFeatures()` returns an `{Array.<ol.Feature>}`.
|
||||
|
||||
#### `ol.TileCoord` changes
|
||||
|
||||
Until now, the API exposed two different types of `ol.TileCoord` tile coordinates: internal ones that increase left to right and upward, and transformed ones that may increase downward, as defined by a transform function on the tile grid. With this change, the API now only exposes tile coordinates that increase left to right and upward.
|
||||
|
||||
Previously, tile grids created by OpenLayers either had their origin at the top-left or at the bottom-left corner of the extent. To make it easier for application developers to transform tile coordinates to the common XYZ tiling scheme, all tile grids that OpenLayers creates internally have their origin now at the top-left corner of the extent.
|
||||
|
||||
This change affects applications that configure a custom `tileUrlFunction` for an `ol.source.Tile`. Previously, the `tileUrlFunction` was called with rather unpredictable tile coordinates, depending on whether a tile coordinate transform took place before calling the `tileUrlFunction`. Now it is always called with OpenLayers tile coordinates. To transform these into the common XYZ tiling scheme, a custom `tileUrlFunction` has to change the `y` value (tile row) of the `ol.TileCoord`:
|
||||
```js
|
||||
function tileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
var urlTemplate = '{z}/{x}/{y}';
|
||||
return urlTemplate
|
||||
.replace('{z}', tileCoord[0].toString())
|
||||
.replace('{x}', tileCoord[1].toString())
|
||||
.replace('{y}', (-tileCoord[2] - 1).toString());
|
||||
}
|
||||
```
|
||||
|
||||
The `ol.tilegrid.TileGrid#createTileCoordTransform()` function which could be used to get the tile grid's tile coordinate transform function has been removed. This function was confusing and should no longer be needed now that application developers get tile coordinates in a known layout.
|
||||
|
||||
The code snippets below show how your application code needs to be changed:
|
||||
|
||||
Old application code (with `ol.tilegrid.TileGrid#createTileCoordTransform()`):
|
||||
```js
|
||||
var transform = source.getTileGrid().createTileCoordTransform();
|
||||
var tileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
tileCoord = transform(tileCoord, projection);
|
||||
return 'http://mytiles.com/' +
|
||||
tileCoord[0] + '/' + tileCoord[1] + '/' + tileCoord[2] + '.png';
|
||||
};
|
||||
```
|
||||
Old application code (with custom `y` transform):
|
||||
```js
|
||||
var tileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
var z = tileCoord[0];
|
||||
var yFromBottom = tileCoord[2];
|
||||
var resolution = tileGrid.getResolution(z);
|
||||
var tileHeight = ol.size.toSize(tileSize)[1];
|
||||
var matrixHeight =
|
||||
Math.floor(ol.extent.getHeight(extent) / tileHeight / resolution);
|
||||
return 'http://mytiles.com/' +
|
||||
tileCoord[0] + '/' + tileCoord[1] + '/' +
|
||||
(matrixHeight - yFromBottom - 1) + '.png';
|
||||
|
||||
};
|
||||
```
|
||||
New application code (simple -y - 1 transform):
|
||||
```js
|
||||
var tileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
return 'http://mytiles.com/' +
|
||||
tileCoord[0] + '/' + tileCoord[1] + '/' + (-tileCoord[2] - 1) + '.png';
|
||||
};
|
||||
```
|
||||
|
||||
#### Removal of `ol.tilegrid.Zoomify`
|
||||
|
||||
The replacement of `ol.tilegrid.Zoomify` is a plain `ol.tilegrid.TileGrid`, configured with `extent`, `origin` and `resolutions`. If the `size` passed to the `ol.source.Zoomify` source is `[width, height]`, then the extent for the tile grid will be `[0, -height, width, 0]`, and the origin will be `[0, 0]`.
|
||||
|
||||
#### Replace `ol.View.fitExtent()` and `ol.View.fitGeometry()` with `ol.View.fit()`
|
||||
* This combines two previously distinct functions into one more flexible call which takes either a geometry or an extent.
|
||||
* Rename all calls to `fitExtent` and `fitGeometry` to `fit`.
|
||||
|
||||
#### Change to `ol.interaction.Modify`
|
||||
|
||||
When single clicking a line or boundary within the `pixelTolerance`, a vertex is now created.
|
||||
|
||||
### v3.6.0
|
||||
|
||||
#### `ol.interaction.Draw` changes
|
||||
|
||||
152
changelog/v3.7.0.md
Normal file
152
changelog/v3.7.0.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# v3.7.0
|
||||
|
||||
## Summary
|
||||
|
||||
The v3.7.0 release includes features and fixes from 43 pull requests since v3.6.0. To simplify the code base, there were some changes to "experimental" features. Please follow the upgrade notes to make your applications work with the latest release.
|
||||
|
||||
## Upgrade notes
|
||||
|
||||
#### Removal of `ol.FeatureOverlay`
|
||||
|
||||
Instead of an `ol.FeatureOverlay`, we now use an `ol.layer.Vector` with an
|
||||
`ol.source.Vector`. If you previously had:
|
||||
```js
|
||||
var featureOverlay = new ol.FeatureOverlay({
|
||||
map: map,
|
||||
style: overlayStyle
|
||||
});
|
||||
featureOverlay.addFeature(feature);
|
||||
featureOverlay.removeFeature(feature);
|
||||
var collection = featureOverlay.getFeatures();
|
||||
```
|
||||
you will have to change this to:
|
||||
```js
|
||||
var collection = new ol.Collection();
|
||||
var featureOverlay = new ol.layer.Vector({
|
||||
map: map,
|
||||
source: new ol.source.Vector({
|
||||
features: collection,
|
||||
useSpatialIndex: false // optional, might improve performance
|
||||
}),
|
||||
style: overlayStyle,
|
||||
updateWhileAnimating: true, // optional, for instant visual feedback
|
||||
updateWhileInteracting: true // optional, for instant visual feedback
|
||||
});
|
||||
featureOverlay.getSource().addFeature(feature);
|
||||
featureOverlay.getSource().removeFeature(feature);
|
||||
```
|
||||
|
||||
With the removal of `ol.FeatureOverlay`, `zIndex` symbolizer properties of overlays are no longer stacked per map, but per layer/overlay. If you previously had multiple feature overlays where you controlled the rendering order of features by using `zIndex` symbolizer properties, you can now achieve the same rendering order only if all overlay features are on the same layer.
|
||||
|
||||
Note that `ol.FeatureOverlay#getFeatures()` returned an `{ol.Collection.<ol.Feature>}`, whereas `ol.source.Vector#getFeatures()` returns an `{Array.<ol.Feature>}`.
|
||||
|
||||
#### `ol.TileCoord` changes
|
||||
|
||||
Until now, the API exposed two different types of `ol.TileCoord` tile coordinates: internal ones that increase left to right and upward, and transformed ones that may increase downward, as defined by a transform function on the tile grid. With this change, the API now only exposes tile coordinates that increase left to right and upward.
|
||||
|
||||
Previously, tile grids created by OpenLayers either had their origin at the top-left or at the bottom-left corner of the extent. To make it easier for application developers to transform tile coordinates to the common XYZ tiling scheme, all tile grids that OpenLayers creates internally have their origin now at the top-left corner of the extent.
|
||||
|
||||
This change affects applications that configure a custom `tileUrlFunction` for an `ol.source.Tile`. Previously, the `tileUrlFunction` was called with rather unpredictable tile coordinates, depending on whether a tile coordinate transform took place before calling the `tileUrlFunction`. Now it is always called with OpenLayers tile coordinates. To transform these into the common XYZ tiling scheme, a custom `tileUrlFunction` has to change the `y` value (tile row) of the `ol.TileCoord`:
|
||||
```js
|
||||
function tileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
var urlTemplate = '{z}/{x}/{y}';
|
||||
return urlTemplate
|
||||
.replace('{z}', tileCoord[0].toString())
|
||||
.replace('{x}', tileCoord[1].toString())
|
||||
.replace('{y}', (-tileCoord[2] - 1).toString());
|
||||
}
|
||||
```
|
||||
|
||||
The `ol.tilegrid.TileGrid#createTileCoordTransform()` function which could be used to get the tile grid's tile coordinate transform function has been removed. This function was confusing and should no longer be needed now that application developers get tile coordinates in a known layout.
|
||||
|
||||
The code snippets below show how your application code needs to be changed:
|
||||
|
||||
Old application code (with `ol.tilegrid.TileGrid#createTileCoordTransform()`):
|
||||
```js
|
||||
var transform = source.getTileGrid().createTileCoordTransform();
|
||||
var tileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
tileCoord = transform(tileCoord, projection);
|
||||
return 'http://mytiles.com/' +
|
||||
tileCoord[0] + '/' + tileCoord[1] + '/' + tileCoord[2] + '.png';
|
||||
};
|
||||
```
|
||||
Old application code (with custom `y` transform):
|
||||
```js
|
||||
var tileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
var z = tileCoord[0];
|
||||
var yFromBottom = tileCoord[2];
|
||||
var resolution = tileGrid.getResolution(z);
|
||||
var tileHeight = ol.size.toSize(tileSize)[1];
|
||||
var matrixHeight =
|
||||
Math.floor(ol.extent.getHeight(extent) / tileHeight / resolution);
|
||||
return 'http://mytiles.com/' +
|
||||
tileCoord[0] + '/' + tileCoord[1] + '/' +
|
||||
(matrixHeight - yFromBottom - 1) + '.png';
|
||||
|
||||
};
|
||||
```
|
||||
New application code (simple -y - 1 transform):
|
||||
```js
|
||||
var tileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
return 'http://mytiles.com/' +
|
||||
tileCoord[0] + '/' + tileCoord[1] + '/' + (-tileCoord[2] - 1) + '.png';
|
||||
};
|
||||
```
|
||||
|
||||
#### Removal of `ol.tilegrid.Zoomify`
|
||||
|
||||
The replacement of `ol.tilegrid.Zoomify` is a plain `ol.tilegrid.TileGrid`, configured with `extent`, `origin` and `resolutions`. If the `size` passed to the `ol.source.Zoomify` source is `[width, height]`, then the extent for the tile grid will be `[0, -height, width, 0]`, and the origin will be `[0, 0]`.
|
||||
|
||||
#### Replace `ol.View.fitExtent()` and `ol.View.fitGeometry()` with `ol.View.fit()`
|
||||
* This combines two previously distinct functions into one more flexible call which takes either a geometry or an extent.
|
||||
* Rename all calls to `fitExtent` and `fitGeometry` to `fit`.
|
||||
|
||||
#### Change to `ol.interaction.Modify`
|
||||
|
||||
When single clicking a line or boundary within the `pixelTolerance`, a vertex is now created.
|
||||
|
||||
## New features and fixes
|
||||
|
||||
* [#3867](https://github.com/openlayers/ol3/pull/3867) - Do not require projection extent for x-wrapping tile sources ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3635](https://github.com/openlayers/ol3/pull/3635) - Create vertex on boundary single click ([@bjornharrtell](https://github.com/bjornharrtell))
|
||||
* [#3806](https://github.com/openlayers/ol3/pull/3806) - Do not clip canvas for vector layers when wrapping the world ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3461](https://github.com/openlayers/ol3/pull/3461) - High level Modify interaction events ([@bjornharrtell](https://github.com/bjornharrtell))
|
||||
* [#3865](https://github.com/openlayers/ol3/pull/3865) - ol.View#fit() ([@bartvde](https://github.com/bartvde))
|
||||
* [#3864](https://github.com/openlayers/ol3/pull/3864) - Check projection.canWrapX() before wrapping tiles ([@klokantech](https://github.com/klokantech))
|
||||
* [#3863](https://github.com/openlayers/ol3/pull/3863) - Handle CDATA in attribute parsing for GML format ([@nhambletCCRI](https://github.com/nhambletCCRI))
|
||||
* [#3860](https://github.com/openlayers/ol3/pull/3860) - Update example layout. ([@tschaub](https://github.com/tschaub))
|
||||
* [#3861](https://github.com/openlayers/ol3/pull/3861) - Don't force 'dom' renderer ([@openlayers](https://github.com/openlayers))
|
||||
* [#3855](https://github.com/openlayers/ol3/pull/3855) - Adding an example with WMTS tiles from IGN Geoportail ([@pgiraud](https://github.com/pgiraud))
|
||||
* [#3856](https://github.com/openlayers/ol3/pull/3856) - ol.source.TileVector(): bind success function of tileLoadFunction to source ([@plepe](https://github.com/plepe))
|
||||
* [#3848](https://github.com/openlayers/ol3/pull/3848) - Check for exports before define. ([@tschaub](https://github.com/tschaub))
|
||||
* [#3845](https://github.com/openlayers/ol3/pull/3845) - Prevent null array to be passed to an ol.Collection ([@fredj](https://github.com/fredj))
|
||||
* [#3849](https://github.com/openlayers/ol3/pull/3849) - Pad min. and sec. with leading zeros in DMS notation ([@pgiraud](https://github.com/pgiraud))
|
||||
* [#3842](https://github.com/openlayers/ol3/pull/3842) - Adding a feature-animation example ([@pgiraud](https://github.com/pgiraud))
|
||||
* [#3833](https://github.com/openlayers/ol3/pull/3833) - Enable use of custom XHR loader for TileVector sources ([@bjornharrtell](https://github.com/bjornharrtell))
|
||||
* [#3834](https://github.com/openlayers/ol3/pull/3834) - ArcGIS tiled example broken in Chrome ([@bartvde](https://github.com/bartvde))
|
||||
* [#3829](https://github.com/openlayers/ol3/pull/3829) - incorrect assert message ([@kzr-pzr](https://github.com/kzr-pzr))
|
||||
* [#3828](https://github.com/openlayers/ol3/pull/3828) - Fix typo in upgrade notes ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3826](https://github.com/openlayers/ol3/pull/3826) - Allow custom tileGrid in ol.source.XYZ ([@klokantech](https://github.com/klokantech))
|
||||
* [#3815](https://github.com/openlayers/ol3/pull/3815) - Simplify tilegrid API and internals ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3820](https://github.com/openlayers/ol3/pull/3820) - Make unmanaged vector layers behave more like ol.FeatureOverlay ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3822](https://github.com/openlayers/ol3/pull/3822) - Correct docs for updateWhileInteracting ([@probins](https://github.com/probins))
|
||||
* [#3818](https://github.com/openlayers/ol3/pull/3818) - Make geometry.transform api stable again. ([@probins](https://github.com/probins))
|
||||
* [#3801](https://github.com/openlayers/ol3/pull/3801) - Respect the tile grid's extent in ol.source.TileVector ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3810](https://github.com/openlayers/ol3/pull/3810) - Improve TileGrid documentation and examples ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3808](https://github.com/openlayers/ol3/pull/3808) - Correct typo in OverlayOptions ([@probins](https://github.com/probins))
|
||||
* [#3766](https://github.com/openlayers/ol3/pull/3766) - Add a clickTolerance option to the Draw interaction ([@elemoine](https://github.com/elemoine))
|
||||
* [#3804](https://github.com/openlayers/ol3/pull/3804) - Remove sentence that was only meant for WMTS tile grids ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3800](https://github.com/openlayers/ol3/pull/3800) - Remove further references to FeatureOverlay ([@probins](https://github.com/probins))
|
||||
* [#3780](https://github.com/openlayers/ol3/pull/3780) - Only expose transformed tile coordinates to the API ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3793](https://github.com/openlayers/ol3/pull/3793) - Use 'managed' instead of 'unmanaged' in LayerState ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3792](https://github.com/openlayers/ol3/pull/3792) - Link to correct layer base class ([@marcjansen](https://github.com/marcjansen))
|
||||
* [#3791](https://github.com/openlayers/ol3/pull/3791) - Remove docs referring to removed feature overlay ([@marcjansen](https://github.com/marcjansen))
|
||||
* [#3790](https://github.com/openlayers/ol3/pull/3790) - Remove unnecessary quotes around object keys ([@fredj](https://github.com/fredj))
|
||||
* [#3787](https://github.com/openlayers/ol3/pull/3787) - Add 'unmanaged' to ol.layer.LayerState ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3784](https://github.com/openlayers/ol3/pull/3784) - Always write the GeoJSONFeature geometry property ([@fredj](https://github.com/fredj))
|
||||
* [#3783](https://github.com/openlayers/ol3/pull/3783) - Fix broken wmts-hidpi example ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3782](https://github.com/openlayers/ol3/pull/3782) - Fix assert documentation typo ([@gberaudo](https://github.com/gberaudo))
|
||||
* [#3758](https://github.com/openlayers/ol3/pull/3758) - Removal of ol.FeatureOverlay ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3775](https://github.com/openlayers/ol3/pull/3775) - Add ol-touch but keep ol-viewport className. ([@pgiraud](https://github.com/pgiraud))
|
||||
* [#3713](https://github.com/openlayers/ol3/pull/3713) - Add missing propertyNames member for olx.format.WFSWriteGetFeatureOptions ([@bartvde](https://github.com/bartvde))
|
||||
* [#3763](https://github.com/openlayers/ol3/pull/3763) - Standardise draw/modify descriptions ([@probins](https://github.com/probins))
|
||||
41
changelog/v3.8.0.md
Normal file
41
changelog/v3.8.0.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# v3.8.0
|
||||
|
||||
## Summary
|
||||
|
||||
The v3.8.0 release includes features and fixes from 33 pull requests since v3.7.0. While summer vacations have slowed the pace of development a bit this month, there are some nice improvements in this release. See the complete list below for details.
|
||||
|
||||
## New features and fixes
|
||||
|
||||
* [#3957](https://github.com/openlayers/ol3/pull/3957) - Properly handle vertex deletion with multiple features. ([@tschaub](https://github.com/tschaub))
|
||||
* [#3954](https://github.com/openlayers/ol3/pull/3954) - Remove ol.control.Control.bindMouseOutFocusOutBlur function. ([@fredj](https://github.com/fredj))
|
||||
* [#3214](https://github.com/openlayers/ol3/pull/3214) - Pixel manipulation with raster sources. ([@tschaub](https://github.com/tschaub))
|
||||
* [#3946](https://github.com/openlayers/ol3/pull/3946) - Fix vertex deletion for Modify interaction on mobile devices. ([@Turbo87](https://github.com/Turbo87))
|
||||
* [#3910](https://github.com/openlayers/ol3/pull/3910) - Do not provide an AMD environment to ol.ext modules. ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3934](https://github.com/openlayers/ol3/pull/3934) - Fix `drawstart` and `drawend` events when drawing a point ([@fredj](https://github.com/fredj))
|
||||
* [#3774](https://github.com/openlayers/ol3/pull/3774) - Measure tooltips touchdevice ([@pgiraud](https://github.com/pgiraud))
|
||||
* [#3949](https://github.com/openlayers/ol3/pull/3949) - Remove count argument from `called` function ([@fredj](https://github.com/fredj))
|
||||
* [#3950](https://github.com/openlayers/ol3/pull/3950) - Remove reference to vbarray.js ([@elemoine](https://github.com/elemoine))
|
||||
* [#3947](https://github.com/openlayers/ol3/pull/3947) - Clarify documentation of Image source ratio option. ([@alvinlindstam](https://github.com/alvinlindstam))
|
||||
* [#3920](https://github.com/openlayers/ol3/pull/3920) - Remove use_types_for_optimization from custom build tutorial. ([@probins](https://github.com/probins))
|
||||
* [#3922](https://github.com/openlayers/ol3/pull/3922) - Document {?-?} pattern in expandUrl ([@probins](https://github.com/probins))
|
||||
* [#3921](https://github.com/openlayers/ol3/pull/3921) - Cache node_modules on Travis. ([@bjornharrtell](https://github.com/bjornharrtell))
|
||||
* [#3942](https://github.com/openlayers/ol3/pull/3942) - Fix WMTS TileMatrixSet lookup by SRS identifier ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3945](https://github.com/openlayers/ol3/pull/3945) - Simplify icon example and show popup at clicked position ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3930](https://github.com/openlayers/ol3/pull/3930) - Use goog.functions.identity instead of goog.identityFunction ([@fredj](https://github.com/fredj))
|
||||
* [#3929](https://github.com/openlayers/ol3/pull/3929) - Expand description for XYZ source ([@probins](https://github.com/probins))
|
||||
* [#3933](https://github.com/openlayers/ol3/pull/3933) - Snap center to pixel to avoid floating point issues ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3932](https://github.com/openlayers/ol3/pull/3932) - SnapOptions: Fix typo in pixelTolerance JSDoc ([@Turbo87](https://github.com/Turbo87))
|
||||
* [#3931](https://github.com/openlayers/ol3/pull/3931) - Remove unused htmlparser2 package ([@fredj](https://github.com/fredj))
|
||||
* [#3912](https://github.com/openlayers/ol3/pull/3912) - Fix the event type fired by goog.fx.Dragger ([@fredj](https://github.com/fredj))
|
||||
* [#3871](https://github.com/openlayers/ol3/pull/3871) - Document change events properly ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3906](https://github.com/openlayers/ol3/pull/3906) - Clear features properly when there is no spatial index ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3896](https://github.com/openlayers/ol3/pull/3896) - Fire WebGL precompose event in same sequence as other renderers ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3359](https://github.com/openlayers/ol3/pull/3359) - Enable deep clone of MultiPolygon. ([@Kenny806](https://github.com/Kenny806))
|
||||
* [#3895](https://github.com/openlayers/ol3/pull/3895) - Rework the tile queue for multiple queues. ([@aisaacs](https://github.com/aisaacs))
|
||||
* [#3894](https://github.com/openlayers/ol3/pull/3894) - Install Python dependencies without sudo. ([@tschaub](https://github.com/tschaub))
|
||||
* [#3824](https://github.com/openlayers/ol3/pull/3824) - Improve docs for interaction.Select. ([@probins](https://github.com/probins))
|
||||
* [#3884](https://github.com/openlayers/ol3/pull/3884) - Provide a debug loader for the library. ([@tschaub](https://github.com/tschaub))
|
||||
* [#3883](https://github.com/openlayers/ol3/pull/3883) - Ignore layer filter for unmanaged layers ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#3859](https://github.com/openlayers/ol3/pull/3859) - Add in crossOrigin option ([@llambanna](https://github.com/llambanna))
|
||||
* [#3873](https://github.com/openlayers/ol3/pull/3873) - Correct minor typo in modifyinteraction ([@probins](https://github.com/probins))
|
||||
* [#3872](https://github.com/openlayers/ol3/pull/3872) - Correct event notations in ol.Feature ([@probins](https://github.com/probins))
|
||||
7
changelog/v3.8.1.md
Normal file
7
changelog/v3.8.1.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# v3.8.1
|
||||
|
||||
## Summary
|
||||
|
||||
This is a patch release that updates the URL for builds shown in the examples. Details below.
|
||||
|
||||
* [#3970](https://github.com/openlayers/ol3/pull/3970) - Pull builds from openlayers.org. ([@tschaub](https://github.com/tschaub))
|
||||
@@ -20,8 +20,7 @@
|
||||
"externs/jquery-1.9.js",
|
||||
"externs/proj4js.js",
|
||||
"externs/tilejson.js",
|
||||
"externs/topojson.js",
|
||||
"externs/vbarray.js"
|
||||
"externs/topojson.js"
|
||||
],
|
||||
"define": [
|
||||
"goog.array.ASSUME_NATIVE_FUNCTIONS=true",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="../css/ol.css" type="text/css">
|
||||
<link rel="stylesheet" href="./resources/layout.css" type="text/css">
|
||||
{{{ extraHead }}}
|
||||
@@ -15,13 +15,11 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container" id="navbar-inner-container">
|
||||
<a class="brand" href="./"><img src="./resources/logo-70x70.png"> OpenLayers 3 Examples</a>
|
||||
</div>
|
||||
<header class="navbar" role="navigation">
|
||||
<div class="container" id="navbar-inner-container">
|
||||
<a class="navbar-brand" href="./"><img src="./resources/logo-70x70.png"> OpenLayers 3 Examples</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container-fluid">
|
||||
|
||||
@@ -46,16 +44,16 @@
|
||||
<textarea class="hidden" name="css">{{ css.source }}</textarea>
|
||||
<textarea class="hidden" name="html">{{ contents }}</textarea>
|
||||
<input type="hidden" name="wrap" value="l">
|
||||
<input type="hidden" name="resources" value="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css,https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js,https://cdnjs.cloudflare.com/ajax/libs/ol3/{{ olVersion }}/ol.css,https://cdnjs.cloudflare.com/ajax/libs/ol3/{{ olVersion }}/ol.js">
|
||||
<input type="hidden" name="resources" value="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css,https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js,http://openlayers.org/en/{{ olVersion }}/css/ol.css,http://openlayers.org/en/{{ olVersion }}/build/ol.js">
|
||||
<pre><code id="example-source" class="language-markup"><!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ title }}</title>
|
||||
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/{{ olVersion }}/ol.css" type="text/css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/{{ olVersion }}/ol.js"></script>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<link rel="stylesheet" href="http://openlayers.org/en/{{ olVersion }}/css/ol.css" type="text/css">
|
||||
<script src="http://openlayers.org/en/{{ olVersion }}/build/ol.js"></script>
|
||||
{{ extraHead }}
|
||||
{{#if css.source}}
|
||||
<style>
|
||||
@@ -77,8 +75,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
|
||||
<script src="http://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="./resources/common.js"></script>
|
||||
<script src="./resources/prism/prism.min.js"></script>
|
||||
{{{ js.tag }}}
|
||||
|
||||
@@ -68,7 +68,7 @@ var self = this;
|
||||
}
|
||||
?>
|
||||
<li class="<?js= (eventDoclet || data).stability !== 'stable' ? 'unstable' : '' ?>">
|
||||
<code><?js= self.linkto(f, type) ?></code>
|
||||
<code><?js= eventClassName ? self.linkto(f, type) : type ?></code>
|
||||
<?js if (eventClassName) {
|
||||
var eventClass = self.find({longname: eventClassName})[0];
|
||||
if (eventClass) { ?>
|
||||
|
||||
@@ -72,7 +72,6 @@ Creating a custom build requires writing a build configuration file. The format
|
||||
"api", "observable"
|
||||
],
|
||||
"compilation_level": "ADVANCED_OPTIMIZATIONS",
|
||||
"use_types_for_optimization": true,
|
||||
"manage_closure_dependencies": true
|
||||
}
|
||||
}
|
||||
@@ -180,7 +179,7 @@ The Closure documentation explains that "externs" are for external names used in
|
||||
|
||||
### Other compiler options
|
||||
|
||||
There are a couple of other compiler options in the config file above. `manage_closure_dependencies` should always be used. `use_types_for_optimization` should be used for better compression rates.
|
||||
There are a couple of other compiler options in the config file above. `manage_closure_dependencies` should always be used.
|
||||
|
||||
You can specify any of the other compiler options here as needed, such as the renaming reports, output manifest, or source maps. There is a full list of available options in [closure-util](https://github.com/openlayers/closure-util/blob/master/compiler-options.txt).
|
||||
|
||||
@@ -219,7 +218,6 @@ Now let's try a more complicated example: [`heatmaps-earthquakes`](http://openla
|
||||
"goog.DEBUG=false"
|
||||
],
|
||||
"compilation_level": "ADVANCED_OPTIMIZATIONS",
|
||||
"use_types_for_optimization": true,
|
||||
"manage_closure_dependencies": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@ template: example.html
|
||||
title: Canvas tiles example
|
||||
shortdesc: Renders tiles with coordinates for debugging.
|
||||
docs: >
|
||||
<p>The black grid tiles are generated on the client with an HTML5 canvas. Note that the tile coordinates are ol3 normalized tile coordinates (origin bottom left), not
|
||||
OSM tile coordinates (origin top left).</p>
|
||||
The black grid tiles are generated on the client with an HTML5 canvas. The
|
||||
displayed tile coordinates are OpenLayers tile coordinates. These increase
|
||||
from bottom to top, but standard XYZ tiling scheme coordinates increase from
|
||||
top to bottom. To calculate the `y` for a standard XYZ tile coordinate, use
|
||||
`-y - 1`.
|
||||
tags: "layers, openstreetmap, canvas"
|
||||
---
|
||||
<div class="row-fluid">
|
||||
|
||||
@@ -7,15 +7,16 @@ goog.require('ol.source.OSM');
|
||||
goog.require('ol.source.TileDebug');
|
||||
|
||||
|
||||
var osmSource = new ol.source.OSM();
|
||||
var map = new ol.Map({
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.OSM()
|
||||
source: osmSource
|
||||
}),
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.TileDebug({
|
||||
projection: 'EPSG:3857',
|
||||
tileGrid: ol.tilegrid.createXYZ({maxZoom: 22})
|
||||
tileGrid: osmSource.getTileGrid()
|
||||
})
|
||||
})
|
||||
],
|
||||
|
||||
@@ -6,7 +6,7 @@ docs: >
|
||||
This example demonstrates how a map's view can be
|
||||
adjusted so a geometry or coordinate is positioned at a specific
|
||||
pixel location. The map above has top, right, bottom, and left
|
||||
padding applied inside the viewport. The view's <code>fitGeometry</code> method
|
||||
padding applied inside the viewport. The view's <code>fit</code> method
|
||||
is used to fit a geometry in the view with the same padding. The
|
||||
view's <code>centerOn</code> method is used to position a coordinate (Lausanne)
|
||||
at a specific pixel location (the center of the black box).
|
||||
|
||||
@@ -65,7 +65,7 @@ zoomtoswitzerlandbest.addEventListener('click', function() {
|
||||
var feature = source.getFeatures()[0];
|
||||
var polygon = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry());
|
||||
var size = /** @type {ol.Size} */ (map.getSize());
|
||||
view.fitGeometry(
|
||||
view.fit(
|
||||
polygon,
|
||||
size,
|
||||
{
|
||||
@@ -81,7 +81,7 @@ zoomtoswitzerlandconstrained.addEventListener('click', function() {
|
||||
var feature = source.getFeatures()[0];
|
||||
var polygon = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry());
|
||||
var size = /** @type {ol.Size} */ (map.getSize());
|
||||
view.fitGeometry(
|
||||
view.fit(
|
||||
polygon,
|
||||
size,
|
||||
{
|
||||
@@ -96,7 +96,7 @@ zoomtoswitzerlandnearest.addEventListener('click', function() {
|
||||
var feature = source.getFeatures()[0];
|
||||
var polygon = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry());
|
||||
var size = /** @type {ol.Size} */ (map.getSize());
|
||||
view.fitGeometry(
|
||||
view.fit(
|
||||
polygon,
|
||||
size,
|
||||
{
|
||||
@@ -111,7 +111,7 @@ zoomtolausanne.addEventListener('click', function() {
|
||||
var feature = source.getFeatures()[1];
|
||||
var point = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry());
|
||||
var size = /** @type {ol.Size} */ (map.getSize());
|
||||
view.fitGeometry(
|
||||
view.fit(
|
||||
point,
|
||||
size,
|
||||
{
|
||||
|
||||
@@ -122,7 +122,7 @@ dragAndDropInteraction.on('addfeatures', function(event) {
|
||||
style: styleFunction
|
||||
})
|
||||
}));
|
||||
map.getView().fitExtent(
|
||||
map.getView().fit(
|
||||
vectorSource.getExtent(), /** @type {ol.Size} */ (map.getSize()));
|
||||
});
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ dragAndDropInteraction.on('addfeatures', function(event) {
|
||||
source: vectorSource,
|
||||
style: styleFunction
|
||||
}));
|
||||
map.getView().fitExtent(
|
||||
map.getView().fit(
|
||||
vectorSource.getExtent(), /** @type {ol.Size} */ (map.getSize()));
|
||||
});
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.events.condition');
|
||||
goog.require('ol.interaction.Draw');
|
||||
goog.require('ol.interaction.Modify');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.MapQuest');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Circle');
|
||||
goog.require('ol.style.Fill');
|
||||
goog.require('ol.style.Stroke');
|
||||
@@ -24,11 +26,9 @@ var map = new ol.Map({
|
||||
})
|
||||
});
|
||||
|
||||
// The features are not added to a regular vector layer/source,
|
||||
// but to a feature overlay which holds a collection of features.
|
||||
// This collection is passed to the modify and also the draw
|
||||
// interaction, so that both can add or modify features.
|
||||
var featureOverlay = new ol.FeatureOverlay({
|
||||
var features = new ol.Collection();
|
||||
var featureOverlay = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({features: features}),
|
||||
style: new ol.style.Style({
|
||||
fill: new ol.style.Fill({
|
||||
color: 'rgba(255, 255, 255, 0.2)'
|
||||
@@ -48,7 +48,7 @@ var featureOverlay = new ol.FeatureOverlay({
|
||||
featureOverlay.setMap(map);
|
||||
|
||||
var modify = new ol.interaction.Modify({
|
||||
features: featureOverlay.getFeatures(),
|
||||
features: features,
|
||||
// the SHIFT key must be pressed to delete vertices, so
|
||||
// that new vertices can be drawn at the same position
|
||||
// of existing vertices
|
||||
@@ -62,7 +62,7 @@ map.addInteraction(modify);
|
||||
var draw; // global so we can remove it later
|
||||
function addInteraction() {
|
||||
draw = new ol.interaction.Draw({
|
||||
features: featureOverlay.getFeatures(),
|
||||
features: features,
|
||||
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value)
|
||||
});
|
||||
map.addInteraction(draw);
|
||||
|
||||
15
examples/feature-animation.html
Normal file
15
examples/feature-animation.html
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
template: example.html
|
||||
title: Feature animation example
|
||||
shortdesc: Demonstrates how to animate features.
|
||||
docs: >
|
||||
This example shows how to use <b>postcompose</b> and <b>vectorContext</b> to
|
||||
animate features. Here we choose to do a flash animation each time a feature
|
||||
is added to the layer.
|
||||
tags: "animation, vector, feature, flash"
|
||||
---
|
||||
<div class="row">
|
||||
<div class="span8">
|
||||
<div id="map" class="map"></div>
|
||||
</div>
|
||||
</div>
|
||||
96
examples/feature-animation.js
Normal file
96
examples/feature-animation.js
Normal file
@@ -0,0 +1,96 @@
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.Observable');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.control');
|
||||
goog.require('ol.easing');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.source.OSM');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Circle');
|
||||
goog.require('ol.style.Stroke');
|
||||
|
||||
|
||||
var map = new ol.Map({
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.OSM({
|
||||
wrapX: false
|
||||
})
|
||||
})
|
||||
],
|
||||
controls: ol.control.defaults({
|
||||
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
|
||||
collapsible: false
|
||||
})
|
||||
}),
|
||||
renderer: common.getRendererFromQueryString(),
|
||||
target: 'map',
|
||||
view: new ol.View({
|
||||
center: [0, 0],
|
||||
zoom: 1
|
||||
})
|
||||
});
|
||||
|
||||
var source = new ol.source.Vector({
|
||||
wrapX: false
|
||||
});
|
||||
var vector = new ol.layer.Vector({
|
||||
source: source
|
||||
});
|
||||
map.addLayer(vector);
|
||||
|
||||
function addRandomFeature() {
|
||||
var x = Math.random() * 360 - 180;
|
||||
var y = Math.random() * 180 - 90;
|
||||
var geom = new ol.geom.Point(ol.proj.transform([x, y],
|
||||
'EPSG:4326', 'EPSG:3857'));
|
||||
var feature = new ol.Feature(geom);
|
||||
source.addFeature(feature);
|
||||
}
|
||||
|
||||
var duration = 3000;
|
||||
function flash(feature) {
|
||||
var start = new Date().getTime();
|
||||
var listenerKey;
|
||||
|
||||
function animate(event) {
|
||||
var vectorContext = event.vectorContext;
|
||||
var frameState = event.frameState;
|
||||
var flashGeom = feature.getGeometry().clone();
|
||||
var elapsed = frameState.time - start;
|
||||
var elapsedRatio = elapsed / duration;
|
||||
// radius will be 5 at start and 30 at end.
|
||||
var radius = ol.easing.easeOut(elapsedRatio) * 25 + 5;
|
||||
var opacity = ol.easing.easeOut(1 - elapsedRatio);
|
||||
|
||||
var flashStyle = new ol.style.Circle({
|
||||
radius: radius,
|
||||
snapToPixel: false,
|
||||
stroke: new ol.style.Stroke({
|
||||
color: 'rgba(255, 0, 0, ' + opacity + ')',
|
||||
width: 1,
|
||||
opacity: opacity
|
||||
})
|
||||
});
|
||||
|
||||
vectorContext.setImageStyle(flashStyle);
|
||||
vectorContext.drawPointGeometry(flashGeom, null);
|
||||
if (elapsed > duration) {
|
||||
ol.Observable.unByKey(listenerKey);
|
||||
return;
|
||||
}
|
||||
// tell OL3 to continue postcompose animation
|
||||
frameState.animate = true;
|
||||
}
|
||||
listenerKey = map.on('postcompose', animate);
|
||||
}
|
||||
|
||||
source.on('addfeature', function(e) {
|
||||
flash(e.feature);
|
||||
});
|
||||
|
||||
window.setInterval(addRandomFeature, 1000);
|
||||
@@ -10,7 +10,7 @@ tags: "fullscreen, geolocation, orientation, mobile"
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="../css/ol.css" type="text/css">
|
||||
<link rel="stylesheet" href="./resources/layout.css" type="text/css">
|
||||
<title>Mobile Geolocation Tracking with Orientation</title>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.Geolocation');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.control');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.OSM');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Circle');
|
||||
goog.require('ol.style.Fill');
|
||||
goog.require('ol.style.Stroke');
|
||||
@@ -85,7 +86,9 @@ geolocation.on('change:position', function() {
|
||||
new ol.geom.Point(coordinates) : null);
|
||||
});
|
||||
|
||||
var featuresOverlay = new ol.FeatureOverlay({
|
||||
var featuresOverlay = new ol.layer.Vector({
|
||||
map: map,
|
||||
features: [accuracyFeature, positionFeature]
|
||||
source: new ol.source.Vector({
|
||||
features: [accuracyFeature, positionFeature]
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.geom.Point');
|
||||
@@ -102,12 +101,14 @@ for (i = 0; i < featureCount; i += 30) {
|
||||
overlayFeatures.push(clone);
|
||||
}
|
||||
|
||||
var featureOverlay = new ol.FeatureOverlay({
|
||||
var featureOverlay = new ol.layer.Vector({
|
||||
map: map,
|
||||
source: new ol.source.Vector({
|
||||
features: overlayFeatures
|
||||
}),
|
||||
style: new ol.style.Style({
|
||||
image: icons[iconCount - 1]
|
||||
}),
|
||||
features: overlayFeatures
|
||||
})
|
||||
});
|
||||
|
||||
map.on('click', function(evt) {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#map {
|
||||
position: relative;
|
||||
}
|
||||
#popup {
|
||||
padding-bottom: 45px;
|
||||
}
|
||||
@@ -71,9 +71,7 @@ map.on('click', function(evt) {
|
||||
return feature;
|
||||
});
|
||||
if (feature) {
|
||||
var geometry = feature.getGeometry();
|
||||
var coord = geometry.getCoordinates();
|
||||
popup.setPosition(coord);
|
||||
popup.setPosition(evt.coordinate);
|
||||
$(element).popover({
|
||||
'placement': 'top',
|
||||
'html': true,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.control');
|
||||
@@ -180,7 +179,8 @@ map.on('postcompose', function(evt) {
|
||||
}
|
||||
});
|
||||
|
||||
var featureOverlay = new ol.FeatureOverlay({
|
||||
var featureOverlay = new ol.layer.Vector({
|
||||
source: new ol.source.Vector(),
|
||||
map: map,
|
||||
style: new ol.style.Style({
|
||||
image: new ol.style.Circle({
|
||||
@@ -203,7 +203,7 @@ document.getElementById('time').addEventListener('input', function() {
|
||||
if (highlight === undefined) {
|
||||
highlight = new ol.Feature(new ol.geom.Point(coordinate));
|
||||
feature.set('highlight', highlight);
|
||||
featureOverlay.addFeature(highlight);
|
||||
featureOverlay.getSource().addFeature(highlight);
|
||||
} else {
|
||||
highlight.getGeometry().setCoordinates(coordinate);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.format.GeoJSON');
|
||||
goog.require('ol.layer.Image');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.ImageVector');
|
||||
goog.require('ol.source.MapQuest');
|
||||
goog.require('ol.source.Vector');
|
||||
@@ -42,7 +42,8 @@ var map = new ol.Map({
|
||||
})
|
||||
});
|
||||
|
||||
var featureOverlay = new ol.FeatureOverlay({
|
||||
var featureOverlay = new ol.layer.Vector({
|
||||
source: new ol.source.Vector(),
|
||||
map: map,
|
||||
style: new ol.style.Style({
|
||||
stroke: new ol.style.Stroke({
|
||||
@@ -71,10 +72,10 @@ var displayFeatureInfo = function(pixel) {
|
||||
|
||||
if (feature !== highlight) {
|
||||
if (highlight) {
|
||||
featureOverlay.removeFeature(highlight);
|
||||
featureOverlay.getSource().removeFeature(highlight);
|
||||
}
|
||||
if (feature) {
|
||||
featureOverlay.addFeature(feature);
|
||||
featureOverlay.getSource().addFeature(feature);
|
||||
}
|
||||
highlight = feature;
|
||||
}
|
||||
|
||||
@@ -4,24 +4,33 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="../css/ol.css" type="text/css">
|
||||
<link rel="stylesheet" href="./resources/layout.css" type="text/css">
|
||||
<style>
|
||||
body {
|
||||
padding-top: 70px;
|
||||
}
|
||||
.navbar-form {
|
||||
margin-top: 12px;
|
||||
}
|
||||
input.search-query {
|
||||
color: #333;
|
||||
}
|
||||
.example {
|
||||
padding: 10px;
|
||||
background-color: #F5F5F5;
|
||||
height: 140px;
|
||||
padding: 3px;
|
||||
background-color: #eee;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin: 10px 0;
|
||||
overflow: auto;
|
||||
}
|
||||
.example p.description {
|
||||
font-size: smaller;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.example:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
.navbar-search.pull-left {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
@@ -174,35 +183,31 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="brand" href="./"><img src="./resources/logo-70x70.png"> OpenLayers 3 Examples</a>
|
||||
<form class="navbar-search pull-left">
|
||||
<input name="q" type="text" id="keywords" class="search-query" placeholder="Search">
|
||||
<span id="count"></span>
|
||||
</form>
|
||||
</div>
|
||||
<header class="navbar navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="./"><img src="./resources/logo-70x70.png"> OpenLayers 3 Examples</a>
|
||||
<form class="navbar-form navbar-left" role="search">
|
||||
<input name="q" type="text" id="keywords" class="search-query" placeholder="Search">
|
||||
<span id="count"></span>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container-fluid">
|
||||
|
||||
<div id="examples"></div>
|
||||
|
||||
<div style="display: none;">
|
||||
<div id="template">
|
||||
<div class="span4 example" jugl:repeat="example examples">
|
||||
<a jugl:attributes="href example.link" class="mainlink">
|
||||
<strong><span jugl:replace="example.title">title</span></strong><br>
|
||||
<small jugl:content="'(' + example.example + ')'"></small>
|
||||
</a>
|
||||
<p><div jugl:content="example.shortdesc"></div></p>
|
||||
<p><small jugl:content="'tags: ' + example.tags"></small></p>
|
||||
<div id="template" class="row">
|
||||
<div class="col-md-4 col-sm-4" jugl:repeat="example examples">
|
||||
<div class="example">
|
||||
<a jugl:attributes="href example.link" class="mainlink">
|
||||
<strong><span jugl:replace="example.title">title</span></strong><br>
|
||||
<small jugl:content="'(' + example.example + ')'"></small>
|
||||
</a>
|
||||
<p class="description" jugl:content="example.shortdesc"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.Observable');
|
||||
goog.require('ol.Overlay');
|
||||
goog.require('ol.Sphere');
|
||||
goog.require('ol.View');
|
||||
@@ -103,27 +104,20 @@ var pointerMoveHandler = function(evt) {
|
||||
}
|
||||
/** @type {string} */
|
||||
var helpMsg = 'Click to start drawing';
|
||||
/** @type {ol.Coordinate|undefined} */
|
||||
var tooltipCoord = evt.coordinate;
|
||||
|
||||
if (sketch) {
|
||||
var output;
|
||||
var geom = (sketch.getGeometry());
|
||||
if (geom instanceof ol.geom.Polygon) {
|
||||
output = formatArea(/** @type {ol.geom.Polygon} */ (geom));
|
||||
helpMsg = continuePolygonMsg;
|
||||
tooltipCoord = geom.getInteriorPoint().getCoordinates();
|
||||
} else if (geom instanceof ol.geom.LineString) {
|
||||
output = formatLength( /** @type {ol.geom.LineString} */ (geom));
|
||||
helpMsg = continueLineMsg;
|
||||
tooltipCoord = geom.getLastCoordinate();
|
||||
}
|
||||
measureTooltipElement.innerHTML = output;
|
||||
measureTooltip.setPosition(tooltipCoord);
|
||||
}
|
||||
|
||||
helpTooltipElement.innerHTML = helpMsg;
|
||||
helpTooltip.setPosition(evt.coordinate);
|
||||
|
||||
$(helpTooltipElement).removeClass('hidden');
|
||||
};
|
||||
|
||||
|
||||
@@ -138,6 +132,10 @@ var map = new ol.Map({
|
||||
|
||||
map.on('pointermove', pointerMoveHandler);
|
||||
|
||||
$(map.getViewport()).on('mouseout', function() {
|
||||
$(helpTooltipElement).addClass('hidden');
|
||||
});
|
||||
|
||||
var typeSelect = document.getElementById('type');
|
||||
var geodesicCheckbox = document.getElementById('geodesic');
|
||||
|
||||
@@ -172,10 +170,28 @@ function addInteraction() {
|
||||
createMeasureTooltip();
|
||||
createHelpTooltip();
|
||||
|
||||
var listener;
|
||||
draw.on('drawstart',
|
||||
function(evt) {
|
||||
// set sketch
|
||||
sketch = evt.feature;
|
||||
|
||||
/** @type {ol.Coordinate|undefined} */
|
||||
var tooltipCoord = evt.coordinate;
|
||||
|
||||
listener = sketch.getGeometry().on('change', function(evt) {
|
||||
var geom = evt.target;
|
||||
var output;
|
||||
if (geom instanceof ol.geom.Polygon) {
|
||||
output = formatArea(/** @type {ol.geom.Polygon} */ (geom));
|
||||
tooltipCoord = geom.getInteriorPoint().getCoordinates();
|
||||
} else if (geom instanceof ol.geom.LineString) {
|
||||
output = formatLength( /** @type {ol.geom.LineString} */ (geom));
|
||||
tooltipCoord = geom.getLastCoordinate();
|
||||
}
|
||||
measureTooltipElement.innerHTML = output;
|
||||
measureTooltip.setPosition(tooltipCoord);
|
||||
});
|
||||
}, this);
|
||||
|
||||
draw.on('drawend',
|
||||
@@ -187,6 +203,7 @@ function addInteraction() {
|
||||
// unset tooltip so that a new one can be created
|
||||
measureTooltipElement = null;
|
||||
createMeasureTooltip();
|
||||
ol.Observable.unByKey(listener);
|
||||
}, this);
|
||||
}
|
||||
|
||||
@@ -199,7 +216,7 @@ function createHelpTooltip() {
|
||||
helpTooltipElement.parentNode.removeChild(helpTooltipElement);
|
||||
}
|
||||
helpTooltipElement = document.createElement('div');
|
||||
helpTooltipElement.className = 'tooltip';
|
||||
helpTooltipElement.className = 'tooltip hidden';
|
||||
helpTooltip = new ol.Overlay({
|
||||
element: helpTooltipElement,
|
||||
offset: [15, 0],
|
||||
|
||||
@@ -24,7 +24,9 @@ var vector = new ol.layer.Vector({
|
||||
})
|
||||
});
|
||||
|
||||
var select = new ol.interaction.Select();
|
||||
var select = new ol.interaction.Select({
|
||||
wrapX: false
|
||||
});
|
||||
|
||||
var modify = new ol.interaction.Modify({
|
||||
features: select.getFeatures()
|
||||
|
||||
31
examples/raster.css
Normal file
31
examples/raster.css
Normal file
@@ -0,0 +1,31 @@
|
||||
.rel {
|
||||
position: relative
|
||||
}
|
||||
|
||||
#plot {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.bar {
|
||||
pointer-events: auto;
|
||||
fill: #AFAFB9;
|
||||
}
|
||||
|
||||
.bar.selected {
|
||||
fill: green;
|
||||
}
|
||||
|
||||
.tip {
|
||||
position: absolute;
|
||||
background: black;
|
||||
color: white;
|
||||
padding: 6px;
|
||||
font-size: 12px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
31
examples/raster.html
Normal file
31
examples/raster.html
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
template: example.html
|
||||
title: Raster Source
|
||||
shortdesc: Demonstrates pixelwise operations with a raster source.
|
||||
docs: >
|
||||
<p>
|
||||
This example uses a <code>ol.source.Raster</code> to generate data
|
||||
based on another source. The raster source accepts any number of
|
||||
input sources (tile or image based) and runs a pipeline of
|
||||
operations on the input pixels. The return from the final
|
||||
operation is used as the data for the output source.
|
||||
</p>
|
||||
<p>
|
||||
In this case, a single tiled source of imagery is used as input.
|
||||
For each pixel, the Vegetaion Greenness Index
|
||||
(<a href="http://www.tandfonline.com/doi/abs/10.1080/10106040108542184#.Vb90ITBViko">VGI</a>)
|
||||
is calculated from the input pixels. A second operation colors
|
||||
those pixels based on a threshold value (values above the
|
||||
threshold are green and those below are transparent).
|
||||
</p>
|
||||
tags: "raster, pixel"
|
||||
resources:
|
||||
- http://d3js.org/d3.v3.min.js
|
||||
- raster.css
|
||||
---
|
||||
<div class="row-fluid">
|
||||
<div class="span12 rel">
|
||||
<div id="map" class="map"></div>
|
||||
<div id="plot"></div>
|
||||
</div>
|
||||
</div>
|
||||
200
examples/raster.js
Normal file
200
examples/raster.js
Normal file
@@ -0,0 +1,200 @@
|
||||
// NOCOMPILE
|
||||
// this example uses d3 for which we don't have an externs file.
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.layer.Image');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.source.BingMaps');
|
||||
goog.require('ol.source.Raster');
|
||||
|
||||
var minVgi = 0;
|
||||
var maxVgi = 0.25;
|
||||
var bins = 10;
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the Vegetation Greenness Index (VGI) from an input pixel. This
|
||||
* is a rough estimate assuming that pixel values correspond to reflectance.
|
||||
* @param {ol.raster.Pixel} pixel An array of [R, G, B, A] values.
|
||||
* @return {number} The VGI value for the given pixel.
|
||||
*/
|
||||
function vgi(pixel) {
|
||||
var r = pixel[0] / 255;
|
||||
var g = pixel[1] / 255;
|
||||
var b = pixel[2] / 255;
|
||||
return (2 * g - r - b) / (2 * g + r + b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Summarize values for a histogram.
|
||||
* @param {numver} value A VGI value.
|
||||
* @param {Object} counts An object for keeping track of VGI counts.
|
||||
*/
|
||||
function summarize(value, counts) {
|
||||
var min = counts.min;
|
||||
var max = counts.max;
|
||||
var num = counts.values.length;
|
||||
if (value < min) {
|
||||
// do nothing
|
||||
} else if (value >= max) {
|
||||
counts.values[num - 1] += 1;
|
||||
} else {
|
||||
var index = Math.floor((value - min) / counts.delta);
|
||||
counts.values[index] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use aerial imagery as the input data for the raster source.
|
||||
*/
|
||||
var bing = new ol.source.BingMaps({
|
||||
key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3',
|
||||
imagerySet: 'Aerial'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Create a raster source where pixels with VGI values above a threshold will
|
||||
* be colored green.
|
||||
*/
|
||||
var raster = new ol.source.Raster({
|
||||
sources: [bing],
|
||||
operation: function(pixels, data) {
|
||||
var pixel = pixels[0];
|
||||
var value = vgi(pixel);
|
||||
summarize(value, data.counts);
|
||||
if (value >= data.threshold) {
|
||||
pixel[0] = 0;
|
||||
pixel[1] = 255;
|
||||
pixel[2] = 0;
|
||||
pixel[3] = 128;
|
||||
} else {
|
||||
pixel[3] = 0;
|
||||
}
|
||||
return pixel;
|
||||
},
|
||||
lib: {
|
||||
vgi: vgi,
|
||||
summarize: summarize
|
||||
}
|
||||
});
|
||||
raster.set('threshold', 0.1);
|
||||
|
||||
function createCounts(min, max, num) {
|
||||
var values = new Array(num);
|
||||
for (var i = 0; i < num; ++i) {
|
||||
values[i] = 0;
|
||||
}
|
||||
return {
|
||||
min: min,
|
||||
max: max,
|
||||
values: values,
|
||||
delta: (max - min) / num
|
||||
};
|
||||
}
|
||||
|
||||
raster.on('beforeoperations', function(event) {
|
||||
event.data.counts = createCounts(minVgi, maxVgi, bins);
|
||||
event.data.threshold = raster.get('threshold');
|
||||
});
|
||||
|
||||
raster.on('afteroperations', function(event) {
|
||||
schedulePlot(event.resolution, event.data.counts, event.data.threshold);
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: bing
|
||||
}),
|
||||
new ol.layer.Image({
|
||||
source: raster
|
||||
})
|
||||
],
|
||||
target: 'map',
|
||||
view: new ol.View({
|
||||
center: [-9651695, 4937351],
|
||||
zoom: 13,
|
||||
minZoom: 12,
|
||||
maxZoom: 19
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
var timer = null;
|
||||
function schedulePlot(resolution, counts, threshold) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
timer = setTimeout(plot.bind(null, resolution, counts, threshold), 1000 / 60);
|
||||
}
|
||||
|
||||
var barWidth = 15;
|
||||
var plotHeight = 150;
|
||||
var chart = d3.select('#plot').append('svg')
|
||||
.attr('width', barWidth * bins)
|
||||
.attr('height', plotHeight);
|
||||
|
||||
var chartRect = chart[0][0].getBoundingClientRect();
|
||||
|
||||
var tip = d3.select(document.body).append('div')
|
||||
.attr('class', 'tip');
|
||||
|
||||
function plot(resolution, counts, threshold) {
|
||||
var yScale = d3.scale.linear()
|
||||
.domain([0, d3.max(counts.values)])
|
||||
.range([0, plotHeight]);
|
||||
|
||||
var bar = chart.selectAll('rect').data(counts.values);
|
||||
|
||||
bar.enter().append('rect');
|
||||
|
||||
bar.attr('class', function(count, index) {
|
||||
var value = counts.min + (index * counts.delta);
|
||||
return 'bar' + (value >= threshold ? ' selected' : '');
|
||||
})
|
||||
.attr('width', barWidth - 2);
|
||||
|
||||
bar.transition().attr('transform', function(value, index) {
|
||||
return 'translate(' + (index * barWidth) + ', ' +
|
||||
(plotHeight - yScale(value)) + ')';
|
||||
})
|
||||
.attr('height', yScale);
|
||||
|
||||
bar.on('mousemove', function(count, index) {
|
||||
var threshold = counts.min + (index * counts.delta);
|
||||
if (raster.get('threshold') !== threshold) {
|
||||
raster.set('threshold', threshold);
|
||||
raster.changed();
|
||||
}
|
||||
});
|
||||
|
||||
bar.on('mouseover', function(count, index) {
|
||||
var area = 0;
|
||||
for (var i = counts.values.length - 1; i >= index; --i) {
|
||||
area += resolution * resolution * counts.values[i];
|
||||
}
|
||||
tip.html(message(counts.min + (index * counts.delta), area));
|
||||
tip.style('display', 'block');
|
||||
tip.transition().style({
|
||||
left: (chartRect.left + (index * barWidth) + (barWidth / 2)) + 'px',
|
||||
top: (d3.event.y - 60) + 'px',
|
||||
opacity: 1
|
||||
});
|
||||
});
|
||||
|
||||
bar.on('mouseout', function() {
|
||||
tip.transition().style('opacity', 0).each('end', function() {
|
||||
tip.style('display', 'none');
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function message(value, area) {
|
||||
var acres = (area / 4046.86).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
return acres + ' acres at<br>' + value.toFixed(2) + ' VGI or above';
|
||||
}
|
||||
4
examples/region-growing.css
Normal file
4
examples/region-growing.css
Normal file
@@ -0,0 +1,4 @@
|
||||
table.controls td {
|
||||
min-width: 110px;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
38
examples/region-growing.html
Normal file
38
examples/region-growing.html
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
template: example.html
|
||||
title: Region Growing
|
||||
shortdesc: Grow a region from a seed pixel
|
||||
docs: >
|
||||
<p>Click a region on the map. The computed region will be red.</p>
|
||||
<p>
|
||||
This example uses a <code>ol.source.Raster</code> to generate data
|
||||
based on another source. The raster source accepts any number of
|
||||
input sources (tile or image based) and runs a pipeline of
|
||||
operations on the input data. The return from the final
|
||||
operation is used as the data for the output source.
|
||||
</p>
|
||||
<p>
|
||||
In this case, a single tiled source of imagery data is used as input.
|
||||
The region is calculated in a single "image" operation using the "seed"
|
||||
pixel provided by the user clicking on the map. The "threshold" value
|
||||
determines whether a given contiguous pixel belongs to the "region" - the
|
||||
difference between a candidate pixel's RGB values and the seed values must
|
||||
be below the threshold.
|
||||
</p>
|
||||
<p>
|
||||
This example also shows how an additional function can be made available
|
||||
to the operation.
|
||||
</p>
|
||||
tags: "raster, region growing"
|
||||
---
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<div id="map" class="map" style="cursor: pointer"></div>
|
||||
<table class="controls">
|
||||
<tr>
|
||||
<td>Threshold: <span id="threshold-value"></span></td>
|
||||
<td><input id="threshold" type="range" min="1" max="50" value="20"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
132
examples/region-growing.js
Normal file
132
examples/region-growing.js
Normal file
@@ -0,0 +1,132 @@
|
||||
// NOCOMPILE
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.layer.Image');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.source.BingMaps');
|
||||
goog.require('ol.source.Raster');
|
||||
|
||||
function growRegion(inputs, data) {
|
||||
var image = inputs[0];
|
||||
var seed = data.pixel;
|
||||
var delta = parseInt(data.delta);
|
||||
if (!seed) {
|
||||
return image;
|
||||
}
|
||||
|
||||
seed = seed.map(Math.round);
|
||||
var width = image.width;
|
||||
var height = image.height;
|
||||
var inputData = image.data;
|
||||
var outputData = new Uint8ClampedArray(inputData);
|
||||
var seedIdx = (seed[1] * width + seed[0]) * 4;
|
||||
var seedR = inputData[seedIdx];
|
||||
var seedG = inputData[seedIdx + 1];
|
||||
var seedB = inputData[seedIdx + 2];
|
||||
var edge = [seed];
|
||||
while (edge.length) {
|
||||
var newedge = [];
|
||||
for (var i = 0, ii = edge.length; i < ii; i++) {
|
||||
// As noted in the Raster source constructor, this function is provided
|
||||
// using the `lib` option. Other functions will NOT be visible unless
|
||||
// provided using the `lib` option.
|
||||
var next = nextEdges(edge[i]);
|
||||
for (var j = 0, jj = next.length; j < jj; j++) {
|
||||
var s = next[j][0], t = next[j][1];
|
||||
if (s >= 0 && s < width && t >= 0 && t < height) {
|
||||
var ci = (t * width + s) * 4;
|
||||
var cr = inputData[ci];
|
||||
var cg = inputData[ci + 1];
|
||||
var cb = inputData[ci + 2];
|
||||
var ca = inputData[ci + 3];
|
||||
// if alpha is zero, carry on
|
||||
if (ca === 0) {
|
||||
continue;
|
||||
}
|
||||
if (Math.abs(seedR - cr) < delta && Math.abs(seedG - cg) < delta &&
|
||||
Math.abs(seedB - cb) < delta) {
|
||||
outputData[ci] = 255;
|
||||
outputData[ci + 1] = 0;
|
||||
outputData[ci + 2] = 0;
|
||||
outputData[ci + 3] = 255;
|
||||
newedge.push([s, t]);
|
||||
}
|
||||
// mark as visited
|
||||
inputData[ci + 3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
edge = newedge;
|
||||
}
|
||||
return new ImageData(outputData, width, height);
|
||||
}
|
||||
|
||||
function next4Edges(edge) {
|
||||
var x = edge[0], y = edge[1];
|
||||
return [
|
||||
[x + 1, y],
|
||||
[x - 1, y],
|
||||
[x, y + 1],
|
||||
[x, y - 1]
|
||||
];
|
||||
}
|
||||
|
||||
var key = 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3';
|
||||
|
||||
var imagery = new ol.layer.Tile({
|
||||
source: new ol.source.BingMaps({key: key, imagerySet: 'Aerial'})
|
||||
});
|
||||
|
||||
var raster = new ol.source.Raster({
|
||||
sources: [imagery.getSource()],
|
||||
operationType: 'image',
|
||||
operation: growRegion,
|
||||
// Functions in the `lib` object will be available to the operation run in
|
||||
// the web worker.
|
||||
lib: {
|
||||
nextEdges: next4Edges
|
||||
}
|
||||
});
|
||||
|
||||
var rasterImage = new ol.layer.Image({
|
||||
opacity: 0.7,
|
||||
source: raster
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
layers: [imagery, rasterImage],
|
||||
target: 'map',
|
||||
view: new ol.View({
|
||||
center: ol.proj.fromLonLat([-119.07, 47.65]),
|
||||
zoom: 11
|
||||
})
|
||||
});
|
||||
|
||||
var coordinate;
|
||||
|
||||
map.on('click', function(event) {
|
||||
coordinate = event.coordinate;
|
||||
raster.changed();
|
||||
});
|
||||
|
||||
raster.on('beforeoperations', function(event) {
|
||||
// the event.data object will be passed to operations
|
||||
var data = event.data;
|
||||
data.delta = thresholdControl.value;
|
||||
if (coordinate) {
|
||||
data.pixel = map.getPixelFromCoordinate(coordinate);
|
||||
}
|
||||
});
|
||||
|
||||
var thresholdControl = document.getElementById('threshold');
|
||||
|
||||
function updateControlValue() {
|
||||
document.getElementById('threshold-value').innerText = thresholdControl.value;
|
||||
}
|
||||
updateControlValue();
|
||||
|
||||
thresholdControl.addEventListener('input', function() {
|
||||
updateControlValue();
|
||||
raster.changed();
|
||||
});
|
||||
@@ -1,15 +1,59 @@
|
||||
@import url(http://fonts.googleapis.com/css?family=Quattrocento+Sans:400,400italic,700);
|
||||
|
||||
body {
|
||||
padding-top: 60px;
|
||||
font-family: 'Quattrocento Sans', sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
.navbar {
|
||||
background-color: #1F6B75;
|
||||
color: white;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.navbar-brand {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 160%;
|
||||
padding: 8px 0;
|
||||
}
|
||||
.navbar-brand:hover,
|
||||
.navbar-brand:focus {
|
||||
color: #aae1e9;
|
||||
}
|
||||
.navbar-brand img {
|
||||
height: 35px;
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
ul.inline,
|
||||
ol.inline {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
ul.inline>li,
|
||||
ol.inline>li {
|
||||
display: inline-block;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.map {
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
background: url(map-background.jpg) repeat;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ol-attribution {
|
||||
.ol-attribution.ol-logo-only,
|
||||
.ol-attribution.ol-uncollapsible {
|
||||
max-width: calc(100% - 3em);
|
||||
height: 1.5em;
|
||||
}
|
||||
.ol-attribution ul {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.ol-control button, .ol-attribution, .ol-scale-line-inner {
|
||||
font-family: 'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;
|
||||
@@ -21,18 +65,3 @@ body {
|
||||
#api-links ul {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
body, h1, h2, h3, h4, p, li, td, th {
|
||||
font-family: Quattrocento Sans;
|
||||
}
|
||||
.navbar-inverse .navbar-inner {
|
||||
background: #1F6B75;
|
||||
}
|
||||
.navbar-inverse .brand {
|
||||
color: white;
|
||||
padding: 5px;
|
||||
}
|
||||
.brand img {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
4
examples/shaded-relief.css
Normal file
4
examples/shaded-relief.css
Normal file
@@ -0,0 +1,4 @@
|
||||
table.controls td {
|
||||
text-align: center;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
46
examples/shaded-relief.html
Normal file
46
examples/shaded-relief.html
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
template: example.html
|
||||
title: Shaded Relief
|
||||
shortdesc: Calculate shaded relief from elevation data
|
||||
docs: >
|
||||
<p>
|
||||
This example uses a <code>ol.source.Raster</code> to generate data
|
||||
based on another source. The raster source accepts any number of
|
||||
input sources (tile or image based) and runs a pipeline of
|
||||
operations on the input data. The return from the final
|
||||
operation is used as the data for the output source.
|
||||
</p>
|
||||
<p>
|
||||
In this case, a single tiled source of elevation data is used as input.
|
||||
The shaded relief is calculated in a single "image" operation. By setting
|
||||
<code>operationType: 'image'</code> on the raster source, operations are
|
||||
called with an <code>ImageData</code> object for each of the input sources.
|
||||
Operations are also called with a general purpose <code>data</code> object.
|
||||
In this example, the sun elevation and azimuth data from the inputs above
|
||||
are assigned to this <code>data</code> object and accessed in the shading
|
||||
operation. The shading operation returns an array of <code>ImageData</code>
|
||||
objects. When the raster source is used by an image layer, the first
|
||||
<code>ImageData</code> object returned by the last operation in the pipeline
|
||||
is used for rendering.
|
||||
</p>
|
||||
tags: "raster, shaded relief"
|
||||
---
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<div id="map" class="map"></div>
|
||||
<table class="controls">
|
||||
<tr>
|
||||
<td>vertical exaggeration: <span id="vertOut"></span>x</td>
|
||||
<td><input id="vert" type="range" min="1" max="5" value="1"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>sun elevation: <span id="sunElOut"></span>°</td>
|
||||
<td><input id="sunEl" type="range" min="0" max="90" value="45"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>sun azimuth: <span id="sunAzOut"></span>°</td>
|
||||
<td><input id="sunAz" type="range" min="0" max="360" value="45"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
158
examples/shaded-relief.js
Normal file
158
examples/shaded-relief.js
Normal file
@@ -0,0 +1,158 @@
|
||||
// NOCOMPILE
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.layer.Image');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.source.Raster');
|
||||
goog.require('ol.source.TileJSON');
|
||||
goog.require('ol.source.XYZ');
|
||||
|
||||
|
||||
/**
|
||||
* Generates a shaded relief image given elevation data. Uses a 3x3
|
||||
* neighborhood for determining slope and aspect.
|
||||
* @param {Array.<ImageData>} inputs Array of input images.
|
||||
* @param {Object} data Data added in the "beforeoperations" event.
|
||||
* @return {Array.<ImageData>} Output images (only the first is rendered).
|
||||
*/
|
||||
function shade(inputs, data) {
|
||||
var elevationImage = inputs[0];
|
||||
var width = elevationImage.width;
|
||||
var height = elevationImage.height;
|
||||
var elevationData = elevationImage.data;
|
||||
var shadeData = new Uint8ClampedArray(elevationData.length);
|
||||
var dp = data.resolution * 2;
|
||||
var maxX = width - 1;
|
||||
var maxY = height - 1;
|
||||
var pixel = [0, 0, 0, 0];
|
||||
var twoPi = 2 * Math.PI;
|
||||
var halfPi = Math.PI / 2;
|
||||
var sunEl = Math.PI * data.sunEl / 180;
|
||||
var sunAz = Math.PI * data.sunAz / 180;
|
||||
var cosSunEl = Math.cos(sunEl);
|
||||
var sinSunEl = Math.sin(sunEl);
|
||||
var pixelX, pixelY, x0, x1, y0, y1, offset,
|
||||
z0, z1, dzdx, dzdy, slope, aspect, cosIncidence, scaled;
|
||||
for (pixelY = 0; pixelY <= maxY; ++pixelY) {
|
||||
y0 = pixelY === 0 ? 0 : pixelY - 1;
|
||||
y1 = pixelY === maxY ? maxY : pixelY + 1;
|
||||
for (pixelX = 0; pixelX <= maxX; ++pixelX) {
|
||||
x0 = pixelX === 0 ? 0 : pixelX - 1;
|
||||
x1 = pixelX === maxX ? maxX : pixelX + 1;
|
||||
|
||||
// determine elevation for (x0, pixelY)
|
||||
offset = (pixelY * width + x0) * 4;
|
||||
pixel[0] = elevationData[offset];
|
||||
pixel[1] = elevationData[offset + 1];
|
||||
pixel[2] = elevationData[offset + 2];
|
||||
pixel[3] = elevationData[offset + 3];
|
||||
z0 = data.vert * (pixel[0] + pixel[1] * 2 + pixel[2] * 3);
|
||||
|
||||
// determine elevation for (x1, pixelY)
|
||||
offset = (pixelY * width + x1) * 4;
|
||||
pixel[0] = elevationData[offset];
|
||||
pixel[1] = elevationData[offset + 1];
|
||||
pixel[2] = elevationData[offset + 2];
|
||||
pixel[3] = elevationData[offset + 3];
|
||||
z1 = data.vert * (pixel[0] + pixel[1] * 2 + pixel[2] * 3);
|
||||
|
||||
dzdx = (z1 - z0) / dp;
|
||||
|
||||
// determine elevation for (pixelX, y0)
|
||||
offset = (y0 * width + pixelX) * 4;
|
||||
pixel[0] = elevationData[offset];
|
||||
pixel[1] = elevationData[offset + 1];
|
||||
pixel[2] = elevationData[offset + 2];
|
||||
pixel[3] = elevationData[offset + 3];
|
||||
z0 = data.vert * (pixel[0] + pixel[1] * 2 + pixel[2] * 3);
|
||||
|
||||
// determine elevation for (pixelX, y1)
|
||||
offset = (y1 * width + pixelX) * 4;
|
||||
pixel[0] = elevationData[offset];
|
||||
pixel[1] = elevationData[offset + 1];
|
||||
pixel[2] = elevationData[offset + 2];
|
||||
pixel[3] = elevationData[offset + 3];
|
||||
z1 = data.vert * (pixel[0] + pixel[1] * 2 + pixel[2] * 3);
|
||||
|
||||
dzdy = (z1 - z0) / dp;
|
||||
|
||||
slope = Math.atan(Math.sqrt(dzdx * dzdx + dzdy * dzdy));
|
||||
|
||||
aspect = Math.atan2(dzdy, -dzdx);
|
||||
if (aspect < 0) {
|
||||
aspect = halfPi - aspect;
|
||||
} else if (aspect > halfPi) {
|
||||
aspect = twoPi - aspect + halfPi;
|
||||
} else {
|
||||
aspect = halfPi - aspect;
|
||||
}
|
||||
|
||||
cosIncidence = sinSunEl * Math.cos(slope) +
|
||||
cosSunEl * Math.sin(slope) * Math.cos(sunAz - aspect);
|
||||
|
||||
offset = (pixelY * width + pixelX) * 4;
|
||||
scaled = 255 * cosIncidence;
|
||||
shadeData[offset] = scaled;
|
||||
shadeData[offset + 1] = scaled;
|
||||
shadeData[offset + 2] = scaled;
|
||||
shadeData[offset + 3] = elevationData[offset + 3];
|
||||
}
|
||||
}
|
||||
|
||||
return new ImageData(shadeData, width, height);
|
||||
}
|
||||
|
||||
var elevation = new ol.source.XYZ({
|
||||
url: 'https://{a-d}.tiles.mapbox.com/v3/aj.sf-dem/{z}/{x}/{y}.png',
|
||||
crossOrigin: 'anonymous'
|
||||
});
|
||||
|
||||
var raster = new ol.source.Raster({
|
||||
sources: [elevation],
|
||||
operationType: 'image',
|
||||
operation: shade
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.TileJSON({
|
||||
url: 'http://api.tiles.mapbox.com/v3/tschaub.miapgppd.jsonp'
|
||||
})
|
||||
}),
|
||||
new ol.layer.Image({
|
||||
opacity: 0.3,
|
||||
source: raster
|
||||
})
|
||||
],
|
||||
view: new ol.View({
|
||||
extent: [-13675026, 4439648, -13580856, 4580292],
|
||||
center: [-13615645, 4497969],
|
||||
minZoom: 10,
|
||||
maxZoom: 16,
|
||||
zoom: 13
|
||||
})
|
||||
});
|
||||
|
||||
var controlIds = ['vert', 'sunEl', 'sunAz'];
|
||||
var controls = {};
|
||||
controlIds.forEach(function(id) {
|
||||
var control = document.getElementById(id);
|
||||
var output = document.getElementById(id + 'Out');
|
||||
control.addEventListener('input', function() {
|
||||
output.innerText = control.value;
|
||||
raster.changed();
|
||||
});
|
||||
output.innerText = control.value;
|
||||
controls[id] = control;
|
||||
});
|
||||
|
||||
raster.on('beforeoperations', function(event) {
|
||||
// the event.data object will be passed to operations
|
||||
var data = event.data;
|
||||
data.resolution = event.resolution;
|
||||
for (var id in controls) {
|
||||
data[id] = Number(controls[id].value);
|
||||
}
|
||||
});
|
||||
@@ -1,4 +1,3 @@
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.format.GeoJSON');
|
||||
@@ -60,7 +59,8 @@ var map = new ol.Map({
|
||||
|
||||
var highlightStyleCache = {};
|
||||
|
||||
var featureOverlay = new ol.FeatureOverlay({
|
||||
var featureOverlay = new ol.layer.Vector({
|
||||
source: new ol.source.Vector(),
|
||||
map: map,
|
||||
style: function(feature, resolution) {
|
||||
var text = resolution < 5000 ? feature.get('name') : '';
|
||||
@@ -106,10 +106,10 @@ var displayFeatureInfo = function(pixel) {
|
||||
|
||||
if (feature !== highlight) {
|
||||
if (highlight) {
|
||||
featureOverlay.removeFeature(highlight);
|
||||
featureOverlay.getSource().removeFeature(highlight);
|
||||
}
|
||||
if (feature) {
|
||||
featureOverlay.addFeature(feature);
|
||||
featureOverlay.getSource().addFeature(feature);
|
||||
}
|
||||
highlight = feature;
|
||||
}
|
||||
|
||||
@@ -1,75 +1,38 @@
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.format.WMTSCapabilities');
|
||||
goog.require('ol.has');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.source.WMTS');
|
||||
goog.require('ol.tilegrid.WMTS');
|
||||
|
||||
|
||||
var template =
|
||||
'{Layer}/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg';
|
||||
var urls = [
|
||||
'http://maps1.wien.gv.at/basemap/' + template,
|
||||
'http://maps2.wien.gv.at/basemap/' + template,
|
||||
'http://maps3.wien.gv.at/basemap/' + template,
|
||||
'http://maps4.wien.gv.at/basemap/' + template,
|
||||
'http://maps.wien.gv.at/basemap/' + template
|
||||
];
|
||||
|
||||
var capabilitiesUrl = 'http://www.basemap.at/wmts/1.0.0/WMTSCapabilities.xml';
|
||||
|
||||
// HiDPI support:
|
||||
// * Use 'bmaphidpi' layer (pixel ratio 2) for device pixel ratio > 1
|
||||
// * Use 'geolandbasemap' layer (pixel ratio 1) for device pixel ratio == 1
|
||||
var hiDPI = ol.has.DEVICE_PIXEL_RATIO > 1;
|
||||
|
||||
var source = new ol.source.WMTS({
|
||||
projection: 'EPSG:3857',
|
||||
layer: hiDPI ? 'bmaphidpi' : 'geolandbasemap',
|
||||
tilePixelRatio: hiDPI ? 2 : 1,
|
||||
style: 'normal',
|
||||
matrixSet: 'google3857',
|
||||
urls: urls,
|
||||
requestEncoding: 'REST',
|
||||
tileGrid: new ol.tilegrid.WMTS({
|
||||
origin: [-20037508.3428, 20037508.3428],
|
||||
resolutions: [
|
||||
559082264.029 * 0.28E-3,
|
||||
279541132.015 * 0.28E-3,
|
||||
139770566.007 * 0.28E-3,
|
||||
69885283.0036 * 0.28E-3,
|
||||
34942641.5018 * 0.28E-3,
|
||||
17471320.7509 * 0.28E-3,
|
||||
8735660.37545 * 0.28E-3,
|
||||
4367830.18773 * 0.28E-3,
|
||||
2183915.09386 * 0.28E-3,
|
||||
1091957.54693 * 0.28E-3,
|
||||
545978.773466 * 0.28E-3,
|
||||
272989.386733 * 0.28E-3,
|
||||
136494.693366 * 0.28E-3,
|
||||
68247.3466832 * 0.28E-3,
|
||||
34123.6733416 * 0.28E-3,
|
||||
17061.8366708 * 0.28E-3,
|
||||
8530.91833540 * 0.28E-3,
|
||||
4265.45916770 * 0.28E-3,
|
||||
2132.72958385 * 0.28E-3,
|
||||
1066.36479193 * 0.28E-3
|
||||
],
|
||||
matrixIds: [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
|
||||
]
|
||||
})
|
||||
});
|
||||
var layer = hiDPI ? 'bmaphidpi' : 'geolandbasemap';
|
||||
var tilePixelRatio = hiDPI ? 2 : 1;
|
||||
|
||||
var map = new ol.Map({
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
extent: [977844.377599999, 5837774.6617, 1915609.8654, 6295560.8122],
|
||||
source: source
|
||||
})
|
||||
],
|
||||
target: 'map',
|
||||
view: new ol.View({
|
||||
center: [1823849, 6143760],
|
||||
zoom: 11
|
||||
})
|
||||
});
|
||||
|
||||
$.ajax(capabilitiesUrl).then(function(response) {
|
||||
var result = new ol.format.WMTSCapabilities().read(response);
|
||||
var options = ol.source.WMTS.optionsFromCapabilities(result, {
|
||||
layer: layer,
|
||||
matrixSet: 'google3857',
|
||||
requestEncoding: 'REST',
|
||||
style: 'normal'
|
||||
});
|
||||
options.tilePixelRatio = tilePixelRatio;
|
||||
map.addLayer(new ol.layer.Tile({
|
||||
source: new ol.source.WMTS(options)
|
||||
}));
|
||||
});
|
||||
|
||||
18
examples/wmts-ign.html
Normal file
18
examples/wmts-ign.html
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
template: example.html
|
||||
title: IGN WMTS example
|
||||
shortdesc: Demonstrates displaying IGN (France) WMTS layers.
|
||||
docs: >
|
||||
In this example an IGN WMTS layer is displayed.
|
||||
For more information on IGN's WMTS service see the
|
||||
<a href="http://professionnels.ign.fr/api-sig">IGN Géoportail API web page
|
||||
</a> and
|
||||
<a href="http://www.geoportail.gouv.fr/depot/api/cgu/DT_APIGeoportail.pdf">
|
||||
Descriptif technique des web services du Géoportail</a> (french).
|
||||
tags: "french, ign, geoportail, wmts"
|
||||
---
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<div id="map" class="map"></div>
|
||||
</div>
|
||||
</div>
|
||||
64
examples/wmts-ign.js
Normal file
64
examples/wmts-ign.js
Normal file
@@ -0,0 +1,64 @@
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.control');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.source.WMTS');
|
||||
goog.require('ol.tilegrid.WMTS');
|
||||
|
||||
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
controls: ol.control.defaults({
|
||||
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
|
||||
collapsible: false
|
||||
})
|
||||
}),
|
||||
view: new ol.View({
|
||||
zoom: 5,
|
||||
center: ol.proj.transform([5, 45], 'EPSG:4326', 'EPSG:3857')
|
||||
})
|
||||
});
|
||||
|
||||
var resolutions = [];
|
||||
var matrixIds = [];
|
||||
var proj3857 = ol.proj.get('EPSG:3857');
|
||||
var maxResolution = ol.extent.getWidth(proj3857.getExtent()) / 256;
|
||||
|
||||
for (var i = 0; i < 18; i++) {
|
||||
matrixIds[i] = i.toString();
|
||||
resolutions[i] = maxResolution / Math.pow(2, i);
|
||||
}
|
||||
|
||||
var tileGrid = new ol.tilegrid.WMTS({
|
||||
origin: [-20037508, 20037508],
|
||||
resolutions: resolutions,
|
||||
matrixIds: matrixIds
|
||||
});
|
||||
|
||||
// API key valid for 'openlayers.org' and 'localhost'.
|
||||
// Expiration date is 06/29/2018.
|
||||
var key = '2mqbg0z6cx7ube8gsou10nrt';
|
||||
|
||||
var ign_source = new ol.source.WMTS({
|
||||
url: 'http://wxs.ign.fr/' + key + '/wmts',
|
||||
layer: 'GEOGRAPHICALGRIDSYSTEMS.MAPS',
|
||||
matrixSet: 'PM',
|
||||
format: 'image/jpeg',
|
||||
projection: 'EPSG:3857',
|
||||
tileGrid: tileGrid,
|
||||
style: 'normal',
|
||||
attributions: [new ol.Attribution({
|
||||
html: '<a href="http://www.geoportail.fr/" target="_blank">' +
|
||||
'<img src="http://api.ign.fr/geoportail/api/js/latest/' +
|
||||
'theme/geoportal/img/logo_gp.gif"></a>'
|
||||
})]
|
||||
});
|
||||
|
||||
var ign = new ol.layer.Tile({
|
||||
source: ign_source
|
||||
});
|
||||
|
||||
map.addLayer(ign);
|
||||
@@ -3,7 +3,7 @@ template: example.html
|
||||
title: XYZ Esri EPSG:4326 tileSize 512 example
|
||||
shortdesc: Example of a XYZ source in EPSG:4326 using Esri 512x512 tiles.
|
||||
docs: >
|
||||
ArcGIS REST tile services with custom tile sizes (here: 512x512 pixels) and projection (here: EPSG:4326) are supported by `ol.source.XYZ`. A custom tile grid and tile url function are required.
|
||||
ArcGIS REST tile services with custom tile sizes (here: 512x512 pixels) and projection (here: EPSG:4326) are supported by `ol.source.XYZ`. A custom tile url function is used to handle zoom level offsets.
|
||||
tags: "xyz, esri, tilesize, custom projection"
|
||||
---
|
||||
<div class="row-fluid">
|
||||
|
||||
@@ -1,33 +1,19 @@
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.source.TileImage');
|
||||
goog.require('ol.tilegrid.TileGrid');
|
||||
goog.require('ol.source.XYZ');
|
||||
|
||||
var attribution = new ol.Attribution({
|
||||
html: 'Copyright:© 2013 ESRI, i-cubed, GeoEye'
|
||||
});
|
||||
|
||||
var projection = ol.proj.get('EPSG:4326');
|
||||
var projectionExtent = projection.getExtent();
|
||||
|
||||
// The tile size supported by the ArcGIS tile service.
|
||||
var tileSize = 512;
|
||||
|
||||
// Calculate the resolutions supported by the ArcGIS tile service.
|
||||
// There are 16 resolutions, with a factor of 2 between successive
|
||||
// resolutions. The max resolution is such that the world (360°)
|
||||
// fits into two (512x512 px) tiles.
|
||||
var maxResolution = ol.extent.getWidth(projectionExtent) / (tileSize * 2);
|
||||
var resolutions = new Array(16);
|
||||
var z;
|
||||
for (z = 0; z < 16; ++z) {
|
||||
resolutions[z] = maxResolution / Math.pow(2, z);
|
||||
}
|
||||
|
||||
var urlTemplate = 'http://services.arcgisonline.com/arcgis/rest/services/' +
|
||||
'ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}';
|
||||
|
||||
@@ -35,31 +21,17 @@ var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
/* ol.source.XYZ and ol.tilegrid.TileGrid have no resolutions config */
|
||||
source: new ol.source.TileImage({
|
||||
source: new ol.source.XYZ({
|
||||
attributions: [attribution],
|
||||
tileUrlFunction: function(tileCoord, pixelRatio, projection) {
|
||||
var z = tileCoord[0];
|
||||
var x = tileCoord[1];
|
||||
var y = -tileCoord[2] - 1;
|
||||
// wrap the world on the X axis
|
||||
var n = Math.pow(2, z + 1); // 2 tiles at z=0
|
||||
x = x % n;
|
||||
if (x * n < 0) {
|
||||
// x and n differ in sign so add n to wrap the result
|
||||
// to the correct sign
|
||||
x = x + n;
|
||||
}
|
||||
return urlTemplate.replace('{z}', z.toString())
|
||||
.replace('{y}', y.toString())
|
||||
.replace('{x}', x.toString());
|
||||
},
|
||||
maxZoom: 16,
|
||||
projection: projection,
|
||||
tileGrid: new ol.tilegrid.TileGrid({
|
||||
origin: ol.extent.getTopLeft(projectionExtent),
|
||||
resolutions: resolutions,
|
||||
tileSize: 512
|
||||
})
|
||||
tileSize: tileSize,
|
||||
tileUrlFunction: function(tileCoord) {
|
||||
return urlTemplate.replace('{z}', (tileCoord[0] - 1).toString())
|
||||
.replace('{x}', tileCoord[1].toString())
|
||||
.replace('{y}', (-tileCoord[2] - 1).toString());
|
||||
},
|
||||
wrapX: true
|
||||
})
|
||||
})
|
||||
],
|
||||
|
||||
@@ -123,7 +123,7 @@ var GeoJSONFeature = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {GeoJSONGeometry}
|
||||
* @type {GeoJSONGeometry|GeoJSONGeometryCollection}
|
||||
*/
|
||||
GeoJSONFeature.prototype.geometry;
|
||||
|
||||
|
||||
@@ -49,6 +49,25 @@ oli.DrawEvent.prototype.feature;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.ModifyEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Collection.<ol.Feature>}
|
||||
*/
|
||||
oli.ModifyEvent.prototype.features;
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.MapBrowserPointerEvent}
|
||||
*/
|
||||
oli.ModifyEvent.prototype.mapBrowserPointerEvent;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
@@ -247,6 +266,30 @@ oli.source.ImageEvent = function() {};
|
||||
oli.source.ImageEvent.prototype.image;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.source.RasterEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
oli.source.RasterEvent.prototype.extent;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
oli.source.RasterEvent.prototype.resolution;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
oli.source.RasterEvent.prototype.data;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
|
||||
399
externs/olx.js
399
externs/olx.js
@@ -1,3 +1,4 @@
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
@@ -331,7 +332,7 @@ olx.OverlayOptions.prototype.element;
|
||||
|
||||
|
||||
/**
|
||||
* Offsets in pixels used when positioning the overlay. The fist element in the
|
||||
* Offsets in pixels used when positioning the overlay. The first element in the
|
||||
* array is the horizontal offset. A positive value shifts the overlay right.
|
||||
* The second element in the array is the vertical offset. A positive value
|
||||
* shifts the overlay down. Default is `[0, 0]`.
|
||||
@@ -472,6 +473,7 @@ olx.ProjectionOptions.prototype.global;
|
||||
*/
|
||||
olx.ProjectionOptions.prototype.worldExtent;
|
||||
|
||||
|
||||
/**
|
||||
* Function to determine resolution at a point. The function is called with a
|
||||
* `{number}` view resolution and an `{ol.Coordinate}` as arguments, and returns
|
||||
@@ -911,6 +913,7 @@ olx.control.AttributionOptions.prototype.tipLabel;
|
||||
*/
|
||||
olx.control.AttributionOptions.prototype.label;
|
||||
|
||||
|
||||
/**
|
||||
* Text label to use for the expanded attributions button. Default is `»`.
|
||||
* Instead of text, also a Node (e.g. a `span` element) can be used.
|
||||
@@ -1910,6 +1913,7 @@ olx.format.WFSOptions.prototype.schemaLocation;
|
||||
* outputFormat: (string|undefined),
|
||||
* maxFeatures: (number|undefined),
|
||||
* geometryName: (string|undefined),
|
||||
* propertyNames: (Array.<string>|undefined),
|
||||
* bbox: (ol.Extent|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
@@ -1981,6 +1985,14 @@ olx.format.WFSWriteGetFeatureOptions.prototype.maxFeatures;
|
||||
olx.format.WFSWriteGetFeatureOptions.prototype.geometryName;
|
||||
|
||||
|
||||
/**
|
||||
* Optional list of property names to serialize.
|
||||
* @type {Array.<string>|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.format.WFSWriteGetFeatureOptions.prototype.propertyNames;
|
||||
|
||||
|
||||
/**
|
||||
* Extent to use for the BBOX filter.
|
||||
* @type {ol.Extent|undefined}
|
||||
@@ -2356,7 +2368,8 @@ olx.interaction.DragZoomOptions.prototype.style;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{features: (ol.Collection.<ol.Feature>|undefined),
|
||||
* @typedef {{clickTolerance: (number|undefined),
|
||||
* features: (ol.Collection.<ol.Feature>|undefined),
|
||||
* source: (ol.source.Vector|undefined),
|
||||
* snapTolerance: (number|undefined),
|
||||
* type: ol.geom.GeometryType,
|
||||
@@ -2366,12 +2379,25 @@ olx.interaction.DragZoomOptions.prototype.style;
|
||||
* geometryFunction: (ol.interaction.DrawGeometryFunctionType|undefined),
|
||||
* geometryName: (string|undefined),
|
||||
* condition: (ol.events.ConditionType|undefined),
|
||||
* freehandCondition: (ol.events.ConditionType|undefined)}}
|
||||
* freehandCondition: (ol.events.ConditionType|undefined),
|
||||
* wrapX: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DrawOptions;
|
||||
|
||||
|
||||
/**
|
||||
* The maximum distance in pixels between "down" and "up" for a "up" event
|
||||
* to be considered a "click" event and actually add a point/vertex to the
|
||||
* geometry being drawn. Default is 6 pixels. That value was chosen for
|
||||
* the draw interaction to behave correctly on mouse as well as on touch
|
||||
* devices.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DrawOptions.prototype.clickTolerance;
|
||||
|
||||
|
||||
/**
|
||||
* Destination collection for the drawn features.
|
||||
* @type {ol.Collection.<ol.Feature>|undefined}
|
||||
@@ -2470,6 +2496,14 @@ olx.interaction.DrawOptions.prototype.condition;
|
||||
olx.interaction.DrawOptions.prototype.freehandCondition;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap the world horizontally on the sketch overlay. Default is `false`.
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DrawOptions.prototype.wrapX;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{condition: (ol.events.ConditionType|undefined),
|
||||
* duration: (number|undefined),
|
||||
@@ -2545,7 +2579,8 @@ olx.interaction.KeyboardZoomOptions.prototype.delta;
|
||||
* @typedef {{deleteCondition: (ol.events.ConditionType|undefined),
|
||||
* pixelTolerance: (number|undefined),
|
||||
* style: (ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined),
|
||||
* features: ol.Collection.<ol.Feature>}}
|
||||
* features: ol.Collection.<ol.Feature>,
|
||||
* wrapX: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.ModifyOptions;
|
||||
@@ -2572,7 +2607,8 @@ olx.interaction.ModifyOptions.prototype.pixelTolerance;
|
||||
|
||||
|
||||
/**
|
||||
* FeatureOverlay style.
|
||||
* Style used for the features being modified. By default the default edit
|
||||
* style is used (see {@link ol.style}).
|
||||
* @type {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -2587,6 +2623,14 @@ olx.interaction.ModifyOptions.prototype.style;
|
||||
olx.interaction.ModifyOptions.prototype.features;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap the world horizontally on the sketch overlay. Default is `false`.
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.ModifyOptions.prototype.wrapX;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{duration: (number|undefined)}}
|
||||
* @api
|
||||
@@ -2708,7 +2752,8 @@ olx.interaction.PointerOptions.prototype.handleUpEvent;
|
||||
* removeCondition: (ol.events.ConditionType|undefined),
|
||||
* toggleCondition: (ol.events.ConditionType|undefined),
|
||||
* multi: (boolean|undefined),
|
||||
* filter: (ol.interaction.SelectFilterFunction|undefined)}}
|
||||
* filter: (ol.interaction.SelectFilterFunction|undefined),
|
||||
* wrapX: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.SelectOptions;
|
||||
@@ -2753,7 +2798,8 @@ olx.interaction.SelectOptions.prototype.layers;
|
||||
|
||||
|
||||
/**
|
||||
* Style for the selected features (those in the FeatureOverlay).
|
||||
* Style for the selected features. By default the default edit style is used
|
||||
* (see {@link ol.style}).
|
||||
* @type {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -2785,6 +2831,7 @@ olx.interaction.SelectOptions.prototype.removeCondition;
|
||||
*/
|
||||
olx.interaction.SelectOptions.prototype.toggleCondition;
|
||||
|
||||
|
||||
/**
|
||||
* A boolean that determines if the default behaviour should select only
|
||||
* single features or all (overlapping) features at the clicked map
|
||||
@@ -2794,6 +2841,7 @@ olx.interaction.SelectOptions.prototype.toggleCondition;
|
||||
*/
|
||||
olx.interaction.SelectOptions.prototype.multi;
|
||||
|
||||
|
||||
/**
|
||||
* A function that takes an {@link ol.Feature} and an {@link ol.layer.Layer} and
|
||||
* returns `true` if the feature may be selected or `false` otherwise.
|
||||
@@ -2803,6 +2851,14 @@ olx.interaction.SelectOptions.prototype.multi;
|
||||
olx.interaction.SelectOptions.prototype.filter;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap the world horizontally on the selection overlay. Default is `true`.
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.SelectOptions.prototype.wrapX;
|
||||
|
||||
|
||||
/**
|
||||
* Options for snap
|
||||
* @typedef {{
|
||||
@@ -2825,7 +2881,7 @@ olx.interaction.SnapOptions.prototype.features;
|
||||
|
||||
/**
|
||||
* Pixel tolerance for considering the pointer close enough to a segment or
|
||||
* vertex for editing. Default is `10` pixels.
|
||||
* vertex for snapping. Default is `10` pixels.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -3282,6 +3338,7 @@ olx.layer.HeatmapOptions.prototype.visible;
|
||||
* hue: (number|undefined),
|
||||
* opacity: (number|undefined),
|
||||
* saturation: (number|undefined),
|
||||
* map: (ol.Map|undefined),
|
||||
* source: (ol.source.Image|undefined),
|
||||
* visible: (boolean|undefined),
|
||||
* extent: (ol.Extent|undefined),
|
||||
@@ -3340,6 +3397,17 @@ olx.layer.ImageOptions.prototype.saturation;
|
||||
olx.layer.ImageOptions.prototype.source;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the layer as overlay on a map. The map will not manage this layer in its
|
||||
* layers collection, and the layer will be rendered on top. This is useful for
|
||||
* temporary layers. The standard way to add a layer to a map and have it
|
||||
* managed by the map is to use {@link ol.Map#addLayer}.
|
||||
* @type {ol.Map|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.layer.ImageOptions.prototype.map;
|
||||
|
||||
|
||||
/**
|
||||
* Visibility. Default is `true` (visible).
|
||||
* @type {boolean|undefined}
|
||||
@@ -3381,6 +3449,7 @@ olx.layer.ImageOptions.prototype.maxResolution;
|
||||
* preload: (number|undefined),
|
||||
* saturation: (number|undefined),
|
||||
* source: (ol.source.Tile|undefined),
|
||||
* map: (ol.Map|undefined),
|
||||
* visible: (boolean|undefined),
|
||||
* extent: (ol.Extent|undefined),
|
||||
* minResolution: (number|undefined),
|
||||
@@ -3448,6 +3517,17 @@ olx.layer.TileOptions.prototype.saturation;
|
||||
olx.layer.TileOptions.prototype.source;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the layer as overlay on a map. The map will not manage this layer in its
|
||||
* layers collection, and the layer will be rendered on top. This is useful for
|
||||
* temporary layers. The standard way to add a layer to a map and have it
|
||||
* managed by the map is to use {@link ol.Map#addLayer}.
|
||||
* @type {ol.Map|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.layer.TileOptions.prototype.map;
|
||||
|
||||
|
||||
/**
|
||||
* Visibility. Default is `true` (visible).
|
||||
* @type {boolean|undefined}
|
||||
@@ -3500,6 +3580,7 @@ olx.layer.TileOptions.prototype.useInterimTilesOnError;
|
||||
* renderBuffer: (number|undefined),
|
||||
* saturation: (number|undefined),
|
||||
* source: (ol.source.Vector|undefined),
|
||||
* map: (ol.Map|undefined),
|
||||
* style: (ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined),
|
||||
* updateWhileAnimating: (boolean|undefined),
|
||||
* updateWhileInteracting: (boolean|undefined),
|
||||
@@ -3543,6 +3624,17 @@ olx.layer.VectorOptions.prototype.renderOrder;
|
||||
olx.layer.VectorOptions.prototype.hue;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the layer as overlay on a map. The map will not manage this layer in its
|
||||
* layers collection, and the layer will be rendered on top. This is useful for
|
||||
* temporary layers. The standard way to add a layer to a map and have it
|
||||
* managed by the map is to use {@link ol.Map#addLayer}.
|
||||
* @type {ol.Map|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.layer.VectorOptions.prototype.map;
|
||||
|
||||
|
||||
/**
|
||||
* The bounding extent for layer rendering. The layer will not be rendered
|
||||
* outside of this extent.
|
||||
@@ -3625,7 +3717,7 @@ olx.layer.VectorOptions.prototype.updateWhileAnimating;
|
||||
|
||||
/**
|
||||
* When set to `true`, feature batches will be recreated during interactions.
|
||||
* See also `updateWhileInteracting`. Default is `false`.
|
||||
* See also `updateWhileAnimating`. Default is `false`.
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -3640,39 +3732,6 @@ olx.layer.VectorOptions.prototype.updateWhileInteracting;
|
||||
olx.layer.VectorOptions.prototype.visible;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{features: (Array.<ol.Feature>|ol.Collection.<ol.Feature>|undefined),
|
||||
* map: (ol.Map|undefined),
|
||||
* style: (ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.FeatureOverlayOptions;
|
||||
|
||||
|
||||
/**
|
||||
* Features.
|
||||
* @type {Array.<ol.Feature>|ol.Collection.<ol.Feature>|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.FeatureOverlayOptions.prototype.features;
|
||||
|
||||
|
||||
/**
|
||||
* Map.
|
||||
* @type {ol.Map|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.FeatureOverlayOptions.prototype.map;
|
||||
|
||||
|
||||
/**
|
||||
* Feature style.
|
||||
* @type {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.FeatureOverlayOptions.prototype.style;
|
||||
|
||||
|
||||
/**
|
||||
* Namespace.
|
||||
* @type {Object}
|
||||
@@ -3968,12 +4027,14 @@ olx.source.TileImageOptions.prototype.wrapX;
|
||||
|
||||
/**
|
||||
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
|
||||
* format: ol.format.Feature,
|
||||
* format: (ol.format.Feature|undefined),
|
||||
* logo: (string|olx.LogoOptions|undefined),
|
||||
* tileGrid: ol.tilegrid.TileGrid,
|
||||
* tileUrlFunction: (ol.TileUrlFunctionType|undefined),
|
||||
* tileLoadFunction: (ol.TileVectorLoadFunctionType|undefined),
|
||||
* url: (string|undefined),
|
||||
* urls: (Array.<string>|undefined)}}
|
||||
* urls: (Array.<string>|undefined),
|
||||
* wrapX: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.source.TileVectorOptions;
|
||||
@@ -3988,8 +4049,8 @@ olx.source.TileVectorOptions.prototype.attributions;
|
||||
|
||||
|
||||
/**
|
||||
* Format.
|
||||
* @type {ol.format.Feature}
|
||||
* Format. Required unless tileLoadFunction is used.
|
||||
* @type {ol.format.Feature|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.TileVectorOptions.prototype.format;
|
||||
@@ -4020,6 +4081,16 @@ olx.source.TileVectorOptions.prototype.tileGrid;
|
||||
olx.source.TileVectorOptions.prototype.tileUrlFunction;
|
||||
|
||||
|
||||
/**
|
||||
* Optional function to override the default loading and format parsing behaviour.
|
||||
* If this option is used format is ignored and the provided function will be
|
||||
* responsible for data retrieval and transformation into features.
|
||||
* @type {ol.TileVectorLoadFunctionType|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.TileVectorOptions.prototype.tileLoadFunction;
|
||||
|
||||
|
||||
/**
|
||||
* URL template. Must include `{x}`, `{y}` or `{-y}`, and `{z}` placeholders.
|
||||
* @type {string|undefined}
|
||||
@@ -4036,6 +4107,16 @@ olx.source.TileVectorOptions.prototype.url;
|
||||
olx.source.TileVectorOptions.prototype.urls;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap the world horizontally. Default is `true`. For vector editing across the
|
||||
* -180° and 180° meridians to work properly, this should be set to `false`. The
|
||||
* resulting geometry coordinates will then exceed the world bounds.
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.TileVectorOptions.prototype.wrapX;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{url: (string|undefined),
|
||||
* displayDpi: (number|undefined),
|
||||
@@ -4103,7 +4184,8 @@ olx.source.ImageMapGuideOptions.prototype.projection;
|
||||
|
||||
/**
|
||||
* Ratio. `1` means image requests are the size of the map viewport, `2` means
|
||||
* twice the size of the map viewport, and so on. Default is `1`.
|
||||
* twice the width and height of the map viewport, and so on. Must be `1` or
|
||||
* higher. Default is `1`.
|
||||
* @type {number|undefined}
|
||||
* @api stable
|
||||
*/
|
||||
@@ -4118,7 +4200,6 @@ olx.source.ImageMapGuideOptions.prototype.ratio;
|
||||
olx.source.ImageMapGuideOptions.prototype.resolutions;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Optional function to load an image given a URL.
|
||||
* @type {ol.TileLoadFunctionType|undefined}
|
||||
@@ -4170,7 +4251,8 @@ olx.source.MapQuestOptions.prototype.url;
|
||||
|
||||
/**
|
||||
* @typedef {{projection: ol.proj.ProjectionLike,
|
||||
* tileGrid: (ol.tilegrid.TileGrid|undefined)}}
|
||||
* tileGrid: (ol.tilegrid.TileGrid|undefined),
|
||||
* wrapX: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.source.TileDebugOptions;
|
||||
@@ -4192,6 +4274,14 @@ olx.source.TileDebugOptions.prototype.projection;
|
||||
olx.source.TileDebugOptions.prototype.tileGrid;
|
||||
|
||||
|
||||
/**
|
||||
* Whether to wrap the world horizontally. Default is `true`.
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.TileDebugOptions.prototype.wrapX;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
|
||||
* crossOrigin: (null|string|undefined),
|
||||
@@ -4313,7 +4403,8 @@ olx.source.ImageCanvasOptions.prototype.projection;
|
||||
|
||||
/**
|
||||
* Ratio. 1 means canvases are the size of the map viewport, 2 means twice the
|
||||
* size of the map viewport, and so on. Default is `1.5`.
|
||||
* width and height of the map viewport, and so on. Must be `1` or higher.
|
||||
* Default is `1.5`.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -4376,7 +4467,8 @@ olx.source.ImageVectorOptions.prototype.projection;
|
||||
|
||||
/**
|
||||
* Ratio. 1 means canvases are the size of the map viewport, 2 means twice the
|
||||
* size of the map viewport, and so on. Default is `1.5`.
|
||||
* width and height of the map viewport, and so on. Must be `1` or higher.
|
||||
* Default is `1.5`.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -4409,6 +4501,65 @@ olx.source.ImageVectorOptions.prototype.source;
|
||||
olx.source.ImageVectorOptions.prototype.style;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{sources: Array.<ol.source.Source>,
|
||||
* operation: (ol.raster.Operation|undefined),
|
||||
* lib: (Object|undefined),
|
||||
* threads: (number|undefined),
|
||||
* operationType: (ol.raster.OperationType|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.source.RasterOptions;
|
||||
|
||||
|
||||
/**
|
||||
* Input sources.
|
||||
* @type {Array.<ol.source.Source>}
|
||||
* @api
|
||||
*/
|
||||
olx.source.RasterOptions.prototype.sources;
|
||||
|
||||
|
||||
/**
|
||||
* Raster operation. The operation will be called with data from input sources
|
||||
* and the output will be assigned to the raster source.
|
||||
* @type {ol.raster.Operation|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.RasterOptions.prototype.operation;
|
||||
|
||||
|
||||
/**
|
||||
* Functions that will be made available to operations run in a worker.
|
||||
* @type {Object|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.RasterOptions.prototype.lib;
|
||||
|
||||
|
||||
/**
|
||||
* By default, operations will be run in a single worker thread. To avoid using
|
||||
* workers altogether, set `threads: 0`. For pixel operations, operations can
|
||||
* be run in multiple worker threads. Note that there is additional overhead in
|
||||
* transferring data to multiple workers, and that depending on the user's
|
||||
* system, it may not be possible to parallelize the work.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.RasterOptions.prototype.threads;
|
||||
|
||||
|
||||
/**
|
||||
* Operation type. Supported values are `'pixel'` and `'image'`. By default,
|
||||
* `'pixel'` operations are assumed, and operations will be called with an
|
||||
* array of pixels from input sources. If set to `'image'`, operations will
|
||||
* be called with an array of ImageData objects from input sources.
|
||||
* @type {ol.raster.OperationType|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.RasterOptions.prototype.operationType;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
|
||||
* crossOrigin: (null|string|undefined),
|
||||
@@ -4500,7 +4651,8 @@ olx.source.ImageWMSOptions.prototype.projection;
|
||||
|
||||
/**
|
||||
* Ratio. `1` means image requests are the size of the map viewport, `2` means
|
||||
* twice the size of the map viewport, and so on. Default is `1.5`.
|
||||
* twice the width and height of the map viewport, and so on. Must be `1` or
|
||||
* higher. Default is `1.5`.
|
||||
* @type {number|undefined}
|
||||
* @api stable
|
||||
*/
|
||||
@@ -4668,6 +4820,7 @@ olx.source.ImageStaticOptions.prototype.url;
|
||||
|
||||
/**
|
||||
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
|
||||
* crossOrigin: (null|string|undefined),
|
||||
* params: (Object.<string, *>|undefined),
|
||||
* logo: (string|olx.LogoOptions|undefined),
|
||||
* tileGrid: (ol.tilegrid.TileGrid|undefined),
|
||||
@@ -4680,6 +4833,7 @@ olx.source.ImageStaticOptions.prototype.url;
|
||||
*/
|
||||
olx.source.TileArcGISRestOptions;
|
||||
|
||||
|
||||
/**
|
||||
* Attributions.
|
||||
* @type {Array.<ol.Attribution>|undefined}
|
||||
@@ -4688,6 +4842,18 @@ olx.source.TileArcGISRestOptions;
|
||||
olx.source.TileArcGISRestOptions.prototype.attributions;
|
||||
|
||||
|
||||
/**
|
||||
* The `crossOrigin` attribute for loaded images. Note that you must provide a
|
||||
* `crossOrigin` value if you are using the WebGL renderer or if you want to
|
||||
* access pixel data with the Canvas renderer. See
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image}
|
||||
* for more detail.
|
||||
* @type {null|string|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.TileArcGISRestOptions.prototype.crossOrigin;
|
||||
|
||||
|
||||
/**
|
||||
* ArcGIS Rest parameters. This field is optional. Service defaults will be
|
||||
* used for any fields not specified. `FORMAT` is `PNG32` by default. `F` is `IMAGE` by
|
||||
@@ -4721,6 +4887,7 @@ olx.source.TileArcGISRestOptions.prototype.logo;
|
||||
*/
|
||||
olx.source.TileArcGISRestOptions.prototype.tileGrid;
|
||||
|
||||
|
||||
/**
|
||||
* Projection.
|
||||
* @type {ol.proj.ProjectionLike}
|
||||
@@ -4977,12 +5144,13 @@ olx.source.TileWMSOptions.prototype.wrapX;
|
||||
|
||||
/**
|
||||
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
|
||||
* features: (Array.<ol.Feature>|undefined),
|
||||
* features: (Array.<ol.Feature>|ol.Collection.<ol.Feature>|undefined),
|
||||
* format: (ol.format.Feature|undefined),
|
||||
* loader: (ol.FeatureLoader|undefined),
|
||||
* logo: (string|olx.LogoOptions|undefined),
|
||||
* strategy: (ol.LoadingStrategy|undefined),
|
||||
* url: (string|undefined),
|
||||
* useSpatialIndex: (boolean|undefined),
|
||||
* wrapX: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
@@ -4998,8 +5166,9 @@ olx.source.VectorOptions.prototype.attributions;
|
||||
|
||||
|
||||
/**
|
||||
* Features.
|
||||
* @type {Array.<ol.Feature>|undefined}
|
||||
* Features. If provided as {@link ol.Collection}, the features in the source
|
||||
* and the collection will stay in sync.
|
||||
* @type {Array.<ol.Feature>|ol.Collection.<ol.Feature>|undefined}
|
||||
* @api stable
|
||||
*/
|
||||
olx.source.VectorOptions.prototype.features;
|
||||
@@ -5052,6 +5221,29 @@ olx.source.VectorOptions.prototype.strategy;
|
||||
olx.source.VectorOptions.prototype.url;
|
||||
|
||||
|
||||
/**
|
||||
* By default, an RTree is used as spatial index. When features are removed and
|
||||
* added frequently, and the total number of features is low, setting this to
|
||||
* `false` may improve performance.
|
||||
*
|
||||
* Note that
|
||||
* {@link ol.source.Vector#getFeaturesInExtent},
|
||||
* {@link ol.source.Vector#getClosestFeatureToCoordinate} and
|
||||
* {@link ol.source.Vector#getExtent} cannot be used when `useSpatialIndex` is
|
||||
* set to `false`, and {@link ol.source.Vector#forEachFeatureInExtent} will loop
|
||||
* through all features.
|
||||
*
|
||||
* When set to `false`, the features will be maintained in an
|
||||
* {@link ol.Collection}, which can be retrieved through
|
||||
* {@link ol.source.Vector#getFeaturesCollection}.
|
||||
*
|
||||
* The default is `true`.
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.VectorOptions.prototype.useSpatialIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap the world horizontally. Default is `true`. For vector editing across the
|
||||
* -180° and 180° meridians to work properly, this should be set to `false`. The
|
||||
@@ -5213,7 +5405,9 @@ olx.source.WMTSOptions.prototype.dimensions;
|
||||
|
||||
/**
|
||||
* A URL for the service. For the RESTful request encoding, this is a URL
|
||||
* template. For KVP encoding, it is normal URL.
|
||||
* template. For KVP encoding, it is normal URL. A `{?-?}` template pattern,
|
||||
* for example `subdomain{a-f}.domain.com`, may be used instead of defining
|
||||
* each one separately in the `urls` option.
|
||||
* @type {string|undefined}
|
||||
* @api stable
|
||||
*/
|
||||
@@ -5259,6 +5453,7 @@ olx.source.WMTSOptions.prototype.wrapX;
|
||||
* projection: ol.proj.ProjectionLike,
|
||||
* maxZoom: (number|undefined),
|
||||
* minZoom: (number|undefined),
|
||||
* tileGrid: (ol.tilegrid.TileGrid|undefined),
|
||||
* tileLoadFunction: (ol.TileLoadFunctionType|undefined),
|
||||
* tilePixelRatio: (number|undefined),
|
||||
* tileSize: (number|ol.Size|undefined),
|
||||
@@ -5323,6 +5518,14 @@ olx.source.XYZOptions.prototype.maxZoom;
|
||||
olx.source.XYZOptions.prototype.minZoom;
|
||||
|
||||
|
||||
/**
|
||||
* Tile grid.
|
||||
* @type {ol.tilegrid.TileGrid}
|
||||
* @api
|
||||
*/
|
||||
olx.source.XYZOptions.prototype.tileGrid;
|
||||
|
||||
|
||||
/**
|
||||
* Optional function to load a tile given a URL.
|
||||
* @type {ol.TileLoadFunctionType|undefined}
|
||||
@@ -5361,6 +5564,8 @@ olx.source.XYZOptions.prototype.tileUrlFunction;
|
||||
|
||||
/**
|
||||
* URL template. Must include `{x}`, `{y}` or `{-y}`, and `{z}` placeholders.
|
||||
* A `{?-?}` template pattern, for example `subdomain{a-f}.domain.com`, may be
|
||||
* used instead of defining each one separately in the `urls` option.
|
||||
* @type {string|undefined}
|
||||
* @api stable
|
||||
*/
|
||||
@@ -6036,8 +6241,7 @@ olx.tilegrid;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{createTileCoordTransform: (undefined|function({extent: (ol.Extent|undefined)}):function(ol.TileCoord, ol.proj.Projection, ol.TileCoord=):ol.TileCoord),
|
||||
* extent: (ol.Extent|undefined),
|
||||
* @typedef {{extent: (ol.Extent|undefined),
|
||||
* minZoom: (number|undefined),
|
||||
* origin: (ol.Coordinate|undefined),
|
||||
* origins: (Array.<ol.Coordinate>|undefined),
|
||||
@@ -6053,8 +6257,7 @@ olx.tilegrid.TileGridOptions;
|
||||
/**
|
||||
* Extent for the tile grid. No tiles outside this extent will be requested by
|
||||
* {@link ol.source.Tile} sources. When no `origin` or `origins` are
|
||||
* configured, the `origin` will be set to the bottom-left corner of the extent.
|
||||
* When no `sizes` are configured, they will be calculated from the extent.
|
||||
* configured, the `origin` will be set to the top-left corner of the extent.
|
||||
* @type {ol.Extent|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -6070,7 +6273,9 @@ olx.tilegrid.TileGridOptions.prototype.minZoom;
|
||||
|
||||
|
||||
/**
|
||||
* Origin, i.e. the bottom-left corner of the grid. Default is null.
|
||||
* The tile grid origin, i.e. where the `x` and `y` axes meet (`[z, 0, 0]`).
|
||||
* Tile coordinates increase left to right and upwards. If not specified,
|
||||
* `extent` or `origins` must be provided.
|
||||
* @type {ol.Coordinate|undefined}
|
||||
* @api stable
|
||||
*/
|
||||
@@ -6078,9 +6283,11 @@ olx.tilegrid.TileGridOptions.prototype.origin;
|
||||
|
||||
|
||||
/**
|
||||
* Origins, i.e. the bottom-left corners of the grid for each zoom level. If
|
||||
* given, the array length should match the length of the `resolutions` array,
|
||||
* i.e. each resolution can have a different origin.
|
||||
* Tile grid origins, i.e. where the `x` and `y` axes meet (`[z, 0, 0]`), for
|
||||
* each zoom level. If given, the array length should match the length of the
|
||||
* `resolutions` array, i.e. each resolution can have a different origin. Tile
|
||||
* coordinates increase left to right and upwards. If not specified, `extent`
|
||||
* or `origin` must be provided.
|
||||
* @type {Array.<ol.Coordinate>|undefined}
|
||||
* @api stable
|
||||
*/
|
||||
@@ -6097,17 +6304,6 @@ olx.tilegrid.TileGridOptions.prototype.origins;
|
||||
olx.tilegrid.TileGridOptions.prototype.resolutions;
|
||||
|
||||
|
||||
/**
|
||||
* Number of tile rows and columns of the grid for each zoom level. This setting
|
||||
* is only needed for tile coordinate transforms that need to work with origins
|
||||
* other than the bottom-left corner of the grid. No tiles outside this range
|
||||
* will be requested by sources. If an `extent` is also configured, it takes
|
||||
* precedence.
|
||||
* @type {Array.<ol.Size>|undefined}
|
||||
*/
|
||||
olx.tilegrid.TileGridOptions.prototype.sizes;
|
||||
|
||||
|
||||
/**
|
||||
* Tile size. Default is `[256, 256]`.
|
||||
* @type {number|ol.Size|undefined}
|
||||
@@ -6141,9 +6337,8 @@ olx.tilegrid.WMTSOptions;
|
||||
|
||||
/**
|
||||
* Extent for the tile grid. No tiles outside this extent will be requested by
|
||||
* {@link ol.source.WMTS} sources. When no `origin` or `origins` are
|
||||
* configured, the `origin` will be calculated from the extent.
|
||||
* When no `sizes` are configured, they will be calculated from the extent.
|
||||
* {@link ol.source.Tile} sources. When no `origin` or `origins` are
|
||||
* configured, the `origin` will be set to the top-left corner of the extent.
|
||||
* @type {ol.Extent|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -6151,19 +6346,23 @@ olx.tilegrid.WMTSOptions.prototype.extent;
|
||||
|
||||
|
||||
/**
|
||||
* Origin, i.e. the top-left corner of the grid.
|
||||
* The tile grid origin, i.e. where the `x` and `y` axes meet (`[z, 0, 0]`).
|
||||
* Tile coordinates increase left to right and upwards. If not specified,
|
||||
* `extent` or `origins` must be provided.
|
||||
* @type {ol.Coordinate|undefined}
|
||||
* @api
|
||||
* @api stable
|
||||
*/
|
||||
olx.tilegrid.WMTSOptions.prototype.origin;
|
||||
|
||||
|
||||
/**
|
||||
* Origins, i.e. the top-left corners of the grid for each zoom level. The
|
||||
* length of this array needs to match the length of the
|
||||
* `resolutions` array.
|
||||
* Tile grid origins, i.e. where the `x` and `y` axes meet (`[z, 0, 0]`), for
|
||||
* each zoom level. If given, the array length should match the length of the
|
||||
* `resolutions` array, i.e. each resolution can have a different origin. Tile
|
||||
* coordinates increase left to right and upwards. If not specified, `extent` or
|
||||
* `origin` must be provided.
|
||||
* @type {Array.<ol.Coordinate>|undefined}
|
||||
* @api
|
||||
* @api stable
|
||||
*/
|
||||
olx.tilegrid.WMTSOptions.prototype.origins;
|
||||
|
||||
@@ -6192,7 +6391,10 @@ olx.tilegrid.WMTSOptions.prototype.matrixIds;
|
||||
* here are the `TileMatrixWidth` and `TileMatrixHeight` advertised in the
|
||||
* GetCapabilities response of the WMTS, and define the grid's extent together
|
||||
* with the `origin`. An `extent` can be configured in addition, and will
|
||||
* further limit the extent for which tile requests are made by sources.
|
||||
* further limit the extent for which tile requests are made by sources. Note
|
||||
* that when the top-left corner of the `extent` is used as `origin` or
|
||||
* `origins`, then the `y` value must be negative because OpenLayers tile
|
||||
* coordinates increase upwards.
|
||||
* @type {Array.<ol.Size>|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -6275,21 +6477,6 @@ olx.tilegrid.XYZOptions.prototype.minZoom;
|
||||
olx.tilegrid.XYZOptions.prototype.tileSize;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{resolutions: !Array.<number>}}
|
||||
* @api
|
||||
*/
|
||||
olx.tilegrid.ZoomifyOptions;
|
||||
|
||||
|
||||
/**
|
||||
* Resolutions.
|
||||
* @type {!Array.<number>}
|
||||
* @api
|
||||
*/
|
||||
olx.tilegrid.ZoomifyOptions.prototype.resolutions;
|
||||
|
||||
|
||||
/**
|
||||
* Namespace.
|
||||
* @type {Object}
|
||||
@@ -6305,7 +6492,7 @@ olx.view;
|
||||
* minResolution: (number|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.view.FitGeometryOptions;
|
||||
olx.view.FitOptions;
|
||||
|
||||
|
||||
/**
|
||||
@@ -6314,7 +6501,7 @@ olx.view.FitGeometryOptions;
|
||||
* @type {!Array.<number>}
|
||||
* @api
|
||||
*/
|
||||
olx.view.FitGeometryOptions.prototype.padding;
|
||||
olx.view.FitOptions.prototype.padding;
|
||||
|
||||
|
||||
/**
|
||||
@@ -6322,7 +6509,7 @@ olx.view.FitGeometryOptions.prototype.padding;
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.view.FitGeometryOptions.prototype.constrainResolution;
|
||||
olx.view.FitOptions.prototype.constrainResolution;
|
||||
|
||||
|
||||
/**
|
||||
@@ -6330,7 +6517,7 @@ olx.view.FitGeometryOptions.prototype.constrainResolution;
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.view.FitGeometryOptions.prototype.nearest;
|
||||
olx.view.FitOptions.prototype.nearest;
|
||||
|
||||
|
||||
/**
|
||||
@@ -6338,7 +6525,7 @@ olx.view.FitGeometryOptions.prototype.nearest;
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.view.FitGeometryOptions.prototype.minResolution;
|
||||
olx.view.FitOptions.prototype.minResolution;
|
||||
|
||||
|
||||
/**
|
||||
@@ -6347,7 +6534,7 @@ olx.view.FitGeometryOptions.prototype.minResolution;
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.view.FitGeometryOptions.prototype.maxZoom;
|
||||
olx.view.FitOptions.prototype.maxZoom;
|
||||
|
||||
|
||||
/* typedefs for object literals exposed by the library */
|
||||
|
||||
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openlayers",
|
||||
"version": "3.6.0",
|
||||
"version": "3.8.1",
|
||||
"description": "Build tools and sources for developing OpenLayers based mapping applications",
|
||||
"keywords": [
|
||||
"map",
|
||||
@@ -12,7 +12,8 @@
|
||||
"install": "node tasks/install.js",
|
||||
"postinstall": "closure-util update",
|
||||
"start": "node tasks/serve.js",
|
||||
"test": "node tasks/test.js"
|
||||
"test": "node tasks/test.js",
|
||||
"debug-server": "node tasks/serve-lib.js"
|
||||
},
|
||||
"main": "dist/ol.js",
|
||||
"repository": {
|
||||
@@ -25,22 +26,22 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "0.9.0",
|
||||
"closure-util": "1.4.0",
|
||||
"browserify": "9.0.3",
|
||||
"closure-util": "1.5.0",
|
||||
"fs-extra": "0.12.0",
|
||||
"glob": "5.0.3",
|
||||
"graceful-fs": "3.0.2",
|
||||
"handlebars": "3.0.1",
|
||||
"htmlparser2": "3.7.3",
|
||||
"jsdoc": "3.3.0-alpha9",
|
||||
"marked": "0.3.3",
|
||||
"metalsmith": "1.6.0",
|
||||
"metalsmith-templates": "0.7.0",
|
||||
"nomnom": "1.8.0",
|
||||
"pixelworks": "1.0.0",
|
||||
"rbush": "1.3.5",
|
||||
"temp": "0.8.1",
|
||||
"walk": "2.3.4",
|
||||
"wrench": "1.5.8",
|
||||
"browserify": "9.0.3"
|
||||
"wrench": "1.5.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-css": "2.2.16",
|
||||
@@ -60,6 +61,7 @@
|
||||
"slimerjs-edge": "0.10.0-pre-2"
|
||||
},
|
||||
"ext": [
|
||||
"rbush"
|
||||
"rbush",
|
||||
{"module": "pixelworks", "browserify": true}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ ol.CollectionProperty = {
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires ol.CollectionEvent
|
||||
* @param {Array.<T>=} opt_array Array.
|
||||
* @param {!Array.<T>=} opt_array Array.
|
||||
* @template T
|
||||
* @api stable
|
||||
*/
|
||||
@@ -89,7 +89,7 @@ ol.Collection = function(opt_array) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<T>}
|
||||
* @type {!Array.<T>}
|
||||
*/
|
||||
this.array_ = goog.isDef(opt_array) ? opt_array : [];
|
||||
|
||||
@@ -113,7 +113,7 @@ ol.Collection.prototype.clear = function() {
|
||||
/**
|
||||
* Add elements to the collection. This pushes each item in the provided array
|
||||
* to the end of the collection.
|
||||
* @param {Array.<T>} arr Array.
|
||||
* @param {!Array.<T>} arr Array.
|
||||
* @return {ol.Collection.<T>} This collection.
|
||||
* @api stable
|
||||
*/
|
||||
@@ -145,7 +145,7 @@ ol.Collection.prototype.forEach = function(f, opt_this) {
|
||||
* 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.
|
||||
* @return {!Array.<T>} Array.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.getArray = function() {
|
||||
|
||||
@@ -3,7 +3,6 @@ goog.provide('ol.control.Control');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.MapEventType');
|
||||
goog.require('ol.Object');
|
||||
|
||||
@@ -79,24 +78,6 @@ ol.control.Control = function(options) {
|
||||
goog.inherits(ol.control.Control, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* Bind a listener that blurs the passed element on any mouseout- or
|
||||
* focusout-event.
|
||||
*
|
||||
* @param {!Element} button The button which shall blur on mouseout- or
|
||||
* focusout-event.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.Control.bindMouseOutFocusOutBlur = function(button) {
|
||||
goog.events.listen(button, [
|
||||
goog.events.EventType.MOUSEOUT,
|
||||
goog.events.EventType.FOCUSOUT
|
||||
], /** @this {Element} */ function() {
|
||||
this.blur();
|
||||
}, false);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
|
||||
@@ -67,8 +67,6 @@ ol.control.FullScreen = function(opt_options) {
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
this.handleClick_, false, this);
|
||||
|
||||
ol.control.Control.bindMouseOutFocusOutBlur(button);
|
||||
|
||||
goog.events.listen(goog.global.document,
|
||||
goog.dom.fullscreen.EventType.CHANGE,
|
||||
this.handleFullScreenChange_, false, this);
|
||||
|
||||
@@ -90,8 +90,6 @@ ol.control.OverviewMap = function(opt_options) {
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
this.handleClick_, false, this);
|
||||
|
||||
ol.control.Control.bindMouseOutFocusOutBlur(button);
|
||||
|
||||
var ovmapDiv = goog.dom.createDom(goog.dom.TagName.DIV, 'ol-overviewmap-map');
|
||||
|
||||
/**
|
||||
@@ -338,7 +336,7 @@ ol.control.OverviewMap.prototype.resetExtent_ = function() {
|
||||
ol.OVERVIEWMAP_MAX_RATIO / ol.OVERVIEWMAP_MIN_RATIO) / Math.LN2;
|
||||
var ratio = 1 / (Math.pow(2, steps / 2) * ol.OVERVIEWMAP_MIN_RATIO);
|
||||
ol.extent.scaleFromCenter(extent, ratio);
|
||||
ovview.fitExtent(extent, ovmapSize);
|
||||
ovview.fit(extent, ovmapSize);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -60,8 +60,6 @@ ol.control.Rotate = function(opt_options) {
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
ol.control.Rotate.prototype.handleClick_, false, this);
|
||||
|
||||
ol.control.Control.bindMouseOutFocusOutBlur(button);
|
||||
|
||||
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
|
||||
ol.css.CLASS_CONTROL;
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, button);
|
||||
|
||||
@@ -50,8 +50,6 @@ ol.control.Zoom = function(opt_options) {
|
||||
goog.events.EventType.CLICK, goog.partial(
|
||||
ol.control.Zoom.prototype.handleClick_, delta), false, this);
|
||||
|
||||
ol.control.Control.bindMouseOutFocusOutBlur(inElement);
|
||||
|
||||
var outElement = goog.dom.createDom(goog.dom.TagName.BUTTON, {
|
||||
'class': className + '-out',
|
||||
'type' : 'button',
|
||||
|
||||
@@ -8,7 +8,7 @@ goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.fx.DragDropEvent');
|
||||
goog.require('goog.fx.DragEvent');
|
||||
goog.require('goog.fx.Dragger');
|
||||
goog.require('goog.fx.Dragger.EventType');
|
||||
goog.require('goog.math');
|
||||
@@ -222,7 +222,7 @@ ol.control.ZoomSlider.prototype.handleContainerClick_ = function(browserEvent) {
|
||||
|
||||
/**
|
||||
* Handle dragger start events.
|
||||
* @param {goog.fx.DragDropEvent} event The dragdropevent.
|
||||
* @param {goog.fx.DragEvent} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.handleDraggerStart_ = function(event) {
|
||||
@@ -233,7 +233,7 @@ ol.control.ZoomSlider.prototype.handleDraggerStart_ = function(event) {
|
||||
/**
|
||||
* Handle dragger drag events.
|
||||
*
|
||||
* @param {goog.fx.DragDropEvent} event The dragdropevent.
|
||||
* @param {goog.fx.DragEvent} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.handleDraggerDrag_ = function(event) {
|
||||
@@ -245,7 +245,7 @@ ol.control.ZoomSlider.prototype.handleDraggerDrag_ = function(event) {
|
||||
|
||||
/**
|
||||
* Handle dragger end events.
|
||||
* @param {goog.fx.DragDropEvent} event The dragdropevent.
|
||||
* @param {goog.fx.DragEvent} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.handleDraggerEnd_ = function(event) {
|
||||
|
||||
@@ -43,8 +43,6 @@ ol.control.ZoomToExtent = function(opt_options) {
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
this.handleClick_, false, this);
|
||||
|
||||
ol.control.Control.bindMouseOutFocusOutBlur(button);
|
||||
|
||||
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
|
||||
ol.css.CLASS_CONTROL;
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, button);
|
||||
@@ -77,5 +75,5 @@ ol.control.ZoomToExtent.prototype.handleZoomToExtent_ = function() {
|
||||
view.getProjection().getExtent() : this.extent_;
|
||||
var size = map.getSize();
|
||||
goog.asserts.assert(goog.isDef(size), 'size should be defined');
|
||||
view.fitExtent(extent, size);
|
||||
view.fit(extent, size);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ goog.provide('ol.CoordinateFormatType');
|
||||
goog.provide('ol.coordinate');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
/**
|
||||
@@ -129,8 +130,8 @@ ol.coordinate.degreesToStringHDMS_ = function(degrees, hemispheres) {
|
||||
var normalizedDegrees = goog.math.modulo(degrees + 180, 360) - 180;
|
||||
var x = Math.abs(Math.round(3600 * normalizedDegrees));
|
||||
return Math.floor(x / 3600) + '\u00b0 ' +
|
||||
Math.floor((x / 60) % 60) + '\u2032 ' +
|
||||
Math.floor(x % 60) + '\u2033 ' +
|
||||
goog.string.padNumber(Math.floor((x / 60) % 60), 2) + '\u2032 ' +
|
||||
goog.string.padNumber(Math.floor(x % 60), 2) + '\u2033 ' +
|
||||
hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0);
|
||||
};
|
||||
|
||||
|
||||
@@ -67,9 +67,11 @@ ol.DeviceOrientationProperty = {
|
||||
*
|
||||
* @see http://www.w3.org/TR/orientation-event/
|
||||
*
|
||||
* To get notified of device orientation changes, register a listener for the
|
||||
* generic `change` event on your `ol.DeviceOrientation` instance.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires change Triggered when the device orientation changes.
|
||||
* @param {olx.DeviceOrientationOptions=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
|
||||
@@ -111,6 +111,18 @@ ol.events.condition.singleClick = function(mapBrowserEvent) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return `true` if the event is a map `dblclick` event, `false` otherwise.
|
||||
*
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event is a map `dblclick` event.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.doubleClick = function(mapBrowserEvent) {
|
||||
return mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return `true` if no modifier key (alt-, shift- or platform-modifier-key) is
|
||||
* pressed.
|
||||
|
||||
@@ -18,7 +18,7 @@ goog.require('ol.style.Style');
|
||||
* GeoJSON.
|
||||
*
|
||||
* Features can be styled individually with `setStyle`; otherwise they use the
|
||||
* style of their vector layer or feature overlay.
|
||||
* style of their vector layer.
|
||||
*
|
||||
* Note that attribute properties are set as {@link ol.Object} properties on
|
||||
* the feature object, so they are observable, and have get/set accessors.
|
||||
@@ -50,8 +50,6 @@ goog.require('ol.style.Style');
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires change Triggered when the id, the geometry or the style of the
|
||||
* feature changes.
|
||||
* @param {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
|
||||
@@ -153,6 +151,7 @@ ol.Feature.prototype.getGeometry = function() {
|
||||
/**
|
||||
* @return {number|string|undefined} Id.
|
||||
* @api stable
|
||||
* @observable
|
||||
*/
|
||||
ol.Feature.prototype.getId = function() {
|
||||
return this.id_;
|
||||
@@ -177,6 +176,7 @@ ol.Feature.prototype.getGeometryName = function() {
|
||||
* @return {ol.style.Style|Array.<ol.style.Style>|
|
||||
* ol.FeatureStyleFunction} The feature style.
|
||||
* @api stable
|
||||
* @observable
|
||||
*/
|
||||
ol.Feature.prototype.getStyle = function() {
|
||||
return this.style_;
|
||||
@@ -238,6 +238,7 @@ ol.Feature.prototype.setGeometry = function(geometry) {
|
||||
* @param {ol.style.Style|Array.<ol.style.Style>|
|
||||
* ol.FeatureStyleFunction} style Style for this feature.
|
||||
* @api stable
|
||||
* @observable
|
||||
*/
|
||||
ol.Feature.prototype.setStyle = function(style) {
|
||||
this.style_ = style;
|
||||
@@ -254,6 +255,7 @@ ol.Feature.prototype.setStyle = function(style) {
|
||||
* method.
|
||||
* @param {number|string|undefined} id The feature id.
|
||||
* @api stable
|
||||
* @observable
|
||||
*/
|
||||
ol.Feature.prototype.setId = function(id) {
|
||||
this.id_ = id;
|
||||
|
||||
@@ -1,326 +0,0 @@
|
||||
goog.provide('ol.FeatureOverlay');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.CollectionEventType');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.render.EventType');
|
||||
goog.require('ol.renderer.vector');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A mechanism for changing the style of a small number of features on a
|
||||
* temporary basis, for example highlighting. This is necessary with the Canvas
|
||||
* renderer, where, unlike in SVG, features cannot be individually referenced.
|
||||
* See examples/vector-layers for an example: create a FeatureOverlay with a
|
||||
* different style, copy the feature(s) you want rendered in this different
|
||||
* style into it, and then remove them again when you're finished.
|
||||
*
|
||||
* @constructor
|
||||
* @param {olx.FeatureOverlayOptions=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Collection.<ol.Feature>}
|
||||
*/
|
||||
this.features_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<goog.events.Key>}
|
||||
*/
|
||||
this.featuresListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, goog.events.Key>}
|
||||
*/
|
||||
this.featureChangeListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.Key}
|
||||
*/
|
||||
this.postComposeListenerKey_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
|
||||
*/
|
||||
this.style_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.StyleFunction|undefined}
|
||||
*/
|
||||
this.styleFunction_ = undefined;
|
||||
|
||||
this.setStyle(goog.isDef(options.style) ?
|
||||
options.style : ol.style.defaultStyleFunction);
|
||||
|
||||
if (goog.isDef(options.features)) {
|
||||
if (goog.isArray(options.features)) {
|
||||
this.setFeatures(new ol.Collection(options.features.slice()));
|
||||
} else {
|
||||
goog.asserts.assertInstanceof(options.features, ol.Collection,
|
||||
'options.features should be an ol.Collection');
|
||||
this.setFeatures(options.features);
|
||||
}
|
||||
} else {
|
||||
this.setFeatures(new ol.Collection());
|
||||
}
|
||||
|
||||
if (goog.isDef(options.map)) {
|
||||
this.setMap(options.map);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add a feature to the overlay.
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.addFeature = function(feature) {
|
||||
this.features_.push(feature);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the features on the overlay.
|
||||
* @return {ol.Collection.<ol.Feature>} Features collection.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.getFeatures = function() {
|
||||
return this.features_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the map associated with the overlay.
|
||||
* @return {?ol.Map} The map with which this feature overlay is associated.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.getMap = function() {
|
||||
return this.map_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleFeatureChange_ = function() {
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleFeaturesAdd_ = function(collectionEvent) {
|
||||
goog.asserts.assert(!goog.isNull(this.featureChangeListenerKeys_),
|
||||
'this.featureChangeListenerKeys_ should not be null');
|
||||
var feature = /** @type {ol.Feature} */ (collectionEvent.element);
|
||||
this.featureChangeListenerKeys_[goog.getUid(feature).toString()] =
|
||||
goog.events.listen(feature, goog.events.EventType.CHANGE,
|
||||
this.handleFeatureChange_, false, this);
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleFeaturesRemove_ = function(collectionEvent) {
|
||||
goog.asserts.assert(!goog.isNull(this.featureChangeListenerKeys_),
|
||||
'this.featureChangeListenerKeys_ should not be null');
|
||||
var feature = /** @type {ol.Feature} */ (collectionEvent.element);
|
||||
var key = goog.getUid(feature).toString();
|
||||
goog.events.unlistenByKey(this.featureChangeListenerKeys_[key]);
|
||||
delete this.featureChangeListenerKeys_[key];
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle changes in image style state.
|
||||
* @param {goog.events.Event} event Image style change event.
|
||||
* @private
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleImageChange_ = function(event) {
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.render.Event} event Event.
|
||||
* @private
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleMapPostCompose_ = function(event) {
|
||||
if (goog.isNull(this.features_)) {
|
||||
return;
|
||||
}
|
||||
var styleFunction = this.styleFunction_;
|
||||
if (!goog.isDef(styleFunction)) {
|
||||
styleFunction = ol.style.defaultStyleFunction;
|
||||
}
|
||||
var replayGroup = /** @type {ol.render.IReplayGroup} */
|
||||
(event.replayGroup);
|
||||
goog.asserts.assert(goog.isDef(replayGroup),
|
||||
'replayGroup should be defined');
|
||||
var frameState = event.frameState;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var squaredTolerance = ol.renderer.vector.getSquaredTolerance(resolution,
|
||||
pixelRatio);
|
||||
var i, ii, styles, featureStyleFunction;
|
||||
this.features_.forEach(function(feature) {
|
||||
featureStyleFunction = feature.getStyleFunction();
|
||||
styles = goog.isDef(featureStyleFunction) ?
|
||||
featureStyleFunction.call(feature, resolution) :
|
||||
styleFunction(feature, resolution);
|
||||
|
||||
if (!goog.isDefAndNotNull(styles)) {
|
||||
return;
|
||||
}
|
||||
ii = styles.length;
|
||||
for (i = 0; i < ii; ++i) {
|
||||
ol.renderer.vector.renderFeature(replayGroup, feature, styles[i],
|
||||
squaredTolerance, this.handleImageChange_, this);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove a feature from the overlay.
|
||||
* @param {ol.Feature} feature The feature to be removed.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.removeFeature = function(feature) {
|
||||
this.features_.remove(feature);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.render_ = function() {
|
||||
if (!goog.isNull(this.map_)) {
|
||||
this.map_.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the features for the overlay.
|
||||
* @param {ol.Collection.<ol.Feature>} features Features collection.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.setFeatures = function(features) {
|
||||
if (!goog.isNull(this.featuresListenerKeys_)) {
|
||||
goog.array.forEach(this.featuresListenerKeys_, goog.events.unlistenByKey);
|
||||
this.featuresListenerKeys_ = null;
|
||||
}
|
||||
if (!goog.isNull(this.featureChangeListenerKeys_)) {
|
||||
goog.array.forEach(
|
||||
goog.object.getValues(this.featureChangeListenerKeys_),
|
||||
goog.events.unlistenByKey);
|
||||
this.featureChangeListenerKeys_ = null;
|
||||
}
|
||||
this.features_ = features;
|
||||
if (!goog.isNull(features)) {
|
||||
this.featuresListenerKeys_ = [
|
||||
goog.events.listen(features, ol.CollectionEventType.ADD,
|
||||
this.handleFeaturesAdd_, false, this),
|
||||
goog.events.listen(features, ol.CollectionEventType.REMOVE,
|
||||
this.handleFeaturesRemove_, false, this)
|
||||
];
|
||||
this.featureChangeListenerKeys_ = {};
|
||||
features.forEach(function(feature) {
|
||||
this.featureChangeListenerKeys_[goog.getUid(feature).toString()] =
|
||||
goog.events.listen(feature, goog.events.EventType.CHANGE,
|
||||
this.handleFeatureChange_, false, this);
|
||||
}, this);
|
||||
}
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the map for the overlay.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.setMap = function(map) {
|
||||
if (!goog.isNull(this.postComposeListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.postComposeListenerKey_);
|
||||
this.postComposeListenerKey_ = null;
|
||||
}
|
||||
this.render_();
|
||||
this.map_ = map;
|
||||
if (!goog.isNull(map)) {
|
||||
this.postComposeListenerKey_ = goog.events.listen(
|
||||
map, ol.render.EventType.POSTCOMPOSE, this.handleMapPostCompose_, false,
|
||||
this);
|
||||
map.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the style for features. This can be a single style object, an array
|
||||
* of styles, or a function that takes a feature and resolution and returns
|
||||
* an array of styles.
|
||||
* @param {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction} style
|
||||
* Overlay style.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.setStyle = function(style) {
|
||||
this.style_ = style;
|
||||
this.styleFunction_ = ol.style.createStyleFunction(style);
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the style for features. This returns whatever was passed to the `style`
|
||||
* option at construction or to the `setStyle` method.
|
||||
* @return {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
|
||||
* Overlay style.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.getStyle = function() {
|
||||
return this.style_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the style function.
|
||||
* @return {ol.style.StyleFunction|undefined} Style function.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.getStyleFunction = function() {
|
||||
return this.styleFunction_;
|
||||
};
|
||||
@@ -198,8 +198,8 @@ ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) {
|
||||
*/
|
||||
ol.format.GeoJSON.writeEmptyGeometryCollectionGeometry_ = function(geometry) {
|
||||
return /** @type {GeoJSONGeometryCollection} */ ({
|
||||
'type': 'GeometryCollection',
|
||||
'geometries': []
|
||||
type: 'GeometryCollection',
|
||||
geometries: []
|
||||
});
|
||||
};
|
||||
|
||||
@@ -219,8 +219,8 @@ ol.format.GeoJSON.writeGeometryCollectionGeometry_ = function(
|
||||
return ol.format.GeoJSON.writeGeometry_(geometry, opt_options);
|
||||
});
|
||||
return /** @type {GeoJSONGeometryCollection} */ ({
|
||||
'type': 'GeometryCollection',
|
||||
'geometries': geometries
|
||||
type: 'GeometryCollection',
|
||||
geometries: geometries
|
||||
});
|
||||
};
|
||||
|
||||
@@ -235,8 +235,8 @@ ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.LineString,
|
||||
'geometry should be an ol.geom.LineString');
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'LineString',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
type: 'LineString',
|
||||
coordinates: geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
@@ -252,8 +252,8 @@ ol.format.GeoJSON.writeMultiLineStringGeometry_ =
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString,
|
||||
'geometry should be an ol.geom.MultiLineString');
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'MultiLineString',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
type: 'MultiLineString',
|
||||
coordinates: geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
@@ -268,8 +268,8 @@ ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiPoint,
|
||||
'geometry should be an ol.geom.MultiPoint');
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'MultiPoint',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
type: 'MultiPoint',
|
||||
coordinates: geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
@@ -288,8 +288,8 @@ ol.format.GeoJSON.writeMultiPolygonGeometry_ = function(geometry, opt_options) {
|
||||
right = opt_options.rightHanded;
|
||||
}
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'MultiPolygon',
|
||||
'coordinates': geometry.getCoordinates(right)
|
||||
type: 'MultiPolygon',
|
||||
coordinates: geometry.getCoordinates(right)
|
||||
});
|
||||
};
|
||||
|
||||
@@ -304,8 +304,8 @@ ol.format.GeoJSON.writePointGeometry_ = function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.Point,
|
||||
'geometry should be an ol.geom.Point');
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'Point',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
type: 'Point',
|
||||
coordinates: geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
@@ -324,8 +324,8 @@ ol.format.GeoJSON.writePolygonGeometry_ = function(geometry, opt_options) {
|
||||
right = opt_options.rightHanded;
|
||||
}
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'Polygon',
|
||||
'coordinates': geometry.getCoordinates(right)
|
||||
type: 'Polygon',
|
||||
coordinates: geometry.getCoordinates(right)
|
||||
});
|
||||
};
|
||||
|
||||
@@ -541,6 +541,8 @@ ol.format.GeoJSON.prototype.writeFeatureObject = function(
|
||||
if (goog.isDefAndNotNull(geometry)) {
|
||||
object['geometry'] =
|
||||
ol.format.GeoJSON.writeGeometry_(geometry, opt_options);
|
||||
} else {
|
||||
object['geometry'] = null;
|
||||
}
|
||||
var properties = feature.getProperties();
|
||||
goog.object.remove(properties, feature.getGeometryName());
|
||||
@@ -582,8 +584,8 @@ ol.format.GeoJSON.prototype.writeFeaturesObject =
|
||||
objects.push(this.writeFeatureObject(features[i], opt_options));
|
||||
}
|
||||
return /** @type {GeoJSONFeatureCollection} */ ({
|
||||
'type': 'FeatureCollection',
|
||||
'features': objects
|
||||
type: 'FeatureCollection',
|
||||
features: objects
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -203,10 +203,11 @@ ol.format.GMLBase.prototype.readFeatureElement = function(node, objectStack) {
|
||||
n = n.nextElementSibling) {
|
||||
var localName = ol.xml.getLocalName(n);
|
||||
// Assume attribute elements have one child node and that the child
|
||||
// is a text node. Otherwise assume it is a geometry node.
|
||||
// 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 === 3 || n.firstChild.nodeType === 4))) {
|
||||
var value = ol.xml.getAllTextContent(n, false);
|
||||
if (goog.string.isEmpty(value)) {
|
||||
value = undefined;
|
||||
|
||||
@@ -39,6 +39,9 @@ ol.GeolocationProperty = {
|
||||
* The [Geolocation API](http://www.w3.org/TR/geolocation-API/)
|
||||
* is used to locate a user's position.
|
||||
*
|
||||
* To get notified of position changes, register a listener for the generic
|
||||
* `change` event on your instance of `ol.Geolocation`.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* var geolocation = new ol.Geolocation({
|
||||
@@ -52,7 +55,6 @@ ol.GeolocationProperty = {
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires change Triggered when the position changes.
|
||||
* @param {olx.GeolocationOptions=} opt_options Options.
|
||||
* @api stable
|
||||
*/
|
||||
|
||||
@@ -50,9 +50,11 @@ ol.geom.GeometryLayout = {
|
||||
* instantiated in apps.
|
||||
* Base class for vector geometries.
|
||||
*
|
||||
* To get notified of changes to the geometry, register a listener for the
|
||||
* generic `change` event on your geometry instance.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires change Triggered when the geometry changes.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry = function() {
|
||||
@@ -229,6 +231,7 @@ ol.geom.Geometry.prototype.translate = goog.abstractMethod;
|
||||
* string identifier or a {@link ol.proj.Projection} object.
|
||||
* @return {ol.geom.Geometry} This geometry. Note that original geometry is
|
||||
* modified in place.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry.prototype.transform = function(source, destination) {
|
||||
this.applyTransform(ol.proj.getTransform(source, destination));
|
||||
|
||||
@@ -2,6 +2,7 @@ goog.provide('ol.geom.MultiPolygon');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryLayout');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
@@ -119,8 +120,10 @@ ol.geom.MultiPolygon.prototype.appendPolygon = function(polygon) {
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.clone = function() {
|
||||
var multiPolygon = new ol.geom.MultiPolygon(null);
|
||||
var newEndss = /** @type {Array.<Array.<number>>} */
|
||||
(goog.object.unsafeClone(this.endss_));
|
||||
multiPolygon.setFlatCoordinates(
|
||||
this.layout, this.flatCoordinates.slice(), this.endss_.slice());
|
||||
this.layout, this.flatCoordinates.slice(), newEndss);
|
||||
return multiPolygon;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
goog.provide('ol.ImageCanvas');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.ImageBase');
|
||||
goog.require('ol.ImageState');
|
||||
|
||||
@@ -13,12 +14,23 @@ goog.require('ol.ImageState');
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {Array.<ol.Attribution>} attributions Attributions.
|
||||
* @param {HTMLCanvasElement} canvas Canvas.
|
||||
* @param {ol.ImageCanvasLoader=} opt_loader Optional loader function to
|
||||
* support asynchronous canvas drawing.
|
||||
*/
|
||||
ol.ImageCanvas = function(extent, resolution, pixelRatio, attributions,
|
||||
canvas) {
|
||||
canvas, opt_loader) {
|
||||
|
||||
goog.base(this, extent, resolution, pixelRatio, ol.ImageState.LOADED,
|
||||
attributions);
|
||||
/**
|
||||
* Optional canvas loader function.
|
||||
* @type {?ol.ImageCanvasLoader}
|
||||
* @private
|
||||
*/
|
||||
this.loader_ = goog.isDef(opt_loader) ? opt_loader : null;
|
||||
|
||||
var state = goog.isDef(opt_loader) ?
|
||||
ol.ImageState.IDLE : ol.ImageState.LOADED;
|
||||
|
||||
goog.base(this, extent, resolution, pixelRatio, state, attributions);
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -26,13 +38,68 @@ ol.ImageCanvas = function(extent, resolution, pixelRatio, attributions,
|
||||
*/
|
||||
this.canvas_ = canvas;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Error}
|
||||
*/
|
||||
this.error_ = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.ImageCanvas, ol.ImageBase);
|
||||
|
||||
|
||||
/**
|
||||
* Get any error associated with asynchronous rendering.
|
||||
* @return {Error} Any error that occurred during rendering.
|
||||
*/
|
||||
ol.ImageCanvas.prototype.getError = function() {
|
||||
return this.error_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle async drawing complete.
|
||||
* @param {Error} err Any error during drawing.
|
||||
* @private
|
||||
*/
|
||||
ol.ImageCanvas.prototype.handleLoad_ = function(err) {
|
||||
if (err) {
|
||||
this.error_ = err;
|
||||
this.state = ol.ImageState.ERROR;
|
||||
} else {
|
||||
this.state = ol.ImageState.LOADED;
|
||||
}
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Trigger drawing on canvas.
|
||||
*/
|
||||
ol.ImageCanvas.prototype.load = function() {
|
||||
if (this.state == ol.ImageState.IDLE) {
|
||||
goog.asserts.assert(!goog.isNull(this.loader_));
|
||||
this.state = ol.ImageState.LOADING;
|
||||
this.changed();
|
||||
this.loader_(goog.bind(this.handleLoad_, this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.ImageCanvas.prototype.getImage = function(opt_context) {
|
||||
return this.canvas_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A function that is called to trigger asynchronous canvas drawing. It is
|
||||
* called with a "done" callback that should be called when drawing is done.
|
||||
* If any error occurs during drawing, the "done" callback should be called with
|
||||
* that error.
|
||||
*
|
||||
* @typedef {function(function(Error))}
|
||||
*/
|
||||
ol.ImageCanvasLoader;
|
||||
|
||||
@@ -10,7 +10,6 @@ goog.require('goog.events.Event');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
goog.require('ol.Object');
|
||||
@@ -27,6 +26,7 @@ goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.interaction.InteractionProperty');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
@@ -80,7 +80,7 @@ goog.inherits(ol.interaction.DrawEvent, goog.events.Event);
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Interaction that allows drawing geometries.
|
||||
* Interaction for drawing feature geometries.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Pointer}
|
||||
@@ -265,14 +265,19 @@ ol.interaction.Draw = function(options) {
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.squaredClickTolerance_ = 4;
|
||||
this.squaredClickTolerance_ = goog.isDef(options.clickTolerance) ?
|
||||
options.clickTolerance * options.clickTolerance : 36;
|
||||
|
||||
/**
|
||||
* Draw overlay where our sketch features are drawn.
|
||||
* @type {ol.FeatureOverlay}
|
||||
* @type {ol.layer.Vector}
|
||||
* @private
|
||||
*/
|
||||
this.overlay_ = new ol.FeatureOverlay({
|
||||
this.overlay_ = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({
|
||||
useSpatialIndex: false,
|
||||
wrapX: goog.isDef(options.wrapX) ? options.wrapX : false
|
||||
}),
|
||||
style: goog.isDef(options.style) ?
|
||||
options.style : ol.interaction.Draw.getDefaultStyleFunction()
|
||||
});
|
||||
@@ -393,10 +398,12 @@ ol.interaction.Draw.handleUpEvent_ = function(event) {
|
||||
this.handlePointerMove_(event);
|
||||
if (goog.isNull(this.finishCoordinate_)) {
|
||||
this.startDrawing_(event);
|
||||
} else if ((this.mode_ === ol.interaction.DrawMode.POINT ||
|
||||
this.mode_ === ol.interaction.DrawMode.CIRCLE) &&
|
||||
!goog.isNull(this.finishCoordinate_) ||
|
||||
this.atFinish_(event)) {
|
||||
if (this.mode_ === ol.interaction.DrawMode.POINT) {
|
||||
this.finishDrawing();
|
||||
}
|
||||
} else if (this.mode_ === ol.interaction.DrawMode.CIRCLE) {
|
||||
this.finishDrawing();
|
||||
} else if (this.atFinish_(event)) {
|
||||
this.finishDrawing();
|
||||
} else {
|
||||
this.addToDrawing_(event);
|
||||
@@ -414,10 +421,7 @@ ol.interaction.Draw.handleUpEvent_ = function(event) {
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Draw.prototype.handlePointerMove_ = function(event) {
|
||||
if (this.mode_ === ol.interaction.DrawMode.POINT &&
|
||||
goog.isNull(this.finishCoordinate_)) {
|
||||
this.startDrawing_(event);
|
||||
} else if (!goog.isNull(this.finishCoordinate_)) {
|
||||
if (!goog.isNull(this.finishCoordinate_)) {
|
||||
this.modifyDrawing_(event);
|
||||
} else {
|
||||
this.createOrUpdateSketchPoint_(event);
|
||||
@@ -674,7 +678,7 @@ ol.interaction.Draw.prototype.abortDrawing_ = function() {
|
||||
this.sketchFeature_ = null;
|
||||
this.sketchPoint_ = null;
|
||||
this.sketchLine_ = null;
|
||||
this.overlay_.getFeatures().clear();
|
||||
this.overlay_.getSource().clear(true);
|
||||
}
|
||||
return sketchFeature;
|
||||
};
|
||||
@@ -701,7 +705,9 @@ ol.interaction.Draw.prototype.updateSketchFeatures_ = function() {
|
||||
if (!goog.isNull(this.sketchPoint_)) {
|
||||
sketchFeatures.push(this.sketchPoint_);
|
||||
}
|
||||
this.overlay_.setFeatures(new ol.Collection(sketchFeatures));
|
||||
var overlaySource = this.overlay_.getSource();
|
||||
overlaySource.clear(true);
|
||||
overlaySource.addFeatures(sketchFeatures);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ goog.provide('ol.interaction.Modify');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.CollectionEventType');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.coordinate');
|
||||
@@ -21,10 +21,66 @@ goog.require('ol.geom.MultiPolygon');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.structs.RBush');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.ModifyEventType = {
|
||||
/**
|
||||
* Triggered upon feature modification start
|
||||
* @event ol.ModifyEvent#modifystart
|
||||
* @api
|
||||
*/
|
||||
MODIFYSTART: 'modifystart',
|
||||
/**
|
||||
* Triggered upon feature modification end
|
||||
* @event ol.ModifyEvent#modifyend
|
||||
* @api
|
||||
*/
|
||||
MODIFYEND: 'modifyend'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted by {@link ol.interaction.Modify} instances are instances of
|
||||
* this type.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
* @implements {oli.ModifyEvent}
|
||||
* @param {ol.ModifyEventType} type Type.
|
||||
* @param {ol.Collection.<ol.Feature>} features The features modified.
|
||||
* @param {ol.MapBrowserPointerEvent} mapBrowserPointerEvent Associated
|
||||
* {@link ol.MapBrowserPointerEvent}.
|
||||
*/
|
||||
ol.ModifyEvent = function(type, features, mapBrowserPointerEvent) {
|
||||
|
||||
goog.base(this, type);
|
||||
|
||||
/**
|
||||
* The features being modified.
|
||||
* @type {ol.Collection.<ol.Feature>}
|
||||
* @api
|
||||
*/
|
||||
this.features = features;
|
||||
|
||||
/**
|
||||
* Associated {@link ol.MapBrowserPointerEvent}.
|
||||
* @type {ol.MapBrowserPointerEvent}
|
||||
* @api
|
||||
*/
|
||||
this.mapBrowserPointerEvent = mapBrowserPointerEvent;
|
||||
};
|
||||
goog.inherits(ol.ModifyEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{depth: (Array.<number>|undefined),
|
||||
* feature: ol.Feature,
|
||||
@@ -38,12 +94,13 @@ ol.interaction.SegmentDataType;
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Interaction for modifying vector data.
|
||||
* Interaction for modifying feature geometries.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.ModifyOptions} options Options.
|
||||
* @api stable
|
||||
* @fires ol.ModifyEvent
|
||||
* @api
|
||||
*/
|
||||
ol.interaction.Modify = function(options) {
|
||||
|
||||
@@ -84,6 +141,14 @@ ol.interaction.Modify = function(options) {
|
||||
*/
|
||||
this.lastPixel_ = [0, 0];
|
||||
|
||||
/**
|
||||
* Tracks if the next `singleclick` event should be ignored to prevent
|
||||
* accidental deletion right after vertex creation.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
|
||||
/**
|
||||
* Segment RTree for each layer
|
||||
* @type {Object.<*, ol.structs.RBush>}
|
||||
@@ -111,13 +176,19 @@ ol.interaction.Modify = function(options) {
|
||||
this.dragSegments_ = null;
|
||||
|
||||
/**
|
||||
* Draw overlay where are sketch features are drawn.
|
||||
* @type {ol.FeatureOverlay}
|
||||
* Draw overlay where sketch features are drawn.
|
||||
* @type {ol.layer.Vector}
|
||||
* @private
|
||||
*/
|
||||
this.overlay_ = new ol.FeatureOverlay({
|
||||
this.overlay_ = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({
|
||||
useSpatialIndex: false,
|
||||
wrapX: goog.isDef(options.wrapX) ? options.wrapX : false
|
||||
}),
|
||||
style: goog.isDef(options.style) ? options.style :
|
||||
ol.interaction.Modify.getDefaultStyleFunction()
|
||||
ol.interaction.Modify.getDefaultStyleFunction(),
|
||||
updateWhileAnimating: true,
|
||||
updateWhileInteracting: true
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -208,7 +279,7 @@ ol.interaction.Modify.prototype.handleFeatureRemove_ = function(evt) {
|
||||
// There remains only vertexFeature…
|
||||
if (!goog.isNull(this.vertexFeature_) &&
|
||||
this.features_.getLength() === 0) {
|
||||
this.overlay_.removeFeature(this.vertexFeature_);
|
||||
this.overlay_.getSource().removeFeature(this.vertexFeature_);
|
||||
this.vertexFeature_ = null;
|
||||
}
|
||||
};
|
||||
@@ -383,7 +454,7 @@ ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ =
|
||||
if (goog.isNull(vertexFeature)) {
|
||||
vertexFeature = new ol.Feature(new ol.geom.Point(coordinates));
|
||||
this.vertexFeature_ = vertexFeature;
|
||||
this.overlay_.addFeature(vertexFeature);
|
||||
this.overlay_.getSource().addFeature(vertexFeature);
|
||||
} else {
|
||||
var geometry = /** @type {ol.geom.Point} */ (vertexFeature.getGeometry());
|
||||
geometry.setCoordinates(coordinates);
|
||||
@@ -459,6 +530,8 @@ ol.interaction.Modify.handleDownEvent_ = function(evt) {
|
||||
for (i = insertVertices.length - 1; i >= 0; --i) {
|
||||
this.insertVertex_.apply(this, insertVertices[i]);
|
||||
}
|
||||
this.dispatchEvent(new ol.ModifyEvent(ol.ModifyEventType.MODIFYSTART,
|
||||
this.features_, evt));
|
||||
}
|
||||
return !goog.isNull(this.vertexFeature_);
|
||||
};
|
||||
@@ -470,6 +543,8 @@ ol.interaction.Modify.handleDownEvent_ = function(evt) {
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Modify.handleDragEvent_ = function(evt) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
|
||||
var vertex = evt.coordinate;
|
||||
for (var i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
|
||||
var dragSegment = this.dragSegments_[i];
|
||||
@@ -530,6 +605,8 @@ ol.interaction.Modify.handleUpEvent_ = function(evt) {
|
||||
this.rBush_.update(ol.extent.boundingExtent(segmentData.segment),
|
||||
segmentData);
|
||||
}
|
||||
this.dispatchEvent(new ol.ModifyEvent(ol.ModifyEventType.MODIFYEND,
|
||||
this.features_, evt));
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -551,11 +628,21 @@ ol.interaction.Modify.handleEvent = function(mapBrowserEvent) {
|
||||
}
|
||||
if (!goog.isNull(this.vertexFeature_) &&
|
||||
this.deleteCondition_(mapBrowserEvent)) {
|
||||
var geometry = this.vertexFeature_.getGeometry();
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.Point,
|
||||
'geometry should be an ol.geom.Point');
|
||||
handled = this.removeVertex_();
|
||||
if (mapBrowserEvent.type != ol.MapBrowserEvent.EventType.SINGLECLICK ||
|
||||
!this.ignoreNextSingleClick_) {
|
||||
var geometry = this.vertexFeature_.getGeometry();
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.Point,
|
||||
'geometry should be an ol.geom.Point');
|
||||
handled = this.removeVertex_();
|
||||
} else {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.SINGLECLICK) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
}
|
||||
|
||||
return ol.interaction.Pointer.handleEvent.call(this, mapBrowserEvent) &&
|
||||
!handled;
|
||||
};
|
||||
@@ -630,7 +717,7 @@ ol.interaction.Modify.prototype.handlePointerAtPixel_ = function(pixel, map) {
|
||||
}
|
||||
}
|
||||
if (!goog.isNull(this.vertexFeature_)) {
|
||||
this.overlay_.removeFeature(this.vertexFeature_);
|
||||
this.overlay_.getSource().removeFeature(this.vertexFeature_);
|
||||
this.vertexFeature_ = null;
|
||||
}
|
||||
};
|
||||
@@ -709,6 +796,7 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) {
|
||||
rTree.insert(ol.extent.boundingExtent(newSegmentData2.segment),
|
||||
newSegmentData2);
|
||||
this.dragSegments_.push([newSegmentData2, 0]);
|
||||
this.ignoreNextSingleClick_ = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -800,8 +888,10 @@ ol.interaction.Modify.prototype.removeVertex_ = function() {
|
||||
newSegmentData);
|
||||
this.updateSegmentIndices_(geometry, index, segmentData.depth, -1);
|
||||
|
||||
this.overlay_.removeFeature(this.vertexFeature_);
|
||||
this.vertexFeature_ = null;
|
||||
if (!goog.isNull(this.vertexFeature_)) {
|
||||
this.overlay_.getSource().removeFeature(this.vertexFeature_);
|
||||
this.vertexFeature_ = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@ goog.require('goog.events.Event');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.CollectionEventType');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.FeatureOverlay');
|
||||
goog.require('ol.events.condition');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
|
||||
@@ -82,10 +83,13 @@ goog.inherits(ol.SelectEvent, goog.events.Event);
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Handles selection of vector data. A {@link ol.FeatureOverlay} is maintained
|
||||
* internally to store the selected feature(s). Which features are selected is
|
||||
* determined by the `condition` option, and optionally the `toggle` or
|
||||
* `add`/`remove` options.
|
||||
* Interaction for selecting vector features. By default, selected features are
|
||||
* styled differently, so this interaction can be used for visual highlighting,
|
||||
* as well as selecting features for other actions, such as modification or
|
||||
* output. There are three ways of controlling which features are selected:
|
||||
* using the browser event as defined by the `condition` and optionally the
|
||||
* `toggle`, `add`/`remove`, and `multi` options; a `layers` filter; and a
|
||||
* further feature filter using the `filter` option.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Interaction}
|
||||
@@ -169,14 +173,20 @@ ol.interaction.Select = function(opt_options) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.FeatureOverlay}
|
||||
* @type {ol.layer.Vector}
|
||||
*/
|
||||
this.featureOverlay_ = new ol.FeatureOverlay({
|
||||
this.featureOverlay_ = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({
|
||||
useSpatialIndex: false,
|
||||
wrapX: options.wrapX
|
||||
}),
|
||||
style: goog.isDef(options.style) ? options.style :
|
||||
ol.interaction.Select.getDefaultStyleFunction()
|
||||
ol.interaction.Select.getDefaultStyleFunction(),
|
||||
updateWhileAnimating: true,
|
||||
updateWhileInteracting: true
|
||||
});
|
||||
|
||||
var features = this.featureOverlay_.getFeatures();
|
||||
var features = this.featureOverlay_.getSource().getFeaturesCollection();
|
||||
goog.events.listen(features, ol.CollectionEventType.ADD,
|
||||
this.addFeature_, false, this);
|
||||
goog.events.listen(features, ol.CollectionEventType.REMOVE,
|
||||
@@ -192,7 +202,7 @@ goog.inherits(ol.interaction.Select, ol.interaction.Interaction);
|
||||
* @api stable
|
||||
*/
|
||||
ol.interaction.Select.prototype.getFeatures = function() {
|
||||
return this.featureOverlay_.getFeatures();
|
||||
return this.featureOverlay_.getSource().getFeaturesCollection();
|
||||
};
|
||||
|
||||
|
||||
@@ -213,9 +223,9 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
|
||||
var toggle = this.toggleCondition_(mapBrowserEvent);
|
||||
var set = !add && !remove && !toggle;
|
||||
var map = mapBrowserEvent.map;
|
||||
var features = this.featureOverlay_.getFeatures();
|
||||
var /** @type {Array.<ol.Feature>} */ deselected = [];
|
||||
var /** @type {Array.<ol.Feature>} */ selected = [];
|
||||
var features = this.featureOverlay_.getSource().getFeaturesCollection();
|
||||
var /** @type {!Array.<ol.Feature>} */ deselected = [];
|
||||
var /** @type {!Array.<ol.Feature>} */ selected = [];
|
||||
var change = false;
|
||||
if (set) {
|
||||
// Replace the currently selected feature(s) with the feature(s) at the
|
||||
@@ -290,7 +300,8 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
|
||||
*/
|
||||
ol.interaction.Select.prototype.setMap = function(map) {
|
||||
var currentMap = this.getMap();
|
||||
var selectedFeatures = this.featureOverlay_.getFeatures();
|
||||
var selectedFeatures =
|
||||
this.featureOverlay_.getSource().getFeaturesCollection();
|
||||
if (!goog.isNull(currentMap)) {
|
||||
selectedFeatures.forEach(currentMap.unskipFeature, currentMap);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ goog.require('goog.object');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.layer.Base');
|
||||
goog.require('ol.layer.LayerProperty');
|
||||
goog.require('ol.render.EventType');
|
||||
goog.require('ol.source.State');
|
||||
|
||||
|
||||
@@ -18,10 +19,11 @@ goog.require('ol.source.State');
|
||||
* Layers group together those properties that pertain to how the data is to be
|
||||
* displayed, irrespective of the source of that data.
|
||||
*
|
||||
* A generic `change` event is fired when the state of the source changes.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.layer.Base}
|
||||
* @fires ol.render.Event
|
||||
* @fires change Triggered when the state of the source changes.
|
||||
* @param {olx.layer.LayerOptions} options Layer options.
|
||||
* @api stable
|
||||
*/
|
||||
@@ -32,12 +34,28 @@ ol.layer.Layer = function(options) {
|
||||
|
||||
goog.base(this, /** @type {olx.layer.LayerOptions} */ (baseOptions));
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.Key}
|
||||
*/
|
||||
this.mapPrecomposeKey_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.Key}
|
||||
*/
|
||||
this.mapRenderKey_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.Key}
|
||||
*/
|
||||
this.sourceChangeKey_ = null;
|
||||
|
||||
if (goog.isDef(options.map)) {
|
||||
this.setMap(options.map);
|
||||
}
|
||||
|
||||
goog.events.listen(this,
|
||||
ol.Object.getChangeEventType(ol.layer.LayerProperty.SOURCE),
|
||||
this.handleSourcePropertyChange_, false, this);
|
||||
@@ -129,6 +147,36 @@ ol.layer.Layer.prototype.handleSourcePropertyChange_ = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the layer to be rendered on a map. The map will not manage this layer in
|
||||
* its layers collection, layer filters in {@link ol.Map#forEachLayerAtPixel}
|
||||
* will not filter the layer, and it will be rendered on top. This is useful for
|
||||
* temporary layers. To remove an unmanaged layer from the map, use
|
||||
* `#setMap(null)`.
|
||||
*
|
||||
* To add the layer to a map and have it managed by the map, use
|
||||
* {@link ol.Map#addLayer} instead.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api
|
||||
*/
|
||||
ol.layer.Layer.prototype.setMap = function(map) {
|
||||
goog.events.unlistenByKey(this.mapPrecomposeKey_);
|
||||
this.changed();
|
||||
goog.events.unlistenByKey(this.mapRenderKey_);
|
||||
if (!goog.isNull(map)) {
|
||||
this.mapPrecomposeKey_ = goog.events.listen(
|
||||
map, ol.render.EventType.PRECOMPOSE, function(evt) {
|
||||
var layerState = this.getLayerState();
|
||||
layerState.managed = false;
|
||||
evt.frameState.layerStatesArray.push(layerState);
|
||||
evt.frameState.layerStates[goog.getUid(this)] = layerState;
|
||||
}, false, this);
|
||||
this.mapRenderKey_ = goog.events.listen(
|
||||
this, goog.events.EventType.CHANGE, map.render, false, map);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the layer source.
|
||||
* @param {ol.source.Source} source The layer source.
|
||||
|
||||
@@ -35,6 +35,7 @@ ol.layer.LayerProperty = {
|
||||
* saturation: number,
|
||||
* sourceState: ol.source.State,
|
||||
* visible: boolean,
|
||||
* managed: boolean,
|
||||
* extent: (ol.Extent|undefined),
|
||||
* maxResolution: number,
|
||||
* minResolution: number}}
|
||||
@@ -142,6 +143,7 @@ ol.layer.Base.prototype.getLayerState = function() {
|
||||
saturation: Math.max(saturation, 0),
|
||||
sourceState: sourceState,
|
||||
visible: visible,
|
||||
managed: true,
|
||||
extent: extent,
|
||||
maxResolution: maxResolution,
|
||||
minResolution: Math.max(minResolution, 0)
|
||||
|
||||
@@ -29,9 +29,10 @@ ol.layer.GroupProperty = {
|
||||
* @classdesc
|
||||
* A {@link ol.Collection} of layers that are handled together.
|
||||
*
|
||||
* A generic `change` event is triggered when the group/Collection changes.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.layer.Base}
|
||||
* @fires change Triggered when the group/Collection changes.
|
||||
* @param {olx.layer.GroupOptions=} opt_options Layer options.
|
||||
* @api stable
|
||||
*/
|
||||
@@ -163,7 +164,7 @@ ol.layer.Group.prototype.handleLayersRemove_ = function(collectionEvent) {
|
||||
* Returns the {@link ol.Collection collection} of {@link ol.layer.Layer layers}
|
||||
* in this group.
|
||||
* @return {!ol.Collection.<ol.layer.Base>} Collection of
|
||||
* {@link ol.layer.Layer layers} that are part of this group.
|
||||
* {@link ol.layer.Base layers} that are part of this group.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
@@ -177,7 +178,7 @@ ol.layer.Group.prototype.getLayers = function() {
|
||||
* Set the {@link ol.Collection collection} of {@link ol.layer.Layer layers}
|
||||
* in this group.
|
||||
* @param {!ol.Collection.<ol.layer.Base>} layers Collection of
|
||||
* {@link ol.layer.Layer layers} that are part of this group.
|
||||
* {@link ol.layer.Base layers} that are part of this group.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,7 @@ goog.require('goog.debug.Console');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.dom.ViewportSizeMonitor');
|
||||
goog.require('goog.dom.classlist');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.events.Event');
|
||||
@@ -266,7 +267,7 @@ ol.Map = function(options) {
|
||||
// prevent page zoom on IE >= 10 browsers
|
||||
this.viewport_.style.msTouchAction = 'none';
|
||||
if (ol.has.TOUCH) {
|
||||
this.viewport_.className = 'ol-touch';
|
||||
goog.dom.classlist.add(this.viewport_, 'ol-touch');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -571,23 +572,20 @@ ol.Map.prototype.disposeInternal = function() {
|
||||
/**
|
||||
* Detect features that intersect a pixel on the viewport, and execute a
|
||||
* callback with each intersecting feature. Layers included in the detection can
|
||||
* be configured through `opt_layerFilter`. Feature overlays will always be
|
||||
* included in the detection.
|
||||
* be configured through `opt_layerFilter`.
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @param {function(this: S, ol.Feature, ol.layer.Layer): T} callback Feature
|
||||
* callback. The callback will be called with two arguments. The first
|
||||
* argument is one {@link ol.Feature feature} at the pixel, the second is
|
||||
* the {@link ol.layer.Layer layer} of the feature. If the detected feature
|
||||
* is not on a layer, but on a {@link ol.FeatureOverlay}, then the second
|
||||
* argument to this function will be `null`. To stop detection, callback
|
||||
* functions can return a truthy value.
|
||||
* the {@link ol.layer.Layer layer} of the feature. To stop detection,
|
||||
* callback functions can return a truthy value.
|
||||
* @param {S=} opt_this Value to use as `this` when executing `callback`.
|
||||
* @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer
|
||||
* filter function. The filter function will receive one argument, the
|
||||
* {@link ol.layer.Layer layer-candidate} and it should return a boolean
|
||||
* value. Only layers which are visible and for which this function returns
|
||||
* `true` will be tested for features. By default, all visible layers will
|
||||
* be tested. Feature overlays will always be tested.
|
||||
* be tested.
|
||||
* @param {U=} opt_this2 Value to use as `this` when executing `layerFilter`.
|
||||
* @return {T|undefined} Callback result, i.e. the return value of last
|
||||
* callback execution, or the first truthy callback return value.
|
||||
@@ -613,22 +611,19 @@ ol.Map.prototype.forEachFeatureAtPixel =
|
||||
/**
|
||||
* Detect layers that have a color value at a pixel on the viewport, and
|
||||
* execute a callback with each matching layer. Layers included in the
|
||||
* detection can be configured through `opt_layerFilter`. Feature overlays will
|
||||
* always be included in the detection.
|
||||
* detection can be configured through `opt_layerFilter`.
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @param {function(this: S, ol.layer.Layer): T} callback Layer
|
||||
* callback. Will receive one argument, the {@link ol.layer.Layer layer}
|
||||
* that contains the color pixel. If the detected color value is not from a
|
||||
* layer, but from a {@link ol.FeatureOverlay}, then the argument to this
|
||||
* function will be `null`. To stop detection, callback functions can return
|
||||
* a truthy value.
|
||||
* that contains the color pixel. To stop detection, callback functions can
|
||||
* return a truthy value.
|
||||
* @param {S=} opt_this Value to use as `this` when executing `callback`.
|
||||
* @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer
|
||||
* filter function. The filter function will receive one argument, the
|
||||
* {@link ol.layer.Layer layer-candidate} and it should return a boolean
|
||||
* value. Only layers which are visible and for which this function returns
|
||||
* `true` will be tested for features. By default, all visible layers will
|
||||
* be tested. Feature overlays will always be tested.
|
||||
* be tested.
|
||||
* @param {U=} opt_this2 Value to use as `this` when executing `layerFilter`.
|
||||
* @return {T|undefined} Callback result, i.e. the return value of last
|
||||
* callback execution, or the first truthy callback return value.
|
||||
@@ -652,15 +647,14 @@ ol.Map.prototype.forEachLayerAtPixel =
|
||||
|
||||
/**
|
||||
* Detect if features intersect a pixel on the viewport. Layers included in the
|
||||
* detection can be configured through `opt_layerFilter`. Feature overlays will
|
||||
* always be included in the detection.
|
||||
* detection can be configured through `opt_layerFilter`.
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer
|
||||
* filter function. The filter function will receive one argument, the
|
||||
* {@link ol.layer.Layer layer-candidate} and it should return a boolean
|
||||
* value. Only layers which are visible and for which this function returns
|
||||
* `true` will be tested for features. By default, all visible layers will
|
||||
* be tested. Feature overlays will always be tested.
|
||||
* be tested.
|
||||
* @param {U=} opt_this Value to use as `this` when executing `layerFilter`.
|
||||
* @return {boolean} Is there a feature at the given pixel?
|
||||
* @template U
|
||||
|
||||
@@ -16,6 +16,7 @@ goog.require('goog.events.EventType');
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
* @fires change
|
||||
* @suppress {checkStructDictInheritance}
|
||||
* @struct
|
||||
* @api stable
|
||||
@@ -46,7 +47,6 @@ ol.Observable.unByKey = function(key) {
|
||||
|
||||
/**
|
||||
* Increases the revision counter and dispatches a 'change' event.
|
||||
* @fires change
|
||||
* @api
|
||||
*/
|
||||
ol.Observable.prototype.changed = function() {
|
||||
@@ -55,6 +55,13 @@ ol.Observable.prototype.changed = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggered when the revision counter is increased.
|
||||
* @event change
|
||||
* @api
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Revision.
|
||||
* @api
|
||||
|
||||
32
src/ol/raster/operation.js
Normal file
32
src/ol/raster/operation.js
Normal file
@@ -0,0 +1,32 @@
|
||||
goog.provide('ol.raster.Operation');
|
||||
goog.provide('ol.raster.OperationType');
|
||||
|
||||
|
||||
/**
|
||||
* Raster operation type. Supported values are `'pixel'` and `'image'`.
|
||||
* @enum {string}
|
||||
* @api
|
||||
*/
|
||||
ol.raster.OperationType = {
|
||||
PIXEL: 'pixel',
|
||||
IMAGE: 'image'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A function that takes an array of input data, performs some operation, and
|
||||
* returns an array of ouput data. For `'pixel'` type operations, functions
|
||||
* will be called with an array of {@link ol.raster.Pixel} data and should
|
||||
* return an array of the same. For `'image'` type operations, functions will
|
||||
* be called with an array of {@link ImageData
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/ImageData} and should return
|
||||
* an array of the same. The operations are called with a second "data"
|
||||
* argument, which can be used for storage. The data object is accessible
|
||||
* from raster events, where it can be initialized in "beforeoperations" and
|
||||
* accessed again in "afteroperations".
|
||||
*
|
||||
* @typedef {function((Array.<ol.raster.Pixel>|Array.<ImageData>), Object):
|
||||
* (Array.<ol.raster.Pixel>|Array.<ImageData>)}
|
||||
* @api
|
||||
*/
|
||||
ol.raster.Operation;
|
||||
9
src/ol/raster/pixel.js
Normal file
9
src/ol/raster/pixel.js
Normal file
@@ -0,0 +1,9 @@
|
||||
goog.provide('ol.raster.Pixel');
|
||||
|
||||
|
||||
/**
|
||||
* An array of numbers representing pixel values.
|
||||
* @typedef {Array.<number>} ol.raster.Pixel
|
||||
* @api
|
||||
*/
|
||||
ol.raster.Pixel;
|
||||
@@ -471,8 +471,8 @@ ol.render.canvas.Immediate.prototype.drawCircleGeometry =
|
||||
* Render a feature into the canvas. In order to respect the zIndex of the
|
||||
* style this method draws asynchronously and thus *after* calls to
|
||||
* drawXxxxGeometry have been finished, effectively drawing the feature
|
||||
* *on top* of everything else. You probably should be using
|
||||
* {@link ol.FeatureOverlay} instead of calling this method directly.
|
||||
* *on top* of everything else. You probably should be using an
|
||||
* {@link ol.layer.Vector} instead of calling this method directly.
|
||||
*
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {ol.style.Style} style Style.
|
||||
|
||||
@@ -353,7 +353,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
||||
'3rd instruction should be a number');
|
||||
dd = /** @type {number} */ (instruction[2]);
|
||||
goog.asserts.assert(goog.isString(instruction[3]),
|
||||
'4th instruction should be a number');
|
||||
'4th instruction should be a string');
|
||||
text = /** @type {string} */ (instruction[3]);
|
||||
goog.asserts.assert(goog.isNumber(instruction[4]),
|
||||
'5th instruction should be a number');
|
||||
|
||||
@@ -35,14 +35,13 @@ ol.render.EventType = {
|
||||
* @param {ol.render.EventType} type Type.
|
||||
* @param {Object=} opt_target Target.
|
||||
* @param {ol.render.VectorContext=} opt_vectorContext Vector context.
|
||||
* @param {ol.render.IReplayGroup=} opt_replayGroup Replay group.
|
||||
* @param {olx.FrameState=} opt_frameState Frame state.
|
||||
* @param {?CanvasRenderingContext2D=} opt_context Context.
|
||||
* @param {?ol.webgl.Context=} opt_glContext WebGL Context.
|
||||
*/
|
||||
ol.render.Event = function(
|
||||
type, opt_target, opt_vectorContext, opt_replayGroup, opt_frameState,
|
||||
opt_context, opt_glContext) {
|
||||
type, opt_target, opt_vectorContext, opt_frameState, opt_context,
|
||||
opt_glContext) {
|
||||
|
||||
goog.base(this, type, opt_target);
|
||||
|
||||
@@ -53,11 +52,6 @@ ol.render.Event = function(
|
||||
*/
|
||||
this.vectorContext = opt_vectorContext;
|
||||
|
||||
/**
|
||||
* @type {ol.render.IReplayGroup|undefined}
|
||||
*/
|
||||
this.replayGroup = opt_replayGroup;
|
||||
|
||||
/**
|
||||
* @type {olx.FrameState|undefined}
|
||||
* @api
|
||||
|
||||
@@ -131,8 +131,8 @@ ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ =
|
||||
var render = new ol.render.canvas.Immediate(
|
||||
context, frameState.pixelRatio, frameState.extent, transform,
|
||||
frameState.viewState.rotation);
|
||||
var composeEvent = new ol.render.Event(type, layer, render, null,
|
||||
frameState, context, null);
|
||||
var composeEvent = new ol.render.Event(type, layer, render, frameState,
|
||||
context, null);
|
||||
layer.dispatchEvent(composeEvent);
|
||||
render.flush();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ goog.require('ol');
|
||||
goog.require('ol.RendererType');
|
||||
goog.require('ol.css');
|
||||
goog.require('ol.dom');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.layer.Image');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.layer.Tile');
|
||||
@@ -18,13 +17,11 @@ goog.require('ol.layer.Vector');
|
||||
goog.require('ol.render.Event');
|
||||
goog.require('ol.render.EventType');
|
||||
goog.require('ol.render.canvas.Immediate');
|
||||
goog.require('ol.render.canvas.ReplayGroup');
|
||||
goog.require('ol.renderer.Map');
|
||||
goog.require('ol.renderer.canvas.ImageLayer');
|
||||
goog.require('ol.renderer.canvas.Layer');
|
||||
goog.require('ol.renderer.canvas.TileLayer');
|
||||
goog.require('ol.renderer.canvas.VectorLayer');
|
||||
goog.require('ol.renderer.vector');
|
||||
goog.require('ol.source.State');
|
||||
goog.require('ol.vec.Mat4');
|
||||
|
||||
@@ -103,55 +100,27 @@ ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ =
|
||||
var extent = frameState.extent;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var viewState = frameState.viewState;
|
||||
var projection = viewState.projection;
|
||||
var resolution = viewState.resolution;
|
||||
var rotation = viewState.rotation;
|
||||
|
||||
var offsetX = 0;
|
||||
if (projection.canWrapX()) {
|
||||
var projectionExtent = projection.getExtent();
|
||||
var worldWidth = ol.extent.getWidth(projectionExtent);
|
||||
var x = frameState.focus[0];
|
||||
if (x < projectionExtent[0] || x > projectionExtent[2]) {
|
||||
var worldsAway = Math.ceil((projectionExtent[0] - x) / worldWidth);
|
||||
offsetX = worldWidth * worldsAway;
|
||||
extent = [
|
||||
extent[0] + offsetX, extent[1],
|
||||
extent[2] + offsetX, extent[3]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
var transform = this.getTransform(frameState, offsetX);
|
||||
|
||||
var tolerance = ol.renderer.vector.getTolerance(resolution, pixelRatio);
|
||||
var replayGroup = new ol.render.canvas.ReplayGroup(
|
||||
tolerance, extent, resolution);
|
||||
var transform = this.getTransform(frameState);
|
||||
|
||||
var vectorContext = new ol.render.canvas.Immediate(context, pixelRatio,
|
||||
extent, transform, rotation);
|
||||
var composeEvent = new ol.render.Event(type, map, vectorContext,
|
||||
replayGroup, frameState, context, null);
|
||||
frameState, context, null);
|
||||
map.dispatchEvent(composeEvent);
|
||||
|
||||
replayGroup.finish();
|
||||
if (!replayGroup.isEmpty()) {
|
||||
replayGroup.replay(context, pixelRatio, transform, rotation, {});
|
||||
|
||||
}
|
||||
vectorContext.flush();
|
||||
this.replayGroup = replayGroup;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {number} offsetX Offset on the x-axis in view coordinates.
|
||||
* @protected
|
||||
* @return {!goog.vec.Mat4.Number} Transform.
|
||||
*/
|
||||
ol.renderer.canvas.Map.prototype.getTransform = function(frameState, offsetX) {
|
||||
ol.renderer.canvas.Map.prototype.getTransform = function(frameState) {
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var viewState = frameState.viewState;
|
||||
var resolution = viewState.resolution;
|
||||
@@ -159,8 +128,7 @@ ol.renderer.canvas.Map.prototype.getTransform = function(frameState, offsetX) {
|
||||
this.canvas_.width / 2, this.canvas_.height / 2,
|
||||
pixelRatio / resolution, -pixelRatio / resolution,
|
||||
-viewState.rotation,
|
||||
-viewState.center[0] - offsetX,
|
||||
-viewState.center[1]);
|
||||
-viewState.center[0], -viewState.center[1]);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -77,9 +77,9 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
|
||||
function(frameState, layerState, context) {
|
||||
|
||||
var extent = frameState.extent;
|
||||
var focus = frameState.focus;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var skippedFeatureUids = frameState.skippedFeatureUids;
|
||||
var skippedFeatureUids = layerState.managed ?
|
||||
frameState.skippedFeatureUids : {};
|
||||
var viewState = frameState.viewState;
|
||||
var projection = viewState.projection;
|
||||
var rotation = viewState.rotation;
|
||||
@@ -108,20 +108,11 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
|
||||
// see http://jsperf.com/context-save-restore-versus-variable
|
||||
var alpha = replayContext.globalAlpha;
|
||||
replayContext.globalAlpha = layerState.opacity;
|
||||
var noSkip = {};
|
||||
var focusX = focus[0];
|
||||
|
||||
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
|
||||
skippedFeatureUids);
|
||||
if (vectorSource.getWrapX() && projection.canWrapX() &&
|
||||
!ol.extent.containsExtent(projectionExtent, extent)) {
|
||||
var projLeft = projectionExtent[0];
|
||||
var projRight = projectionExtent[2];
|
||||
// A feature from skippedFeatureUids will only be skipped in the world
|
||||
// that has the frameState's focus, because this is where a feature
|
||||
// overlay for highlighting or selection would render the skipped
|
||||
// feature.
|
||||
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
|
||||
projLeft <= focusX && focusX <= projRight ?
|
||||
skippedFeatureUids : noSkip);
|
||||
var startX = extent[0];
|
||||
var worldWidth = ol.extent.getWidth(projectionExtent);
|
||||
var world = 0;
|
||||
@@ -131,8 +122,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
|
||||
offsetX = worldWidth * world;
|
||||
transform = this.getTransform(frameState, offsetX);
|
||||
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
|
||||
projLeft + offsetX <= focusX && focusX <= projRight + offsetX ?
|
||||
skippedFeatureUids : noSkip);
|
||||
skippedFeatureUids);
|
||||
startX += worldWidth;
|
||||
}
|
||||
world = 0;
|
||||
@@ -142,13 +132,11 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
|
||||
offsetX = worldWidth * world;
|
||||
transform = this.getTransform(frameState, offsetX);
|
||||
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
|
||||
projLeft + offsetX <= focusX && focusX <= projRight + offsetX ?
|
||||
skippedFeatureUids : noSkip);
|
||||
skippedFeatureUids);
|
||||
startX -= worldWidth;
|
||||
}
|
||||
} else {
|
||||
replayGroup.replay(
|
||||
replayContext, pixelRatio, transform, rotation, skippedFeatureUids);
|
||||
// restore original transform for render and compose events
|
||||
transform = this.getTransform(frameState, 0);
|
||||
}
|
||||
|
||||
if (replayContext != context) {
|
||||
@@ -174,10 +162,11 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate =
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var rotation = frameState.viewState.rotation;
|
||||
var layer = this.getLayer();
|
||||
var layerState = frameState.layerStates[goog.getUid(layer)];
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate,
|
||||
resolution, rotation, frameState.skippedFeatureUids,
|
||||
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
|
||||
rotation, layerState.managed ? frameState.skippedFeatureUids : {},
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
@@ -249,9 +238,15 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
|
||||
|
||||
if (vectorSource.getWrapX() && viewState.projection.canWrapX() &&
|
||||
!ol.extent.containsExtent(projectionExtent, frameState.extent)) {
|
||||
// do not clip when the view crosses the -180° or 180° meridians
|
||||
extent[0] = projectionExtent[0];
|
||||
extent[2] = projectionExtent[2];
|
||||
// For the replay group, we need an extent that intersects the real world
|
||||
// (-180° to +180°). To support geometries in a coordinate range from -540°
|
||||
// to +540°, we add at least 1 world width on each side of the projection
|
||||
// extent. If the viewport is wider than the world, we need to add half of
|
||||
// the viewport width to make sure we cover the whole viewport.
|
||||
var worldWidth = ol.extent.getWidth(projectionExtent);
|
||||
var buffer = Math.max(ol.extent.getWidth(extent) / 2, worldWidth);
|
||||
extent[0] = projectionExtent[0] - buffer;
|
||||
extent[2] = projectionExtent[2] + buffer;
|
||||
}
|
||||
|
||||
if (!this.dirty_ &&
|
||||
|
||||
@@ -20,13 +20,11 @@ goog.require('ol.layer.Vector');
|
||||
goog.require('ol.render.Event');
|
||||
goog.require('ol.render.EventType');
|
||||
goog.require('ol.render.canvas.Immediate');
|
||||
goog.require('ol.render.canvas.ReplayGroup');
|
||||
goog.require('ol.renderer.Map');
|
||||
goog.require('ol.renderer.dom.ImageLayer');
|
||||
goog.require('ol.renderer.dom.Layer');
|
||||
goog.require('ol.renderer.dom.TileLayer');
|
||||
goog.require('ol.renderer.dom.VectorLayer');
|
||||
goog.require('ol.renderer.vector');
|
||||
goog.require('ol.source.State');
|
||||
goog.require('ol.vec.Mat4');
|
||||
|
||||
@@ -139,7 +137,6 @@ ol.renderer.dom.Map.prototype.dispatchComposeEvent_ =
|
||||
var extent = frameState.extent;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var viewState = frameState.viewState;
|
||||
var resolution = viewState.resolution;
|
||||
var rotation = viewState.rotation;
|
||||
var context = this.context_;
|
||||
var canvas = context.canvas;
|
||||
@@ -153,18 +150,10 @@ ol.renderer.dom.Map.prototype.dispatchComposeEvent_ =
|
||||
-viewState.center[0], -viewState.center[1]);
|
||||
var vectorContext = new ol.render.canvas.Immediate(context, pixelRatio,
|
||||
extent, this.transform_, rotation);
|
||||
var replayGroup = new ol.render.canvas.ReplayGroup(
|
||||
ol.renderer.vector.getTolerance(resolution, pixelRatio), extent,
|
||||
resolution);
|
||||
var composeEvent = new ol.render.Event(type, map, vectorContext,
|
||||
replayGroup, frameState, context, null);
|
||||
frameState, context, null);
|
||||
map.dispatchEvent(composeEvent);
|
||||
replayGroup.finish();
|
||||
if (!replayGroup.isEmpty()) {
|
||||
replayGroup.replay(context, pixelRatio, this.transform_, rotation, {});
|
||||
}
|
||||
vectorContext.flush();
|
||||
this.replayGroup = replayGroup;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ ol.renderer.dom.VectorLayer.prototype.composeFrame =
|
||||
|
||||
context.globalAlpha = layerState.opacity;
|
||||
replayGroup.replay(context, pixelRatio, transform, viewRotation,
|
||||
frameState.skippedFeatureUids);
|
||||
layerState.managed ? frameState.skippedFeatureUids : {});
|
||||
|
||||
this.dispatchEvent_(ol.render.EventType.RENDER, frameState, transform);
|
||||
}
|
||||
@@ -165,8 +165,8 @@ ol.renderer.dom.VectorLayer.prototype.dispatchEvent_ =
|
||||
var render = new ol.render.canvas.Immediate(
|
||||
context, frameState.pixelRatio, frameState.extent, transform,
|
||||
frameState.viewState.rotation);
|
||||
var event = new ol.render.Event(type, layer, render, null,
|
||||
frameState, context, null);
|
||||
var event = new ol.render.Event(type, layer, render, frameState,
|
||||
context, null);
|
||||
layer.dispatchEvent(event);
|
||||
render.flush();
|
||||
}
|
||||
@@ -184,10 +184,11 @@ ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtCoordinate =
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var rotation = frameState.viewState.rotation;
|
||||
var layer = this.getLayer();
|
||||
var layerState = frameState.layerStates[goog.getUid(layer)];
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate,
|
||||
resolution, rotation, frameState.skippedFeatureUids,
|
||||
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
|
||||
rotation, layerState.managed ? frameState.skippedFeatureUids : {},
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
|
||||
@@ -113,7 +113,6 @@ ol.renderer.Layer.prototype.createLoadedTileFinder = function(source, tiles) {
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @return {ol.layer.Layer} Layer.
|
||||
*/
|
||||
ol.renderer.Layer.prototype.getLayer = function() {
|
||||
|
||||
@@ -48,12 +48,6 @@ ol.renderer.Map = function(container, map) {
|
||||
*/
|
||||
this.map_ = map;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.render.IReplayGroup}
|
||||
*/
|
||||
this.replayGroup = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.renderer.Layer>}
|
||||
@@ -137,7 +131,6 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
|
||||
var result;
|
||||
var viewState = frameState.viewState;
|
||||
var viewResolution = viewState.resolution;
|
||||
var viewRotation = viewState.rotation;
|
||||
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
@@ -168,21 +161,15 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
|
||||
}
|
||||
}
|
||||
|
||||
if (!goog.isNull(this.replayGroup)) {
|
||||
result = this.replayGroup.forEachFeatureAtCoordinate(translatedCoordinate,
|
||||
viewResolution, viewRotation, {}, forEachFeatureAtCoordinate);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
var layerStates = frameState.layerStatesArray;
|
||||
var numLayers = layerStates.length;
|
||||
var i;
|
||||
for (i = numLayers - 1; i >= 0; --i) {
|
||||
var layerState = layerStates[i];
|
||||
var layer = layerState.layer;
|
||||
if (ol.layer.Layer.visibleAtResolution(layerState, viewResolution) &&
|
||||
layerFilter.call(thisArg2, layer)) {
|
||||
if (!layerState.managed ||
|
||||
(ol.layer.Layer.visibleAtResolution(layerState, viewResolution) &&
|
||||
layerFilter.call(thisArg2, layer))) {
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
result = layerRenderer.forEachFeatureAtCoordinate(
|
||||
layer.getSource().getWrapX() ? translatedCoordinate : coordinate,
|
||||
@@ -216,20 +203,7 @@ ol.renderer.Map.prototype.forEachLayerAtPixel =
|
||||
var result;
|
||||
var viewState = frameState.viewState;
|
||||
var viewResolution = viewState.resolution;
|
||||
var viewRotation = viewState.rotation;
|
||||
|
||||
if (!goog.isNull(this.replayGroup)) {
|
||||
var coordinate = this.getMap().getCoordinateFromPixel(pixel);
|
||||
var hasFeature = this.replayGroup.forEachFeatureAtCoordinate(coordinate,
|
||||
viewResolution, viewRotation, {}, goog.functions.TRUE);
|
||||
|
||||
if (hasFeature) {
|
||||
result = callback.call(thisArg, null);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
var layerStates = frameState.layerStatesArray;
|
||||
var numLayers = layerStates.length;
|
||||
var i;
|
||||
|
||||
@@ -247,7 +247,7 @@ ol.renderer.webgl.Layer.prototype.dispatchComposeEvent_ =
|
||||
var render = new ol.render.webgl.Immediate(
|
||||
context, center, resolution, rotation, size, extent, pixelRatio);
|
||||
var composeEvent = new ol.render.Event(
|
||||
type, layer, render, null, frameState, null, context);
|
||||
type, layer, render, frameState, null, context);
|
||||
layer.dispatchEvent(composeEvent);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,9 +24,7 @@ goog.require('ol.layer.Vector');
|
||||
goog.require('ol.render.Event');
|
||||
goog.require('ol.render.EventType');
|
||||
goog.require('ol.render.webgl.Immediate');
|
||||
goog.require('ol.render.webgl.ReplayGroup');
|
||||
goog.require('ol.renderer.Map');
|
||||
goog.require('ol.renderer.vector');
|
||||
goog.require('ol.renderer.webgl.ImageLayer');
|
||||
goog.require('ol.renderer.webgl.Layer');
|
||||
goog.require('ol.renderer.webgl.TileLayer');
|
||||
@@ -287,27 +285,14 @@ ol.renderer.webgl.Map.prototype.dispatchComposeEvent_ =
|
||||
var resolution = viewState.resolution;
|
||||
var center = viewState.center;
|
||||
var rotation = viewState.rotation;
|
||||
var tolerance = ol.renderer.vector.getTolerance(resolution, pixelRatio);
|
||||
|
||||
var vectorContext = new ol.render.webgl.Immediate(context,
|
||||
center, resolution, rotation, size, extent, pixelRatio);
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(tolerance, extent);
|
||||
var composeEvent = new ol.render.Event(type, map, vectorContext,
|
||||
replayGroup, frameState, null, context);
|
||||
frameState, null, context);
|
||||
map.dispatchEvent(composeEvent);
|
||||
|
||||
replayGroup.finish(context);
|
||||
if (!replayGroup.isEmpty()) {
|
||||
// use default color values
|
||||
var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_;
|
||||
replayGroup.replay(context, center, resolution, rotation, size,
|
||||
pixelRatio, d.opacity, d.brightness, d.contrast,
|
||||
d.hue, d.saturation, {});
|
||||
}
|
||||
replayGroup.getDeleteResourcesFunction(context)();
|
||||
|
||||
vectorContext.flush();
|
||||
this.replayGroup = replayGroup;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -482,6 +467,8 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
|
||||
this.textureCache_.set((-frameState.index).toString(), null);
|
||||
++this.textureCacheFrameMarkerCount_;
|
||||
|
||||
this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, frameState);
|
||||
|
||||
/** @type {Array.<ol.layer.LayerState>} */
|
||||
var layerStatesToDraw = [];
|
||||
var layerStatesArray = frameState.layerStatesArray;
|
||||
@@ -514,8 +501,6 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
|
||||
gl.enable(goog.webgl.BLEND);
|
||||
gl.viewport(0, 0, this.canvas_.width, this.canvas_.height);
|
||||
|
||||
this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, frameState);
|
||||
|
||||
for (i = 0, ii = layerStatesToDraw.length; i < ii; ++i) {
|
||||
layerState = layerStatesToDraw[i];
|
||||
layerRenderer = this.getLayerRenderer(layerState.layer);
|
||||
@@ -561,37 +546,8 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate =
|
||||
return false;
|
||||
}
|
||||
|
||||
var context = this.getContext();
|
||||
var viewState = frameState.viewState;
|
||||
|
||||
// do the hit-detection for the overlays first
|
||||
if (!goog.isNull(this.replayGroup)) {
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
|
||||
// use default color values
|
||||
var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_;
|
||||
|
||||
result = this.replayGroup.forEachFeatureAtCoordinate(coordinate,
|
||||
context, viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio,
|
||||
d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {},
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
goog.asserts.assert(goog.isDef(feature), 'received a feature');
|
||||
var key = goog.getUid(feature).toString();
|
||||
if (!(key in features)) {
|
||||
features[key] = true;
|
||||
return callback.call(thisArg, feature, null);
|
||||
}
|
||||
});
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
var layerStates = frameState.layerStatesArray;
|
||||
var numLayers = layerStates.length;
|
||||
var i;
|
||||
@@ -623,22 +579,8 @@ ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate =
|
||||
return false;
|
||||
}
|
||||
|
||||
var context = this.getContext();
|
||||
var viewState = frameState.viewState;
|
||||
|
||||
// do the hit-detection for the overlays first
|
||||
if (!goog.isNull(this.replayGroup)) {
|
||||
// use default color values
|
||||
var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_;
|
||||
|
||||
hasFeature = this.replayGroup.hasFeatureAtCoordinate(coordinate,
|
||||
context, viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio,
|
||||
d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {});
|
||||
if (hasFeature) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
var layerStates = frameState.layerStatesArray;
|
||||
var numLayers = layerStates.length;
|
||||
var i;
|
||||
@@ -669,27 +611,9 @@ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel =
|
||||
return false;
|
||||
}
|
||||
|
||||
var context = this.getContext();
|
||||
var viewState = frameState.viewState;
|
||||
var result;
|
||||
|
||||
// do the hit-detection for the overlays first
|
||||
if (!goog.isNull(this.replayGroup)) {
|
||||
// use default color values
|
||||
var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_;
|
||||
var coordinate = this.getMap().getCoordinateFromPixel(pixel);
|
||||
|
||||
var hasFeature = this.replayGroup.hasFeatureAtCoordinate(coordinate,
|
||||
context, viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio,
|
||||
d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {});
|
||||
if (hasFeature) {
|
||||
result = callback.call(thisArg, null);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
var layerStates = frameState.layerStatesArray;
|
||||
var numLayers = layerStates.length;
|
||||
var i;
|
||||
|
||||
@@ -83,7 +83,8 @@ ol.renderer.webgl.VectorLayer.prototype.composeFrame =
|
||||
viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio, layerState.opacity,
|
||||
layerState.brightness, layerState.contrast, layerState.hue,
|
||||
layerState.saturation, frameState.skippedFeatureUids);
|
||||
layerState.saturation,
|
||||
layerState.managed ? frameState.skippedFeatureUids : {});
|
||||
}
|
||||
|
||||
};
|
||||
@@ -121,7 +122,8 @@ ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate =
|
||||
context, viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio,
|
||||
layerState.opacity, layerState.brightness, layerState.contrast,
|
||||
layerState.hue, layerState.saturation, frameState.skippedFeatureUids,
|
||||
layerState.hue, layerState.saturation,
|
||||
layerState.managed ? frameState.skippedFeatureUids : {},
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
|
||||
@@ -114,34 +114,35 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse =
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
var culture = this.culture_;
|
||||
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
|
||||
tileGrid.createTileCoordTransform(),
|
||||
ol.TileUrlFunction.createFromTileUrlFunctions(
|
||||
goog.array.map(
|
||||
resource.imageUrlSubdomains,
|
||||
function(subdomain) {
|
||||
var imageUrl = resource.imageUrl
|
||||
.replace('{subdomain}', subdomain)
|
||||
.replace('{culture}', culture);
|
||||
return (
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {ol.proj.Projection} projection Projection.
|
||||
* @return {string|undefined} Tile URL.
|
||||
*/
|
||||
function(tileCoord, pixelRatio, projection) {
|
||||
goog.asserts.assert(ol.proj.equivalent(
|
||||
projection, sourceProjection),
|
||||
'projections are equivalent');
|
||||
if (goog.isNull(tileCoord)) {
|
||||
return undefined;
|
||||
} else {
|
||||
return imageUrl.replace(
|
||||
'{quadkey}', ol.tilecoord.quadKey(tileCoord));
|
||||
}
|
||||
});
|
||||
})));
|
||||
this.tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions(
|
||||
goog.array.map(
|
||||
resource.imageUrlSubdomains,
|
||||
function(subdomain) {
|
||||
var quadKeyTileCoord = [0, 0, 0];
|
||||
var imageUrl = resource.imageUrl
|
||||
.replace('{subdomain}', subdomain)
|
||||
.replace('{culture}', culture);
|
||||
return (
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {ol.proj.Projection} projection Projection.
|
||||
* @return {string|undefined} Tile URL.
|
||||
*/
|
||||
function(tileCoord, pixelRatio, projection) {
|
||||
goog.asserts.assert(ol.proj.equivalent(
|
||||
projection, sourceProjection),
|
||||
'projections are equivalent');
|
||||
if (goog.isNull(tileCoord)) {
|
||||
return undefined;
|
||||
} else {
|
||||
ol.tilecoord.createOrUpdate(tileCoord[0], tileCoord[1],
|
||||
-tileCoord[2] - 1, quadKeyTileCoord);
|
||||
return imageUrl.replace('{quadkey}', ol.tilecoord.quadKey(
|
||||
quadKeyTileCoord));
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
if (resource.imageryProviders) {
|
||||
var transform = ol.proj.getTransformFromProjections(
|
||||
|
||||
535
src/ol/source/rastersource.js
Normal file
535
src/ol/source/rastersource.js
Normal file
@@ -0,0 +1,535 @@
|
||||
goog.provide('ol.source.Raster');
|
||||
goog.provide('ol.source.RasterEvent');
|
||||
goog.provide('ol.source.RasterEventType');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.ImageCanvas');
|
||||
goog.require('ol.TileQueue');
|
||||
goog.require('ol.dom');
|
||||
goog.require('ol.ext.pixelworks');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.layer.Image');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.raster.OperationType');
|
||||
goog.require('ol.renderer.canvas.ImageLayer');
|
||||
goog.require('ol.renderer.canvas.TileLayer');
|
||||
goog.require('ol.source.Image');
|
||||
goog.require('ol.source.State');
|
||||
goog.require('ol.source.Tile');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A source that transforms data from any number of input sources using an array
|
||||
* of {@link ol.raster.Operation} functions to transform input pixel values into
|
||||
* output pixel values.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.source.Image}
|
||||
* @param {olx.source.RasterOptions} options Options.
|
||||
* @api
|
||||
*/
|
||||
ol.source.Raster = function(options) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {*}
|
||||
*/
|
||||
this.worker_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.raster.OperationType}
|
||||
*/
|
||||
this.operationType_ = goog.isDef(options.operationType) ?
|
||||
options.operationType : ol.raster.OperationType.PIXEL;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.threads_ = goog.isDef(options.threads) ? options.threads : 1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<ol.renderer.canvas.Layer>}
|
||||
*/
|
||||
this.renderers_ = ol.source.Raster.createRenderers_(options.sources);
|
||||
|
||||
for (var r = 0, rr = this.renderers_.length; r < rr; ++r) {
|
||||
goog.events.listen(this.renderers_[r], goog.events.EventType.CHANGE,
|
||||
this.changed, false, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {CanvasRenderingContext2D}
|
||||
*/
|
||||
this.canvasContext_ = ol.dom.createCanvasContext2D();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TileQueue}
|
||||
*/
|
||||
this.tileQueue_ = new ol.TileQueue(
|
||||
goog.functions.constant(1),
|
||||
goog.bind(this.changed, this));
|
||||
|
||||
var layerStatesArray = ol.source.Raster.getLayerStatesArray_(this.renderers_);
|
||||
var layerStates = {};
|
||||
for (var i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
layerStates[goog.getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* The most recently rendered state.
|
||||
* @type {?ol.source.Raster.RenderedState}
|
||||
* @private
|
||||
*/
|
||||
this.renderedState_ = null;
|
||||
|
||||
/**
|
||||
* The most recently rendered image canvas.
|
||||
* @type {ol.ImageCanvas}
|
||||
* @private
|
||||
*/
|
||||
this.renderedImageCanvas_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {olx.FrameState}
|
||||
*/
|
||||
this.frameState_ = {
|
||||
animate: false,
|
||||
attributions: {},
|
||||
coordinateToPixelMatrix: goog.vec.Mat4.createNumber(),
|
||||
extent: null,
|
||||
focus: null,
|
||||
index: 0,
|
||||
layerStates: layerStates,
|
||||
layerStatesArray: layerStatesArray,
|
||||
logos: {},
|
||||
pixelRatio: 1,
|
||||
pixelToCoordinateMatrix: goog.vec.Mat4.createNumber(),
|
||||
postRenderFunctions: [],
|
||||
size: [0, 0],
|
||||
skippedFeatureUids: {},
|
||||
tileQueue: this.tileQueue_,
|
||||
time: Date.now(),
|
||||
usedTiles: {},
|
||||
viewState: /** @type {olx.ViewState} */ ({
|
||||
rotation: 0
|
||||
}),
|
||||
viewHints: [],
|
||||
wantedTiles: {}
|
||||
};
|
||||
|
||||
goog.base(this, {});
|
||||
|
||||
if (goog.isDef(options.operation)) {
|
||||
this.setOperation(options.operation, options.lib);
|
||||
}
|
||||
|
||||
};
|
||||
goog.inherits(ol.source.Raster, ol.source.Image);
|
||||
|
||||
|
||||
/**
|
||||
* Set the operation.
|
||||
* @param {ol.raster.Operation} operation New operation.
|
||||
* @param {Object=} opt_lib Functions that will be available to operations run
|
||||
* in a worker.
|
||||
* @api
|
||||
*/
|
||||
ol.source.Raster.prototype.setOperation = function(operation, opt_lib) {
|
||||
this.worker_ = new ol.ext.pixelworks.Processor({
|
||||
operation: operation,
|
||||
imageOps: this.operationType_ === ol.raster.OperationType.IMAGE,
|
||||
queue: 1,
|
||||
lib: opt_lib,
|
||||
threads: this.threads_
|
||||
});
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the stored frame state.
|
||||
* @param {ol.Extent} extent The view extent (in map units).
|
||||
* @param {number} resolution The view resolution.
|
||||
* @param {ol.proj.Projection} projection The view projection.
|
||||
* @return {olx.FrameState} The updated frame state.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.prototype.updateFrameState_ =
|
||||
function(extent, resolution, projection) {
|
||||
|
||||
var frameState = /** @type {olx.FrameState} */ (
|
||||
goog.object.clone(this.frameState_));
|
||||
|
||||
frameState.viewState = /** @type {olx.ViewState} */ (
|
||||
goog.object.clone(frameState.viewState));
|
||||
|
||||
var center = ol.extent.getCenter(extent);
|
||||
var width = Math.round(ol.extent.getWidth(extent) / resolution);
|
||||
var height = Math.round(ol.extent.getHeight(extent) / resolution);
|
||||
|
||||
frameState.extent = extent;
|
||||
frameState.focus = ol.extent.getCenter(extent);
|
||||
frameState.size[0] = width;
|
||||
frameState.size[1] = height;
|
||||
|
||||
var viewState = frameState.viewState;
|
||||
viewState.center = center;
|
||||
viewState.projection = projection;
|
||||
viewState.resolution = resolution;
|
||||
return frameState;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the most recently rendered image canvas is dirty.
|
||||
* @param {ol.Extent} extent The requested extent.
|
||||
* @param {number} resolution The requested resolution.
|
||||
* @return {boolean} The image is dirty.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.prototype.isDirty_ = function(extent, resolution) {
|
||||
var state = this.renderedState_;
|
||||
return !state ||
|
||||
this.getRevision() !== state.revision ||
|
||||
resolution !== state.resolution ||
|
||||
!ol.extent.equals(extent, state.extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.Raster.prototype.getImage =
|
||||
function(extent, resolution, pixelRatio, projection) {
|
||||
|
||||
if (!this.allSourcesReady_()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.isDirty_(extent, resolution)) {
|
||||
return this.renderedImageCanvas_;
|
||||
}
|
||||
|
||||
var context = this.canvasContext_;
|
||||
var canvas = context.canvas;
|
||||
|
||||
var width = Math.round(ol.extent.getWidth(extent) / resolution);
|
||||
var height = Math.round(ol.extent.getHeight(extent) / resolution);
|
||||
|
||||
if (width !== canvas.width ||
|
||||
height !== canvas.height) {
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
}
|
||||
|
||||
var frameState = this.updateFrameState_(extent, resolution, projection);
|
||||
|
||||
var imageCanvas = new ol.ImageCanvas(
|
||||
extent, resolution, 1, this.getAttributions(), canvas,
|
||||
this.composeFrame_.bind(this, frameState));
|
||||
|
||||
this.renderedImageCanvas_ = imageCanvas;
|
||||
|
||||
this.renderedState_ = {
|
||||
extent: extent,
|
||||
resolution: resolution,
|
||||
revision: this.getRevision()
|
||||
};
|
||||
|
||||
return imageCanvas;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine if all sources are ready.
|
||||
* @return {boolean} All sources are ready.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.prototype.allSourcesReady_ = function() {
|
||||
var ready = true;
|
||||
var source;
|
||||
for (var i = 0, ii = this.renderers_.length; i < ii; ++i) {
|
||||
source = this.renderers_[i].getLayer().getSource();
|
||||
if (source.getState() !== ol.source.State.READY) {
|
||||
ready = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ready;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compose the frame. This renders data from all sources, runs pixel-wise
|
||||
* operations, and renders the result to the stored canvas context.
|
||||
* @param {olx.FrameState} frameState The frame state.
|
||||
* @param {function(Error)} callback Called when composition is complete.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.prototype.composeFrame_ = function(frameState, callback) {
|
||||
var len = this.renderers_.length;
|
||||
var imageDatas = new Array(len);
|
||||
for (var i = 0; i < len; ++i) {
|
||||
var imageData = ol.source.Raster.getImageData_(
|
||||
this.renderers_[i], frameState, frameState.layerStatesArray[i]);
|
||||
if (imageData) {
|
||||
imageDatas[i] = imageData;
|
||||
} else {
|
||||
// image not yet ready
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var data = {};
|
||||
this.dispatchEvent(new ol.source.RasterEvent(
|
||||
ol.source.RasterEventType.BEFOREOPERATIONS, frameState, data));
|
||||
|
||||
this.worker_.process(imageDatas, data,
|
||||
this.onWorkerComplete_.bind(this, frameState, callback));
|
||||
|
||||
frameState.tileQueue.loadMoreTiles(16, 16);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called when pixel processing is complete.
|
||||
* @param {olx.FrameState} frameState The frame state.
|
||||
* @param {function(Error)} callback Called when rendering is complete.
|
||||
* @param {Error} err Any error during processing.
|
||||
* @param {ImageData} output The output image data.
|
||||
* @param {Object} data The user data.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.prototype.onWorkerComplete_ =
|
||||
function(frameState, callback, err, output, data) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if (goog.isNull(output)) {
|
||||
// job aborted
|
||||
return;
|
||||
}
|
||||
|
||||
this.dispatchEvent(new ol.source.RasterEvent(
|
||||
ol.source.RasterEventType.AFTEROPERATIONS, frameState, data));
|
||||
|
||||
var resolution = frameState.viewState.resolution / frameState.pixelRatio;
|
||||
if (!this.isDirty_(frameState.extent, resolution)) {
|
||||
this.canvasContext_.putImageData(output, 0, 0);
|
||||
}
|
||||
|
||||
callback(null);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get image data from a renderer.
|
||||
* @param {ol.renderer.canvas.Layer} renderer Layer renderer.
|
||||
* @param {olx.FrameState} frameState The frame state.
|
||||
* @param {ol.layer.LayerState} layerState The layer state.
|
||||
* @return {ImageData} The image data.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.getImageData_ = function(renderer, frameState, layerState) {
|
||||
renderer.prepareFrame(frameState, layerState);
|
||||
// We should be able to call renderer.composeFrame(), but this is inefficient
|
||||
// for tiled sources (we've already rendered to an intermediate canvas in the
|
||||
// prepareFrame call and we don't need to render again to the output canvas).
|
||||
// TODO: make all canvas renderers render to a single canvas
|
||||
var image = renderer.getImage();
|
||||
if (!image) {
|
||||
return null;
|
||||
}
|
||||
var imageTransform = renderer.getImageTransform();
|
||||
var dx = Math.round(goog.vec.Mat4.getElement(imageTransform, 0, 3));
|
||||
var dy = Math.round(goog.vec.Mat4.getElement(imageTransform, 1, 3));
|
||||
var width = frameState.size[0];
|
||||
var height = frameState.size[1];
|
||||
if (image instanceof Image) {
|
||||
if (!ol.source.Raster.context_) {
|
||||
ol.source.Raster.context_ = ol.dom.createCanvasContext2D(width, height);
|
||||
} else {
|
||||
var canvas = ol.source.Raster.context_.canvas;
|
||||
if (canvas.width !== width || canvas.height !== height) {
|
||||
ol.source.Raster.context_ = ol.dom.createCanvasContext2D(width, height);
|
||||
} else {
|
||||
ol.source.Raster.context_.clearRect(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
var dw = Math.round(
|
||||
image.width * goog.vec.Mat4.getElement(imageTransform, 0, 0));
|
||||
var dh = Math.round(
|
||||
image.height * goog.vec.Mat4.getElement(imageTransform, 1, 1));
|
||||
ol.source.Raster.context_.drawImage(image, dx, dy, dw, dh);
|
||||
return ol.source.Raster.context_.getImageData(0, 0, width, height);
|
||||
} else {
|
||||
return image.getContext('2d').getImageData(-dx, -dy, width, height);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A reusable canvas context.
|
||||
* @type {CanvasRenderingContext2D}
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.context_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of layer states from a list of renderers.
|
||||
* @param {Array.<ol.renderer.canvas.Layer>} renderers Layer renderers.
|
||||
* @return {Array.<ol.layer.LayerState>} The layer states.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.getLayerStatesArray_ = function(renderers) {
|
||||
return renderers.map(function(renderer) {
|
||||
return renderer.getLayer().getLayerState();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create renderers for all sources.
|
||||
* @param {Array.<ol.source.Source>} sources The sources.
|
||||
* @return {Array.<ol.renderer.canvas.Layer>} Array of layer renderers.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.createRenderers_ = function(sources) {
|
||||
var len = sources.length;
|
||||
var renderers = new Array(len);
|
||||
for (var i = 0; i < len; ++i) {
|
||||
renderers[i] = ol.source.Raster.createRenderer_(sources[i]);
|
||||
}
|
||||
return renderers;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a renderer for the provided source.
|
||||
* @param {ol.source.Source} source The source.
|
||||
* @return {ol.renderer.canvas.Layer} The renderer.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.createRenderer_ = function(source) {
|
||||
var renderer = null;
|
||||
if (source instanceof ol.source.Tile) {
|
||||
renderer = ol.source.Raster.createTileRenderer_(
|
||||
/** @type {ol.source.Tile} */ (source));
|
||||
} else if (source instanceof ol.source.Image) {
|
||||
renderer = ol.source.Raster.createImageRenderer_(
|
||||
/** @type {ol.source.Image} */ (source));
|
||||
} else {
|
||||
goog.asserts.fail('Unsupported source type: ' + source);
|
||||
}
|
||||
return renderer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create an image renderer for the provided source.
|
||||
* @param {ol.source.Image} source The source.
|
||||
* @return {ol.renderer.canvas.Layer} The renderer.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.createImageRenderer_ = function(source) {
|
||||
var layer = new ol.layer.Image({source: source});
|
||||
return new ol.renderer.canvas.ImageLayer(layer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a tile renderer for the provided source.
|
||||
* @param {ol.source.Tile} source The source.
|
||||
* @return {ol.renderer.canvas.Layer} The renderer.
|
||||
* @private
|
||||
*/
|
||||
ol.source.Raster.createTileRenderer_ = function(source) {
|
||||
var layer = new ol.layer.Tile({source: source});
|
||||
return new ol.renderer.canvas.TileLayer(layer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{revision: number,
|
||||
* resolution: number,
|
||||
* extent: ol.Extent}}
|
||||
*/
|
||||
ol.source.Raster.RenderedState;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted by {@link ol.source.Raster} instances are instances of this
|
||||
* type.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
* @implements {oli.source.RasterEvent}
|
||||
* @param {string} type Type.
|
||||
* @param {olx.FrameState} frameState The frame state.
|
||||
* @param {Object} data An object made available to operations.
|
||||
*/
|
||||
ol.source.RasterEvent = function(type, frameState, data) {
|
||||
goog.base(this, type);
|
||||
|
||||
/**
|
||||
* The raster extent.
|
||||
* @type {ol.Extent}
|
||||
* @api
|
||||
*/
|
||||
this.extent = frameState.extent;
|
||||
|
||||
/**
|
||||
* The pixel resolution (map units per pixel).
|
||||
* @type {number}
|
||||
* @api
|
||||
*/
|
||||
this.resolution = frameState.viewState.resolution / frameState.pixelRatio;
|
||||
|
||||
/**
|
||||
* An object made available to all operations. This can be used by operations
|
||||
* as a storage object (e.g. for calculating statistics).
|
||||
* @type {Object}
|
||||
* @api
|
||||
*/
|
||||
this.data = data;
|
||||
|
||||
};
|
||||
goog.inherits(ol.source.RasterEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.source.RasterEventType = {
|
||||
/**
|
||||
* Triggered before operations are run.
|
||||
* @event ol.source.RasterEvent#beforeoperations
|
||||
* @api
|
||||
*/
|
||||
BEFOREOPERATIONS: 'beforeoperations',
|
||||
|
||||
/**
|
||||
* Triggered after operations are run.
|
||||
* @event ol.source.RasterEvent#afteroperations
|
||||
* @api
|
||||
*/
|
||||
AFTEROPERATIONS: 'afteroperations'
|
||||
};
|
||||
@@ -37,9 +37,10 @@ ol.source.SourceOptions;
|
||||
* instantiated in apps.
|
||||
* Base class for {@link ol.layer.Layer} sources.
|
||||
*
|
||||
* A generic `change` event is triggered when the state of the source changes.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires change Triggered when the state of the source changes.
|
||||
* @param {ol.source.SourceOptions} options Source options.
|
||||
* @api stable
|
||||
*/
|
||||
|
||||
@@ -39,6 +39,7 @@ ol.source.TileArcGISRest = function(opt_options) {
|
||||
|
||||
goog.base(this, {
|
||||
attributions: options.attributions,
|
||||
crossOrigin: options.crossOrigin,
|
||||
logo: options.logo,
|
||||
projection: options.projection,
|
||||
tileGrid: options.tileGrid,
|
||||
@@ -111,7 +112,7 @@ ol.source.TileArcGISRest.prototype.getRequestUrl_ =
|
||||
params['BBOX'] = tileExtent.join(',');
|
||||
params['BBOXSR'] = srid;
|
||||
params['IMAGESR'] = srid;
|
||||
params['DPI'] = 90 * pixelRatio;
|
||||
params['DPI'] = Math.round(90 * pixelRatio);
|
||||
|
||||
var url;
|
||||
if (urls.length == 1) {
|
||||
|
||||
@@ -7,7 +7,6 @@ goog.require('ol.dom');
|
||||
goog.require('ol.size');
|
||||
goog.require('ol.source.Tile');
|
||||
goog.require('ol.tilecoord');
|
||||
goog.require('ol.tilegrid.TileGrid');
|
||||
|
||||
|
||||
|
||||
@@ -15,10 +14,11 @@ goog.require('ol.tilegrid.TileGrid');
|
||||
* @constructor
|
||||
* @extends {ol.Tile}
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
|
||||
* @param {ol.Size} tileSize Tile size.
|
||||
* @param {string} text Text.
|
||||
* @private
|
||||
*/
|
||||
ol.DebugTile_ = function(tileCoord, tileGrid) {
|
||||
ol.DebugTile_ = function(tileCoord, tileSize, text) {
|
||||
|
||||
goog.base(this, tileCoord, ol.TileState.LOADED);
|
||||
|
||||
@@ -26,8 +26,13 @@ ol.DebugTile_ = function(tileCoord, tileGrid) {
|
||||
* @private
|
||||
* @type {ol.Size}
|
||||
*/
|
||||
this.tileSize_ = ol.size.toSize(
|
||||
tileGrid.getTileSize(tileCoord[0]));
|
||||
this.tileSize_ = tileSize;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.text_ = text;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -58,8 +63,7 @@ ol.DebugTile_.prototype.getImage = function(opt_context) {
|
||||
context.textAlign = 'center';
|
||||
context.textBaseline = 'middle';
|
||||
context.font = '24px sans-serif';
|
||||
context.fillText(ol.tilecoord.toString(this.tileCoord),
|
||||
tileSize[0] / 2, tileSize[1] / 2);
|
||||
context.fillText(this.text_, tileSize[0] / 2, tileSize[1] / 2);
|
||||
|
||||
this.canvasByContext_[key] = context.canvas;
|
||||
return context.canvas;
|
||||
@@ -87,7 +91,8 @@ ol.source.TileDebug = function(options) {
|
||||
goog.base(this, {
|
||||
opaque: false,
|
||||
projection: options.projection,
|
||||
tileGrid: options.tileGrid
|
||||
tileGrid: options.tileGrid,
|
||||
wrapX: goog.isDef(options.wrapX) ? options.wrapX : true
|
||||
});
|
||||
|
||||
};
|
||||
@@ -102,7 +107,12 @@ ol.source.TileDebug.prototype.getTile = function(z, x, y) {
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
return /** @type {!ol.DebugTile_} */ (this.tileCache.get(tileCoordKey));
|
||||
} else {
|
||||
var tile = new ol.DebugTile_([z, x, y], this.tileGrid);
|
||||
var tileSize = ol.size.toSize(this.tileGrid.getTileSize(z));
|
||||
var tileCoord = [z, x, y];
|
||||
var textTileCoord = this.getTileCoordForTileUrlFunction(tileCoord);
|
||||
var text = goog.isNull(textTileCoord) ? '' : ol.tilecoord.toString(
|
||||
this.getTileCoordForTileUrlFunction(textTileCoord));
|
||||
var tile = new ol.DebugTile_(tileCoord, tileSize, text);
|
||||
this.tileCache.set(tileCoordKey, tile);
|
||||
return tile;
|
||||
}
|
||||
|
||||
@@ -75,9 +75,7 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
|
||||
});
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
|
||||
tileGrid.createTileCoordTransform(),
|
||||
ol.TileUrlFunction.createFromTemplates(tileJSON.tiles));
|
||||
this.tileUrlFunction = ol.TileUrlFunction.createFromTemplates(tileJSON.tiles);
|
||||
|
||||
if (goog.isDef(tileJSON.attribution) &&
|
||||
goog.isNull(this.getAttributions())) {
|
||||
|
||||
@@ -217,8 +217,9 @@ ol.source.Tile.prototype.getTilePixelSize =
|
||||
|
||||
|
||||
/**
|
||||
* Handles x-axis wrapping and returns a tile coordinate when it is within
|
||||
* the resolution and extent range.
|
||||
* Returns a tile coordinate wrapped around the x-axis. When the tile coordinate
|
||||
* is outside the resolution and extent range of the tile grid, `null` will be
|
||||
* returned.
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {ol.proj.Projection=} opt_projection Projection.
|
||||
* @return {ol.TileCoord} Tile coordinate to be passed to the tileUrlFunction or
|
||||
@@ -230,10 +231,10 @@ ol.source.Tile.prototype.getTileCoordForTileUrlFunction =
|
||||
opt_projection : this.getProjection();
|
||||
var tileGrid = this.getTileGridForProjection(projection);
|
||||
goog.asserts.assert(!goog.isNull(tileGrid), 'tile grid needed');
|
||||
if (this.getWrapX()) {
|
||||
if (this.getWrapX() && projection.isGlobal()) {
|
||||
tileCoord = ol.tilecoord.wrapX(tileCoord, tileGrid, projection);
|
||||
}
|
||||
return ol.tilecoord.restrictByExtentAndZ(tileCoord, tileGrid);
|
||||
return ol.tilecoord.withinExtentAndZ(tileCoord, tileGrid) ? tileCoord : null;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -136,9 +136,7 @@ ol.source.TileUTFGrid.prototype.handleTileJSONResponse = function(tileJSON) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.tileUrlFunction_ = ol.TileUrlFunction.withTileCoordTransform(
|
||||
tileGrid.createTileCoordTransform(),
|
||||
ol.TileUrlFunction.createFromTemplates(grids));
|
||||
this.tileUrlFunction_ = ol.TileUrlFunction.createFromTemplates(grids);
|
||||
|
||||
if (goog.isDef(tileJSON.attribution)) {
|
||||
var attributionExtent = goog.isDef(extent) ?
|
||||
@@ -175,7 +173,9 @@ ol.source.TileUTFGrid.prototype.getTile =
|
||||
} else {
|
||||
goog.asserts.assert(projection, 'argument projection is truthy');
|
||||
var tileCoord = [z, x, y];
|
||||
var tileUrl = this.tileUrlFunction_(tileCoord, pixelRatio, projection);
|
||||
var urlTileCoord =
|
||||
this.getTileCoordForTileUrlFunction(tileCoord, projection);
|
||||
var tileUrl = this.tileUrlFunction_(urlTileCoord, pixelRatio, projection);
|
||||
var tile = new ol.source.TileUTFGridTile_(
|
||||
tileCoord,
|
||||
goog.isDef(tileUrl) ? ol.TileState.IDLE : ol.TileState.EMPTY,
|
||||
|
||||
@@ -3,11 +3,11 @@ goog.provide('ol.source.TileVector');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
goog.require('ol.featureloader');
|
||||
goog.require('ol.source.State');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.tilecoord');
|
||||
goog.require('ol.tilegrid.TileGrid');
|
||||
|
||||
|
||||
@@ -28,17 +28,15 @@ ol.source.TileVector = function(options) {
|
||||
attributions: options.attributions,
|
||||
logo: options.logo,
|
||||
projection: undefined,
|
||||
state: ol.source.State.READY
|
||||
state: ol.source.State.READY,
|
||||
wrapX: options.wrapX
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.format.Feature}
|
||||
* @type {ol.format.Feature|undefined}
|
||||
*/
|
||||
this.format_ = options.format;
|
||||
|
||||
goog.asserts.assert(goog.isDefAndNotNull(this.format_),
|
||||
'ol.source.TileVector requires a format');
|
||||
this.format_ = goog.isDef(options.format) ? options.format : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -54,9 +52,14 @@ ol.source.TileVector = function(options) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TileCoordTransformType}
|
||||
* @type {?ol.TileVectorLoadFunctionType}
|
||||
*/
|
||||
this.tileCoordTransform_ = this.tileGrid_.createTileCoordTransform();
|
||||
this.tileLoadFunction_ = goog.isDef(options.tileLoadFunction) ?
|
||||
options.tileLoadFunction : null;
|
||||
|
||||
goog.asserts.assert(!goog.isNull(this.format_) ||
|
||||
!goog.isNull(this.tileLoadFunction_),
|
||||
'Either format or tileLoadFunction are required');
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -237,6 +240,28 @@ ol.source.TileVector.prototype.getFeaturesAtCoordinateAndResolution =
|
||||
ol.source.TileVector.prototype.getFeaturesInExtent = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Handles x-axis wrapping and returns a tile coordinate transformed from the
|
||||
* internal tile scheme to the tile grid's tile scheme. When the tile coordinate
|
||||
* is outside the resolution and extent range of the tile grid, `null` will be
|
||||
* returned.
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {ol.proj.Projection} projection Projection.
|
||||
* @return {ol.TileCoord} Tile coordinate to be passed to the tileUrlFunction or
|
||||
* null if no tile URL should be created for the passed `tileCoord`.
|
||||
*/
|
||||
ol.source.TileVector.prototype.getTileCoordForTileUrlFunction =
|
||||
function(tileCoord, projection) {
|
||||
var tileGrid = this.tileGrid_;
|
||||
goog.asserts.assert(!goog.isNull(tileGrid), 'tile grid needed');
|
||||
if (this.getWrapX() && projection.isGlobal()) {
|
||||
tileCoord = ol.tilecoord.wrapX(tileCoord, tileGrid, projection);
|
||||
}
|
||||
return ol.tilecoord.withinExtentAndZ(tileCoord, tileGrid) ?
|
||||
tileCoord : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} z Z.
|
||||
* @param {number} x X.
|
||||
@@ -254,7 +279,6 @@ ol.source.TileVector.prototype.getTileKeyZXY_ = function(z, x, y) {
|
||||
*/
|
||||
ol.source.TileVector.prototype.loadFeatures =
|
||||
function(extent, resolution, projection) {
|
||||
var tileCoordTransform = this.tileCoordTransform_;
|
||||
var tileGrid = this.tileGrid_;
|
||||
var tileUrlFunction = this.tileUrlFunction_;
|
||||
var tiles = this.tiles_;
|
||||
@@ -275,16 +299,22 @@ ol.source.TileVector.prototype.loadFeatures =
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
var tileKey = this.getTileKeyZXY_(z, x, y);
|
||||
if (!(tileKey in tiles)) {
|
||||
tileCoord[0] = z;
|
||||
tileCoord[1] = x;
|
||||
tileCoord[2] = y;
|
||||
tileCoordTransform(tileCoord, projection, tileCoord);
|
||||
var url = tileUrlFunction(tileCoord, 1, projection);
|
||||
var urlTileCoord = this.getTileCoordForTileUrlFunction(
|
||||
tileCoord, projection);
|
||||
var url = goog.isNull(urlTileCoord) ? undefined :
|
||||
tileUrlFunction(urlTileCoord, 1, projection);
|
||||
if (goog.isDef(url)) {
|
||||
tiles[tileKey] = [];
|
||||
var loader = ol.featureloader.loadFeaturesXhr(url, this.format_,
|
||||
goog.partial(success, tileKey));
|
||||
loader.call(this, extent, resolution, projection);
|
||||
var tileSuccess = goog.partial(success, tileKey);
|
||||
if (!goog.isNull(this.tileLoadFunction_)) {
|
||||
this.tileLoadFunction_(url, goog.bind(tileSuccess, this));
|
||||
} else {
|
||||
var loader = ol.featureloader.loadFeaturesXhr(url,
|
||||
/** @type {ol.format.Feature} */ (this.format_), tileSuccess);
|
||||
loader.call(this, extent, resolution, projection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user