Compare commits

...

53 Commits

Author SHA1 Message Date
Tim Schaub
d7acbc40d5 Changes for 6.0.1 2019-09-30 12:35:08 -06:00
Olivier Guyot
176dccd6df Merge pull request #10060 from mike-000/patch-1
Ensure zoom level is not less than minimum integer zoom level for extent
2019-09-30 17:34:45 +02:00
Tim Schaub
526679433e Merge pull request #10045 from tschaub/immediate-geographic
Make the immediate API work with a user projection
2019-09-30 09:27:40 -06:00
Tim Schaub
b64ab8a6b2 Rendering test for immediate API with geographic coordinates 2019-09-30 08:52:07 -06:00
Tim Schaub
6c6c4ab1df Mark example as experimental 2019-09-30 08:45:44 -06:00
Tim Schaub
d3b47c794e Make the immediate API work with a user projection 2019-09-30 08:28:50 -06:00
Andreas Hocevar
8aa4a59fcf Merge pull request #10068 from ahocevar/jsdoc-plugin
Update jsdoc-plugin-typescript to 2.0.3
2019-09-30 08:47:07 +02:00
Andreas Hocevar
61e8b39626 Update jsdoc-plugin-typescript to 2.0.3 2019-09-29 21:46:50 +02:00
Tim Schaub
8c7aafd4df Merge pull request #10063 from tschaub/does-not-throw
Use the same spelling used elsewhere
2019-09-29 14:38:48 -05:00
Andreas Hocevar
37f9a6a6e9 Merge pull request #10067 from KlausBenndorf/jsdoc-event-annotations
fixed jsdoc type annotations
2019-09-29 20:02:24 +02:00
Simon Seyock
2e1dee1994 fixed jsdoc type annotations 2019-09-29 19:35:11 +02:00
Tim Schaub
ec9dcbee88 Merge pull request #10065 from openlayers/greenkeeper/mocha-6.2.1
Update mocha to the latest version 🚀
2019-09-29 10:36:09 -05:00
Tim Schaub
211c2ee531 Merge pull request #10064 from openlayers/greenkeeper/handlebars-4.4.0
Update handlebars to the latest version 🚀
2019-09-29 09:21:00 -05:00
greenkeeper[bot]
e1d3560dbf chore(package): update lockfile package-lock.json 2019-09-29 14:14:51 +00:00
greenkeeper[bot]
1d6284725d chore(package): update mocha to version 6.2.1 2019-09-29 14:14:39 +00:00
greenkeeper[bot]
c69201d5ad chore(package): update lockfile package-lock.json 2019-09-29 13:32:46 +00:00
greenkeeper[bot]
92e025b8e5 chore(package): update handlebars to version 4.4.0 2019-09-29 13:32:42 +00:00
Tim Schaub
7c8b2215d4 Remove unused code 2019-09-29 07:05:48 -06:00
Tim Schaub
d2b25533c2 Use the same spelling used elsewhere 2019-09-29 07:37:45 -05:00
mike-000
733b883ac0 Correct expected result to reflect #10054
Correct world extent constrained resolution test to expect integer zoom level
2019-09-29 12:19:42 +01:00
mike-000
eaa5af2c7a Fix for #10054
Ensure zoom level is not less than minimum integer zoom level for extent
2019-09-29 12:00:08 +01:00
Tim Schaub
1260dfc153 Merge pull request #10057 from tschaub/fewer-extensions
Remove unused test extensions
2019-09-28 19:02:02 -05:00
Tim Schaub
76df721b98 Merge pull request #10056 from tschaub/uncalled
Remove called assert extension
2019-09-28 19:01:15 -05:00
Andreas Hocevar
a55fec2759 Merge pull request #10055 from ahocevar/ensure-tile-load-sequence
Ensure proper tile load sequence
2019-09-29 01:34:59 +02:00
Tim Schaub
c984b28752 Remove unused test extensions 2019-09-28 12:02:48 -05:00
Tim Schaub
3b02f5597e Remove called assert extension 2019-09-28 18:55:38 +02:00
Andreas Hocevar
40f8510083 Merge pull request #10052 from openlayers/greenkeeper/handlebars-4.3.4
Update handlebars to the latest version 🚀
2019-09-28 15:33:38 +02:00
Andreas Hocevar
7f8fdd6219 Ensure proper tile load sequence 2019-09-28 15:24:37 +02:00
greenkeeper[bot]
ea0e1bff29 chore(package): update lockfile package-lock.json 2019-09-28 11:39:45 +00:00
greenkeeper[bot]
9b2089bc8f chore(package): update handlebars to version 4.3.4 2019-09-28 11:39:41 +00:00
Tim Schaub
32644c7ba9 Merge pull request #10051 from tschaub/unchained
Simplify the assertion
2019-09-28 08:17:09 +02:00
Tim Schaub
80b4f51d6e Merge pull request #10050 from tschaub/expect-fail
Use expect().fail() instead of expect.fail()
2019-09-28 08:15:42 +02:00
Tim Schaub
c8456868bd Simplify the assertion 2019-09-27 23:49:57 +02:00
Tim Schaub
239f5745c1 Correct fail 2019-09-27 23:23:24 +02:00
Andreas Hocevar
70706443f5 Merge pull request #10048 from ahocevar/early-empty-state
Early EMPTY state for VectorRenderTile
2019-09-27 22:29:42 +02:00
Andreas Hocevar
47dd60104d Set EMPTY state of VectorRenderTile early 2019-09-27 19:04:21 +02:00
Tim Schaub
80cf76e783 Merge pull request #10043 from tschaub/snap-geographic
User coordinates during snapping
2019-09-27 17:20:16 +02:00
Frédéric Junod
a7605c7447 Merge pull request #10042 from fredj/better_typing
Better typing
2019-09-27 16:39:26 +02:00
Andreas Hocevar
76af2b6466 Revert "Handle empty source tiles and queue them properly"
This reverts commit 818bdc411c.
2019-09-27 16:09:27 +02:00
Tim Schaub
a996d62d46 Test snap with geographic coordinates 2019-09-27 14:12:10 +02:00
Frederic Junod
f67476dd8f Mark properties as nullable 2019-09-27 13:57:59 +02:00
Frederic Junod
0e402073da Add more typecast for typescript 2019-09-27 13:11:30 +02:00
Tim Schaub
07678d960a User coordinates during snapping 2019-09-27 11:55:48 +02:00
Andreas Hocevar
a47025b9c9 Merge pull request #10040 from ahocevar/test-getclosestpoint
Additional tests for LineString
2019-09-27 11:22:29 +02:00
Andreas Hocevar
99c56a1f08 Additional tests for LineString 2019-09-27 11:10:14 +02:00
Frederic Junod
701dc3b54a Use the right variable to get the hitTolerance value 2019-09-27 11:03:21 +02:00
Frederic Junod
ea88e6cbd4 Remove invalid undefined type in params 2019-09-27 11:01:50 +02:00
Tim Schaub
b40709ea5b Merge pull request #10041 from openlayers/greenkeeper/handlebars-4.3.2
Update handlebars to the latest version 🚀
2019-09-27 09:07:09 +02:00
greenkeeper[bot]
20de880d2b chore(package): update lockfile package-lock.json 2019-09-26 22:21:37 +00:00
greenkeeper[bot]
1827d7a0d9 chore(package): update handlebars to version 4.3.2 2019-09-26 22:21:32 +00:00
Tim Schaub
400667fe95 Merge pull request #10038 from KlausBenndorf/stalebot
do not stale issues with `bug` or `pull request accepted` labels
2019-09-26 23:48:57 +02:00
Tim Schaub
d0a1fdc1d2 Merge pull request #10039 from openlayers/release-v6.0.0
🚀 Release 6
2019-09-26 23:33:42 +02:00
Simon Seyock
dd1243db73 do not stale issues with bug or pull request accepted labels 2019-09-26 22:31:37 +02:00
63 changed files with 719 additions and 452 deletions

2
.github/stale.yml vendored
View File

@@ -6,6 +6,8 @@ daysUntilClose: 7
exemptLabels: exemptLabels:
- blocker - blocker
- regression - regression
- bug
- 'pull request accepted'
# Label to use when marking an issue as stale # Label to use when marking an issue as stale
staleLabel: stale staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable # Comment to post when marking an issue as stale. Set to `false` to disable

34
changelog/v6.0.1.md Normal file
View File

