Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f86bad7459 | ||
|
|
2e531377e2 | ||
|
|
deb523f6f5 | ||
|
|
4718ec500b | ||
|
|
5b4c682f2a | ||
|
|
9224678627 | ||
|
|
df7a911687 | ||
|
|
72cb135aff | ||
|
|
5293efc6e2 | ||
|
|
4cbf04d029 | ||
|
|
bc04e96556 | ||
|
|
6a03e1c34f | ||
|
|
f7efb60843 | ||
|
|
9ee1768a1d | ||
|
|
4e5a7fba77 | ||
|
|
f26130ee54 | ||
|
|
cb6a00e13a | ||
|
|
60c259df02 | ||
|
|
aa110486a1 | ||
|
|
33bffbcdad | ||
|
|
c4e10a34c8 | ||
|
|
c1be8cf618 | ||
|
|
1872b56355 | ||
|
|
6bc8d0cd96 | ||
|
|
d4bc7d3f39 | ||
|
|
60790fea18 | ||
|
|
77ca0c2de5 | ||
|
|
c0009d5985 | ||
|
|
c85a6016c4 | ||
|
|
d5a27dae4f | ||
|
|
0186ca74f1 | ||
|
|
9834f683b9 | ||
|
|
4f5e59d7f0 | ||
|
|
940011fb56 | ||
|
|
974fdebafa | ||
|
|
fb0550ea5c | ||
|
|
b55f8e8f40 | ||
|
|
d8d4f21437 | ||
|
|
7c556951c8 | ||
|
|
b15de51344 | ||
|
|
4822589e26 | ||
|
|
00e880f534 | ||
|
|
f4c2cbdb9b | ||
|
|
1be2c459c4 | ||
|
|
84729e985f | ||
|
|
6506efab0c | ||
|
|
243b21a2e1 | ||
|
|
9d709cb3d9 | ||
|
|
ba444117bb | ||
|
|
78a4efab8c | ||
|
|
54871b6c52 | ||
|
|
709139c657 | ||
|
|
9e37182649 | ||
|
|
d7b0191c78 | ||
|
|
5f118b0244 | ||
|
|
e74d15659f | ||
|
|
1942f3f91b | ||
|
|
2d3d6cae31 | ||
|
|
f2f5a51455 | ||
|
|
1c4bcd7ceb | ||
|
|
fd178c71e6 | ||
|
|
aee95cf690 | ||
|
|
a32dc03a78 | ||
|
|
17b8e80f0a | ||
|
|
b3c417d1c2 | ||
|
|
06884c1f35 | ||
|
|
13da248cbf | ||
|
|
2274598ea3 | ||
|
|
c5a4e842a3 | ||
|
|
b929e02f78 | ||
|
|
a4186fae3c | ||
|
|
bfb6c0ffb5 | ||
|
|
9d167413e7 | ||
|
|
bec5e9676a | ||
|
|
676f538642 | ||
|
|
c81a486615 | ||
|
|
722769695d | ||
|
|
9511063f7e | ||
|
|
d755fbc507 | ||
|
|
f7aba759c2 | ||
|
|
79cfeb9a07 | ||
|
|
564d4f867f | ||
|
|
d66f2f4091 | ||
|
|
481dc9792c | ||
|
|
5c61d5b06c | ||
|
|
b068a339f5 | ||
|
|
7ac93be8dd | ||
|
|
7a6b9f8a33 | ||
|
|
ef5d00cb9a | ||
|
|
2a0a71107e | ||
|
|
6b1232b922 | ||
|
|
2b5ea17d79 | ||
|
|
3ec1ed6bf0 | ||
|
|
d2a2234eec | ||
|
|
a281b7c1aa | ||
|
|
eafcbb3ec0 | ||
|
|
820c123335 | ||
|
|
711ae69bb5 | ||
|
|
ba65896cef | ||
|
|
aa58a358ea |
@@ -1,5 +1,9 @@
|
||||
## Upgrade notes
|
||||
|
||||
### v6.9.0
|
||||
|
||||
There should be nothing special required when upgrading from v6.8 to v6.9.
|
||||
|
||||
### v6.8.0
|
||||
|
||||
There should be nothing special required when upgrading from v6.7 to v6.8.
|
||||
|
||||
5
changelog/v6.8.1.md
Normal file
5
changelog/v6.8.1.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# 6.8.1
|
||||
|
||||
This is a patch release which updates `ol.css` to restore a legible control button size in applications that do not have a css `font-size` set for `button` elements.
|
||||
|
||||
* [#12811](https://github.com/openlayers/openlayers/pull/12811) - Controls inherit font size from parent ([@tschaub](https://github.com/tschaub))
|
||||
51
changelog/v6.9.0.md
Normal file
51
changelog/v6.9.0.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# 6.9.0
|
||||
|
||||
The 6.9 release brings a few new features and a number of fixes. GeoTIFF sources now have a `normalize` option. Set `normalize: false` if you want your style expressions to work with raw floating point values instead of normalized values from 0 to 1. The GeoTIFF source also now uses nodata values from the source imagery – so in most cases you don't need to specify this yourself. For people configuring vector layers with styles that use custom rendering, you can now get hit detection on the rendered result. See details on these features and other included fixes below.
|
||||
|
||||
* [#12813](https://github.com/openlayers/openlayers/pull/12813) - Do not replace icon color if image not loaded ([@mike-000](https://github.com/mike-000))
|
||||
* [#12870](https://github.com/openlayers/openlayers/pull/12870) - Fix publicPath problem in legacy build ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#12889](https://github.com/openlayers/openlayers/pull/12889) - Simplified ESLint config ([@tschaub](https://github.com/tschaub))
|
||||
* [#12875](https://github.com/openlayers/openlayers/pull/12875) - Only trigger change event if animating a tile transition ([@tschaub](https://github.com/tschaub))
|
||||
* [#12885](https://github.com/openlayers/openlayers/pull/12885) - Fix typeDefs for several Control modules ([@MatthijsBon](https://github.com/MatthijsBon))
|
||||
* [#12861](https://github.com/openlayers/openlayers/pull/12861) - Update geotiff to 1.0.8; allow version range ([@ahocevar](https://github.com/ahocevar))
|
||||
* [#12865](https://github.com/openlayers/openlayers/pull/12865) - Add a note about installing git before using create-ol-app ([@tschaub](https://github.com/tschaub))
|
||||
* [#12847](https://github.com/openlayers/openlayers/pull/12847) - Add more definitions for GeoTIFF types ([@tschaub](https://github.com/tschaub))
|
||||
* [#12850](https://github.com/openlayers/openlayers/pull/12850) - Fix issues with animate on View without center or resolution ([@MoonE](https://github.com/MoonE))
|
||||
* [#12846](https://github.com/openlayers/openlayers/pull/12846) - Use nodata values in the GeoTIFF headers for fill value ([@tschaub](https://github.com/tschaub))
|
||||
* [#12837](https://github.com/openlayers/openlayers/pull/12837) - forEachLayerAtPixel return null for unsupported layer types ([@mike-000](https://github.com/mike-000))
|
||||
* [#12836](https://github.com/openlayers/openlayers/pull/12836) - Support a normalize option on the GeoTIFF source ([@tschaub](https://github.com/tschaub))
|
||||
* [#12646](https://github.com/openlayers/openlayers/pull/12646) - Support for hit detection in styles with custom rendering ([@ashchurova](https://github.com/ashchurova))
|
||||
* [#12831](https://github.com/openlayers/openlayers/pull/12831) - Fix rendering VectorImage with no features in view extent ([@MoonE](https://github.com/MoonE))
|
||||
* [#12830](https://github.com/openlayers/openlayers/pull/12830) - bugfix: Fix type of `layers` option in `OverviewMap` ([@ejn](https://github.com/ejn))
|
||||
* [#12815](https://github.com/openlayers/openlayers/pull/12815) - Spelling correction ([@tschaub](https://github.com/tschaub))
|
||||
* [#12812](https://github.com/openlayers/openlayers/pull/12812) - Release v6.8.1 ([@openlayers](https://github.com/openlayers))
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Dependency Updates</summary>
|
||||
|
||||
* [#12881](https://github.com/openlayers/openlayers/pull/12881) - Bump webpack from 5.56.1 to 5.58.1 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12882](https://github.com/openlayers/openlayers/pull/12882) - Bump marked from 3.0.4 to 3.0.7 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12878](https://github.com/openlayers/openlayers/pull/12878) - Bump webpack-dev-server from 4.3.0 to 4.3.1 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12879](https://github.com/openlayers/openlayers/pull/12879) - Bump @babel/preset-env from 7.15.6 to 7.15.8 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12880](https://github.com/openlayers/openlayers/pull/12880) - Bump @babel/eslint-parser from 7.15.7 to 7.15.8 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12884](https://github.com/openlayers/openlayers/pull/12884) - Bump @babel/core from 7.15.5 to 7.15.8 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12877](https://github.com/openlayers/openlayers/pull/12877) - Bump webpack-cli from 4.8.0 to 4.9.0 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12854](https://github.com/openlayers/openlayers/pull/12854) - Bump webpack from 5.54.0 to 5.56.1 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12857](https://github.com/openlayers/openlayers/pull/12857) - Bump webpack-dev-server from 4.2.1 to 4.3.0 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12856](https://github.com/openlayers/openlayers/pull/12856) - Bump @rollup/plugin-commonjs from 20.0.0 to 21.0.0 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12855](https://github.com/openlayers/openlayers/pull/12855) - Bump rollup from 2.57.0 to 2.58.0 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12853](https://github.com/openlayers/openlayers/pull/12853) - Bump clean-css-cli from 5.3.3 to 5.4.1 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12822](https://github.com/openlayers/openlayers/pull/12822) - Bump glob from 7.1.7 to 7.2.0 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12824](https://github.com/openlayers/openlayers/pull/12824) - Bump rollup from 2.56.3 to 2.57.0 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12818](https://github.com/openlayers/openlayers/pull/12818) - Bump threads from 1.6.5 to 1.7.0 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12821](https://github.com/openlayers/openlayers/pull/12821) - Bump @rollup/plugin-node-resolve from 13.0.4 to 13.0.5 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12823](https://github.com/openlayers/openlayers/pull/12823) - Bump walk from 2.3.14 to 2.3.15 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12819](https://github.com/openlayers/openlayers/pull/12819) - Bump webpack-dev-middleware from 5.1.0 to 5.2.1 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12820](https://github.com/openlayers/openlayers/pull/12820) - Bump mocha from 9.1.1 to 9.1.2 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12817](https://github.com/openlayers/openlayers/pull/12817) - Bump yargs from 17.1.1 to 17.2.1 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12825](https://github.com/openlayers/openlayers/pull/12825) - Bump webpack from 5.53.0 to 5.54.0 ([@openlayers](https://github.com/openlayers))
|
||||
* [#12826](https://github.com/openlayers/openlayers/pull/12826) - Bump puppeteer from 10.2.0 to 10.4.0 ([@openlayers](https://github.com/openlayers))
|
||||
|
||||
|
||||
</details>
|
||||
@@ -48,6 +48,7 @@ export default {
|
||||
},
|
||||
output: {
|
||||
path: path.resolve('./build/legacy'),
|
||||
publicPath: '',
|
||||
filename: 'ol.js',
|
||||
library: 'ol',
|
||||
libraryTarget: 'umd',
|
||||
|
||||
@@ -15,6 +15,8 @@ Create a new empty directory for your project and navigate to it by running `mkd
|
||||
|
||||
npx create-ol-app
|
||||
|
||||
*You will need to have `git` installed for the above command to work. If you receive an error, make that [Git is installed](https://github.com/git-guides/install-git) on your system.*
|
||||
|
||||
This will install the `ol` package, set up a development environment with additional dependencies, and give you an `index.html` and `main.js` starting point for your application. By default, [Parcel](https://parceljs.org) will be used as a module loader and bundler. See the [`create-ol-app`](https://github.com/openlayers/create-ol-app) documentation for details on using another bundler.
|
||||
|
||||
To start the development server
|
||||
|
||||
12
examples/custom-hit-detection-renderer.html
Normal file
12
examples/custom-hit-detection-renderer.html
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Custom Hit Detection Render
|
||||
shortdesc: Example of a custom hit detection renderer.
|
||||
docs: >
|
||||
This example demonstrates the use of 'ol/style/Style' hitDetectionRender option function in
|
||||
detecting if pointer is over a particular feature.
|
||||
Move pointer over the label for Columbus Circle feature and see that only label is used in
|
||||
hit detection.
|
||||
tags: "circle, feature, vector, render, custom, hitDetectionRenderer"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
103
examples/custom-hit-detection-renderer.js
Normal file
103
examples/custom-hit-detection-renderer.js
Normal file
@@ -0,0 +1,103 @@
|
||||
import Feature from '../src/ol/Feature.js';
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {Circle} from '../src/ol/geom.js';
|
||||
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
||||
import {Style} from '../src/ol/style.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import {fromLonLat} from '../src/ol/proj.js';
|
||||
|
||||
const columbusCircleCoords = fromLonLat([-73.98189, 40.76805]);
|
||||
const labelTextStroke = 'rgba(120, 120, 120, 1)';
|
||||
const labelText = 'Columbus Circle';
|
||||
|
||||
let pointerOverFeature = null;
|
||||
|
||||
const renderLabelText = (ctx, x, y, stroke) => {
|
||||
ctx.fillStyle = 'rgba(255,0,0,1)';
|
||||
ctx.strokeStyle = stroke;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.font = `bold 30px verdana`;
|
||||
ctx.filter = 'drop-shadow(7px 7px 2px #e81)';
|
||||
ctx.fillText(labelText, x, y);
|
||||
ctx.strokeText(labelText, x, y);
|
||||
};
|
||||
|
||||
const circleFeature = new Feature({
|
||||
geometry: new Circle(columbusCircleCoords, 50),
|
||||
});
|
||||
|
||||
circleFeature.set('label-color', labelTextStroke);
|
||||
|
||||
circleFeature.setStyle(
|
||||
new Style({
|
||||
renderer(coordinates, state) {
|
||||
const [[x, y], [x1, y1]] = coordinates;
|
||||
const ctx = state.context;
|
||||
const dx = x1 - x;
|
||||
const dy = y1 - y;
|
||||
const radius = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
const innerRadius = 0;
|
||||
const outerRadius = radius * 1.4;
|
||||
|
||||
const gradient = ctx.createRadialGradient(
|
||||
x,
|
||||
y,
|
||||
innerRadius,
|
||||
x,
|
||||
y,
|
||||
outerRadius
|
||||
);
|
||||
gradient.addColorStop(0, 'rgba(255,0,0,0)');
|
||||
gradient.addColorStop(0.6, 'rgba(255,0,0,0.2)');
|
||||
gradient.addColorStop(1, 'rgba(255,0,0,0.8)');
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = 'rgba(255,0,0,1)';
|
||||
ctx.stroke();
|
||||
|
||||
renderLabelText(ctx, x, y, circleFeature.get('label-color'));
|
||||
},
|
||||
hitDetectionRenderer(coordinates, state) {
|
||||
const [x, y] = coordinates[0];
|
||||
const ctx = state.context;
|
||||
renderLabelText(ctx, x, y, circleFeature.get('label-color'));
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const map = new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new OSM(),
|
||||
visible: true,
|
||||
}),
|
||||
new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: [circleFeature],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: columbusCircleCoords,
|
||||
zoom: 19,
|
||||
}),
|
||||
});
|
||||
|
||||
map.on('pointermove', (evt) => {
|
||||
const featureOver = map.forEachFeatureAtPixel(evt.pixel, (feature) => {
|
||||
feature.set('label-color', 'rgba(255,255,255,1)');
|
||||
return feature;
|
||||
});
|
||||
|
||||
if (pointerOverFeature && pointerOverFeature != featureOver) {
|
||||
pointerOverFeature.set('label-color', labelTextStroke);
|
||||
}
|
||||
pointerOverFeature = featureOver;
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017
|
||||
}
|
||||
}
|
||||
2636
package-lock.json
generated
2636
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ol",
|
||||
"version": "6.8.0",
|
||||
"version": "6.9.0",
|
||||
"description": "OpenLayers mapping library",
|
||||
"keywords": [
|
||||
"map",
|
||||
@@ -45,18 +45,17 @@
|
||||
"url": "https://opencollective.com/openlayers"
|
||||
},
|
||||
"dependencies": {
|
||||
"geotiff": "1.0.6",
|
||||
"geotiff": "^1.0.8",
|
||||
"ol-mapbox-style": "^6.5.1",
|
||||
"pbf": "3.2.1",
|
||||
"rbush": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.6.4",
|
||||
"@babel/eslint-parser": "^7.13.14",
|
||||
"@babel/preset-env": "^7.4.4",
|
||||
"@openlayers/eslint-plugin": "^4.0.0",
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"@rollup/plugin-commonjs": "^20.0.0",
|
||||
"@rollup/plugin-commonjs": "^21.0.0",
|
||||
"@rollup/plugin-node-resolve": "^13.0.0",
|
||||
"@types/arcgis-rest-api": "^10.4.4",
|
||||
"@types/geojson": "^7946.0.7",
|
||||
@@ -64,13 +63,13 @@
|
||||
"@types/topojson-specification": "^1.0.1",
|
||||
"babel-loader": "^8.2.2",
|
||||
"chaikin-smooth": "^1.0.4",
|
||||
"clean-css-cli": "5.3.3",
|
||||
"clean-css-cli": "5.4.1",
|
||||
"copy-webpack-plugin": "^9.0.0",
|
||||
"coverage-istanbul-loader": "^3.0.5",
|
||||
"coveralls": "3.1.1",
|
||||
"es-main": "^1.0.2",
|
||||
"eslint": "^7.2.0",
|
||||
"eslint-config-openlayers": "^15.0.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-openlayers": "^16.0.1",
|
||||
"expect.js": "0.3.1",
|
||||
"express": "^4.17.1",
|
||||
"front-matter": "^4.0.0",
|
||||
@@ -91,12 +90,12 @@
|
||||
"karma-sourcemap-loader": "^0.3.8",
|
||||
"karma-webpack": "^5.0.0",
|
||||
"loglevelnext": "^5.0.5",
|
||||
"marked": "3.0.4",
|
||||
"mocha": "9.1.1",
|
||||
"marked": "3.0.7",
|
||||
"mocha": "9.1.2",
|
||||
"pixelmatch": "^5.1.0",
|
||||
"pngjs": "^6.0.0",
|
||||
"proj4": "^2.7.5",
|
||||
"puppeteer": "10.2.0",
|
||||
"puppeteer": "10.4.0",
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"rollup": "^2.42.3",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
@@ -117,10 +116,6 @@
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "openlayers",
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"requireConfigFile": false
|
||||
},
|
||||
"plugins": [
|
||||
"@openlayers"
|
||||
],
|
||||
|
||||
@@ -621,29 +621,36 @@ class View extends BaseObject {
|
||||
callback = arguments[animationCount - 1];
|
||||
--animationCount;
|
||||
}
|
||||
if (!this.isDef()) {
|
||||
|
||||
let i = 0;
|
||||
for (; i < animationCount && !this.isDef(); ++i) {
|
||||
// if view properties are not yet set, shortcut to the final state
|
||||
const state = arguments[animationCount - 1];
|
||||
const state = arguments[i];
|
||||
if (state.center) {
|
||||
this.setCenterInternal(state.center);
|
||||
}
|
||||
if (state.zoom !== undefined) {
|
||||
this.setZoom(state.zoom);
|
||||
} else if (state.resolution) {
|
||||
this.setResolution(state.resolution);
|
||||
}
|
||||
if (state.rotation !== undefined) {
|
||||
this.setRotation(state.rotation);
|
||||
}
|
||||
}
|
||||
if (i === animationCount) {
|
||||
if (callback) {
|
||||
animationCallback(callback, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let start = Date.now();
|
||||
let center = this.targetCenter_.slice();
|
||||
let resolution = this.targetResolution_;
|
||||
let rotation = this.targetRotation_;
|
||||
const series = [];
|
||||
for (let i = 0; i < animationCount; ++i) {
|
||||
for (; i < animationCount; ++i) {
|
||||
const options = /** @type {AnimationOptions} */ (arguments[i]);
|
||||
|
||||
const animation = {
|
||||
|
||||
@@ -20,7 +20,7 @@ import {removeChildren, replaceNode} from '../dom.js';
|
||||
* @property {boolean} [collapsed=true] Specify if attributions should
|
||||
* be collapsed at startup.
|
||||
* @property {string} [tipLabel='Attributions'] Text label to use for the button tip.
|
||||
* @property {string} [label='i'] Text label to use for the
|
||||
* @property {string|HTMLElement} [label='i'] Text label to use for the
|
||||
* collapsed attributions button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [expandClassName=className + '-expand'] CSS class name for the
|
||||
|
||||
@@ -44,15 +44,15 @@ const FullScreenEventType = {
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-full-screen'] CSS class name.
|
||||
* @property {string|Text} [label='\u2922'] Text label to use for the button.
|
||||
* @property {string|Text|HTMLElement} [label='\u2922'] Text label to use for the button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string|Text} [labelActive='\u00d7'] Text label to use for the
|
||||
* @property {string|Text|HTMLElement} [labelActive='\u00d7'] Text label to use for the
|
||||
* button when full-screen is active.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [activeClassName=className + '-true'] CSS class name for the button
|
||||
* when full-screen is active.
|
||||
* @property {string} [inactiveClassName=className + '-false'] CSS class name for the button
|
||||
* when full-screen is inactive.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [tipLabel='Toggle full-screen'] Text label to use for the button tip.
|
||||
* @property {boolean} [keys=false] Full keyboard access.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the
|
||||
@@ -133,7 +133,7 @@ class FullScreen extends Control {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Text}
|
||||
* @type {Text|HTMLElement}
|
||||
*/
|
||||
this.labelNode_ =
|
||||
typeof label === 'string' ? document.createTextNode(label) : label;
|
||||
@@ -143,7 +143,7 @@ class FullScreen extends Control {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Text}
|
||||
* @type {Text|HTMLElement}
|
||||
*/
|
||||
this.labelActiveNode_ =
|
||||
typeof labelActive === 'string'
|
||||
|
||||
@@ -53,7 +53,7 @@ class ControlledMap extends PluggableMap {
|
||||
* @property {boolean} [collapsible=true] Whether the control can be collapsed or not.
|
||||
* @property {string|HTMLElement} [label='›'] Text label to use for the collapsed
|
||||
* overviewmap button. Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {Array<import("../layer/Layer.js").default>|import("../Collection.js").default<import("../layer/Layer.js").default>} [layers]
|
||||
* @property {Array<import("../layer/Base.js").default>|import("../Collection.js").default<import("../layer/Base.js").default>} [layers]
|
||||
* Layers for the overview map.
|
||||
* @property {function(import("../MapEvent.js").default):void} [render] Function called when the control
|
||||
* should be re-rendered. This is called in a `requestAnimationFrame` callback.
|
||||
|
||||
@@ -89,7 +89,7 @@ export class DragAndDropEvent extends Event {
|
||||
* Handles input of vector data by drag and drop.
|
||||
*
|
||||
* Note that the DragAndDrop interaction uses the TextDecoder() constructor if the supplied
|
||||
* combinnation of formats read both text string and ArrayBuffer sources. Older browsers such
|
||||
* combination of formats read both text string and ArrayBuffer sources. Older browsers such
|
||||
* as IE which do not support this will need a TextDecoder polyfill to be loaded before use.
|
||||
*
|
||||
* @api
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
font-size: inherit;
|
||||
text-align: center;
|
||||
height: 1.375em;
|
||||
width: 1.375em;
|
||||
|
||||
@@ -15,8 +15,9 @@ class VectorContext {
|
||||
* @param {import("../geom/SimpleGeometry.js").default} geometry Geometry.
|
||||
* @param {import("../Feature.js").FeatureLike} feature Feature.
|
||||
* @param {Function} renderer Renderer.
|
||||
* @param {Function} hitDetectionRenderer Renderer.
|
||||
*/
|
||||
drawCustom(geometry, feature, renderer) {}
|
||||
drawCustom(geometry, feature, renderer, hitDetectionRenderer) {}
|
||||
|
||||
/**
|
||||
* Render a geometry.
|
||||
|
||||
@@ -247,97 +247,104 @@ class CanvasBuilder extends VectorContext {
|
||||
* @param {import("../../geom/SimpleGeometry.js").default} geometry Geometry.
|
||||
* @param {import("../../Feature.js").FeatureLike} feature Feature.
|
||||
* @param {Function} renderer Renderer.
|
||||
* @param {Function} hitDetectionRenderer Renderer.
|
||||
*/
|
||||
drawCustom(geometry, feature, renderer) {
|
||||
drawCustom(geometry, feature, renderer, hitDetectionRenderer) {
|
||||
this.beginGeometry(geometry, feature);
|
||||
|
||||
const type = geometry.getType();
|
||||
const stride = geometry.getStride();
|
||||
const builderBegin = this.coordinates.length;
|
||||
|
||||
let flatCoordinates, builderEnd, builderEnds, builderEndss;
|
||||
let offset;
|
||||
if (type == GeometryType.MULTI_POLYGON) {
|
||||
flatCoordinates =
|
||||
/** @type {import("../../geom/MultiPolygon.js").default} */ (
|
||||
geometry
|
||||
).getOrientedFlatCoordinates();
|
||||
builderEndss = [];
|
||||
const endss =
|
||||
/** @type {import("../../geom/MultiPolygon.js").default} */ (
|
||||
geometry
|
||||
).getEndss();
|
||||
offset = 0;
|
||||
for (let i = 0, ii = endss.length; i < ii; ++i) {
|
||||
const myEnds = [];
|
||||
|
||||
switch (type) {
|
||||
case GeometryType.MULTI_POLYGON:
|
||||
flatCoordinates =
|
||||
/** @type {import("../../geom/MultiPolygon.js").default} */ (
|
||||
geometry
|
||||
).getOrientedFlatCoordinates();
|
||||
builderEndss = [];
|
||||
const endss =
|
||||
/** @type {import("../../geom/MultiPolygon.js").default} */ (
|
||||
geometry
|
||||
).getEndss();
|
||||
offset = 0;
|
||||
for (let i = 0, ii = endss.length; i < ii; ++i) {
|
||||
const myEnds = [];
|
||||
offset = this.drawCustomCoordinates_(
|
||||
flatCoordinates,
|
||||
offset,
|
||||
endss[i],
|
||||
stride,
|
||||
myEnds
|
||||
);
|
||||
builderEndss.push(myEnds);
|
||||
}
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEndss,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateMultiCoordinatesArray,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEndss,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
inflateMultiCoordinatesArray,
|
||||
]);
|
||||
break;
|
||||
case GeometryType.POLYGON:
|
||||
case GeometryType.MULTI_LINE_STRING:
|
||||
builderEnds = [];
|
||||
flatCoordinates =
|
||||
type == GeometryType.POLYGON
|
||||
? /** @type {import("../../geom/Polygon.js").default} */ (
|
||||
geometry
|
||||
).getOrientedFlatCoordinates()
|
||||
: geometry.getFlatCoordinates();
|
||||
offset = this.drawCustomCoordinates_(
|
||||
flatCoordinates,
|
||||
offset,
|
||||
endss[i],
|
||||
0,
|
||||
/** @type {import("../../geom/Polygon.js").default|import("../../geom/MultiLineString.js").default} */ (
|
||||
geometry
|
||||
).getEnds(),
|
||||
stride,
|
||||
myEnds
|
||||
builderEnds
|
||||
);
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnds,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateCoordinatesArray,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnds,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
inflateCoordinatesArray,
|
||||
]);
|
||||
break;
|
||||
case GeometryType.LINE_STRING:
|
||||
case GeometryType.CIRCLE:
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
builderEnd = this.appendFlatLineCoordinates(
|
||||
flatCoordinates,
|
||||
0,
|
||||
flatCoordinates.length,
|
||||
stride,
|
||||
false,
|
||||
false
|
||||
);
|
||||
builderEndss.push(myEnds);
|
||||
}
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEndss,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateMultiCoordinatesArray,
|
||||
]);
|
||||
} else if (
|
||||
type == GeometryType.POLYGON ||
|
||||
type == GeometryType.MULTI_LINE_STRING
|
||||
) {
|
||||
builderEnds = [];
|
||||
flatCoordinates =
|
||||
type == GeometryType.POLYGON
|
||||
? /** @type {import("../../geom/Polygon.js").default} */ (
|
||||
geometry
|
||||
).getOrientedFlatCoordinates()
|
||||
: geometry.getFlatCoordinates();
|
||||
offset = this.drawCustomCoordinates_(
|
||||
flatCoordinates,
|
||||
0,
|
||||
/** @type {import("../../geom/Polygon.js").default|import("../../geom/MultiLineString.js").default} */ (
|
||||
geometry
|
||||
).getEnds(),
|
||||
stride,
|
||||
builderEnds
|
||||
);
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnds,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateCoordinatesArray,
|
||||
]);
|
||||
} else if (
|
||||
type == GeometryType.LINE_STRING ||
|
||||
type == GeometryType.CIRCLE
|
||||
) {
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
builderEnd = this.appendFlatLineCoordinates(
|
||||
flatCoordinates,
|
||||
0,
|
||||
flatCoordinates.length,
|
||||
stride,
|
||||
false,
|
||||
false
|
||||
);
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
} else if (type == GeometryType.MULTI_POINT) {
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
builderEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);
|
||||
if (builderEnd > builderBegin) {
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
@@ -346,18 +353,59 @@ class CanvasBuilder extends VectorContext {
|
||||
renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
}
|
||||
} else if (type == GeometryType.POINT) {
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
|
||||
builderEnd = this.coordinates.length;
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
renderer,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
break;
|
||||
case GeometryType.MULTI_POINT:
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
builderEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);
|
||||
|
||||
if (builderEnd > builderBegin) {
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
}
|
||||
break;
|
||||
case GeometryType.POINT:
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
|
||||
builderEnd = this.coordinates.length;
|
||||
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
renderer,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
this.endGeometry(feature);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class LayerRenderer extends Observable {
|
||||
* returned, and empty array will be returned.
|
||||
*/
|
||||
getDataAtPixel(pixel, frameState, hitTolerance) {
|
||||
return abstract();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -120,6 +120,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
|
||||
),
|
||||
})
|
||||
);
|
||||
let emptyImage = true;
|
||||
const image = new ImageCanvas(
|
||||
renderedExtent,
|
||||
viewResolution,
|
||||
@@ -131,8 +132,10 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
|
||||
vectorRenderer.replayGroupChanged
|
||||
) {
|
||||
vectorRenderer.clipping = false;
|
||||
vectorRenderer.renderFrame(imageFrameState, null);
|
||||
vectorRenderer.renderDeclutter(imageFrameState);
|
||||
if (vectorRenderer.renderFrame(imageFrameState, null)) {
|
||||
vectorRenderer.renderDeclutter(imageFrameState);
|
||||
emptyImage = false;
|
||||
}
|
||||
callback();
|
||||
}
|
||||
}
|
||||
@@ -141,24 +144,25 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
|
||||
image.addEventListener(
|
||||
EventType.CHANGE,
|
||||
function () {
|
||||
if (image.getState() === ImageState.LOADED) {
|
||||
this.image_ = image;
|
||||
const imageResolution = image.getResolution();
|
||||
const imagePixelRatio = image.getPixelRatio();
|
||||
const renderedResolution =
|
||||
(imageResolution * pixelRatio) / imagePixelRatio;
|
||||
this.renderedResolution = renderedResolution;
|
||||
this.coordinateToVectorPixelTransform_ = compose(
|
||||
this.coordinateToVectorPixelTransform_,
|
||||
width / 2,
|
||||
height / 2,
|
||||
1 / renderedResolution,
|
||||
-1 / renderedResolution,
|
||||
0,
|
||||
-viewState.center[0],
|
||||
-viewState.center[1]
|
||||
);
|
||||
if (image.getState() !== ImageState.LOADED) {
|
||||
return;
|
||||
}
|
||||
this.image_ = emptyImage ? null : image;
|
||||
const imageResolution = image.getResolution();
|
||||
const imagePixelRatio = image.getPixelRatio();
|
||||
const renderedResolution =
|
||||
(imageResolution * pixelRatio) / imagePixelRatio;
|
||||
this.renderedResolution = renderedResolution;
|
||||
this.coordinateToVectorPixelTransform_ = compose(
|
||||
this.coordinateToVectorPixelTransform_,
|
||||
width / 2,
|
||||
height / 2,
|
||||
1 / renderedResolution,
|
||||
-1 / renderedResolution,
|
||||
0,
|
||||
-viewState.center[0],
|
||||
-viewState.center[1]
|
||||
);
|
||||
}.bind(this)
|
||||
);
|
||||
image.load();
|
||||
|
||||
@@ -208,7 +208,8 @@ function renderGeometry(replayGroup, geometry, style, feature) {
|
||||
replay.drawCustom(
|
||||
/** @type {import("../geom/SimpleGeometry.js").default} */ (geometry),
|
||||
feature,
|
||||
style.getRenderer()
|
||||
style.getRenderer(),
|
||||
style.getHitDetectionRenderer()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,10 @@ import {fromCode as unitsFromCode} from '../proj/Units.js';
|
||||
* the configured min and max.
|
||||
* @property {number} [max] The maximum source data value. Rendered values are scaled from 0 to 1 based on
|
||||
* the configured min and max.
|
||||
* @property {number} [nodata] Values to discard. When provided, an additional band (alpha) will be added
|
||||
* to the data.
|
||||
* @property {number} [nodata] Values to discard (overriding any nodata values in the metadata).
|
||||
* When provided, an additional alpha band will be added to the data. Often the GeoTIFF metadata
|
||||
* will include information about nodata values, so you should only need to set this property if
|
||||
* you find that it is not already extracted from the metadata.
|
||||
* @property {Array<number>} [bands] Band numbers to be read from (where the first band is `1`). If not provided, all bands will
|
||||
* be read. For example, if a GeoTIFF has blue (1), green (2), red (3), and near-infrared (4) bands, and you only need the
|
||||
* near-infrared band, configure `bands: [4]`.
|
||||
@@ -44,6 +46,18 @@ import {fromCode as unitsFromCode} from '../proj/Units.js';
|
||||
* @property {number} ProjectedCSTypeGeoKey Projected coordinate system code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} GeoTIFF
|
||||
* @property {function():Promise<number>} getImageCount Get the number of internal subfile images.
|
||||
* @property {function(number):Promise<GeoTIFFImage>} getImage Get the image at the specified index.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MultiGeoTIFF
|
||||
* @property {function():Promise<number>} getImageCount Get the number of internal subfile images.
|
||||
* @property {function(number):Promise<GeoTIFFImage>} getImage Get the image at the specified index.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} GeoTIFFImage
|
||||
* @property {Object} fileDirectory The file directory.
|
||||
@@ -54,6 +68,12 @@ import {fromCode as unitsFromCode} from '../proj/Units.js';
|
||||
* @property {function():Array<number>} getBoundingBox Get the image bounding box.
|
||||
* @property {function():Array<number>} getOrigin Get the image origin.
|
||||
* @property {function(GeoTIFFImage):Array<number>} getResolution Get the image resolution.
|
||||
* @property {function():number} getWidth Get the pixel width of the image.
|
||||
* @property {function():number} getHeight Get the pixel height of the image.
|
||||
* @property {function():number} getTileWidth Get the pixel width of image tiles.
|
||||
* @property {function():number} getTileHeight Get the pixel height of image tiles.
|
||||
* @property {function():number|null} getGDALNoData Get the nodata value (or null if none).
|
||||
* @property {function():number} getSamplesPerPixel Get the number of samples per pixel.
|
||||
*/
|
||||
|
||||
let workerPool;
|
||||
@@ -154,8 +174,8 @@ function getProjection(image) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("geotiff/src/geotiff.js").GeoTIFF|import("geotiff/src/geotiff.js").MultiGeoTIFF} tiff A GeoTIFF.
|
||||
* @return {Promise<Array<import("geotiff/src/geotiffimage.js").GeoTIFFImage>>} Resolves to a list of images.
|
||||
* @param {GeoTIFF|MultiGeoTIFF} tiff A GeoTIFF.
|
||||
* @return {Promise<Array<GeoTIFFImage>>} Resolves to a list of images.
|
||||
*/
|
||||
function getImagesForTIFF(tiff) {
|
||||
return tiff.getImageCount().then(function (count) {
|
||||
@@ -169,7 +189,7 @@ function getImagesForTIFF(tiff) {
|
||||
|
||||
/**
|
||||
* @param {SourceInfo} source The GeoTIFF source.
|
||||
* @return {Promise<Array<import("geotiff/src/geotiffimage.js").GeoTIFFImage>>} Resolves to a list of images.
|
||||
* @return {Promise<Array<GeoTIFFImage>>} Resolves to a list of images.
|
||||
*/
|
||||
function getImagesForSource(source) {
|
||||
let request;
|
||||
@@ -273,6 +293,10 @@ function getMaxForDataType(array) {
|
||||
* @property {boolean} [convertToRGB = false] By default, bands from the sources are read as-is. When
|
||||
* reading GeoTIFFs with the purpose of displaying them as RGB images, setting this to `true` will
|
||||
* convert other color spaces (YCbCr, CMYK) to RGB.
|
||||
* @property {boolean} [normalize=true] By default, the source data is normalized to values between
|
||||
* 0 and 1 with scaling factors based on the `min` and `max` properties of each source. If instead
|
||||
* you want to work with the raw values in a style expression, set this to `false`. Setting this option
|
||||
* to `false` will make it so any `min` and `max` properties on sources are ignored.
|
||||
* @property {boolean} [opaque=false] Whether the layer is opaque.
|
||||
* @property {number} [transition=250] Duration of the opacity transition for rendering.
|
||||
* To disable the opacity transition, pass `transition: 0`.
|
||||
@@ -305,7 +329,7 @@ class GeoTIFFSource extends DataTile {
|
||||
const numSources = this.sourceInfo_.length;
|
||||
|
||||
/**
|
||||
* @type {Array<Array<import("geotiff/src/geotiffimage.js").GeoTIFFImage>>}
|
||||
* @type {Array<Array<GeoTIFFImage>>}
|
||||
* @private
|
||||
*/
|
||||
this.sourceImagery_ = new Array(numSources);
|
||||
@@ -328,6 +352,12 @@ class GeoTIFFSource extends DataTile {
|
||||
*/
|
||||
this.nodataValues_;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.normalize_ = options.normalize !== false;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
@@ -382,7 +412,7 @@ class GeoTIFFSource extends DataTile {
|
||||
/**
|
||||
* Configure the tile grid based on images within the source GeoTIFFs. Each GeoTIFF
|
||||
* must have the same internal tiled structure.
|
||||
* @param {Array<Array<import("geotiff/src/geotiffimage.js").GeoTIFFImage>>} sources Each source is a list of images
|
||||
* @param {Array<Array<GeoTIFFImage>>} sources Each source is a list of images
|
||||
* from a single GeoTIFF.
|
||||
* @private
|
||||
*/
|
||||
@@ -572,6 +602,7 @@ class GeoTIFFSource extends DataTile {
|
||||
const addAlpha = this.addAlpha_;
|
||||
const bandCount = this.bandCount;
|
||||
const samplesPerPixel = this.samplesPerPixel_;
|
||||
const nodataValues = this.nodataValues_;
|
||||
const sourceInfo = this.sourceInfo_;
|
||||
for (let sourceIndex = 0; sourceIndex < sourceCount; ++sourceIndex) {
|
||||
const source = sourceInfo[sourceIndex];
|
||||
@@ -589,12 +620,27 @@ class GeoTIFFSource extends DataTile {
|
||||
return bandNumber - 1;
|
||||
});
|
||||
}
|
||||
|
||||
/** @type {number|Array<number>} */
|
||||
let fillValue;
|
||||
if (!isNaN(source.nodata)) {
|
||||
fillValue = source.nodata;
|
||||
} else {
|
||||
if (!samples) {
|
||||
fillValue = nodataValues[sourceIndex];
|
||||
} else {
|
||||
fillValue = samples.map(function (sampleIndex) {
|
||||
return nodataValues[sourceIndex][sampleIndex];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
requests[sourceIndex] = image[this.readMethod_]({
|
||||
window: pixelBounds,
|
||||
width: size[0],
|
||||
height: size[1],
|
||||
samples: samples,
|
||||
fillValue: source.nodata,
|
||||
fillValue: fillValue,
|
||||
pool: getWorkerPool(),
|
||||
interleave: false,
|
||||
});
|
||||
@@ -602,26 +648,37 @@ class GeoTIFFSource extends DataTile {
|
||||
|
||||
const pixelCount = size[0] * size[1];
|
||||
const dataLength = pixelCount * bandCount;
|
||||
const nodataValues = this.nodataValues_;
|
||||
const normalize = this.normalize_;
|
||||
|
||||
return Promise.all(requests).then(function (sourceSamples) {
|
||||
const data = new Uint8Array(dataLength);
|
||||
/** @type {Uint8Array|Float32Array} */
|
||||
let data;
|
||||
if (normalize) {
|
||||
data = new Uint8Array(dataLength);
|
||||
} else {
|
||||
data = new Float32Array(dataLength);
|
||||
}
|
||||
|
||||
let dataIndex = 0;
|
||||
for (let pixelIndex = 0; pixelIndex < pixelCount; ++pixelIndex) {
|
||||
let transparent = addAlpha;
|
||||
for (let sourceIndex = 0; sourceIndex < sourceCount; ++sourceIndex) {
|
||||
const source = sourceInfo[sourceIndex];
|
||||
let min = source.min;
|
||||
if (min === undefined) {
|
||||
min = getMinForDataType(sourceSamples[sourceIndex][0]);
|
||||
}
|
||||
let max = source.max;
|
||||
if (max === undefined) {
|
||||
max = getMaxForDataType(sourceSamples[sourceIndex][0]);
|
||||
}
|
||||
|
||||
const gain = 255 / (max - min);
|
||||
const bias = -min * gain;
|
||||
let min = source.min;
|
||||
let max = source.max;
|
||||
let gain, bias;
|
||||
if (normalize) {
|
||||
if (min === undefined) {
|
||||
min = getMinForDataType(sourceSamples[sourceIndex][0]);
|
||||
}
|
||||
if (max === undefined) {
|
||||
max = getMaxForDataType(sourceSamples[sourceIndex][0]);
|
||||
}
|
||||
|
||||
gain = 255 / (max - min);
|
||||
bias = -min * gain;
|
||||
}
|
||||
|
||||
for (
|
||||
let sampleIndex = 0;
|
||||
@@ -631,7 +688,13 @@ class GeoTIFFSource extends DataTile {
|
||||
const sourceValue =
|
||||
sourceSamples[sourceIndex][sampleIndex][pixelIndex];
|
||||
|
||||
const value = clamp(gain * sourceValue + bias, 0, 255);
|
||||
let value;
|
||||
if (normalize) {
|
||||
value = clamp(gain * sourceValue + bias, 0, 255);
|
||||
} else {
|
||||
value = sourceValue;
|
||||
}
|
||||
|
||||
if (!addAlpha) {
|
||||
data[dataIndex] = value;
|
||||
} else {
|
||||
|
||||
@@ -862,7 +862,9 @@ class RasterSource extends ImageSource {
|
||||
this.dispatchEvent(
|
||||
new RasterSourceEvent(RasterEventType.AFTEROPERATIONS, frameState, data)
|
||||
);
|
||||
requestAnimationFrame(this.changed.bind(this));
|
||||
if (frameState.animate) {
|
||||
requestAnimationFrame(this.changed.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
disposeInternal() {
|
||||
|
||||
@@ -219,7 +219,11 @@ class IconImage extends EventTarget {
|
||||
* @private
|
||||
*/
|
||||
replaceColor_(pixelRatio) {
|
||||
if (!this.color_ || this.canvas_[pixelRatio]) {
|
||||
if (
|
||||
!this.color_ ||
|
||||
this.canvas_[pixelRatio] ||
|
||||
this.imageState_ !== ImageState.LOADED
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ import {assert} from '../asserts.js';
|
||||
* @property {import("./Image.js").default} [image] Image style.
|
||||
* @property {RenderFunction} [renderer] Custom renderer. When configured, `fill`, `stroke` and `image` will be
|
||||
* ignored, and the provided function will be called with each render frame for each geometry.
|
||||
* @property {RenderFunction} [hitDetectionRenderer] Custom renderer for hit detection. If provided will be used
|
||||
* in hit detection rendering.
|
||||
* @property {import("./Stroke.js").default} [stroke] Stroke style.
|
||||
* @property {import("./Text.js").default} [text] Text style.
|
||||
* @property {number} [zIndex] Z index.
|
||||
@@ -186,6 +188,15 @@ class Style {
|
||||
*/
|
||||
this.renderer_ = options.renderer !== undefined ? options.renderer : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {RenderFunction|null}
|
||||
*/
|
||||
this.hitDetectionRenderer_ =
|
||||
options.hitDetectionRenderer !== undefined
|
||||
? options.hitDetectionRenderer
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./Stroke.js").default}
|
||||
@@ -248,6 +259,26 @@ class Style {
|
||||
this.renderer_ = renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom renderer function for this style used
|
||||
* in hit detection.
|
||||
* @param {RenderFunction|null} renderer Custom renderer function.
|
||||
* @api
|
||||
*/
|
||||
setHitDetectionRenderer(renderer) {
|
||||
this.hitDetectionRenderer_ = renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom renderer function that was configured with
|
||||
* {@link #setHitDetectionRenderer} or the `hitDetectionRenderer` constructor option.
|
||||
* @return {RenderFunction|null} Custom renderer function.
|
||||
* @api
|
||||
*/
|
||||
getHitDetectionRenderer() {
|
||||
return this.hitDetectionRenderer_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry to be rendered.
|
||||
* @return {string|import("../geom/Geometry.js").default|GeometryFunction}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,46 +734,82 @@ describe('ol/View', function () {
|
||||
expect(view.getAnimating()).to.eql(false);
|
||||
});
|
||||
|
||||
it('immediately completes if view is not defined before', function () {
|
||||
const view = new View();
|
||||
const center = [1, 2];
|
||||
const zoom = 3;
|
||||
const rotation = 0.4;
|
||||
describe('Set final animation state if view is not defined.', function () {
|
||||
it('immediately completes if view is not defined before', function () {
|
||||
const view = new View();
|
||||
const center = [1, 2];
|
||||
const zoom = 3;
|
||||
const rotation = 0.4;
|
||||
|
||||
view.animate({
|
||||
zoom: zoom,
|
||||
center: center,
|
||||
rotation: rotation,
|
||||
duration: 25,
|
||||
});
|
||||
expect(view.getAnimating()).to.eql(false);
|
||||
expect(view.getCenter()).to.eql(center);
|
||||
expect(view.getZoom()).to.eql(zoom);
|
||||
expect(view.getRotation()).to.eql(rotation);
|
||||
});
|
||||
|
||||
it('sets final animation state if view is not defined before', function () {
|
||||
const view = new View();
|
||||
|
||||
const center = [1, 2];
|
||||
const zoom = 3;
|
||||
const rotation = 0.4;
|
||||
|
||||
view.animate(
|
||||
{zoom: 1},
|
||||
{center: [2, 3]},
|
||||
{rotation: 4},
|
||||
{
|
||||
view.animate({
|
||||
zoom: zoom,
|
||||
center: center,
|
||||
rotation: rotation,
|
||||
duration: 25,
|
||||
}
|
||||
);
|
||||
expect(view.getAnimating()).to.eql(false);
|
||||
expect(view.getCenter()).to.eql(center);
|
||||
expect(view.getZoom()).to.eql(zoom);
|
||||
expect(view.getRotation()).to.eql(rotation);
|
||||
});
|
||||
expect(view.getAnimating()).to.eql(false);
|
||||
expect(view.getCenter()).to.eql(center);
|
||||
expect(view.getZoom()).to.eql(zoom);
|
||||
expect(view.getRotation()).to.eql(rotation);
|
||||
});
|
||||
|
||||
it('prefers zoom over resolution', function () {
|
||||
const view = new View();
|
||||
const zoom = 1;
|
||||
view.animate({
|
||||
center: [0, 0],
|
||||
zoom: zoom,
|
||||
resolution: 1,
|
||||
});
|
||||
expect(view.getZoom()).to.eql(zoom);
|
||||
});
|
||||
|
||||
it('uses all animation steps to get final state', function () {
|
||||
const view = new View();
|
||||
|
||||
const center = [1, 2];
|
||||
const resolution = 3;
|
||||
const rotation = 0.4;
|
||||
|
||||
view.animate(
|
||||
{center: [2, 3]},
|
||||
{
|
||||
center: center,
|
||||
rotation: 4,
|
||||
},
|
||||
{
|
||||
rotation: rotation,
|
||||
},
|
||||
{resolution: resolution}
|
||||
);
|
||||
expect(view.getAnimating()).to.be(false);
|
||||
expect(view.getCenter()).to.eql(center);
|
||||
expect(view.getResolution()).to.be(resolution);
|
||||
expect(view.getRotation()).to.be(rotation);
|
||||
});
|
||||
|
||||
it('animates remaining steps after it becomes defined', function () {
|
||||
const view = new View();
|
||||
|
||||
const center = [1, 2];
|
||||
const resolution = 3;
|
||||
|
||||
view.animate(
|
||||
{center: [2, 3]},
|
||||
{
|
||||
resolution: resolution,
|
||||
center: center,
|
||||
},
|
||||
{
|
||||
rotation: 2,
|
||||
duration: 25,
|
||||
}
|
||||
);
|
||||
expect(view.getAnimating()).to.be(true);
|
||||
expect(view.getCenter()).to.eql(center);
|
||||
expect(view.getResolution()).to.be(resolution);
|
||||
expect(view.getRotation()).to.be(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('prefers zoom over resolution', function (done) {
|
||||
|
||||
@@ -236,87 +236,193 @@ describe('ol.render.canvas.BuilderGroup', function () {
|
||||
expect(lineDashOffset).to.be(4);
|
||||
});
|
||||
|
||||
it('calls the renderer function configured for the style', function () {
|
||||
const calls = [];
|
||||
const style = new Style({
|
||||
renderer: function (coords, state) {
|
||||
calls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
describe('use renderer and hitDetectionRenderer defined in style', function () {
|
||||
let point, multipoint, linestring, multilinestring;
|
||||
let polygon, multipolygon, geometrycollection;
|
||||
|
||||
/**
|
||||
* @param {BuilderGroup} builder The builder to get instructions from.
|
||||
* @param {number} [pixelRatio] The pixel ratio.
|
||||
* @param {boolean} [overlaps] Whether there is overlaps.
|
||||
* @param {Array<number>} [coordinate] Used for hit detection.
|
||||
*/
|
||||
function executeHitDetectionForCoordinate(
|
||||
builder,
|
||||
pixelRatio,
|
||||
overlaps,
|
||||
coordinate
|
||||
) {
|
||||
const executor = new ExecutorGroup(
|
||||
[-180, -90, 180, 90],
|
||||
1,
|
||||
pixelRatio || 1,
|
||||
!!overlaps,
|
||||
builder.finish()
|
||||
);
|
||||
|
||||
executor.execute(context, 1, transform, 0, false);
|
||||
executor.forEachFeatureAtCoordinate(coordinate, 1, 0, 1, () => {});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
point = new Feature(new Point([45, 90]));
|
||||
multipoint = new Feature(
|
||||
new MultiPoint([
|
||||
[45, 90],
|
||||
[90, 45],
|
||||
])
|
||||
);
|
||||
linestring = new Feature(
|
||||
new LineString([
|
||||
[45, 90],
|
||||
[45, 45],
|
||||
[90, 45],
|
||||
])
|
||||
);
|
||||
multilinestring = new Feature(
|
||||
new MultiLineString([
|
||||
linestring.getGeometry().getCoordinates(),
|
||||
linestring.getGeometry().getCoordinates(),
|
||||
])
|
||||
);
|
||||
polygon = feature1;
|
||||
multipolygon = new Feature(
|
||||
new MultiPolygon([
|
||||
polygon.getGeometry().getCoordinates(),
|
||||
polygon.getGeometry().getCoordinates(),
|
||||
])
|
||||
);
|
||||
geometrycollection = new Feature(
|
||||
new GeometryCollection([
|
||||
point.getGeometry(),
|
||||
linestring.getGeometry(),
|
||||
polygon.getGeometry(),
|
||||
])
|
||||
);
|
||||
});
|
||||
it('calls the renderer function in hit detection', function () {
|
||||
const calls = [];
|
||||
const style = new Style({
|
||||
renderer: function (coords, state) {
|
||||
calls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
builder = new BuilderGroup(1, [-180, -90, 180, 90], 1, 1, true);
|
||||
renderFeature(builder, point, style, 1);
|
||||
renderFeature(builder, multipoint, style, 1);
|
||||
renderFeature(builder, linestring, style, 1);
|
||||
renderFeature(builder, multilinestring, style, 1);
|
||||
renderFeature(builder, polygon, style, 1);
|
||||
renderFeature(builder, multipolygon, style, 1);
|
||||
renderFeature(builder, geometrycollection, style, 1);
|
||||
scaleTransform(transform, 0.1, 0.1);
|
||||
executeHitDetectionForCoordinate(builder, 1, true, [45, 90]);
|
||||
|
||||
// since renderer will be used for rendering and hit detection
|
||||
// expect calls.length to be ass twice was in rendering
|
||||
expect(calls.length).to.be(18);
|
||||
});
|
||||
|
||||
it('calls the hit detection renderer in hit detection', function () {
|
||||
const calls = [];
|
||||
const hitDetectionCalls = [];
|
||||
const style = new Style({
|
||||
renderer: function (coords, state) {
|
||||
calls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
hitDetectionRenderer: function (coords, state) {
|
||||
hitDetectionCalls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
builder = new BuilderGroup(1, [-180, -90, 180, 90], 1, 1, true);
|
||||
renderFeature(builder, point, style, 1);
|
||||
renderFeature(builder, multipoint, style, 1);
|
||||
renderFeature(builder, linestring, style, 1);
|
||||
renderFeature(builder, multilinestring, style, 1);
|
||||
renderFeature(builder, polygon, style, 1);
|
||||
renderFeature(builder, multipolygon, style, 1);
|
||||
renderFeature(builder, geometrycollection, style, 1);
|
||||
scaleTransform(transform, 0.1, 0.1);
|
||||
executeHitDetectionForCoordinate(builder, 1, true, [45, 90]);
|
||||
expect(calls.length).to.be(9);
|
||||
expect(hitDetectionCalls.length).to.be(9);
|
||||
});
|
||||
|
||||
it('calls the renderer function configured for the style', function () {
|
||||
const calls = [];
|
||||
const style = new Style({
|
||||
renderer: function (coords, state) {
|
||||
calls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
builder = new BuilderGroup(1, [-180, -90, 180, 90], 1, 1, true);
|
||||
renderFeature(builder, point, style, 1);
|
||||
renderFeature(builder, multipoint, style, 1);
|
||||
renderFeature(builder, linestring, style, 1);
|
||||
renderFeature(builder, multilinestring, style, 1);
|
||||
renderFeature(builder, polygon, style, 1);
|
||||
renderFeature(builder, multipolygon, style, 1);
|
||||
renderFeature(builder, geometrycollection, style, 1);
|
||||
scaleTransform(transform, 0.1, 0.1);
|
||||
execute(builder, 1, true);
|
||||
expect(calls.length).to.be(9);
|
||||
expect(calls[0].geometry).to.be(point.getGeometry());
|
||||
expect(calls[0].feature).to.be(point);
|
||||
expect(calls[0].context).to.be(context);
|
||||
expect(calls[0].pixelRatio).to.be(1);
|
||||
expect(calls[0].rotation).to.be(0);
|
||||
expect(calls[0].resolution).to.be(1);
|
||||
expect(calls[0].coords).to.eql([4.5, 9]);
|
||||
expect(calls[1].feature).to.be(multipoint);
|
||||
expect(calls[1].coords[0]).to.eql([4.5, 9]);
|
||||
expect(calls[2].feature).to.be(linestring);
|
||||
expect(calls[2].coords[0]).to.eql([4.5, 9]);
|
||||
expect(calls[3].feature).to.be(multilinestring);
|
||||
expect(calls[3].coords[0][0]).to.eql([4.5, 9]);
|
||||
expect(calls[4].feature).to.be(polygon);
|
||||
expect(calls[4].coords[0][0]).to.eql([-9, -4.5]);
|
||||
expect(calls[5].feature).to.be(multipolygon);
|
||||
expect(calls[5].coords[0][0][0]).to.eql([-9, -4.5]);
|
||||
expect(calls[6].feature).to.be(geometrycollection);
|
||||
expect(calls[6].geometry.getCoordinates()).to.eql([45, 90]);
|
||||
expect(calls[7].geometry.getCoordinates()[0]).to.eql([45, 90]);
|
||||
expect(calls[8].geometry.getCoordinates()[0][0]).to.eql([-90, -45]);
|
||||
});
|
||||
const point = new Feature(new Point([45, 90]));
|
||||
const multipoint = new Feature(
|
||||
new MultiPoint([
|
||||
[45, 90],
|
||||
[90, 45],
|
||||
])
|
||||
);
|
||||
const linestring = new Feature(
|
||||
new LineString([
|
||||
[45, 90],
|
||||
[45, 45],
|
||||
[90, 45],
|
||||
])
|
||||
);
|
||||
const multilinestring = new Feature(
|
||||
new MultiLineString([
|
||||
linestring.getGeometry().getCoordinates(),
|
||||
linestring.getGeometry().getCoordinates(),
|
||||
])
|
||||
);
|
||||
const polygon = feature1;
|
||||
const multipolygon = new Feature(
|
||||
new MultiPolygon([
|
||||
polygon.getGeometry().getCoordinates(),
|
||||
polygon.getGeometry().getCoordinates(),
|
||||
])
|
||||
);
|
||||
const geometrycollection = new Feature(
|
||||
new GeometryCollection([
|
||||
point.getGeometry(),
|
||||
linestring.getGeometry(),
|
||||
polygon.getGeometry(),
|
||||
])
|
||||
);
|
||||
builder = new BuilderGroup(1, [-180, -90, 180, 90], 1, 1, true);
|
||||
renderFeature(builder, point, style, 1);
|
||||
renderFeature(builder, multipoint, style, 1);
|
||||
renderFeature(builder, linestring, style, 1);
|
||||
renderFeature(builder, multilinestring, style, 1);
|
||||
renderFeature(builder, polygon, style, 1);
|
||||
renderFeature(builder, multipolygon, style, 1);
|
||||
renderFeature(builder, geometrycollection, style, 1);
|
||||
scaleTransform(transform, 0.1, 0.1);
|
||||
execute(builder, 1, true);
|
||||
expect(calls.length).to.be(9);
|
||||
expect(calls[0].geometry).to.be(point.getGeometry());
|
||||
expect(calls[0].feature).to.be(point);
|
||||
expect(calls[0].context).to.be(context);
|
||||
expect(calls[0].pixelRatio).to.be(1);
|
||||
expect(calls[0].rotation).to.be(0);
|
||||
expect(calls[0].resolution).to.be(1);
|
||||
expect(calls[0].coords).to.eql([4.5, 9]);
|
||||
expect(calls[1].feature).to.be(multipoint);
|
||||
expect(calls[1].coords[0]).to.eql([4.5, 9]);
|
||||
expect(calls[2].feature).to.be(linestring);
|
||||
expect(calls[2].coords[0]).to.eql([4.5, 9]);
|
||||
expect(calls[3].feature).to.be(multilinestring);
|
||||
expect(calls[3].coords[0][0]).to.eql([4.5, 9]);
|
||||
expect(calls[4].feature).to.be(polygon);
|
||||
expect(calls[4].coords[0][0]).to.eql([-9, -4.5]);
|
||||
expect(calls[5].feature).to.be(multipolygon);
|
||||
expect(calls[5].coords[0][0][0]).to.eql([-9, -4.5]);
|
||||
expect(calls[6].feature).to.be(geometrycollection);
|
||||
expect(calls[6].geometry.getCoordinates()).to.eql([45, 90]);
|
||||
expect(calls[7].geometry.getCoordinates()[0]).to.eql([45, 90]);
|
||||
expect(calls[8].geometry.getCoordinates()[0][0]).to.eql([-90, -45]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import CanvasVectorImageLayerRenderer from '../../../../../../src/ol/renderer/canvas/VectorImageLayer.js';
|
||||
import Feature from '../../../../../../src/ol/Feature.js';
|
||||
import ImageCanvas from '../../../../../../src/ol/ImageCanvas.js';
|
||||
import Point from '../../../../../../src/ol/geom/Point.js';
|
||||
import VectorImageLayer from '../../../../../../src/ol/layer/VectorImage.js';
|
||||
import VectorSource from '../../../../../../src/ol/source/Vector.js';
|
||||
import {create} from '../../../../../../src/ol/transform.js';
|
||||
@@ -19,12 +22,19 @@ describe('ol/renderer/canvas/VectorImageLayer', function () {
|
||||
});
|
||||
|
||||
describe('#prepareFrame', function () {
|
||||
it('sets correct extent with imageRatio = 2', function () {
|
||||
const layer = new VectorImageLayer({
|
||||
/** @type {VectorImageLayer} */
|
||||
let layer;
|
||||
/** @type {CanvasVectorImageLayerRenderer} */
|
||||
let renderer;
|
||||
let frameState;
|
||||
this.beforeEach(function () {
|
||||
layer = new VectorImageLayer({
|
||||
imageRatio: 2,
|
||||
source: new VectorSource(),
|
||||
source: new VectorSource({
|
||||
features: [new Feature(new Point([0, 0]))],
|
||||
}),
|
||||
});
|
||||
const renderer = new CanvasVectorImageLayerRenderer(layer);
|
||||
renderer = new CanvasVectorImageLayerRenderer(layer);
|
||||
const projection = getProjection('EPSG:3857');
|
||||
const projExtent = projection.getExtent();
|
||||
const extent = [
|
||||
@@ -33,7 +43,7 @@ describe('ol/renderer/canvas/VectorImageLayer', function () {
|
||||
projExtent[0] + 10000,
|
||||
10000,
|
||||
];
|
||||
const frameState = {
|
||||
frameState = {
|
||||
layerStatesArray: [layer.getLayerState()],
|
||||
layerIndex: 0,
|
||||
extent: extent,
|
||||
@@ -46,12 +56,22 @@ describe('ol/renderer/canvas/VectorImageLayer', function () {
|
||||
rotation: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
it('sets image to null if no features are rendered', function () {
|
||||
renderer.prepareFrame(frameState);
|
||||
const expected = renderer.image_.getExtent();
|
||||
expect(renderer.image_).to.be.a(ImageCanvas);
|
||||
|
||||
layer.getSource().clear();
|
||||
renderer.prepareFrame(frameState);
|
||||
expect(renderer.image_).to.be(null);
|
||||
});
|
||||
it('sets correct extent with imageRatio = 2', function () {
|
||||
const extent = frameState.extent.slice();
|
||||
scaleFromCenter(extent, 2);
|
||||
|
||||
expect(expected).to.eql(extent);
|
||||
renderer.prepareFrame(frameState);
|
||||
const imageExtent = renderer.image_.getExtent();
|
||||
expect(imageExtent).to.eql(extent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ describe('ol/source/GeoTIFF', function () {
|
||||
});
|
||||
expect(source.readMethod_).to.be('readRasters');
|
||||
});
|
||||
|
||||
it('configures readMethod_ to read RGB', function () {
|
||||
const source = new GeoTIFFSource({
|
||||
convertToRGB: true,
|
||||
@@ -25,6 +26,37 @@ describe('ol/source/GeoTIFF', function () {
|
||||
});
|
||||
expect(source.readMethod_).to.be('readRGB');
|
||||
});
|
||||
|
||||
it('generates Float32Array data if normalize is set to false', (done) => {
|
||||
const source = new GeoTIFFSource({
|
||||
normalize: false,
|
||||
sources: [{url: 'spec/ol/source/images/0-0-0.tif'}],
|
||||
});
|
||||
source.on('change', () => {
|
||||
const tile = source.getTile(0, 0, 0);
|
||||
source.on('tileloadend', () => {
|
||||
expect(tile.getState()).to.be(TileState.LOADED);
|
||||
expect(tile.getData()).to.be.a(Float32Array);
|
||||
done();
|
||||
});
|
||||
tile.load();
|
||||
});
|
||||
});
|
||||
|
||||
it('generates Uint8Array data if normalize is not set to false', (done) => {
|
||||
const source = new GeoTIFFSource({
|
||||
sources: [{url: 'spec/ol/source/images/0-0-0.tif'}],
|
||||
});
|
||||
source.on('change', () => {
|
||||
const tile = source.getTile(0, 0, 0);
|
||||
source.on('tileloadend', () => {
|
||||
expect(tile.getState()).to.be(TileState.LOADED);
|
||||
expect(tile.getData()).to.be.a(Uint8Array);
|
||||
done();
|
||||
});
|
||||
tile.load();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('loading', function () {
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017
|
||||
},
|
||||
"globals": {
|
||||
"render": false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user