@@ -0,0 +1,34 @@
# 6.0.1
Hot on the heels of the 6.0 release, this patch release includes a few fixes for existing functionality. There should be nothing special needed to upgrade an application from 6.0.0 to 6.0.1. See the 6.0.0 release notes for details on upgrading from an older version.
## Changes
* [#10060](https://github.com/openlayers/openlayers/pull/10060) - Ensure zoom level is not less than minimum integer zoom level for extent ([@mike-000](https://github.com/mike-000))
* [#10045](https://github.com/openlayers/openlayers/pull/10045) - Make the immediate API work with a user projection ([@tschaub](https://github.com/tschaub))
* [#10068](https://github.com/openlayers/openlayers/pull/10068) - Update jsdoc-plugin-typescript to 2.0.3 ([@ahocevar](https://github.com/ahocevar))
* [#10063](https://github.com/openlayers/openlayers/pull/10063) - Use the same spelling used elsewhere ([@tschaub](https://github.com/tschaub))
* [#10067](https://github.com/openlayers/openlayers/pull/10067) - fixed jsdoc type annotations ([@KlausBenndorf](https://github.com/KlausBenndorf))
* [#10057](https://github.com/openlayers/openlayers/pull/10057) - Remove unused test extensions ([@tschaub](https://github.com/tschaub))
* [#10056](https://github.com/openlayers/openlayers/pull/10056) - Remove called assert extension ([@tschaub](https://github.com/tschaub))
* [#10055](https://github.com/openlayers/openlayers/pull/10055) - Ensure proper tile load sequence ([@ahocevar](https://github.com/ahocevar))
* [#10051](https://github.com/openlayers/openlayers/pull/10051) - Simplify the assertion ([@tschaub](https://github.com/tschaub))
* [#10050](https://github.com/openlayers/openlayers/pull/10050) - Use expect().fail() instead of expect.fail() ([@tschaub](https://github.com/tschaub))
* [#10048](https://github.com/openlayers/openlayers/pull/10048) - Early EMPTY state for VectorRenderTile ([@ahocevar](https://github.com/ahocevar))
* [#10043](https://github.com/openlayers/openlayers/pull/10043) - User coordinates during snapping ([@tschaub](https://github.com/tschaub))
* [#10042](https://github.com/openlayers/openlayers/pull/10042) - Better typing ([@fredj](https://github.com/fredj))
* [#10040](https://github.com/openlayers/openlayers/pull/10040) - Additional tests for LineString ([@ahocevar](https://github.com/ahocevar))
* [#10038](https://github.com/openlayers/openlayers/pull/10038) - do not stale issues with `bug` or `pull request accepted` labels ([@KlausBenndorf](https://github.com/KlausBenndorf))
* [#10039](https://github.com/openlayers/openlayers/pull/10039) - 🚀 Release 6 ([@openlayers](https://github.com/openlayers))
<details>
<summary>Dependency Updates</summary>
* [#10065](https://github.com/openlayers/openlayers/pull/10065) - Update mocha to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
* [#10064](https://github.com/openlayers/openlayers/pull/10064) - Update handlebars to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
* [#10052](https://github.com/openlayers/openlayers/pull/10052) - Update handlebars to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
* [#10041](https://github.com/openlayers/openlayers/pull/10041) - Update handlebars to the latest version 🚀 ([@openlayers](https://github.com/openlayers))
</details>

View File

@@ -1,6 +1,6 @@
import {Map, View} from '../src/ol/index.js'; import {Map, View} from '../src/ol/index.js';
import GeoJSON from '../src/ol/format/GeoJSON.js'; import GeoJSON from '../src/ol/format/GeoJSON.js';
import {Modify, Select, Draw} from '../src/ol/interaction.js'; import {Modify, Select, Draw, Snap} from '../src/ol/interaction.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js'; import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js'; import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {useGeographic} from '../src/ol/proj.js'; import {useGeographic} from '../src/ol/proj.js';
@@ -39,19 +39,30 @@ const draw = new Draw({
source: source source: source
}); });
const snap = new Snap({
source: source
});
function removeInteractions() {
map.removeInteraction(modify);
map.removeInteraction(select);
map.removeInteraction(draw);
map.removeInteraction(select);
}
const mode = document.getElementById('mode'); const mode = document.getElementById('mode');
function onChange() { function onChange() {
removeInteractions();
switch (mode.value) { switch (mode.value) {
case 'draw': { case 'draw': {
map.removeInteraction(modify);
map.removeInteraction(select);
map.addInteraction(draw); map.addInteraction(draw);
map.addInteraction(snap);
break; break;
} }
case 'modify': { case 'modify': {
map.removeInteraction(draw);
map.addInteraction(select); map.addInteraction(select);
map.addInteraction(modify); map.addInteraction(modify);
map.addInteraction(snap);
break; break;
} }
default: { default: {

View File

@@ -0,0 +1,15 @@
---
layout: example.html
title: Immediate Rendering (Geographic)
shortdesc: Using the immediate rendering API with geometries in geographic coordinates.
docs: >
This example uses the "immediate" rendering API with geometries in geographic coordinates.
The immediate rendering API lets you draw styled geometries without adding them to a layer first.
Use the `getVectorContext` function to create a rendering context from a render event. Using the
`context.drawGeometry()` and `context.setStyle()` methods on this rendering context, you can draw
any geometry on each render frame. The `useGeographic` function is used in this example so that
geometries can be in geographic coordinates.
tags: "immediate, geographic"
experimental: true
---
<div id="map" class="map"></div>

View File

@@ -0,0 +1,64 @@
import {Map, View} from '../src/ol/index.js';
import {Point} from '../src/ol/geom.js';
import TileLayer from '../src/ol/layer/Tile.js';
import Stamen from '../src/ol/source/Stamen.js';
import {Circle, Fill, Style} from '../src/ol/style.js';
import {getVectorContext} from '../src/ol/render.js';
import {useGeographic} from '../src/ol/proj.js';
import {upAndDown} from '../src/ol/easing.js';
useGeographic();
const layer = new TileLayer({
source: new Stamen({
layer: 'toner'
})
});
const map = new Map({
layers: [layer],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2
})
});
const image = new Circle({
radius: 8,
fill: new Fill({color: 'rgb(255, 153, 0)'})
});
const style = new Style({
image: image
});
const n = 1000;
const geometries = new Array(n);
for (let i = 0; i < n; ++i) {
const lon = 360 * Math.random() - 180;
const lat = 180 * Math.random() - 90;
geometries[i] = new Point([lon, lat]);
}
layer.on('postrender', function(event) {
const vectorContext = getVectorContext(event);
for (let i = 0; i < n; ++i) {
const importance = upAndDown(Math.pow((n - i) / n, 0.15));
if (importance < 0.1) {
continue;
}
image.setOpacity(importance);
image.setScale(importance);
vectorContext.setStyle(style);
vectorContext.drawGeometry(geometries[i]);
}
const lon = 360 * Math.random() - 180;
const lat = 180 * Math.random() - 90;
geometries.push(new Point([lon, lat]));
geometries.shift();
map.render();
});

171
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "ol", "name": "ol",
"version": "6.0.0-beta.15", "version": "6.0.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@@ -5349,9 +5349,9 @@
"dev": true "dev": true
}, },
"handlebars": { "handlebars": {
"version": "4.3.1", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.3.1.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.0.tgz",
"integrity": "sha512-c0HoNHzDiHpBt4Kqe99N8tdLPKAnGCQ73gYMPWtAYM4PwGnf7xl8PBUHJqh9ijlzt2uQKaSRxbXRt+rZ7M2/kA==", "integrity": "sha512-xkRtOt3/3DzTKMOt3xahj2M/EqNhY988T+imYSlMgs5fVhLN2fmKVVj0LtEGmb+3UUYV5Qmm1052Mm3dIQxOvw==",
"dev": true, "dev": true,
"requires": { "requires": {
"neo-async": "^2.6.0", "neo-async": "^2.6.0",
@@ -6455,9 +6455,9 @@
} }
}, },
"jsdoc-plugin-typescript": { "jsdoc-plugin-typescript": {
"version": "2.0.2", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/jsdoc-plugin-typescript/-/jsdoc-plugin-typescript-2.0.2.tgz", "resolved": "https://registry.npmjs.org/jsdoc-plugin-typescript/-/jsdoc-plugin-typescript-2.0.3.tgz",
"integrity": "sha512-4/SveLQzTCkcQFfx9bDtVNRASmpv9E7iKncbSPkjnb+tm+9qHhCkF1Ewml3vBKZKU58LgW1zUsn4JYRlowP7NQ==", "integrity": "sha512-pcAHwWRyui9kUQ06L36Uyxw2m0Iy5dXqt/rGDg3cKj+2NSDZGeuw+TlbIURBJBpAkWi43zwojTtYpXo30vQJ+A==",
"dev": true "dev": true
}, },
"jsesc": { "jsesc": {
@@ -7298,9 +7298,9 @@
} }
}, },
"mocha": { "mocha": {
"version": "6.2.0", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.1.tgz",
"integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", "integrity": "sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A==",
"dev": true, "dev": true,
"requires": { "requires": {
"ansi-colors": "3.2.3", "ansi-colors": "3.2.3",
@@ -7323,9 +7323,9 @@
"supports-color": "6.0.0", "supports-color": "6.0.0",
"which": "1.3.1", "which": "1.3.1",
"wide-align": "1.1.3", "wide-align": "1.1.3",
"yargs": "13.2.2", "yargs": "13.3.0",
"yargs-parser": "13.0.0", "yargs-parser": "13.1.1",
"yargs-unparser": "1.5.0" "yargs-unparser": "1.6.0"
}, },
"dependencies": { "dependencies": {
"ansi-colors": { "ansi-colors": {
@@ -7340,6 +7340,17 @@
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true "dev": true
}, },
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true,
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
}
},
"debug": { "debug": {
"version": "3.2.6", "version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
@@ -7392,23 +7403,33 @@
"has-flag": "^3.0.0" "has-flag": "^3.0.0"
} }
}, },
"yargs": { "wrap-ansi": {
"version": "13.2.2", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"cliui": "^4.0.0", "ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}
},
"yargs": {
"version": "13.3.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
"integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
"dev": true,
"requires": {
"cliui": "^5.0.0",
"find-up": "^3.0.0", "find-up": "^3.0.0",
"get-caller-file": "^2.0.1", "get-caller-file": "^2.0.1",
"os-locale": "^3.1.0",
"require-directory": "^2.1.1", "require-directory": "^2.1.1",
"require-main-filename": "^2.0.0", "require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0", "set-blocking": "^2.0.0",
"string-width": "^3.0.0", "string-width": "^3.0.0",
"which-module": "^2.0.0", "which-module": "^2.0.0",
"y18n": "^4.0.0", "y18n": "^4.0.0",
"yargs-parser": "^13.0.0" "yargs-parser": "^13.1.1"
} }
} }
} }
@@ -11368,9 +11389,9 @@
} }
}, },
"yargs-parser": { "yargs-parser": {
"version": "13.0.0", "version": "13.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
"integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"camelcase": "^5.0.0", "camelcase": "^5.0.0",
@@ -11386,62 +11407,80 @@
} }
}, },
"yargs-unparser": { "yargs-unparser": {
"version": "1.5.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
"integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
"dev": true, "dev": true,
"requires": { "requires": {
"flat": "^4.1.0", "flat": "^4.1.0",
"lodash": "^4.17.11", "lodash": "^4.17.15",
"yargs": "^12.0.5" "yargs": "^13.3.0"
}, },
"dependencies": { "dependencies": {
"camelcase": { "ansi-regex": {
"version": "5.3.1", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true "dev": true
}, },
"get-caller-file": { "cliui": {
"version": "1.0.3", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true
},
"require-main-filename": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true
},
"yargs": {
"version": "12.0.5",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
"integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
"dev": true, "dev": true,
"requires": { "requires": {
"cliui": "^4.0.0", "string-width": "^3.1.0",
"decamelize": "^1.2.0", "strip-ansi": "^5.2.0",
"find-up": "^3.0.0", "wrap-ansi": "^5.1.0"
"get-caller-file": "^1.0.1",
"os-locale": "^3.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1 || ^4.0.0",
"yargs-parser": "^11.1.1"
} }
}, },
"yargs-parser": { "string-width": {
"version": "11.1.1", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true, "dev": true,
"requires": { "requires": {
"camelcase": "^5.0.0", "emoji-regex": "^7.0.1",
"decamelize": "^1.2.0" "is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}
},
"yargs": {
"version": "13.3.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
"integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
"dev": true,
"requires": {
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.1"
} }
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "ol", "name": "ol",
"version": "6.0.0", "version": "6.0.1",
"description": "OpenLayers mapping library", "description": "OpenLayers mapping library",
"keywords": [ "keywords": [
"map", "map",
@@ -63,13 +63,13 @@
"fs-extra": "^8.0.0", "fs-extra": "^8.0.0",
"glob": "^7.1.4", "glob": "^7.1.4",
"globby": "^10.0.0", "globby": "^10.0.0",
"handlebars": "4.3.1", "handlebars": "4.4.0",
"html-to-image": "^0.1.0", "html-to-image": "^0.1.0",
"istanbul": "0.4.5", "istanbul": "0.4.5",
"istanbul-instrumenter-loader": "^3.0.1", "istanbul-instrumenter-loader": "^3.0.1",
"jquery": "3.4.1", "jquery": "3.4.1",
"jsdoc": "3.6.3", "jsdoc": "3.6.3",
"jsdoc-plugin-typescript": "^2.0.2", "jsdoc-plugin-typescript": "2.0.3",
"karma": "^4.1.0", "karma": "^4.1.0",
"karma-chrome-launcher": "3.1.0", "karma-chrome-launcher": "3.1.0",
"karma-coverage": "^2.0.1", "karma-coverage": "^2.0.1",
@@ -80,7 +80,7 @@
"karma-webpack": "^4.0.0-rc.2", "karma-webpack": "^4.0.0-rc.2",
"loglevelnext": "^3.0.1", "loglevelnext": "^3.0.1",
"marked": "0.7.0", "marked": "0.7.0",
"mocha": "6.2.0", "mocha": "6.2.1",
"ol-mapbox-style": "^5.0.0-beta.3", "ol-mapbox-style": "^5.0.0-beta.3",
"pixelmatch": "^5.0.0", "pixelmatch": "^5.0.0",
"pngjs": "^3.4.0", "pngjs": "^3.4.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -0,0 +1,40 @@
import {Map, View} from '../../../src/ol/index.js';
import {Point} from '../../../src/ol/geom.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import {useGeographic} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import {Style, Circle, Fill} from '../../../src/ol/style.js';
import {getVectorContext} from '../../../src/ol/render.js';
useGeographic();
const center = [8.6, 50.1];
const layer = new TileLayer({
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
transition: 0
})
});
layer.on('postrender', event => {
const context = getVectorContext(event);
context.setStyle(new Style({
image: new Circle({
radius: 5,
fill: new Fill({color: 'red'})
})
}));
context.drawGeometry(new Point(center));
});
new Map({
target: 'map',
layers: [layer],
view: new View({
center: center,
zoom: 3
})
});
render();

View File

@@ -231,7 +231,7 @@ class Feature extends BaseObject {
* styles. If it is `null` the feature has no style (a `null` style). * styles. If it is `null` the feature has no style (a `null` style).
* @param {import("./style/Style.js").StyleLike} style Style for this feature. * @param {import("./style/Style.js").StyleLike} style Style for this feature.
* @api * @api
* @fires module:ol/events/Event~Event#event:change * @fires module:ol/events/Event~BaseEvent#event:change
*/ */
setStyle(style) { setStyle(style) {
this.style_ = style; this.style_ = style;
@@ -246,7 +246,7 @@ class Feature extends BaseObject {
* {@link module:ol/source/Vector~VectorSource#getFeatureById} method. * {@link module:ol/source/Vector~VectorSource#getFeatureById} method.
* @param {number|string|undefined} id The feature id. * @param {number|string|undefined} id The feature id.
* @api * @api
* @fires module:ol/events/Event~Event#event:change * @fires module:ol/events/Event~BaseEvent#event:change
*/ */
setId(id) { setId(id) {
this.id_ = id; this.id_ = id;

View File

@@ -81,7 +81,7 @@ class GeolocationError extends BaseEvent {
* window.console.log(geolocation.getPosition()); * window.console.log(geolocation.getPosition());
* }); * });
* *
* @fires module:ol/events/Event~Event#event:error * @fires module:ol/events/Event~BaseEvent#event:error
* @api * @api
*/ */
class Geolocation extends BaseObject { class Geolocation extends BaseObject {
@@ -98,7 +98,7 @@ class Geolocation extends BaseObject {
/** /**
* The unprojected (EPSG:4326) device position. * The unprojected (EPSG:4326) device position.
* @private * @private
* @type {import("./coordinate.js").Coordinate} * @type {?import("./coordinate.js").Coordinate}
*/ */
this.position_ = null; this.position_ = null;

View File

@@ -59,7 +59,7 @@ class ImageWrapper extends ImageBase {
/** /**
* @private * @private
* @type {function():void} * @type {?function():void}
*/ */
this.unlisten_ = null; this.unlisten_ = null;

View File

@@ -46,7 +46,7 @@ class ImageTile extends Tile {
/** /**
* @private * @private
* @type {function():void} * @type {?function():void}
*/ */
this.unlisten_ = null; this.unlisten_ = null;

View File

@@ -31,13 +31,13 @@ class MapBrowserEvent extends MapEvent {
/** /**
* The map pixel relative to the viewport corresponding to the original browser event. * The map pixel relative to the viewport corresponding to the original browser event.
* @type {import("./pixel.js").Pixel} * @type {?import("./pixel.js").Pixel}
*/ */
this.pixel_ = null; this.pixel_ = null;
/** /**
* The coordinate in the user projection corresponding to the original browser event. * The coordinate in the user projection corresponding to the original browser event.
* @type {import("./coordinate.js").Coordinate} * @type {?import("./coordinate.js").Coordinate}
*/ */
this.coordinate_ = null; this.coordinate_ = null;

View File

@@ -13,7 +13,7 @@ import EventType from './events/EventType.js';
* and unregistration. A generic `change` event is always available through * and unregistration. A generic `change` event is always available through
* {@link module:ol/Observable~Observable#changed}. * {@link module:ol/Observable~Observable#changed}.
* *
* @fires import("./events/Event.js").Event * @fires import("./events/Event.js").default
* @api * @api
*/ */
class Observable extends EventTarget { class Observable extends EventTarget {

View File

@@ -436,8 +436,8 @@ class Overlay extends BaseObject {
/** /**
* Get the extent of an element relative to the document * Get the extent of an element relative to the document
* @param {HTMLElement|undefined} element The element. * @param {HTMLElement} element The element.
* @param {import("./size.js").Size|undefined} size The size of the element. * @param {import("./size.js").Size} size The size of the element.
* @return {import("./extent.js").Extent} The extent. * @return {import("./extent.js").Extent} The extent.
* @protected * @protected
*/ */

View File

@@ -232,7 +232,7 @@ class PluggableMap extends BaseObject {
/** /**
* @private * @private
* @type {Array<import("./events.js").EventsKey>} * @type {?Array<import("./events.js").EventsKey>}
*/ */
this.layerGroupPropertyListenerKeys_ = null; this.layerGroupPropertyListenerKeys_ = null;
@@ -292,7 +292,7 @@ class PluggableMap extends BaseObject {
/** /**
* @private * @private
* @type {Array<import("./events.js").EventsKey>} * @type {?Array<import("./events.js").EventsKey>}
*/ */
this.keyHandlerKeys_ = null; this.keyHandlerKeys_ = null;
@@ -375,9 +375,9 @@ class PluggableMap extends BaseObject {
* @param {import("./control/Control.js").default} control Control. * @param {import("./control/Control.js").default} control Control.
* @this {PluggableMap} * @this {PluggableMap}
*/ */
(function(control) { function(control) {
control.setMap(this); control.setMap(this);
}).bind(this)); }.bind(this));
this.controls.addEventListener(CollectionEventType.ADD, this.controls.addEventListener(CollectionEventType.ADD,
/** /**
@@ -400,9 +400,9 @@ class PluggableMap extends BaseObject {
* @param {import("./interaction/Interaction.js").default} interaction Interaction. * @param {import("./interaction/Interaction.js").default} interaction Interaction.
* @this {PluggableMap} * @this {PluggableMap}
*/ */
(function(interaction) { function(interaction) {
interaction.setMap(this); interaction.setMap(this);
}).bind(this)); }.bind(this));
this.interactions.addEventListener(CollectionEventType.ADD, this.interactions.addEventListener(CollectionEventType.ADD,
/** /**
@@ -604,7 +604,7 @@ class PluggableMap extends BaseObject {
} }
const options = opt_options || /** @type {AtPixelOptions} */ ({}); const options = opt_options || /** @type {AtPixelOptions} */ ({});
const hitTolerance = options.hitTolerance !== undefined ? const hitTolerance = options.hitTolerance !== undefined ?
opt_options.hitTolerance * this.frameState_.pixelRatio : 0; options.hitTolerance * this.frameState_.pixelRatio : 0;
const layerFilter = options.layerFilter || TRUE; const layerFilter = options.layerFilter || TRUE;
return this.renderer_.forEachLayerAtPixel(pixel, this.frameState_, hitTolerance, callback, layerFilter); return this.renderer_.forEachLayerAtPixel(pixel, this.frameState_, hitTolerance, callback, layerFilter);
} }

View File

@@ -241,6 +241,9 @@ class Tile extends EventTarget {
* @api * @api
*/ */
setState(state) { setState(state) {
if (this.state !== TileState.ERROR && this.state > state) {
throw new Error('Tile load sequence violation');
}
this.state = state; this.state = state;
this.changed(); this.changed();
} }

View File

@@ -112,12 +112,10 @@ class TileQueue extends PriorityQueue {
if (state === TileState.ABORT) { if (state === TileState.ABORT) {
abortedTiles = true; abortedTiles = true;
} else if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) { } else if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
this.tilesLoadingKeys_[tileKey] = true;
++this.tilesLoading_;
++newLoads;
tile.load(); tile.load();
if (tile.getState() === TileState.LOADING) {
this.tilesLoadingKeys_[tileKey] = true;
++this.tilesLoading_;
++newLoads;
}
} }
} }
if (newLoads === 0 && abortedTiles) { if (newLoads === 0 && abortedTiles) {

View File

@@ -97,7 +97,7 @@ class MousePosition extends Control {
/** /**
* @private * @private
* @type {import("../proj/Projection.js").default} * @type {?import("../proj/Projection.js").default}
*/ */
this.mapProjection_ = null; this.mapProjection_ = null;

View File

@@ -41,7 +41,7 @@ class ZoomToExtent extends Control {
}); });
/** /**
* @type {import("../extent.js").Extent} * @type {?import("../extent.js").Extent}
* @protected * @protected
*/ */
this.extent = options.extent ? options.extent : null; this.extent = options.extent ? options.extent : null;

View File

@@ -72,6 +72,9 @@ export const CLASS_COLLAPSED = 'ol-collapsed';
* @return {FontParameters} The font families (or null if the input spec is invalid). * @return {FontParameters} The font families (or null if the input spec is invalid).
*/ */
export const getFontParameters = (function() { export const getFontParameters = (function() {
/**
* @type {CSSStyleDeclaration}
*/
let style; let style;
/** /**
* @type {Object<string, FontParameters>} * @type {Object<string, FontParameters>}

View File

@@ -9,14 +9,14 @@
export default { export default {
/** /**
* Generic change event. Triggered when the revision counter is increased. * Generic change event. Triggered when the revision counter is increased.
* @event module:ol/events/Event~Event#change * @event module:ol/events/Event~BaseEvent#change
* @api * @api
*/ */
CHANGE: 'change', CHANGE: 'change',
/** /**
* Generic error event. Triggered when an error occurs. * Generic error event. Triggered when an error occurs.
* @event module:ol/events/Event~Event#error * @event module:ol/events/Event~BaseEvent#error
* @api * @api
*/ */
ERROR: 'error', ERROR: 'error',

View File

@@ -73,7 +73,7 @@ class TopoJSON extends JSONFeature {
/** /**
* @private * @private
* @type {Array<string>} * @type {?Array<string>}
*/ */
this.layers_ = options.layers ? options.layers : null; this.layers_ = options.layers ? options.layers : null;

View File

@@ -5,7 +5,7 @@ import {abstract} from '../util.js';
import BaseObject from '../Object.js'; import BaseObject from '../Object.js';
import {createEmpty, getHeight, returnOrUpdate} from '../extent.js'; import {createEmpty, getHeight, returnOrUpdate} from '../extent.js';
import {transform2D} from './flat/transform.js'; import {transform2D} from './flat/transform.js';
import {get as getProjection, getTransform, getTransformFromProjections} from '../proj.js'; import {get as getProjection, getTransform} from '../proj.js';
import Units from '../proj/Units.js'; import Units from '../proj/Units.js';
import {create as createTransform, compose as composeTransform} from '../transform.js'; import {create as createTransform, compose as composeTransform} from '../transform.js';
import {memoizeOne} from '../functions.js'; import {memoizeOne} from '../functions.js';
@@ -62,17 +62,15 @@ class Geometry extends BaseObject {
* @abstract * @abstract
* @param {number} revision The geometry revision. * @param {number} revision The geometry revision.
* @param {number} squaredTolerance Squared tolerance. * @param {number} squaredTolerance Squared tolerance.
* @param {import("../proj/Projection.js").default} [sourceProjection] The source projection. * @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.
* @param {import("../proj/Projection.js").default} [destProjection] The destination projection.
* @return {Geometry} Simplified geometry. * @return {Geometry} Simplified geometry.
*/ */
this.simplifyTransformedInternal = memoizeOne(function(revision, squaredTolerance, sourceProjection, destProjection) { this.simplifyTransformedInternal = memoizeOne(function(revision, squaredTolerance, opt_transform) {
if (!sourceProjection || !destProjection) { if (!opt_transform) {
return this.getSimplifiedGeometry(squaredTolerance); return this.getSimplifiedGeometry(squaredTolerance);
} }
const transform = getTransformFromProjections(sourceProjection, destProjection);
const clone = this.clone(); const clone = this.clone();
clone.applyTransform(transform); clone.applyTransform(opt_transform);
return clone.getSimplifiedGeometry(squaredTolerance); return clone.getSimplifiedGeometry(squaredTolerance);
}); });
@@ -82,12 +80,11 @@ class Geometry extends BaseObject {
* Get a transformed and simplified version of the geometry. * Get a transformed and simplified version of the geometry.
* @abstract * @abstract
* @param {number} squaredTolerance Squared tolerance. * @param {number} squaredTolerance Squared tolerance.
* @param {import("../proj/Projection.js").default} sourceProjection The source projection. * @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.
* @param {import("../proj/Projection.js").default} destProjection The destination projection.
* @return {Geometry} Simplified geometry. * @return {Geometry} Simplified geometry.
*/ */
simplifyTransformed(squaredTolerance, sourceProjection, destProjection) { simplifyTransformed(squaredTolerance, opt_transform) {
return this.simplifyTransformedInternal(this.getRevision(), squaredTolerance, sourceProjection, destProjection); return this.simplifyTransformedInternal(this.getRevision(), squaredTolerance, opt_transform);
} }
/** /**

View File

@@ -115,7 +115,7 @@ class DragAndDrop extends Interaction {
/** /**
* @private * @private
* @type {Array<import("../events.js").EventsKey>} * @type {?Array<import("../events.js").EventsKey>}
*/ */
this.dropListenKeys_ = null; this.dropListenKeys_ = null;

View File

@@ -920,12 +920,12 @@ class Modify extends PointerInteraction {
*/ */
handlePointerAtPixel_(pixel, map) { handlePointerAtPixel_(pixel, map) {
const pixelCoordinate = map.getCoordinateFromPixel(pixel); const pixelCoordinate = map.getCoordinateFromPixel(pixel);
const projection = map.getView().getProjection();
const sortByDistance = function(a, b) { const sortByDistance = function(a, b) {
return pointDistanceToSegmentDataSquared(pixelCoordinate, a) - return projectedDistanceToSegmentDataSquared(pixelCoordinate, a, projection) -
pointDistanceToSegmentDataSquared(pixelCoordinate, b); projectedDistanceToSegmentDataSquared(pixelCoordinate, b, projection);
}; };
const projection = map.getView().getProjection();
const viewExtent = fromUserExtent(createExtent(pixelCoordinate, tempExtent), projection); const viewExtent = fromUserExtent(createExtent(pixelCoordinate, tempExtent), projection);
const buffer = map.getView().getResolution() * this.pixelTolerance_; const buffer = map.getView().getResolution() * this.pixelTolerance_;
const box = toUserExtent(bufferExtent(viewExtent, buffer, tempExtent), projection); const box = toUserExtent(bufferExtent(viewExtent, buffer, tempExtent), projection);
@@ -1235,9 +1235,10 @@ function compareIndexes(a, b) {
* which to calculate the distance. * which to calculate the distance.
* @param {SegmentData} segmentData The object describing the line * @param {SegmentData} segmentData The object describing the line
* segment we are calculating the distance to. * segment we are calculating the distance to.
* @param {import("../proj/Projection.js").default} projection The view projection.
* @return {number} The square of the distance between a point and a line segment. * @return {number} The square of the distance between a point and a line segment.
*/ */
function pointDistanceToSegmentDataSquared(pointCoordinates, segmentData) { function projectedDistanceToSegmentDataSquared(pointCoordinates, segmentData, projection) {
const geometry = segmentData.geometry; const geometry = segmentData.geometry;
if (geometry.getType() === GeometryType.CIRCLE) { if (geometry.getType() === GeometryType.CIRCLE) {
@@ -1251,7 +1252,11 @@ function pointDistanceToSegmentDataSquared(pointCoordinates, segmentData) {
return distanceToCircumference * distanceToCircumference; return distanceToCircumference * distanceToCircumference;
} }
} }
return squaredDistanceToSegment(pointCoordinates, segmentData.segment);
const coordinate = fromUserCoordinate(pointCoordinates, projection);
tempSegment[0] = fromUserCoordinate(segmentData.segment[0], projection);
tempSegment[1] = fromUserCoordinate(segmentData.segment[1], projection);
return squaredDistanceToSegment(coordinate, tempSegment);
} }
/** /**

View File

@@ -14,6 +14,7 @@ import PointerInteraction from './Pointer.js';
import {getValues} from '../obj.js'; import {getValues} from '../obj.js';
import VectorEventType from '../source/VectorEventType.js'; import VectorEventType from '../source/VectorEventType.js';
import RBush from '../structs/RBush.js'; import RBush from '../structs/RBush.js';
import {fromUserCoordinate, toUserCoordinate} from '../proj.js';
/** /**
@@ -52,9 +53,10 @@ function getFeatureFromEvent(evt) {
} else if (/** @type {import("../Collection.js").CollectionEvent} */ (evt).element) { } else if (/** @type {import("../Collection.js").CollectionEvent} */ (evt).element) {
return /** @type {import("../Feature.js").default} */ (/** @type {import("../Collection.js").CollectionEvent} */ (evt).element); return /** @type {import("../Feature.js").default} */ (/** @type {import("../Collection.js").CollectionEvent} */ (evt).element);
} }
} }
const tempSegment = [];
/** /**
* @classdesc * @classdesc
* Handles snapping of vector features while modifying or drawing them. The * Handles snapping of vector features while modifying or drawing them. The
@@ -70,10 +72,12 @@ function getFeatureFromEvent(evt) {
* *
* import Snap from 'ol/interaction/Snap'; * import Snap from 'ol/interaction/Snap';
* *
* var snap = new Snap({ * const snap = new Snap({
* source: source * source: source
* }); * });
* *
* map.addInteraction(snap);
*
* @api * @api
*/ */
class Snap extends PointerInteraction { class Snap extends PointerInteraction {
@@ -149,13 +153,6 @@ class Snap extends PointerInteraction {
*/ */
this.pendingFeatures_ = {}; this.pendingFeatures_ = {};
/**
* Used for distance sorting in sortByDistance_
* @type {import("../coordinate.js").Coordinate}
* @private
*/
this.pixelCoordinate_ = null;
/** /**
* @type {number} * @type {number}
* @private * @private
@@ -163,13 +160,6 @@ class Snap extends PointerInteraction {
this.pixelTolerance_ = options.pixelTolerance !== undefined ? this.pixelTolerance_ = options.pixelTolerance !== undefined ?
options.pixelTolerance : 10; options.pixelTolerance : 10;
/**
* @type {function(SegmentData, SegmentData): number}
* @private
*/
this.sortByDistance_ = sortByDistance.bind(this);
/** /**
* Segment RTree for each layer * Segment RTree for each layer
* @type {import("../structs/RBush.js").default<SegmentData>} * @type {import("../structs/RBush.js").default<SegmentData>}
@@ -177,22 +167,21 @@ class Snap extends PointerInteraction {
*/ */
this.rBush_ = new RBush(); this.rBush_ = new RBush();
/** /**
* @const * @const
* @private * @private
* @type {Object<string, function(import("../Feature.js").default, import("../geom/Geometry.js").default): void>} * @type {Object<string, function(import("../Feature.js").default, import("../geom/Geometry.js").default): void>}
*/ */
this.SEGMENT_WRITERS_ = { this.SEGMENT_WRITERS_ = {
'Point': this.writePointGeometry_, 'Point': this.writePointGeometry_.bind(this),
'LineString': this.writeLineStringGeometry_, 'LineString': this.writeLineStringGeometry_.bind(this),
'LinearRing': this.writeLineStringGeometry_, 'LinearRing': this.writeLineStringGeometry_.bind(this),
'Polygon': this.writePolygonGeometry_, 'Polygon': this.writePolygonGeometry_.bind(this),
'MultiPoint': this.writeMultiPointGeometry_, 'MultiPoint': this.writeMultiPointGeometry_.bind(this),
'MultiLineString': this.writeMultiLineStringGeometry_, 'MultiLineString': this.writeMultiLineStringGeometry_.bind(this),
'MultiPolygon': this.writeMultiPolygonGeometry_, 'MultiPolygon': this.writeMultiPolygonGeometry_.bind(this),
'GeometryCollection': this.writeGeometryCollectionGeometry_, 'GeometryCollection': this.writeGeometryCollectionGeometry_.bind(this),
'Circle': this.writeCircleGeometry_ 'Circle': this.writeCircleGeometry_.bind(this)
}; };
} }
@@ -211,7 +200,7 @@ class Snap extends PointerInteraction {
const segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()]; const segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()];
if (segmentWriter) { if (segmentWriter) {
this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent(createEmpty()); this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent(createEmpty());
segmentWriter.call(this, feature, geometry); segmentWriter(feature, geometry);
} }
} }
@@ -383,10 +372,9 @@ class Snap extends PointerInteraction {
* @return {Result} Snap result * @return {Result} Snap result
*/ */
snapTo(pixel, pixelCoordinate, map) { snapTo(pixel, pixelCoordinate, map) {
const lowerLeft = map.getCoordinateFromPixel(
const lowerLeft = map.getCoordinateFromPixelInternal(
[pixel[0] - this.pixelTolerance_, pixel[1] + this.pixelTolerance_]); [pixel[0] - this.pixelTolerance_, pixel[1] + this.pixelTolerance_]);
const upperRight = map.getCoordinateFromPixelInternal( const upperRight = map.getCoordinateFromPixel(
[pixel[0] + this.pixelTolerance_, pixel[1] - this.pixelTolerance_]); [pixel[0] + this.pixelTolerance_, pixel[1] - this.pixelTolerance_]);
const box = boundingExtent([lowerLeft, upperRight]); const box = boundingExtent([lowerLeft, upperRight]);
@@ -400,57 +388,78 @@ class Snap extends PointerInteraction {
}); });
} }
let snappedToVertex = false;
let snapped = false; let snapped = false;
let vertex = null; let vertex = null;
let vertexPixel = null; let vertexPixel = null;
let dist, pixel1, pixel2, squaredDist1, squaredDist2;
if (segments.length > 0) { if (segments.length === 0) {
this.pixelCoordinate_ = pixelCoordinate; return {
segments.sort(this.sortByDistance_); snapped: snapped,
const closestSegment = segments[0].segment; vertex: vertex,
const isCircle = segments[0].feature.getGeometry().getType() === vertexPixel: vertexPixel
GeometryType.CIRCLE; };
if (this.vertex_ && !this.edge_) { }
pixel1 = map.getPixelFromCoordinateInternal(closestSegment[0]);
pixel2 = map.getPixelFromCoordinateInternal(closestSegment[1]); const projection = map.getView().getProjection();
squaredDist1 = squaredCoordinateDistance(pixel, pixel1); const projectedCoordinate = fromUserCoordinate(pixelCoordinate, projection);
squaredDist2 = squaredCoordinateDistance(pixel, pixel2);
dist = Math.sqrt(Math.min(squaredDist1, squaredDist2)); let closestSegmentData;
snappedToVertex = dist <= this.pixelTolerance_; let minSquaredDistance = Infinity;
if (snappedToVertex) { for (let i = 0; i < segments.length; ++i) {
snapped = true; const segmentData = segments[i];
vertex = squaredDist1 > squaredDist2 ? closestSegment[1] : closestSegment[0]; tempSegment[0] = fromUserCoordinate(segmentData.segment[0], projection);
vertexPixel = map.getPixelFromCoordinateInternal(vertex); tempSegment[1] = fromUserCoordinate(segmentData.segment[1], projection);
} const delta = squaredDistanceToSegment(projectedCoordinate, tempSegment);
} else if (this.edge_) { if (delta < minSquaredDistance) {
if (isCircle) { closestSegmentData = segmentData;
vertex = closestOnCircle(pixelCoordinate, minSquaredDistance = delta;
/** @type {import("../geom/Circle.js").default} */ (segments[0].feature.getGeometry())); }
} else { }
vertex = closestOnSegment(pixelCoordinate, closestSegment); const closestSegment = closestSegmentData.segment;
}
vertexPixel = map.getPixelFromCoordinateInternal(vertex); if (this.vertex_ && !this.edge_) {
if (coordinateDistance(pixel, vertexPixel) <= this.pixelTolerance_) { const pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
snapped = true; const pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
if (this.vertex_ && !isCircle) { const squaredDist1 = squaredCoordinateDistance(pixel, pixel1);
pixel1 = map.getPixelFromCoordinateInternal(closestSegment[0]); const squaredDist2 = squaredCoordinateDistance(pixel, pixel2);
pixel2 = map.getPixelFromCoordinateInternal(closestSegment[1]); const dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
squaredDist1 = squaredCoordinateDistance(vertexPixel, pixel1); if (dist <= this.pixelTolerance_) {
squaredDist2 = squaredCoordinateDistance(vertexPixel, pixel2); snapped = true;
dist = Math.sqrt(Math.min(squaredDist1, squaredDist2)); vertex = squaredDist1 > squaredDist2 ? closestSegment[1] : closestSegment[0];
snappedToVertex = dist <= this.pixelTolerance_; vertexPixel = map.getPixelFromCoordinate(vertex);
if (snappedToVertex) { }
vertex = squaredDist1 > squaredDist2 ? closestSegment[1] : closestSegment[0]; } else if (this.edge_) {
vertexPixel = map.getPixelFromCoordinateInternal(vertex); const isCircle = closestSegmentData.feature.getGeometry().getType() === GeometryType.CIRCLE;
} if (isCircle) {
vertex = closestOnCircle(pixelCoordinate,
/** @type {import("../geom/Circle.js").default} */ (closestSegmentData.feature.getGeometry()));
} else {
tempSegment[0] = fromUserCoordinate(closestSegment[0], projection);
tempSegment[1] = fromUserCoordinate(closestSegment[1], projection);
vertex = toUserCoordinate(closestOnSegment(projectedCoordinate, tempSegment), projection);
}
vertexPixel = map.getPixelFromCoordinate(vertex);
if (coordinateDistance(pixel, vertexPixel) <= this.pixelTolerance_) {
snapped = true;
if (this.vertex_ && !isCircle) {
const pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
const pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
const squaredDist1 = squaredCoordinateDistance(vertexPixel, pixel1);
const squaredDist2 = squaredCoordinateDistance(vertexPixel, pixel2);
const dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
if (dist <= this.pixelTolerance_) {
vertex = squaredDist1 > squaredDist2 ? closestSegment[1] : closestSegment[0];
vertexPixel = map.getPixelFromCoordinate(vertex);
} }
} }
} }
if (snapped) {
vertexPixel = [Math.round(vertexPixel[0]), Math.round(vertexPixel[1])];
}
} }
if (snapped) {
vertexPixel = [Math.round(vertexPixel[0]), Math.round(vertexPixel[1])];
}
return { return {
snapped: snapped, snapped: snapped,
vertex: vertex, vertex: vertex,
@@ -495,7 +504,7 @@ class Snap extends PointerInteraction {
for (let i = 0; i < geometries.length; ++i) { for (let i = 0; i < geometries.length; ++i) {
const segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()]; const segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()];
if (segmentWriter) { if (segmentWriter) {
segmentWriter.call(this, feature, geometries[i]); segmentWriter(feature, geometries[i]);
} }
} }
} }
@@ -613,17 +622,4 @@ class Snap extends PointerInteraction {
} }
/**
* Sort segments by distance, helper function
* @param {SegmentData} a The first segment data.
* @param {SegmentData} b The second segment data.
* @return {number} The difference in distance.
* @this {Snap}
*/
function sortByDistance(a, b) {
const deltaA = squaredDistanceToSegment(this.pixelCoordinate_, a.segment);
const deltaB = squaredDistanceToSegment(this.pixelCoordinate_, b.segment);
return deltaA - deltaB;
}
export default Snap; export default Snap;

View File

@@ -5,11 +5,6 @@ import BaseImageLayer from './BaseImage.js';
import CanvasImageLayerRenderer from '../renderer/canvas/ImageLayer.js'; import CanvasImageLayerRenderer from '../renderer/canvas/ImageLayer.js';
/**
* @typedef {import("./BaseImage.js").Options} Options
*/
/** /**
* @classdesc * @classdesc
* Server-rendered images that are available for arbitrary extents and * Server-rendered images that are available for arbitrary extents and
@@ -23,7 +18,7 @@ import CanvasImageLayerRenderer from '../renderer/canvas/ImageLayer.js';
class ImageLayer extends BaseImageLayer { class ImageLayer extends BaseImageLayer {
/** /**
* @param {Options=} opt_options Layer options. * @param {import("./BaseImage.js").Options=} opt_options Layer options.
*/ */
constructor(opt_options) { constructor(opt_options) {
super(opt_options); super(opt_options);

View File

@@ -9,6 +9,8 @@ import {
scale as scaleTransform scale as scaleTransform
} from './transform.js'; } from './transform.js';
import CanvasImmediateRenderer from './render/canvas/Immediate.js'; import CanvasImmediateRenderer from './render/canvas/Immediate.js';
import {getSquaredTolerance} from './renderer/vector.js';
import {getUserProjection, getTransformFromProjections} from './proj.js';
/** /**
@@ -92,9 +94,15 @@ export function toContext(context, opt_options) {
export function getVectorContext(event) { export function getVectorContext(event) {
const frameState = event.frameState; const frameState = event.frameState;
const transform = multiplyTransform(event.inversePixelTransform.slice(), frameState.coordinateToPixelTransform); const transform = multiplyTransform(event.inversePixelTransform.slice(), frameState.coordinateToPixelTransform);
const squaredTolerance = getSquaredTolerance(frameState.viewState.resolution, frameState.pixelRatio);
let userTransform;
const userProjection = getUserProjection();
if (userProjection) {
userTransform = getTransformFromProjections(userProjection, frameState.viewState.projection);
}
return new CanvasImmediateRenderer( return new CanvasImmediateRenderer(
event.context, frameState.pixelRatio, frameState.extent, transform, event.context, frameState.pixelRatio, frameState.extent, transform,
frameState.viewState.rotation); frameState.viewState.rotation, squaredTolerance, userTransform);
} }
/** /**

View File

@@ -204,11 +204,10 @@ class RenderFeature {
* Get a transformed and simplified version of the geometry. * Get a transformed and simplified version of the geometry.
* @abstract * @abstract
* @param {number} squaredTolerance Squared tolerance. * @param {number} squaredTolerance Squared tolerance.
* @param {import("../proj/Projection.js").default} sourceProjection The source projection. * @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.
* @param {import("../proj/Projection.js").default} destProjection The destination projection.
* @return {RenderFeature} Simplified geometry. * @return {RenderFeature} Simplified geometry.
*/ */
simplifyTransformed(squaredTolerance, sourceProjection, destProjection) { simplifyTransformed(squaredTolerance, opt_transform) {
return this; return this;
} }

View File

@@ -300,6 +300,9 @@ function getMeasureContext() {
* @return {import("../size.js").Size} Measurement. * @return {import("../size.js").Size} Measurement.
*/ */
export const measureTextHeight = (function() { export const measureTextHeight = (function() {
/**
* @type {HTMLDivElement}
*/
let div; let div;
const heights = textHeights; const heights = textHeights;
return function(font) { return function(font) {

View File

@@ -31,8 +31,10 @@ class CanvasImmediateRenderer extends VectorContext {
* @param {import("../../extent.js").Extent} extent Extent. * @param {import("../../extent.js").Extent} extent Extent.
* @param {import("../../transform.js").Transform} transform Transform. * @param {import("../../transform.js").Transform} transform Transform.
* @param {number} viewRotation View rotation. * @param {number} viewRotation View rotation.
* @param {number=} opt_squaredTolerance Optional squared tolerance for simplification.
* @param {import("../../proj.js").TransformFunction=} opt_userTransform Transform from user to view projection.
*/ */
constructor(context, pixelRatio, extent, transform, viewRotation) { constructor(context, pixelRatio, extent, transform, viewRotation, opt_squaredTolerance, opt_userTransform) {
super(); super();
/** /**
@@ -65,6 +67,18 @@ class CanvasImmediateRenderer extends VectorContext {
*/ */
this.viewRotation_ = viewRotation; this.viewRotation_ = viewRotation;
/**
* @private
* @type {number}
*/
this.squaredTolerance_ = opt_squaredTolerance;
/**
* @private
* @type {import("../../proj.js").TransformFunction}
*/
this.userTransform_ = opt_userTransform;
/** /**
* @private * @private
* @type {?import("../canvas.js").FillState} * @type {?import("../canvas.js").FillState}
@@ -505,6 +519,9 @@ class CanvasImmediateRenderer extends VectorContext {
* @override * @override
*/ */
drawPoint(geometry) { drawPoint(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/Point.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
}
const flatCoordinates = geometry.getFlatCoordinates(); const flatCoordinates = geometry.getFlatCoordinates();
const stride = geometry.getStride(); const stride = geometry.getStride();
if (this.image_) { if (this.image_) {
@@ -523,6 +540,9 @@ class CanvasImmediateRenderer extends VectorContext {
* @override * @override
*/ */
drawMultiPoint(geometry) { drawMultiPoint(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/MultiPoint.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
}
const flatCoordinates = geometry.getFlatCoordinates(); const flatCoordinates = geometry.getFlatCoordinates();
const stride = geometry.getStride(); const stride = geometry.getStride();
if (this.image_) { if (this.image_) {
@@ -541,6 +561,9 @@ class CanvasImmediateRenderer extends VectorContext {
* @override * @override
*/ */
drawLineString(geometry) { drawLineString(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/LineString.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
}
if (!intersects(this.extent_, geometry.getExtent())) { if (!intersects(this.extent_, geometry.getExtent())) {
return; return;
} }
@@ -567,6 +590,9 @@ class CanvasImmediateRenderer extends VectorContext {
* @override * @override
*/ */
drawMultiLineString(geometry) { drawMultiLineString(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/MultiLineString.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
}
const geometryExtent = geometry.getExtent(); const geometryExtent = geometry.getExtent();
if (!intersects(this.extent_, geometryExtent)) { if (!intersects(this.extent_, geometryExtent)) {
return; return;
@@ -598,6 +624,9 @@ class CanvasImmediateRenderer extends VectorContext {
* @override * @override
*/ */
drawPolygon(geometry) { drawPolygon(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/Polygon.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
}
if (!intersects(this.extent_, geometry.getExtent())) { if (!intersects(this.extent_, geometry.getExtent())) {
return; return;
} }
@@ -632,6 +661,9 @@ class CanvasImmediateRenderer extends VectorContext {
* @override * @override
*/ */
drawMultiPolygon(geometry) { drawMultiPolygon(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/MultiPolygon.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
}
if (!intersects(this.extent_, geometry.getExtent())) { if (!intersects(this.extent_, geometry.getExtent())) {
return; return;
} }

View File

@@ -4,7 +4,7 @@
import {getUid} from '../../util.js'; import {getUid} from '../../util.js';
import ViewHint from '../../ViewHint.js'; import ViewHint from '../../ViewHint.js';
import {buffer, createEmpty, containsExtent, getWidth, intersects as intersectsExtent} from '../../extent.js'; import {buffer, createEmpty, containsExtent, getWidth, intersects as intersectsExtent} from '../../extent.js';
import {fromUserExtent, toUserExtent, getUserProjection} from '../../proj.js'; import {fromUserExtent, toUserExtent, getUserProjection, getTransformFromProjections} from '../../proj.js';
import CanvasBuilderGroup from '../../render/canvas/BuilderGroup.js'; import CanvasBuilderGroup from '../../render/canvas/BuilderGroup.js';
import ExecutorGroup, {replayDeclutter} from '../../render/canvas/ExecutorGroup.js'; import ExecutorGroup, {replayDeclutter} from '../../render/canvas/ExecutorGroup.js';
import CanvasLayerRenderer from './Layer.js'; import CanvasLayerRenderer from './Layer.js';
@@ -307,8 +307,10 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
pixelRatio, vectorLayer.getDeclutter()); pixelRatio, vectorLayer.getDeclutter());
const userProjection = getUserProjection(); const userProjection = getUserProjection();
let userTransform;
if (userProjection) { if (userProjection) {
vectorSource.loadFeatures(toUserExtent(extent, projection), resolution, userProjection); vectorSource.loadFeatures(toUserExtent(extent, projection), resolution, userProjection);
userTransform = getTransformFromProjections(userProjection, projection);
} else { } else {
vectorSource.loadFeatures(extent, resolution, projection); vectorSource.loadFeatures(extent, resolution, projection);
} }
@@ -326,7 +328,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
styles = styleFunction(feature, resolution); styles = styleFunction(feature, resolution);
} }
if (styles) { if (styles) {
const dirty = this.renderFeature(feature, squaredTolerance, styles, replayGroup, projection); const dirty = this.renderFeature(feature, squaredTolerance, styles, replayGroup, userTransform);
this.dirty_ = this.dirty_ || dirty; this.dirty_ = this.dirty_ || dirty;
} }
}.bind(this); }.bind(this);
@@ -370,10 +372,10 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
* @param {number} squaredTolerance Squared render tolerance. * @param {number} squaredTolerance Squared render tolerance.
* @param {import("../../style/Style.js").default|Array<import("../../style/Style.js").default>} styles The style or array of styles. * @param {import("../../style/Style.js").default|Array<import("../../style/Style.js").default>} styles The style or array of styles.
* @param {import("../../render/canvas/BuilderGroup.js").default} builderGroup Builder group. * @param {import("../../render/canvas/BuilderGroup.js").default} builderGroup Builder group.
* @param {import("../../proj/Projection.js").default} projection The view projection. * @param {import("../../proj.js").TransformFunction} opt_transform Transform from user to view projection.
* @return {boolean} `true` if an image is loading. * @return {boolean} `true` if an image is loading.
*/ */
renderFeature(feature, squaredTolerance, styles, builderGroup, projection) { renderFeature(feature, squaredTolerance, styles, builderGroup, opt_transform) {
if (!styles) { if (!styles) {
return false; return false;
} }
@@ -382,12 +384,12 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
for (let i = 0, ii = styles.length; i < ii; ++i) { for (let i = 0, ii = styles.length; i < ii; ++i) {
loading = renderFeature( loading = renderFeature(
builderGroup, feature, styles[i], squaredTolerance, builderGroup, feature, styles[i], squaredTolerance,
this.boundHandleStyleImageChange_, projection) || loading; this.boundHandleStyleImageChange_, opt_transform) || loading;
} }
} else { } else {
loading = renderFeature( loading = renderFeature(
builderGroup, feature, styles, squaredTolerance, builderGroup, feature, styles, squaredTolerance,
this.boundHandleStyleImageChange_, projection); this.boundHandleStyleImageChange_, opt_transform);
} }
return loading; return loading;
} }

View File

@@ -5,7 +5,6 @@ import {getUid} from '../util.js';
import ImageState from '../ImageState.js'; import ImageState from '../ImageState.js';
import GeometryType from '../geom/GeometryType.js'; import GeometryType from '../geom/GeometryType.js';
import BuilderType from '../render/canvas/BuilderType.js'; import BuilderType from '../render/canvas/BuilderType.js';
import {getUserProjection} from '../proj.js';
/** /**
@@ -93,11 +92,11 @@ function renderCircleGeometry(builderGroup, geometry, style, feature) {
* @param {import("../style/Style.js").default} style Style. * @param {import("../style/Style.js").default} style Style.
* @param {number} squaredTolerance Squared tolerance. * @param {number} squaredTolerance Squared tolerance.
* @param {function(import("../events/Event.js").default): void} listener Listener function. * @param {function(import("../events/Event.js").default): void} listener Listener function.
* @param {import("../proj/Projection.js").default} [projection] The view projection. * @param {import("../proj.js").TransformFunction} [opt_transform] Transform from user to view projection.
* @return {boolean} `true` if style is loading. * @return {boolean} `true` if style is loading.
* @template T * @template T
*/ */
export function renderFeature(replayGroup, feature, style, squaredTolerance, listener, projection) { export function renderFeature(replayGroup, feature, style, squaredTolerance, listener, opt_transform) {
let loading = false; let loading = false;
const imageStyle = style.getImage(); const imageStyle = style.getImage();
if (imageStyle) { if (imageStyle) {
@@ -113,7 +112,7 @@ export function renderFeature(replayGroup, feature, style, squaredTolerance, lis
loading = true; loading = true;
} }
} }
renderFeatureInternal(replayGroup, feature, style, squaredTolerance, projection); renderFeatureInternal(replayGroup, feature, style, squaredTolerance, opt_transform);
return loading; return loading;
} }
@@ -124,14 +123,14 @@ export function renderFeature(replayGroup, feature, style, squaredTolerance, lis
* @param {import("../Feature.js").FeatureLike} feature Feature. * @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {import("../style/Style.js").default} style Style. * @param {import("../style/Style.js").default} style Style.
* @param {number} squaredTolerance Squared tolerance. * @param {number} squaredTolerance Squared tolerance.
* @param {import("../proj/Projection.js").default} [projection] The view projection. * @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.
*/ */
function renderFeatureInternal(replayGroup, feature, style, squaredTolerance, projection) { function renderFeatureInternal(replayGroup, feature, style, squaredTolerance, opt_transform) {
const geometry = style.getGeometryFunction()(feature); const geometry = style.getGeometryFunction()(feature);
if (!geometry) { if (!geometry) {
return; return;
} }
const simplifiedGeometry = geometry.simplifyTransformed(squaredTolerance, getUserProjection(), projection); const simplifiedGeometry = geometry.simplifyTransformed(squaredTolerance, opt_transform);
const renderer = style.getRenderer(); const renderer = style.getRenderer();
if (renderer) { if (renderer) {
renderGeometry(replayGroup, simplifiedGeometry, style, feature); renderGeometry(replayGroup, simplifiedGeometry, style, feature);

View File

@@ -109,7 +109,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
/** /**
* @param {import("../../layer/Layer.js").default} layer Layer. * @param {import("../../layer/Layer.js").default} layer Layer.
* @param {Options=} options Options. * @param {Options} options Options.
*/ */
constructor(layer, options) { constructor(layer, options) {
const uniforms = options.uniforms || {}; const uniforms = options.uniforms || {};

View File

@@ -104,7 +104,7 @@ class ReprojTile extends Tile {
/** /**
* @private * @private
* @type {Array<import("../events.js").EventsKey>} * @type {?Array<import("../events.js").EventsKey>}
*/ */
this.sourcesListenerKeys_ = null; this.sourcesListenerKeys_ = null;

View File

@@ -127,10 +127,14 @@ export function createSnapToPower(power, maxResolution, opt_minResolution, opt_s
return getSmoothClampedResolution(resolution, cappedMaxRes, minResolution); return getSmoothClampedResolution(resolution, cappedMaxRes, minResolution);
} }
const offset = -direction * (0.5 - 1e-9) + 0.5; const tolerance = 1e-9;
const minZoomLevel = Math.ceil(
Math.log(maxResolution / cappedMaxRes) / Math.log(power) - tolerance);
const offset = -direction * (0.5 - tolerance) + 0.5;
const capped = Math.min(cappedMaxRes, resolution); const capped = Math.min(cappedMaxRes, resolution);
const zoomLevel = Math.floor( const cappedZoomLevel = Math.floor(
Math.log(maxResolution / capped) / Math.log(power) + offset); Math.log(maxResolution / capped) / Math.log(power) + offset);
const zoomLevel = Math.max(minZoomLevel, cappedZoomLevel);
const newResolution = maxResolution / Math.pow(power, zoomLevel); const newResolution = maxResolution / Math.pow(power, zoomLevel);
return clamp(newResolution, minResolution, cappedMaxRes); return clamp(newResolution, minResolution, cappedMaxRes);
} else { } else {

View File

@@ -81,7 +81,7 @@ class TileWMS extends TileImage {
*/ */
constructor(opt_options) { constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : /** @type {Options} */ ({});
const params = options.params || {}; const params = options.params || {};

View File

@@ -10,7 +10,6 @@ import UrlTile from './UrlTile.js';
import {getKeyZXY, getKey} from '../tilecoord.js'; import {getKeyZXY, getKey} from '../tilecoord.js';
import {createXYZ, extentFromProjection, createForProjection} from '../tilegrid.js'; import {createXYZ, extentFromProjection, createForProjection} from '../tilegrid.js';
import {buffer as bufferExtent, getIntersection, intersects} from '../extent.js'; import {buffer as bufferExtent, getIntersection, intersects} from '../extent.js';
import {listen, unlistenByKey} from '../events.js';
import EventType from '../events/EventType.js'; import EventType from '../events/EventType.js';
import {loadFeaturesXhr} from '../featureloader.js'; import {loadFeaturesXhr} from '../featureloader.js';
import {isEmpty} from '../obj.js'; import {isEmpty} from '../obj.js';
@@ -200,11 +199,10 @@ class VectorTile extends UrlTile {
const minZoom = sourceTileGrid.getMinZoom(); const minZoom = sourceTileGrid.getMinZoom();
const previousSourceTiles = this.sourceTilesByTileKey_[tile.getKey()]; const previousSourceTiles = this.sourceTilesByTileKey_[tile.getKey()];
let sourceTiles, covered, empty, loadedZ; let sourceTiles, covered, loadedZ;
if (previousSourceTiles && previousSourceTiles.length > 0 && previousSourceTiles[0].tileCoord[0] === sourceZ) { if (previousSourceTiles && previousSourceTiles.length > 0 && previousSourceTiles[0].tileCoord[0] === sourceZ) {
sourceTiles = previousSourceTiles; sourceTiles = previousSourceTiles;
covered = true; covered = true;
empty = false;
loadedZ = sourceZ; loadedZ = sourceZ;
} else { } else {
sourceTiles = []; sourceTiles = [];
@@ -212,7 +210,6 @@ class VectorTile extends UrlTile {
do { do {
--loadedZ; --loadedZ;
covered = true; covered = true;
empty = true;
sourceTileGrid.forEachTileCoord(extent, loadedZ, function(sourceTileCoord) { sourceTileGrid.forEachTileCoord(extent, loadedZ, function(sourceTileCoord) {
const coordKey = getKey(sourceTileCoord); const coordKey = getKey(sourceTileCoord);
let sourceTile; let sourceTile;
@@ -220,7 +217,6 @@ class VectorTile extends UrlTile {
sourceTile = this.sourceTileByCoordKey_[coordKey]; sourceTile = this.sourceTileByCoordKey_[coordKey];
const state = sourceTile.getState(); const state = sourceTile.getState();
if (state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) { if (state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) {
empty = empty && state === TileState.EMPTY;
sourceTiles.push(sourceTile); sourceTiles.push(sourceTile);
return; return;
} }
@@ -233,28 +229,25 @@ class VectorTile extends UrlTile {
sourceTile.projection = projection; sourceTile.projection = projection;
sourceTile.resolution = sourceTileGrid.getResolution(sourceTileCoord[0]); sourceTile.resolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
this.sourceTileByCoordKey_[coordKey] = sourceTile; this.sourceTileByCoordKey_[coordKey] = sourceTile;
empty = false;
sourceTile.addEventListener(EventType.CHANGE, this.handleTileChange.bind(this)); sourceTile.addEventListener(EventType.CHANGE, this.handleTileChange.bind(this));
sourceTile.load(); sourceTile.load();
} else {
sourceTile = null;
} }
} else {
empty = false;
} }
covered = false; covered = false;
if (sourceTile === undefined) { if (!sourceTile) {
return; return;
} }
if (sourceTile !== null && tile.getState() === TileState.IDLE) { if (sourceTile.getState() !== TileState.EMPTY && tile.getState() === TileState.IDLE) {
tile.loadingSourceTiles++; tile.loadingSourceTiles++;
const key = listen(sourceTile, EventType.CHANGE, function() { const onSourceTileChange = function() {
const state = sourceTile.getState(); const state = sourceTile.getState();
const sourceTileKey = sourceTile.getKey(); const sourceTileKey = sourceTile.getKey();
if (state === TileState.LOADED || state === TileState.ERROR) { if (state === TileState.LOADED || state === TileState.ERROR) {
if (state === TileState.LOADED) { if (state === TileState.LOADED) {
unlistenByKey(key); sourceTile.removeEventListener(EventType.CHANGE, onSourceTileChange);
tile.loadingSourceTiles--; tile.loadingSourceTiles--;
// eslint-disable-next-line no-use-before-define
tile.removeEventListener(EventType.CHANGE, onTileChange);
delete tile.errorSourceTileKeys[sourceTileKey]; delete tile.errorSourceTileKeys[sourceTileKey];
} else if (state === TileState.ERROR) { } else if (state === TileState.ERROR) {
tile.errorSourceTileKeys[sourceTileKey] = true; tile.errorSourceTileKeys[sourceTileKey] = true;
@@ -265,7 +258,15 @@ class VectorTile extends UrlTile {
tile.setState(isEmpty(tile.errorSourceTileKeys) ? TileState.LOADED : TileState.ERROR); tile.setState(isEmpty(tile.errorSourceTileKeys) ? TileState.LOADED : TileState.ERROR);
} }
} }
}); };
const onTileChange = function() {
if (tile.getState() === TileState.ABORT) {
sourceTile.removeEventListener(EventType.CHANGE, onSourceTileChange);
tile.removeEventListener(EventType.CHANGE, onTileChange);
}
};
sourceTile.addEventListener(EventType.CHANGE, onSourceTileChange);
tile.addEventListener(EventType.CHANGE, onTileChange);
} }
}.bind(this)); }.bind(this));
if (!covered) { if (!covered) {
@@ -274,14 +275,14 @@ class VectorTile extends UrlTile {
} while (!covered && loadedZ > minZoom); } while (!covered && loadedZ > minZoom);
} }
if (!empty && tile.getState() === TileState.IDLE) { if (tile.getState() === TileState.IDLE) {
tile.setState(TileState.LOADING); tile.setState(TileState.LOADING);
} }
if (covered || empty) { if (covered) {
tile.hifi = sourceZ === loadedZ; tile.hifi = sourceZ === loadedZ;
tile.sourceZ = loadedZ; tile.sourceZ = loadedZ;
if (tile.getState() < TileState.LOADED) { if (tile.getState() < TileState.LOADED) {
tile.setState(empty ? TileState.EMPTY : TileState.LOADED); tile.setState(TileState.LOADED);
} else if (!previousSourceTiles || !equals(sourceTiles, previousSourceTiles)) { } else if (!previousSourceTiles || !equals(sourceTiles, previousSourceTiles)) {
this.removeSourceTiles(tile); this.removeSourceTiles(tile);
this.addSourceTiles(tile, sourceTiles); this.addSourceTiles(tile, sourceTiles);
@@ -336,8 +337,8 @@ class VectorTile extends UrlTile {
const tileCoord = [z, x, y]; const tileCoord = [z, x, y];
let urlTileCoord = this.getTileCoordForTileUrlFunction(tileCoord, projection); let urlTileCoord = this.getTileCoordForTileUrlFunction(tileCoord, projection);
const sourceExtent = this.getTileGrid().getExtent(); const sourceExtent = this.getTileGrid().getExtent();
const tileGrid = this.getTileGridForProjection(projection);
if (urlTileCoord && sourceExtent) { if (urlTileCoord && sourceExtent) {
const tileGrid = this.getTileGridForProjection(projection);
const tileExtent = tileGrid.getTileCoordExtent(urlTileCoord); const tileExtent = tileGrid.getTileCoordExtent(urlTileCoord);
// make extent 1 pixel smaller so we don't load tiles for < 0.5 pixel render space // make extent 1 pixel smaller so we don't load tiles for < 0.5 pixel render space
bufferExtent(tileExtent, -tileGrid.getResolution(z), tileExtent); bufferExtent(tileExtent, -tileGrid.getResolution(z), tileExtent);
@@ -345,9 +346,21 @@ class VectorTile extends UrlTile {
urlTileCoord = null; urlTileCoord = null;
} }
} }
let empty = true;
if (urlTileCoord !== null) {
const sourceTileGrid = this.tileGrid;
const resolution = tileGrid.getResolution(z);
const sourceZ = sourceTileGrid.getZForResolution(resolution, 1);
// make extent 1 pixel smaller so we don't load tiles for < 0.5 pixel render space
const extent = tileGrid.getTileCoordExtent(urlTileCoord);
bufferExtent(extent, -resolution, extent);
sourceTileGrid.forEachTileCoord(extent, sourceZ, function(sourceTileCoord) {
empty = empty && !this.tileUrlFunction(sourceTileCoord, pixelRatio, projection);
}.bind(this));
}
const newTile = new VectorRenderTile( const newTile = new VectorRenderTile(
tileCoord, tileCoord,
urlTileCoord !== null ? TileState.IDLE : TileState.EMPTY, empty ? TileState.EMPTY : TileState.IDLE,
urlTileCoord, urlTileCoord,
this.tileGrid, this.tileGrid,
this.getSourceTiles.bind(this, pixelRatio, projection), this.getSourceTiles.bind(this, pixelRatio, projection),

View File

@@ -22,7 +22,7 @@ import EventType from '../events/EventType.js';
* Object's properties (e.g. 'hasOwnProperty' is not allowed as a key). Expiring * Object's properties (e.g. 'hasOwnProperty' is not allowed as a key). Expiring
* items from the cache is the responsibility of the user. * items from the cache is the responsibility of the user.
* *
* @fires import("../events/Event.js").Event * @fires import("../events/Event.js").default
* @template T * @template T
*/ */
class LRUCache extends EventTarget { class LRUCache extends EventTarget {
@@ -96,7 +96,7 @@ class LRUCache extends EventTarget {
/** /**
* @param {function(T, string, LRUCache): ?} f The function * @param {function(T, string, LRUCache<T>): ?} f The function
* to call for every entry from the oldest to the newer. This function takes * to call for every entry from the oldest to the newer. This function takes
* 3 arguments (the entry value, the entry key and the LRUCache object). * 3 arguments (the entry value, the entry key and the LRUCache object).
* The return value is ignored. * The return value is ignored.

View File

@@ -53,7 +53,7 @@ class IconImage extends EventTarget {
/** /**
* @private * @private
* @type {function():void} * @type {?function():void}
*/ */
this.unlisten_ = null; this.unlisten_ = null;

View File

@@ -101,7 +101,7 @@ const DEFAULT_FRAGMENT_SHADER = `
class WebGLPostProcessingPass { class WebGLPostProcessingPass {
/** /**
* @param {Options=} options Options. * @param {Options} options Options.
*/ */
constructor(options) { constructor(options) {
this.gl_ = options.webGlContext; this.gl_ = options.webGlContext;

View File

@@ -95,7 +95,7 @@ describe('ol.collection', function() {
describe('on an empty collection', function() { describe('on an empty collection', function() {
it('does not call the callback', function() { it('does not call the callback', function() {
collection.forEach(cb); collection.forEach(cb);
expect(cb).to.not.be.called(); expect(cb.called).to.be(false);
}); });
}); });
describe('on a non-empty collection', function() { describe('on a non-empty collection', function() {
@@ -120,7 +120,7 @@ describe('ol.collection', function() {
const cb = sinon.spy(); const cb = sinon.spy();
listen(collection, CollectionEventType.REMOVE, cb); listen(collection, CollectionEventType.REMOVE, cb);
expect(collection.remove(1)).to.eql(1); expect(collection.remove(1)).to.eql(1);
expect(cb).to.be.called(); expect(cb.called).to.be(true);
expect(cb.lastCall.args[0].element).to.eql(1); expect(cb.lastCall.args[0].element).to.eql(1);
}); });
it('does not remove more than one matching element', function() { it('does not remove more than one matching element', function() {
@@ -216,21 +216,21 @@ describe('ol.collection', function() {
describe('insertAt', function() { describe('insertAt', function() {
it('triggers change:length event', function() { it('triggers change:length event', function() {
collection.insertAt(2, 3); collection.insertAt(2, 3);
expect(cb).to.be.called(); expect(cb.called).to.be(true);
}); });
}); });
describe('removeAt', function() { describe('removeAt', function() {
it('triggers change:length event', function() { it('triggers change:length event', function() {
collection.removeAt(0); collection.removeAt(0);
expect(cb).to.be.called(); expect(cb.called).to.be(true);
}); });
}); });
describe('setAt', function() { describe('setAt', function() {
it('does not trigger change:length event', function() { it('does not trigger change:length event', function() {
collection.setAt(1, 1); collection.setAt(1, 1);
expect(cb).to.not.be.called(); expect(cb.called).to.be(false);
}); });
}); });
}); });

View File

@@ -2,21 +2,6 @@
describe('expect.js', function() { describe('expect.js', function() {
describe('arreqlNaN', function() {
it('considers NaN in array to be equal', function() {
expect([1, NaN, 2]).to.arreqlNaN([1, NaN, 2]);
expect([1, NaN, 2]).not.to.arreqlNaN([1, 1.5, 2]);
});
it('allows a mix of number and string', function() {
expect([1, NaN, 'foo']).to.arreqlNaN([1, NaN, 'foo']);
expect([1, NaN, 'foo']).not.to.arreqlNaN([1, NaN, 'bar']);
expect([1, NaN]).not.to.arreqlNaN([1, 'foo']);
});
});
describe('roughlyEqual', function() { describe('roughlyEqual', function() {
it('can tell the difference between 1 and 3', function() { it('can tell the difference between 1 and 3', function() {
@@ -42,38 +27,6 @@ describe('expect.js', function() {
}); });
describe('called', function() {
let telephone;
beforeEach(function() {
telephone = sinon.spy();
});
it('has caller ID', function() {
telephone();
expect(telephone).to.be.called();
});
it('also knows when it\'s speaking to the hand', function() {
(function() {})();
expect(telephone).not.to.be.called();
});
it('reminds you that you forgot', function() {
expect(function() {
expect(telephone).to.be.called();
}).to.throwException();
});
it('gets moody all too quickly', function() {
telephone();
expect(function() {
expect(telephone).not.to.be.called();
}).to.throwException();
});
});
describe('Test equality of XML documents - xmleql', function() { describe('Test equality of XML documents - xmleql', function() {
it('Test XML document with single root, different prefix', function() { it('Test XML document with single root, different prefix', function() {

View File

@@ -208,7 +208,7 @@ describe('ol.Feature', function() {
expect(feature.getGeometry()).to.be(point2); expect(feature.getGeometry()).to.be(point2);
feature.on('change', function() { feature.on('change', function() {
expect.fail(); expect().fail();
}); });
point.setCoordinates([0, 2]); point.setCoordinates([0, 2]);
}); });

View File

@@ -73,6 +73,12 @@ describe('ol.geom.LineString', function() {
expect(lineString.getStride()).to.be(2); expect(lineString.getStride()).to.be(2);
}); });
describe('#intersectsCoordinate', function() {
it('returns true for an intersecting coordinate', function() {
expect(lineString.intersectsCoordinate([1.5, 2.5])).to.be(true);
});
});
describe('#intersectsExtent', function() { describe('#intersectsExtent', function() {
it('return false for non matching extent', function() { it('return false for non matching extent', function() {
@@ -89,6 +95,23 @@ describe('ol.geom.LineString', function() {
}); });
describe('#intersectsCoordinate', function() {
it('detects intersecting coordinates', function() {
expect(lineString.intersectsCoordinate([1, 2])).to.be(true);
});
});
describe('#getClosestPoint', function() {
it('uses existing vertices', function() {
const closestPoint = lineString.getClosestPoint([0.9, 1.8]);
expect(closestPoint).to.eql([1, 2]);
});
});
describe('#getCoordinateAt', function() { describe('#getCoordinateAt', function() {
it('return the first point when fraction is 0', function() { it('return the first point when fraction is 0', function() {

View File

@@ -1,5 +1,5 @@
import Point from '../../../../src/ol/geom/Point.js'; import Point from '../../../../src/ol/geom/Point.js';
import {get as getProjection} from '../../../../src/ol/proj.js'; import {get as getProjection, getTransformFromProjections} from '../../../../src/ol/proj.js';
describe('ol.geom.Point', function() { describe('ol.geom.Point', function() {
@@ -161,9 +161,10 @@ describe('ol.geom.Point', function() {
const geom = new Point([1, 2]); const geom = new Point([1, 2]);
const source = getProjection('EPSG:4326'); const source = getProjection('EPSG:4326');
const dest = getProjection('EPSG:3857'); const dest = getProjection('EPSG:3857');
const transform = getTransformFromProjections(source, dest);
const squaredTolerance = 0.5; const squaredTolerance = 0.5;
const first = geom.simplifyTransformed(squaredTolerance, source, dest); const first = geom.simplifyTransformed(squaredTolerance, transform);
const second = geom.simplifyTransformed(squaredTolerance, source, dest); const second = geom.simplifyTransformed(squaredTolerance, transform);
expect(second).to.be(first); expect(second).to.be(first);
}); });
@@ -171,9 +172,10 @@ describe('ol.geom.Point', function() {
const geom = new Point([1, 2]); const geom = new Point([1, 2]);
const source = getProjection('EPSG:4326'); const source = getProjection('EPSG:4326');
const dest = getProjection('EPSG:3857'); const dest = getProjection('EPSG:3857');
const transform = getTransformFromProjections(source, dest);
const squaredTolerance = 0.5; const squaredTolerance = 0.5;
const first = geom.simplifyTransformed(squaredTolerance, source, dest); const first = geom.simplifyTransformed(squaredTolerance, transform);
const second = geom.simplifyTransformed(squaredTolerance * 2, source, dest); const second = geom.simplifyTransformed(squaredTolerance * 2, transform);
expect(second).not.to.be(first); expect(second).not.to.be(first);
}); });
@@ -181,11 +183,12 @@ describe('ol.geom.Point', function() {
const geom = new Point([1, 2]); const geom = new Point([1, 2]);
const source = getProjection('EPSG:4326'); const source = getProjection('EPSG:4326');
const dest = getProjection('EPSG:3857'); const dest = getProjection('EPSG:3857');
const transform = getTransformFromProjections(source, dest);
const squaredTolerance = 0.5; const squaredTolerance = 0.5;
const first = geom.simplifyTransformed(squaredTolerance, source, dest); const first = geom.simplifyTransformed(squaredTolerance, transform);
geom.setCoordinates([3, 4]); geom.setCoordinates([3, 4]);
const second = geom.simplifyTransformed(squaredTolerance * 2, source, dest); const second = geom.simplifyTransformed(squaredTolerance * 2, transform);
expect(second).not.to.be(first); expect(second).not.to.be(first);
}); });

View File

@@ -15,8 +15,8 @@ describe('HTML Image loading', function() {
listenImage(img, handleLoad, handleError); listenImage(img, handleLoad, handleError);
setTimeout(function() { setTimeout(function() {
expect(handleLoad).to.be.called(); expect(handleLoad.called).to.be(true);
expect(handleError).not.to.be.called(); expect(handleError.called).to.be(false);
done(); done();
}, 200); }, 200);
}); });
@@ -26,8 +26,8 @@ describe('HTML Image loading', function() {
img.src = 'spec/ol/data/dot.png'; img.src = 'spec/ol/data/dot.png';
setTimeout(function() { setTimeout(function() {
expect(handleLoad).to.be.called(); expect(handleLoad.called).to.be(true);
expect(handleError).not.to.be.called(); expect(handleError.called).to.be(false);
done(); done();
}, 200); }, 200);
}); });
@@ -37,8 +37,8 @@ describe('HTML Image loading', function() {
listenImage(img, handleLoad, handleError); listenImage(img, handleLoad, handleError);
setTimeout(function() { setTimeout(function() {
expect(handleLoad).not.to.be.called(); expect(handleLoad.called).to.be(false);
expect(handleError).to.be.called(); expect(handleError.called).to.be(true);
done(); done();
}, 200); }, 200);
}); });
@@ -48,8 +48,8 @@ describe('HTML Image loading', function() {
listenImage(img, handleLoad, handleError)(); listenImage(img, handleLoad, handleError)();
setTimeout(function() { setTimeout(function() {
expect(handleLoad).not.to.be.called(); expect(handleLoad.called).to.be(false);
expect(handleError).not.to.be.called(); expect(handleError.called).to.be(false);
done(); done();
}, 200); }, 200);
}); });

View File

@@ -216,8 +216,8 @@ describe('ol.interaction.Draw', function() {
simulateEvent('pointermove', 10, 20); simulateEvent('pointermove', 10, 20);
simulateEvent('pointerdown', 10, 20); simulateEvent('pointerdown', 10, 20);
simulateEvent('pointerup', 10, 20); simulateEvent('pointerup', 10, 20);
expect(ds).to.be.called(); expect(ds.called).to.be(true);
expect(de).to.be.called(); expect(de.called).to.be(true);
simulateEvent('pointermove', 20, 20); simulateEvent('pointermove', 20, 20);
expect(ds.callCount).to.be(1); expect(ds.callCount).to.be(1);
expect(de.callCount).to.be(1); expect(de.callCount).to.be(1);
@@ -390,7 +390,6 @@ describe('ol.interaction.Draw', function() {
simulateEvent('pointerup', 60, 70); simulateEvent('pointerup', 60, 70);
const features = source.getFeatures(); const features = source.getFeatures();
// expect(features).to.have.length(1);
const geometry = features[0].getGeometry(); const geometry = features[0].getGeometry();
expect(geometry).to.be.a(LineString); expect(geometry).to.be.a(LineString);
expect(geometry.getCoordinates()).to.eql( expect(geometry.getCoordinates()).to.eql(
@@ -478,9 +477,9 @@ describe('ol.interaction.Draw', function() {
simulateEvent('pointerup', 30, 20); simulateEvent('pointerup', 30, 20);
simulateEvent('pointermove', 10, 20); simulateEvent('pointermove', 10, 20);
expect(ds).to.be.called(); expect(ds.called).to.be(true);
expect(ds.callCount).to.be(1); expect(ds.callCount).to.be(1);
expect(de).to.be.called(); expect(de.called).to.be(true);
expect(de.callCount).to.be(1); expect(de.callCount).to.be(1);
}); });
@@ -801,9 +800,9 @@ describe('ol.interaction.Draw', function() {
simulateEvent('pointerdown', 10, 20); simulateEvent('pointerdown', 10, 20);
simulateEvent('pointerup', 10, 20); simulateEvent('pointerup', 10, 20);
expect(ds).to.be.called(); expect(ds.called).to.be(true);
expect(ds.callCount).to.be(1); expect(ds.callCount).to.be(1);
expect(de).to.be.called(); expect(de.called).to.be(true);
expect(de.callCount).to.be(1); expect(de.callCount).to.be(1);
}); });
@@ -963,9 +962,9 @@ describe('ol.interaction.Draw', function() {
simulateEvent('pointerdown', 30, 20); simulateEvent('pointerdown', 30, 20);
simulateEvent('pointerup', 30, 20); simulateEvent('pointerup', 30, 20);
expect(ds).to.be.called(); expect(ds.called).to.be(true);
expect(ds.callCount).to.be(1); expect(ds.callCount).to.be(1);
expect(de).to.be.called(); expect(de.called).to.be(true);
expect(de.callCount).to.be(1); expect(de.callCount).to.be(1);
}); });

View File

@@ -708,7 +708,7 @@ describe('ol.interaction.Modify', function() {
collection.remove(features[0]); collection.remove(features[0]);
expect(function() { expect(function() {
simulateEvent('pointerup', -10, -10, null, 0); simulateEvent('pointerup', -10, -10, null, 0);
}).to.not.throwError(); }).to.not.throwException();
}); });
}); });

View File

@@ -6,6 +6,8 @@ import Circle from '../../../../src/ol/geom/Circle.js';
import Point from '../../../../src/ol/geom/Point.js'; import Point from '../../../../src/ol/geom/Point.js';
import LineString from '../../../../src/ol/geom/LineString.js'; import LineString from '../../../../src/ol/geom/LineString.js';
import Snap from '../../../../src/ol/interaction/Snap.js'; import Snap from '../../../../src/ol/interaction/Snap.js';
import {useGeographic, clearUserProjection} from '../../../../src/ol/proj.js';
import {overrideRAF} from '../../util.js';
describe('ol.interaction.Snap', function() { describe('ol.interaction.Snap', function() {
@@ -190,6 +192,78 @@ describe('ol.interaction.Snap', function() {
expect(event.coordinate).to.eql([10, 0]); expect(event.coordinate).to.eql([10, 0]);
}); });
});
describe('handleEvent - useGeographic', () => {
let target, map;
const size = 256;
let restoreRAF;
beforeEach(done => {
restoreRAF = overrideRAF();
useGeographic();
target = document.createElement('div');
Object.assign(target.style, {
position: 'absolute',
top: 0,
left: 0,
width: `${size}px`,
height: `${size}px`
});
document.body.appendChild(target);
map = new Map({
target: target,
view: new View({
center: [0, 0],
zoom: 0
})
});
map.once('postrender', () => {
done();
});
});
afterEach(() => {
map.dispose();
document.body.removeChild(target);
clearUserProjection();
restoreRAF();
});
it('snaps to user coordinates', () => {
const lon = -90;
const lat = 45;
const point = new Feature(new Point([lon, lat]));
const snap = new Snap({
features: new Collection([point])
});
snap.setMap(map);
const expectedPixel = map.getPixelFromCoordinate([lon, lat]).map(value => Math.round(value));
const delta = 5;
const pixel = expectedPixel.slice();
pixel[0] += delta;
pixel[1] += delta;
const coordinate = map.getCoordinateFromPixel(pixel);
const event = {
pixel: pixel,
coordinate: coordinate,
map: map
};
snap.handleEvent(event);
expect(event.coordinate).to.eql([lon, lat]);
expect(event.pixel).to.eql(expectedPixel);
});
}); });

View File

@@ -67,7 +67,7 @@ describe('ol.net', function() {
}; };
}; };
function callback() { function callback() {
expect.fail(); expect().fail();
} }
function errback() { function errback() {
expect(window[key]).to.be(undefined); expect(window[key]).to.be(undefined);

View File

@@ -156,7 +156,7 @@ describe('ol.Object', function() {
it('dispatches events to object', function() { it('dispatches events to object', function() {
o.set('k', 1); o.set('k', 1);
expect(listener1).to.be.called(); expect(listener1.called).to.be(true);
expect(o.getKeys()).to.eql(['k']); expect(o.getKeys()).to.eql(['k']);
}); });
@@ -190,7 +190,7 @@ describe('ol.Object', function() {
it('does not call the setter', function() { it('does not call the setter', function() {
o.set('x', 1); o.set('x', 1);
expect(o.get('x')).to.eql(1); expect(o.get('x')).to.eql(1);
expect(o.setX).to.not.be.called(); expect(o.setX.called).to.be(false);
expect(o.getKeys()).to.eql(['x']); expect(o.getKeys()).to.eql(['x']);
}); });
@@ -206,7 +206,7 @@ describe('ol.Object', function() {
it('does not call the getter', function() { it('does not call the getter', function() {
expect(o.get('x')).to.be(undefined); expect(o.get('x')).to.be(undefined);
expect(o.getX).to.not.be.called(); expect(o.getX.called).to.be(false);
}); });
}); });
@@ -231,8 +231,8 @@ describe('ol.Object', function() {
it('dispatches the expected event', function() { it('dispatches the expected event', function() {
o.set('K', 1); o.set('K', 1);
expect(listener1).to.not.be.called(); expect(listener1.called).to.be(false);
expect(listener2).to.be.called(); expect(listener2.called).to.be(true);
expect(o.getKeys()).to.eql(['K']); expect(o.getKeys()).to.eql(['K']);
}); });

View File

@@ -30,15 +30,11 @@ describe('ol.obj.assign()', function() {
}); });
it('throws a TypeError with `undefined` as target', function() { it('throws a TypeError with `undefined` as target', function() {
expect(assign).withArgs(undefined).to.throwException(function(e) { expect(() => assign()).to.throwException(/Cannot convert undefined or null to object/);
expect(e).to.be.a(TypeError);
});
}); });
it('throws a TypeError with `null` as target', function() { it('throws a TypeError with `null` as target', function() {
expect(assign).withArgs(null).to.throwException(function(e) { expect(() => assign(null)).to.throwException(/Cannot convert undefined or null to object/);
expect(e).to.be.a(TypeError);
});
}); });
}); });

View File

@@ -74,7 +74,8 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
source = new VectorTileSource({ source = new VectorTileSource({
format: new MVT(), format: new MVT(),
tileClass: TileClass, tileClass: TileClass,
tileGrid: createXYZ() tileGrid: createXYZ(),
url: '{z}/{x}/{y}.pbf'
}); });
source.getSourceTiles = function() { source.getSourceTiles = function() {
return [new TileClass([0, 0, 0])]; return [new TileClass([0, 0, 0])];

View File

@@ -17,7 +17,7 @@ import Feature from '../../../../src/ol/Feature.js';
describe('ol.renderer.vector', function() { describe('ol.renderer.vector', function() {
describe('#renderFeature', function() { describe('#renderFeature', function() {
let builderGroup; let builderGroup;
let feature, iconStyle, style, squaredTolerance, listener, listenerThis; let feature, iconStyle, style, squaredTolerance, listener;
let iconStyleLoadSpy; let iconStyleLoadSpy;
beforeEach(function() { beforeEach(function() {
@@ -33,7 +33,6 @@ describe('ol.renderer.vector', function() {
}); });
squaredTolerance = 1; squaredTolerance = 1;
listener = function() {}; listener = function() {};
listenerThis = {};
iconStyleLoadSpy = sinon.stub(iconStyle, 'load').callsFake(function() { iconStyleLoadSpy = sinon.stub(iconStyle, 'load').callsFake(function() {
iconStyle.iconImage_.imageState_ = 1; // LOADING iconStyle.iconImage_.imageState_ = 1; // LOADING
}); });
@@ -49,16 +48,14 @@ describe('ol.renderer.vector', function() {
let listeners; let listeners;
// call #1 // call #1
renderFeature(builderGroup, feature, renderFeature(builderGroup, feature, style, squaredTolerance, listener);
style, squaredTolerance, listener, listenerThis);
expect(iconStyleLoadSpy.calledOnce).to.be.ok(); expect(iconStyleLoadSpy.calledOnce).to.be.ok();
listeners = iconStyle.iconImage_.listeners_['change']; listeners = iconStyle.iconImage_.listeners_['change'];
expect(listeners.length).to.eql(1); expect(listeners.length).to.eql(1);
// call #2 // call #2
renderFeature(builderGroup, feature, renderFeature(builderGroup, feature, style, squaredTolerance, listener);
style, squaredTolerance, listener, listenerThis);
expect(iconStyleLoadSpy.calledOnce).to.be.ok(); expect(iconStyleLoadSpy.calledOnce).to.be.ok();
listeners = iconStyle.iconImage_.listeners_['change']; listeners = iconStyle.iconImage_.listeners_['change'];
@@ -75,8 +72,7 @@ describe('ol.renderer.vector', function() {
style.getZIndex(), 'Image'); style.getZIndex(), 'Image');
const setImageStyleSpy = sinon.spy(imageReplay, 'setImageStyle'); const setImageStyleSpy = sinon.spy(imageReplay, 'setImageStyle');
const drawPointSpy = sinon.stub(imageReplay, 'drawPoint').callsFake(VOID); const drawPointSpy = sinon.stub(imageReplay, 'drawPoint').callsFake(VOID);
renderFeature(builderGroup, feature, renderFeature(builderGroup, feature, style, squaredTolerance, listener);
style, squaredTolerance, listener, listenerThis);
expect(setImageStyleSpy.called).to.be(false); expect(setImageStyleSpy.called).to.be(false);
setImageStyleSpy.restore(); setImageStyleSpy.restore();
drawPointSpy.restore(); drawPointSpy.restore();
@@ -88,8 +84,7 @@ describe('ol.renderer.vector', function() {
style.getZIndex(), 'Image'); style.getZIndex(), 'Image');
const setImageStyleSpy = sinon.spy(imageReplay, 'setImageStyle'); const setImageStyleSpy = sinon.spy(imageReplay, 'setImageStyle');
const drawMultiPointSpy = sinon.stub(imageReplay, 'drawMultiPoint').callsFake(VOID); const drawMultiPointSpy = sinon.stub(imageReplay, 'drawMultiPoint').callsFake(VOID);
renderFeature(builderGroup, feature, renderFeature(builderGroup, feature, style, squaredTolerance, listener);
style, squaredTolerance, listener, listenerThis);
expect(setImageStyleSpy.called).to.be(false); expect(setImageStyleSpy.called).to.be(false);
setImageStyleSpy.restore(); setImageStyleSpy.restore();
drawMultiPointSpy.restore(); drawMultiPointSpy.restore();
@@ -102,8 +97,7 @@ describe('ol.renderer.vector', function() {
const setFillStrokeStyleSpy = sinon.spy(lineStringReplay, const setFillStrokeStyleSpy = sinon.spy(lineStringReplay,
'setFillStrokeStyle'); 'setFillStrokeStyle');
const drawLineStringSpy = sinon.stub(lineStringReplay, 'drawLineString').callsFake(VOID); const drawLineStringSpy = sinon.stub(lineStringReplay, 'drawLineString').callsFake(VOID);
renderFeature(builderGroup, feature, renderFeature(builderGroup, feature, style, squaredTolerance, listener);
style, squaredTolerance, listener, listenerThis);
expect(setFillStrokeStyleSpy.called).to.be(true); expect(setFillStrokeStyleSpy.called).to.be(true);
expect(drawLineStringSpy.called).to.be(true); expect(drawLineStringSpy.called).to.be(true);
setFillStrokeStyleSpy.restore(); setFillStrokeStyleSpy.restore();
@@ -117,8 +111,7 @@ describe('ol.renderer.vector', function() {
const setFillStrokeStyleSpy = sinon.spy(lineStringReplay, const setFillStrokeStyleSpy = sinon.spy(lineStringReplay,
'setFillStrokeStyle'); 'setFillStrokeStyle');
const drawMultiLineStringSpy = sinon.stub(lineStringReplay, 'drawMultiLineString').callsFake(VOID); const drawMultiLineStringSpy = sinon.stub(lineStringReplay, 'drawMultiLineString').callsFake(VOID);
renderFeature(builderGroup, feature, renderFeature(builderGroup, feature, style, squaredTolerance, listener);
style, squaredTolerance, listener, listenerThis);
expect(setFillStrokeStyleSpy.called).to.be(true); expect(setFillStrokeStyleSpy.called).to.be(true);
expect(drawMultiLineStringSpy.called).to.be(true); expect(drawMultiLineStringSpy.called).to.be(true);
setFillStrokeStyleSpy.restore(); setFillStrokeStyleSpy.restore();
@@ -133,8 +126,7 @@ describe('ol.renderer.vector', function() {
const setFillStrokeStyleSpy = sinon.spy(polygonReplay, const setFillStrokeStyleSpy = sinon.spy(polygonReplay,
'setFillStrokeStyle'); 'setFillStrokeStyle');
const drawPolygonSpy = sinon.stub(polygonReplay, 'drawPolygon').callsFake(VOID); const drawPolygonSpy = sinon.stub(polygonReplay, 'drawPolygon').callsFake(VOID);
renderFeature(builderGroup, feature, renderFeature(builderGroup, feature, style, squaredTolerance, listener);
style, squaredTolerance, listener, listenerThis);
expect(setFillStrokeStyleSpy.called).to.be(true); expect(setFillStrokeStyleSpy.called).to.be(true);
expect(drawPolygonSpy.called).to.be(true); expect(drawPolygonSpy.called).to.be(true);
setFillStrokeStyleSpy.restore(); setFillStrokeStyleSpy.restore();
@@ -149,8 +141,7 @@ describe('ol.renderer.vector', function() {
const setFillStrokeStyleSpy = sinon.spy(polygonReplay, const setFillStrokeStyleSpy = sinon.spy(polygonReplay,
'setFillStrokeStyle'); 'setFillStrokeStyle');
const drawMultiPolygonSpy = sinon.stub(polygonReplay, 'drawMultiPolygon').callsFake(VOID); const drawMultiPolygonSpy = sinon.stub(polygonReplay, 'drawMultiPolygon').callsFake(VOID);
renderFeature(builderGroup, feature, renderFeature(builderGroup, feature, style, squaredTolerance, listener);
style, squaredTolerance, listener, listenerThis);
expect(setFillStrokeStyleSpy.called).to.be(true); expect(setFillStrokeStyleSpy.called).to.be(true);
expect(drawMultiPolygonSpy.called).to.be(true); expect(drawMultiPolygonSpy.called).to.be(true);
setFillStrokeStyleSpy.restore(); setFillStrokeStyleSpy.restore();

View File

@@ -211,7 +211,7 @@ describe('ol.source.ImageWMS', function() {
const source = new ImageWMS(options); const source = new ImageWMS(options);
const image = source.getImage(extent, resolution, pixelRatio, projection); const image = source.getImage(extent, resolution, pixelRatio, projection);
image.load(); image.load();
expect(imageLoadFunction).to.be.called(); expect(imageLoadFunction.called).to.be(true);
expect(imageLoadFunction.calledWith(image, image.src_)).to.be(true); expect(imageLoadFunction.calledWith(image, image.src_)).to.be(true);
}); });

View File

@@ -34,7 +34,7 @@ describe('ol.source.Vector', function() {
it('does not call the callback', function() { it('does not call the callback', function() {
const f = sinon.spy(); const f = sinon.spy();
vectorSource.forEachFeatureInExtent(infiniteExtent, f); vectorSource.forEachFeatureInExtent(infiniteExtent, f);
expect(f).not.to.be.called(); expect(f.called).to.be(false);
}); });
}); });
@@ -71,7 +71,7 @@ describe('ol.source.Vector', function() {
const listener = sinon.spy(); const listener = sinon.spy();
listen(vectorSource, 'change', listener); listen(vectorSource, 'change', listener);
vectorSource.addFeature(pointFeature); vectorSource.addFeature(pointFeature);
expect(listener).to.be.called(); expect(listener.called).to.be(true);
}); });
it('adds same id features only once', function() { it('adds same id features only once', function() {
@@ -249,9 +249,9 @@ describe('ol.source.Vector', function() {
vectorSource.clear(true); vectorSource.clear(true);
expect(vectorSource.getFeatures()).to.eql([]); expect(vectorSource.getFeatures()).to.eql([]);
expect(vectorSource.isEmpty()).to.be(true); expect(vectorSource.isEmpty()).to.be(true);
expect(removeFeatureSpy).not.to.be.called(); expect(removeFeatureSpy.called).to.be(false);
expect(removeFeatureSpy.callCount).to.be(0); expect(removeFeatureSpy.callCount).to.be(0);
expect(clearSourceSpy).to.be.called(); expect(clearSourceSpy.called).to.be(true);
expect(clearSourceSpy.callCount).to.be(1); expect(clearSourceSpy.callCount).to.be(1);
}); });
@@ -263,9 +263,9 @@ describe('ol.source.Vector', function() {
vectorSource.clear(); vectorSource.clear();
expect(vectorSource.getFeatures()).to.eql([]); expect(vectorSource.getFeatures()).to.eql([]);
expect(vectorSource.isEmpty()).to.be(true); expect(vectorSource.isEmpty()).to.be(true);
expect(removeFeatureSpy).to.be.called(); expect(removeFeatureSpy.called).to.be(true);
expect(removeFeatureSpy.callCount).to.be(features.length); expect(removeFeatureSpy.callCount).to.be(features.length);
expect(clearSourceSpy).to.be.called(); expect(clearSourceSpy.called).to.be(true);
expect(clearSourceSpy.callCount).to.be(1); expect(clearSourceSpy.callCount).to.be(1);
}); });
@@ -323,14 +323,14 @@ describe('ol.source.Vector', function() {
const listener = sinon.spy(); const listener = sinon.spy();
listen(vectorSource, 'change', listener); listen(vectorSource, 'change', listener);
vectorSource.removeFeature(features[0]); vectorSource.removeFeature(features[0]);
expect(listener).to.be.called(); expect(listener.called).to.be(true);
}); });
it('fires a removefeature event', function() { it('fires a removefeature event', function() {
const listener = sinon.spy(); const listener = sinon.spy();
listen(vectorSource, 'removefeature', listener); listen(vectorSource, 'removefeature', listener);
vectorSource.removeFeature(features[0]); vectorSource.removeFeature(features[0]);
expect(listener).to.be.called(); expect(listener.called).to.be(true);
}); });
}); });
@@ -416,7 +416,7 @@ describe('ol.source.Vector', function() {
const listener = sinon.spy(); const listener = sinon.spy();
listen(vectorSource, 'change', listener); listen(vectorSource, 'change', listener);
feature.set('foo', 'bar'); feature.set('foo', 'bar');
expect(listener).to.be.called(); expect(listener.called).to.be(true);
}); });
it('fires a changefeature event when updating a feature', function() { it('fires a changefeature event when updating a feature', function() {
@@ -427,7 +427,7 @@ describe('ol.source.Vector', function() {
}); });
vectorSource.on('changefeature', listener); vectorSource.on('changefeature', listener);
feature.setStyle(null); feature.setStyle(null);
expect(listener).to.be.called(); expect(listener.called).to.be(true);
}); });
}); });

View File

@@ -71,19 +71,13 @@ describe('ol.source.VectorTile', function() {
}); });
}); });
it('handles empty tiles', function(done) { it('handles empty tiles', function() {
const source = new VectorTileSource({ const source = new VectorTileSource({
format: new GeoJSON(), format: new GeoJSON(),
url: '' url: ''
}); });
const tile = source.getTile(0, 0, 0, 1, source.getProjection()); const tile = source.getTile(0, 0, 0, 1, source.getProjection());
expect(tile.getState()).to.be(TileState.EMPTY);
const key = listen(tile, 'change', function(e) {
unlistenByKey(key);
expect(tile.getState()).to.be(TileState.EMPTY);
done();
});
tile.load();
}); });
it('creates empty tiles outside the source extent', function() { it('creates empty tiles outside the source extent', function() {
@@ -103,14 +97,30 @@ describe('ol.source.VectorTile', function() {
expect(tile.getState()).to.be(TileState.EMPTY); expect(tile.getState()).to.be(TileState.EMPTY);
}); });
it('creates empty tiles when the tileUrlFunction returns undefined', function() {
const source = new VectorTileSource({
tileUrlFunction: function(tileCoord) {
return;
}
});
const tile = source.getTile(1, 1, 1, 1, source.getProjection());
expect(tile.getState()).to.be(TileState.EMPTY);
});
it('creates non-empty tiles outside the world extent when wrapX === true', function() { it('creates non-empty tiles outside the world extent when wrapX === true', function() {
const source = new VectorTileSource({}); const source = new VectorTileSource({
url: '{z}/{x}/{y}.pbf'
});
const tile = source.getTile(0, -1, 0, 1, source.getProjection()); const tile = source.getTile(0, -1, 0, 1, source.getProjection());
expect(tile.getState()).to.be(TileState.IDLE); expect(tile.getState()).to.be(TileState.IDLE);
}); });
it('creates non-empty tiles for overzoomed resolutions', function() { it('creates non-empty tiles for overzoomed resolutions', function() {
const source = new VectorTileSource({ const source = new VectorTileSource({
url: '{z}/{x}/{y}.pbf',
tileLoadFunction: function(tile) {
tile.setLoader(function() {});
},
maxZoom: 16 maxZoom: 16
}); });
const tile = source.getTile(24, 9119385, 5820434, 1, source.getProjection()); const tile = source.getTile(24, 9119385, 5820434, 1, source.getProjection());

View File

@@ -454,7 +454,7 @@ describe('ol.View', function() {
maxResolution: maxResolution, maxResolution: maxResolution,
constrainResolution: true constrainResolution: true
}); });
expect(fn(defaultMaxRes, 0, size)).to.be(defaultMaxRes / 2); expect(fn(defaultMaxRes, 0, size)).to.be(maxResolution / 4);
}); });
it('enabled, with constrainResolution', function() { it('enabled, with constrainResolution', function() {

17
test/spec/util.js Normal file
View File

@@ -0,0 +1,17 @@
export function overrideRAF() {
const raf = window.requestAnimationFrame;
const caf = window.cancelAnimationFrame;
window.requestAnimationFrame = function(callback) {
return setTimeout(callback, 1);
};
window.cancelAnimationFrame = function(key) {
return clearTimeout(key);
};
return function() {
window.requestAnimationFrame = raf;
window.cancelAnimationFrame = caf;
};
}

View File

@@ -1,4 +1,3 @@
import {equals} from '../src/ol/array.js';
// avoid importing anything that results in an instanceof check // avoid importing anything that results in an instanceof check
// since these extensions are global, instanceof checks fail with modules // since these extensions are global, instanceof checks fail with modules
@@ -88,23 +87,6 @@ import {equals} from '../src/ol/array.js';
}; };
/**
* Assert that a sinon spy was called.
* @return {expect.Assertion} The assertion.
*/
expect.Assertion.prototype.called = function() {
this.assert(
this.obj.called,
function() {
return 'expected ' + expect.stringify(this.obj) + ' to be called';
},
function() {
return 'expected ' + expect.stringify(this.obj) + ' not to be called';
});
return this;
};
function getChildNodes(node, options) { function getChildNodes(node, options) {
// check whitespace // check whitespace
if (options && options.includeWhiteSpace) { if (options && options.includeWhiteSpace) {
@@ -309,50 +291,6 @@ import {equals} from '../src/ol/array.js';
}; };
/**
* Checks if the array sort of equals another array.
* @param {Object} obj The other object.
* @return {expect.Assertion} The assertion.
*/
expect.Assertion.prototype.arreql = function(obj) {
this.assert(
equals(this.obj, obj),
function() {
return 'expected ' + expect.stringify(this.obj) +
' to sort of equal ' + expect.stringify(obj);
},
function() {
return 'expected ' + expect.stringify(this.obj) +
' to sort of not equal ' + expect.stringify(obj);
});
return this;
};
/**
* Checks if the array sort of equals another array (allows NaNs to be equal).
* @param {Object} obj The other object.
* @return {expect.Assertion} The assertion.
*/
expect.Assertion.prototype.arreqlNaN = function(obj) {
function compare(a, i) {
const b = obj[i];
return a === b || (typeof a === 'number' && typeof b === 'number' &&
isNaN(a) && isNaN(b));
}
this.assert(
this.obj.length === obj.length && this.obj.every(compare),
function() {
return 'expected ' + expect.stringify(this.obj) +
' to sort of equal ' + expect.stringify(obj);
},
function() {
return 'expected ' + expect.stringify(this.obj) +
' to sort of not equal ' + expect.stringify(obj);
});
return this;
};
global.createMapDiv = function(width, height) { global.createMapDiv = function(width, height) {
const target = document.createElement('div'); const target = document.createElement('div');
const style = target.style; const style = target.style;