Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7acbc40d5 | ||
|
|
176dccd6df | ||
|
|
526679433e | ||
|
|
b64ab8a6b2 | ||
|
|
6c6c4ab1df | ||
|
|
d3b47c794e | ||
|
|
8aa4a59fcf | ||
|
|
61e8b39626 | ||
|
|
8c7aafd4df | ||
|
|
37f9a6a6e9 | ||
|
|
2e1dee1994 | ||
|
|
ec9dcbee88 | ||
|
|
211c2ee531 | ||
|
|
e1d3560dbf | ||
|
|
1d6284725d | ||
|
|
c69201d5ad | ||
|
|
92e025b8e5 | ||
|
|
7c8b2215d4 | ||
|
|
d2b25533c2 | ||
|
|
733b883ac0 | ||
|
|
eaa5af2c7a | ||
|
|
1260dfc153 | ||
|
|
76df721b98 | ||
|
|
a55fec2759 | ||
|
|
c984b28752 | ||
|
|
3b02f5597e | ||
|
|
40f8510083 | ||
|
|
7f8fdd6219 | ||
|
|
ea0e1bff29 | ||
|
|
9b2089bc8f | ||
|
|
32644c7ba9 | ||
|
|
80b4f51d6e | ||
|
|
c8456868bd | ||
|
|
239f5745c1 | ||
|
|
70706443f5 | ||
|
|
47dd60104d | ||
|
|
80cf76e783 | ||
|
|
a7605c7447 | ||
|
|
76af2b6466 | ||
|
|
a996d62d46 | ||
|
|
f67476dd8f | ||
|
|
0e402073da | ||
|
|
07678d960a | ||
|
|
a47025b9c9 | ||
|
|
99c56a1f08 | ||
|
|
701dc3b54a | ||
|
|
ea88e6cbd4 | ||
|
|
b40709ea5b | ||
|
|
20de880d2b | ||
|
|
1827d7a0d9 | ||
|
|
400667fe95 | ||
|
|
d0a1fdc1d2 | ||
|
|
dd1243db73 |
2
.github/stale.yml
vendored
2
.github/stale.yml
vendored
@@ -6,6 +6,8 @@ daysUntilClose: 7
|
||||
exemptLabels:
|
||||
- blocker
|
||||
- regression
|
||||
- bug
|
||||
- 'pull request accepted'
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
|
||||
34
changelog/v6.0.1.md
Normal file
34
changelog/v6.0.1.md
Normal 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>
|
||||
@@ -1,6 +1,6 @@
|
||||
import {Map, View} from '../src/ol/index.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 {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
||||
import {useGeographic} from '../src/ol/proj.js';
|
||||
@@ -39,19 +39,30 @@ const draw = new Draw({
|
||||
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');
|
||||
function onChange() {
|
||||
removeInteractions();
|
||||
switch (mode.value) {
|
||||
case 'draw': {
|
||||
map.removeInteraction(modify);
|
||||
map.removeInteraction(select);
|
||||
map.addInteraction(draw);
|
||||
map.addInteraction(snap);
|
||||
break;
|
||||
}
|
||||
case 'modify': {
|
||||
map.removeInteraction(draw);
|
||||
map.addInteraction(select);
|
||||
map.addInteraction(modify);
|
||||
map.addInteraction(snap);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
15
examples/immediate-geographic.html
Normal file
15
examples/immediate-geographic.html
Normal 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>
|
||||
64
examples/immediate-geographic.js
Normal file
64
examples/immediate-geographic.js
Normal 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
171
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ol",
|
||||
"version": "6.0.0-beta.15",
|
||||
"version": "6.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -5349,9 +5349,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.3.1.tgz",
|
||||
"integrity": "sha512-c0HoNHzDiHpBt4Kqe99N8tdLPKAnGCQ73gYMPWtAYM4PwGnf7xl8PBUHJqh9ijlzt2uQKaSRxbXRt+rZ7M2/kA==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.0.tgz",
|
||||
"integrity": "sha512-xkRtOt3/3DzTKMOt3xahj2M/EqNhY988T+imYSlMgs5fVhLN2fmKVVj0LtEGmb+3UUYV5Qmm1052Mm3dIQxOvw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"neo-async": "^2.6.0",
|
||||
@@ -6455,9 +6455,9 @@
|
||||
}
|
||||
},
|
||||
"jsdoc-plugin-typescript": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc-plugin-typescript/-/jsdoc-plugin-typescript-2.0.2.tgz",
|
||||
"integrity": "sha512-4/SveLQzTCkcQFfx9bDtVNRASmpv9E7iKncbSPkjnb+tm+9qHhCkF1Ewml3vBKZKU58LgW1zUsn4JYRlowP7NQ==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc-plugin-typescript/-/jsdoc-plugin-typescript-2.0.3.tgz",
|
||||
"integrity": "sha512-pcAHwWRyui9kUQ06L36Uyxw2m0Iy5dXqt/rGDg3cKj+2NSDZGeuw+TlbIURBJBpAkWi43zwojTtYpXo30vQJ+A==",
|
||||
"dev": true
|
||||
},
|
||||
"jsesc": {
|
||||
@@ -7298,9 +7298,9 @@
|
||||
}
|
||||
},
|
||||
"mocha": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz",
|
||||
"integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==",
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.1.tgz",
|
||||
"integrity": "sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-colors": "3.2.3",
|
||||
@@ -7323,9 +7323,9 @@
|
||||
"supports-color": "6.0.0",
|
||||
"which": "1.3.1",
|
||||
"wide-align": "1.1.3",
|
||||
"yargs": "13.2.2",
|
||||
"yargs-parser": "13.0.0",
|
||||
"yargs-unparser": "1.5.0"
|
||||
"yargs": "13.3.0",
|
||||
"yargs-parser": "13.1.1",
|
||||
"yargs-unparser": "1.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-colors": {
|
||||
@@ -7340,6 +7340,17 @@
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"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": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
@@ -7392,23 +7403,33 @@
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "13.2.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
|
||||
"integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
|
||||
"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": {
|
||||
"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",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"os-locale": "^3.1.0",
|
||||
"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.0.0"
|
||||
"yargs-parser": "^13.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11368,9 +11389,9 @@
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
|
||||
"integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
|
||||
"integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
@@ -11386,62 +11407,80 @@
|
||||
}
|
||||
},
|
||||
"yargs-unparser": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
|
||||
"integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
|
||||
"integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"flat": "^4.1.0",
|
||||
"lodash": "^4.17.11",
|
||||
"yargs": "^12.0.5"
|
||||
"lodash": "^4.17.15",
|
||||
"yargs": "^13.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"dev": true
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
|
||||
"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==",
|
||||
"cliui": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
|
||||
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^4.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^3.0.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"
|
||||
"string-width": "^3.1.0",
|
||||
"strip-ansi": "^5.2.0",
|
||||
"wrap-ansi": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
|
||||
"integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
|
||||
"string-width": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
||||
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
"emoji-regex": "^7.0.1",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ol",
|
||||
"version": "6.0.0",
|
||||
"version": "6.0.1",
|
||||
"description": "OpenLayers mapping library",
|
||||
"keywords": [
|
||||
"map",
|
||||
@@ -63,13 +63,13 @@
|
||||
"fs-extra": "^8.0.0",
|
||||
"glob": "^7.1.4",
|
||||
"globby": "^10.0.0",
|
||||
"handlebars": "4.3.1",
|
||||
"handlebars": "4.4.0",
|
||||
"html-to-image": "^0.1.0",
|
||||
"istanbul": "0.4.5",
|
||||
"istanbul-instrumenter-loader": "^3.0.1",
|
||||
"jquery": "3.4.1",
|
||||
"jsdoc": "3.6.3",
|
||||
"jsdoc-plugin-typescript": "^2.0.2",
|
||||
"jsdoc-plugin-typescript": "2.0.3",
|
||||
"karma": "^4.1.0",
|
||||
"karma-chrome-launcher": "3.1.0",
|
||||
"karma-coverage": "^2.0.1",
|
||||
@@ -80,7 +80,7 @@
|
||||
"karma-webpack": "^4.0.0-rc.2",
|
||||
"loglevelnext": "^3.0.1",
|
||||
"marked": "0.7.0",
|
||||
"mocha": "6.2.0",
|
||||
"mocha": "6.2.1",
|
||||
"ol-mapbox-style": "^5.0.0-beta.3",
|
||||
"pixelmatch": "^5.0.0",
|
||||
"pngjs": "^3.4.0",
|
||||
|
||||
BIN
rendering/cases/immediate-geographic/expected.png
Normal file
BIN
rendering/cases/immediate-geographic/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
40
rendering/cases/immediate-geographic/main.js
Normal file
40
rendering/cases/immediate-geographic/main.js
Normal 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();
|
||||
@@ -231,7 +231,7 @@ class Feature extends BaseObject {
|
||||
* styles. If it is `null` the feature has no style (a `null` style).
|
||||
* @param {import("./style/Style.js").StyleLike} style Style for this feature.
|
||||
* @api
|
||||
* @fires module:ol/events/Event~Event#event:change
|
||||
* @fires module:ol/events/Event~BaseEvent#event:change
|
||||
*/
|
||||
setStyle(style) {
|
||||
this.style_ = style;
|
||||
@@ -246,7 +246,7 @@ class Feature extends BaseObject {
|
||||
* {@link module:ol/source/Vector~VectorSource#getFeatureById} method.
|
||||
* @param {number|string|undefined} id The feature id.
|
||||
* @api
|
||||
* @fires module:ol/events/Event~Event#event:change
|
||||
* @fires module:ol/events/Event~BaseEvent#event:change
|
||||
*/
|
||||
setId(id) {
|
||||
this.id_ = id;
|
||||
|
||||
@@ -81,7 +81,7 @@ class GeolocationError extends BaseEvent {
|
||||
* window.console.log(geolocation.getPosition());
|
||||
* });
|
||||
*
|
||||
* @fires module:ol/events/Event~Event#event:error
|
||||
* @fires module:ol/events/Event~BaseEvent#event:error
|
||||
* @api
|
||||
*/
|
||||
class Geolocation extends BaseObject {
|
||||
@@ -98,7 +98,7 @@ class Geolocation extends BaseObject {
|
||||
/**
|
||||
* The unprojected (EPSG:4326) device position.
|
||||
* @private
|
||||
* @type {import("./coordinate.js").Coordinate}
|
||||
* @type {?import("./coordinate.js").Coordinate}
|
||||
*/
|
||||
this.position_ = null;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ class ImageWrapper extends ImageBase {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {function():void}
|
||||
* @type {?function():void}
|
||||
*/
|
||||
this.unlisten_ = null;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class ImageTile extends Tile {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {function():void}
|
||||
* @type {?function():void}
|
||||
*/
|
||||
this.unlisten_ = null;
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ class MapBrowserEvent extends MapEvent {
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import EventType from './events/EventType.js';
|
||||
* and unregistration. A generic `change` event is always available through
|
||||
* {@link module:ol/Observable~Observable#changed}.
|
||||
*
|
||||
* @fires import("./events/Event.js").Event
|
||||
* @fires import("./events/Event.js").default
|
||||
* @api
|
||||
*/
|
||||
class Observable extends EventTarget {
|
||||
|
||||
@@ -436,8 +436,8 @@ class Overlay extends BaseObject {
|
||||
|
||||
/**
|
||||
* Get the extent of an element relative to the document
|
||||
* @param {HTMLElement|undefined} element The element.
|
||||
* @param {import("./size.js").Size|undefined} size The size of the element.
|
||||
* @param {HTMLElement} element The element.
|
||||
* @param {import("./size.js").Size} size The size of the element.
|
||||
* @return {import("./extent.js").Extent} The extent.
|
||||
* @protected
|
||||
*/
|
||||
|
||||
@@ -232,7 +232,7 @@ class PluggableMap extends BaseObject {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<import("./events.js").EventsKey>}
|
||||
* @type {?Array<import("./events.js").EventsKey>}
|
||||
*/
|
||||
this.layerGroupPropertyListenerKeys_ = null;
|
||||
|
||||
@@ -292,7 +292,7 @@ class PluggableMap extends BaseObject {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<import("./events.js").EventsKey>}
|
||||
* @type {?Array<import("./events.js").EventsKey>}
|
||||
*/
|
||||
this.keyHandlerKeys_ = null;
|
||||
|
||||
@@ -375,9 +375,9 @@ class PluggableMap extends BaseObject {
|
||||
* @param {import("./control/Control.js").default} control Control.
|
||||
* @this {PluggableMap}
|
||||
*/
|
||||
(function(control) {
|
||||
function(control) {
|
||||
control.setMap(this);
|
||||
}).bind(this));
|
||||
}.bind(this));
|
||||
|
||||
this.controls.addEventListener(CollectionEventType.ADD,
|
||||
/**
|
||||
@@ -400,9 +400,9 @@ class PluggableMap extends BaseObject {
|
||||
* @param {import("./interaction/Interaction.js").default} interaction Interaction.
|
||||
* @this {PluggableMap}
|
||||
*/
|
||||
(function(interaction) {
|
||||
function(interaction) {
|
||||
interaction.setMap(this);
|
||||
}).bind(this));
|
||||
}.bind(this));
|
||||
|
||||
this.interactions.addEventListener(CollectionEventType.ADD,
|
||||
/**
|
||||
@@ -604,7 +604,7 @@ class PluggableMap extends BaseObject {
|
||||
}
|
||||
const options = opt_options || /** @type {AtPixelOptions} */ ({});
|
||||
const hitTolerance = options.hitTolerance !== undefined ?
|
||||
opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
|
||||
options.hitTolerance * this.frameState_.pixelRatio : 0;
|
||||
const layerFilter = options.layerFilter || TRUE;
|
||||
return this.renderer_.forEachLayerAtPixel(pixel, this.frameState_, hitTolerance, callback, layerFilter);
|
||||
}
|
||||
|
||||
@@ -241,6 +241,9 @@ class Tile extends EventTarget {
|
||||
* @api
|
||||
*/
|
||||
setState(state) {
|
||||
if (this.state !== TileState.ERROR && this.state > state) {
|
||||
throw new Error('Tile load sequence violation');
|
||||
}
|
||||
this.state = state;
|
||||
this.changed();
|
||||
}
|
||||
|
||||
@@ -112,12 +112,10 @@ class TileQueue extends PriorityQueue {
|
||||
if (state === TileState.ABORT) {
|
||||
abortedTiles = true;
|
||||
} else if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
|
||||
this.tilesLoadingKeys_[tileKey] = true;
|
||||
++this.tilesLoading_;
|
||||
++newLoads;
|
||||
tile.load();
|
||||
if (tile.getState() === TileState.LOADING) {
|
||||
this.tilesLoadingKeys_[tileKey] = true;
|
||||
++this.tilesLoading_;
|
||||
++newLoads;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newLoads === 0 && abortedTiles) {
|
||||
|
||||
@@ -97,7 +97,7 @@ class MousePosition extends Control {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../proj/Projection.js").default}
|
||||
* @type {?import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.mapProjection_ = null;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class ZoomToExtent extends Control {
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {import("../extent.js").Extent}
|
||||
* @type {?import("../extent.js").Extent}
|
||||
* @protected
|
||||
*/
|
||||
this.extent = options.extent ? options.extent : null;
|
||||
|
||||
@@ -72,6 +72,9 @@ export const CLASS_COLLAPSED = 'ol-collapsed';
|
||||
* @return {FontParameters} The font families (or null if the input spec is invalid).
|
||||
*/
|
||||
export const getFontParameters = (function() {
|
||||
/**
|
||||
* @type {CSSStyleDeclaration}
|
||||
*/
|
||||
let style;
|
||||
/**
|
||||
* @type {Object<string, FontParameters>}
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
export default {
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
CHANGE: 'change',
|
||||
|
||||
/**
|
||||
* Generic error event. Triggered when an error occurs.
|
||||
* @event module:ol/events/Event~Event#error
|
||||
* @event module:ol/events/Event~BaseEvent#error
|
||||
* @api
|
||||
*/
|
||||
ERROR: 'error',
|
||||
|
||||
@@ -73,7 +73,7 @@ class TopoJSON extends JSONFeature {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<string>}
|
||||
* @type {?Array<string>}
|
||||
*/
|
||||
this.layers_ = options.layers ? options.layers : null;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import {abstract} from '../util.js';
|
||||
import BaseObject from '../Object.js';
|
||||
import {createEmpty, getHeight, returnOrUpdate} from '../extent.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 {create as createTransform, compose as composeTransform} from '../transform.js';
|
||||
import {memoizeOne} from '../functions.js';
|
||||
@@ -62,17 +62,15 @@ class Geometry extends BaseObject {
|
||||
* @abstract
|
||||
* @param {number} revision The geometry revision.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {import("../proj/Projection.js").default} [sourceProjection] The source projection.
|
||||
* @param {import("../proj/Projection.js").default} [destProjection] The destination projection.
|
||||
* @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.
|
||||
* @return {Geometry} Simplified geometry.
|
||||
*/
|
||||
this.simplifyTransformedInternal = memoizeOne(function(revision, squaredTolerance, sourceProjection, destProjection) {
|
||||
if (!sourceProjection || !destProjection) {
|
||||
this.simplifyTransformedInternal = memoizeOne(function(revision, squaredTolerance, opt_transform) {
|
||||
if (!opt_transform) {
|
||||
return this.getSimplifiedGeometry(squaredTolerance);
|
||||
}
|
||||
const transform = getTransformFromProjections(sourceProjection, destProjection);
|
||||
const clone = this.clone();
|
||||
clone.applyTransform(transform);
|
||||
clone.applyTransform(opt_transform);
|
||||
return clone.getSimplifiedGeometry(squaredTolerance);
|
||||
});
|
||||
|
||||
@@ -82,12 +80,11 @@ class Geometry extends BaseObject {
|
||||
* Get a transformed and simplified version of the geometry.
|
||||
* @abstract
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {import("../proj/Projection.js").default} sourceProjection The source projection.
|
||||
* @param {import("../proj/Projection.js").default} destProjection The destination projection.
|
||||
* @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.
|
||||
* @return {Geometry} Simplified geometry.
|
||||
*/
|
||||
simplifyTransformed(squaredTolerance, sourceProjection, destProjection) {
|
||||
return this.simplifyTransformedInternal(this.getRevision(), squaredTolerance, sourceProjection, destProjection);
|
||||
simplifyTransformed(squaredTolerance, opt_transform) {
|
||||
return this.simplifyTransformedInternal(this.getRevision(), squaredTolerance, opt_transform);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -115,7 +115,7 @@ class DragAndDrop extends Interaction {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<import("../events.js").EventsKey>}
|
||||
* @type {?Array<import("../events.js").EventsKey>}
|
||||
*/
|
||||
this.dropListenKeys_ = null;
|
||||
|
||||
|
||||
@@ -920,12 +920,12 @@ class Modify extends PointerInteraction {
|
||||
*/
|
||||
handlePointerAtPixel_(pixel, map) {
|
||||
const pixelCoordinate = map.getCoordinateFromPixel(pixel);
|
||||
const projection = map.getView().getProjection();
|
||||
const sortByDistance = function(a, b) {
|
||||
return pointDistanceToSegmentDataSquared(pixelCoordinate, a) -
|
||||
pointDistanceToSegmentDataSquared(pixelCoordinate, b);
|
||||
return projectedDistanceToSegmentDataSquared(pixelCoordinate, a, projection) -
|
||||
projectedDistanceToSegmentDataSquared(pixelCoordinate, b, projection);
|
||||
};
|
||||
|
||||
const projection = map.getView().getProjection();
|
||||
const viewExtent = fromUserExtent(createExtent(pixelCoordinate, tempExtent), projection);
|
||||
const buffer = map.getView().getResolution() * this.pixelTolerance_;
|
||||
const box = toUserExtent(bufferExtent(viewExtent, buffer, tempExtent), projection);
|
||||
@@ -1235,9 +1235,10 @@ function compareIndexes(a, b) {
|
||||
* which to calculate the distance.
|
||||
* @param {SegmentData} segmentData The object describing the line
|
||||
* 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.
|
||||
*/
|
||||
function pointDistanceToSegmentDataSquared(pointCoordinates, segmentData) {
|
||||
function projectedDistanceToSegmentDataSquared(pointCoordinates, segmentData, projection) {
|
||||
const geometry = segmentData.geometry;
|
||||
|
||||
if (geometry.getType() === GeometryType.CIRCLE) {
|
||||
@@ -1251,7 +1252,11 @@ function pointDistanceToSegmentDataSquared(pointCoordinates, segmentData) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@ import PointerInteraction from './Pointer.js';
|
||||
import {getValues} from '../obj.js';
|
||||
import VectorEventType from '../source/VectorEventType.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) {
|
||||
return /** @type {import("../Feature.js").default} */ (/** @type {import("../Collection.js").CollectionEvent} */ (evt).element);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const tempSegment = [];
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Handles snapping of vector features while modifying or drawing them. The
|
||||
@@ -70,10 +72,12 @@ function getFeatureFromEvent(evt) {
|
||||
*
|
||||
* import Snap from 'ol/interaction/Snap';
|
||||
*
|
||||
* var snap = new Snap({
|
||||
* const snap = new Snap({
|
||||
* source: source
|
||||
* });
|
||||
*
|
||||
* map.addInteraction(snap);
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Snap extends PointerInteraction {
|
||||
@@ -149,13 +153,6 @@ class Snap extends PointerInteraction {
|
||||
*/
|
||||
this.pendingFeatures_ = {};
|
||||
|
||||
/**
|
||||
* Used for distance sorting in sortByDistance_
|
||||
* @type {import("../coordinate.js").Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.pixelCoordinate_ = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
@@ -163,13 +160,6 @@ class Snap extends PointerInteraction {
|
||||
this.pixelTolerance_ = options.pixelTolerance !== undefined ?
|
||||
options.pixelTolerance : 10;
|
||||
|
||||
/**
|
||||
* @type {function(SegmentData, SegmentData): number}
|
||||
* @private
|
||||
*/
|
||||
this.sortByDistance_ = sortByDistance.bind(this);
|
||||
|
||||
|
||||
/**
|
||||
* Segment RTree for each layer
|
||||
* @type {import("../structs/RBush.js").default<SegmentData>}
|
||||
@@ -177,22 +167,21 @@ class Snap extends PointerInteraction {
|
||||
*/
|
||||
this.rBush_ = new RBush();
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Object<string, function(import("../Feature.js").default, import("../geom/Geometry.js").default): void>}
|
||||
*/
|
||||
this.SEGMENT_WRITERS_ = {
|
||||
'Point': this.writePointGeometry_,
|
||||
'LineString': this.writeLineStringGeometry_,
|
||||
'LinearRing': this.writeLineStringGeometry_,
|
||||
'Polygon': this.writePolygonGeometry_,
|
||||
'MultiPoint': this.writeMultiPointGeometry_,
|
||||
'MultiLineString': this.writeMultiLineStringGeometry_,
|
||||
'MultiPolygon': this.writeMultiPolygonGeometry_,
|
||||
'GeometryCollection': this.writeGeometryCollectionGeometry_,
|
||||
'Circle': this.writeCircleGeometry_
|
||||
'Point': this.writePointGeometry_.bind(this),
|
||||
'LineString': this.writeLineStringGeometry_.bind(this),
|
||||
'LinearRing': this.writeLineStringGeometry_.bind(this),
|
||||
'Polygon': this.writePolygonGeometry_.bind(this),
|
||||
'MultiPoint': this.writeMultiPointGeometry_.bind(this),
|
||||
'MultiLineString': this.writeMultiLineStringGeometry_.bind(this),
|
||||
'MultiPolygon': this.writeMultiPolygonGeometry_.bind(this),
|
||||
'GeometryCollection': this.writeGeometryCollectionGeometry_.bind(this),
|
||||
'Circle': this.writeCircleGeometry_.bind(this)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -211,7 +200,7 @@ class Snap extends PointerInteraction {
|
||||
const segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()];
|
||||
if (segmentWriter) {
|
||||
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
|
||||
*/
|
||||
snapTo(pixel, pixelCoordinate, map) {
|
||||
|
||||
const lowerLeft = map.getCoordinateFromPixelInternal(
|
||||
const lowerLeft = map.getCoordinateFromPixel(
|
||||
[pixel[0] - this.pixelTolerance_, pixel[1] + this.pixelTolerance_]);
|
||||
const upperRight = map.getCoordinateFromPixelInternal(
|
||||
const upperRight = map.getCoordinateFromPixel(
|
||||
[pixel[0] + this.pixelTolerance_, pixel[1] - this.pixelTolerance_]);
|
||||
const box = boundingExtent([lowerLeft, upperRight]);
|
||||
|
||||
@@ -400,57 +388,78 @@ class Snap extends PointerInteraction {
|
||||
});
|
||||
}
|
||||
|
||||
let snappedToVertex = false;
|
||||
let snapped = false;
|
||||
let vertex = null;
|
||||
let vertexPixel = null;
|
||||
let dist, pixel1, pixel2, squaredDist1, squaredDist2;
|
||||
if (segments.length > 0) {
|
||||
this.pixelCoordinate_ = pixelCoordinate;
|
||||
segments.sort(this.sortByDistance_);
|
||||
const closestSegment = segments[0].segment;
|
||||
const isCircle = segments[0].feature.getGeometry().getType() ===
|
||||
GeometryType.CIRCLE;
|
||||
if (this.vertex_ && !this.edge_) {
|
||||
pixel1 = map.getPixelFromCoordinateInternal(closestSegment[0]);
|
||||
pixel2 = map.getPixelFromCoordinateInternal(closestSegment[1]);
|
||||
squaredDist1 = squaredCoordinateDistance(pixel, pixel1);
|
||||
squaredDist2 = squaredCoordinateDistance(pixel, pixel2);
|
||||
dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
|
||||
snappedToVertex = dist <= this.pixelTolerance_;
|
||||
if (snappedToVertex) {
|
||||
snapped = true;
|
||||
vertex = squaredDist1 > squaredDist2 ? closestSegment[1] : closestSegment[0];
|
||||
vertexPixel = map.getPixelFromCoordinateInternal(vertex);
|
||||
}
|
||||
} else if (this.edge_) {
|
||||
if (isCircle) {
|
||||
vertex = closestOnCircle(pixelCoordinate,
|
||||
/** @type {import("../geom/Circle.js").default} */ (segments[0].feature.getGeometry()));
|
||||
} else {
|
||||
vertex = closestOnSegment(pixelCoordinate, closestSegment);
|
||||
}
|
||||
vertexPixel = map.getPixelFromCoordinateInternal(vertex);
|
||||
if (coordinateDistance(pixel, vertexPixel) <= this.pixelTolerance_) {
|
||||
snapped = true;
|
||||
if (this.vertex_ && !isCircle) {
|
||||
pixel1 = map.getPixelFromCoordinateInternal(closestSegment[0]);
|
||||
pixel2 = map.getPixelFromCoordinateInternal(closestSegment[1]);
|
||||
squaredDist1 = squaredCoordinateDistance(vertexPixel, pixel1);
|
||||
squaredDist2 = squaredCoordinateDistance(vertexPixel, pixel2);
|
||||
dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
|
||||
snappedToVertex = dist <= this.pixelTolerance_;
|
||||
if (snappedToVertex) {
|
||||
vertex = squaredDist1 > squaredDist2 ? closestSegment[1] : closestSegment[0];
|
||||
vertexPixel = map.getPixelFromCoordinateInternal(vertex);
|
||||
}
|
||||
|
||||
if (segments.length === 0) {
|
||||
return {
|
||||
snapped: snapped,
|
||||
vertex: vertex,
|
||||
vertexPixel: vertexPixel
|
||||
};
|
||||
}
|
||||
|
||||
const projection = map.getView().getProjection();
|
||||
const projectedCoordinate = fromUserCoordinate(pixelCoordinate, projection);
|
||||
|
||||
let closestSegmentData;
|
||||
let minSquaredDistance = Infinity;
|
||||
for (let i = 0; i < segments.length; ++i) {
|
||||
const segmentData = segments[i];
|
||||
tempSegment[0] = fromUserCoordinate(segmentData.segment[0], projection);
|
||||
tempSegment[1] = fromUserCoordinate(segmentData.segment[1], projection);
|
||||
const delta = squaredDistanceToSegment(projectedCoordinate, tempSegment);
|
||||
if (delta < minSquaredDistance) {
|
||||
closestSegmentData = segmentData;
|
||||
minSquaredDistance = delta;
|
||||
}
|
||||
}
|
||||
const closestSegment = closestSegmentData.segment;
|
||||
|
||||
if (this.vertex_ && !this.edge_) {
|
||||
const pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
|
||||
const pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
|
||||
const squaredDist1 = squaredCoordinateDistance(pixel, pixel1);
|
||||
const squaredDist2 = squaredCoordinateDistance(pixel, pixel2);
|
||||
const dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
|
||||
if (dist <= this.pixelTolerance_) {
|
||||
snapped = true;
|
||||
vertex = squaredDist1 > squaredDist2 ? closestSegment[1] : closestSegment[0];
|
||||
vertexPixel = map.getPixelFromCoordinate(vertex);
|
||||
}
|
||||
} else if (this.edge_) {
|
||||
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 {
|
||||
snapped: snapped,
|
||||
vertex: vertex,
|
||||
@@ -495,7 +504,7 @@ class Snap extends PointerInteraction {
|
||||
for (let i = 0; i < geometries.length; ++i) {
|
||||
const segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()];
|
||||
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;
|
||||
|
||||
@@ -5,11 +5,6 @@ import BaseImageLayer from './BaseImage.js';
|
||||
import CanvasImageLayerRenderer from '../renderer/canvas/ImageLayer.js';
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {import("./BaseImage.js").Options} Options
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* 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 {
|
||||
|
||||
/**
|
||||
* @param {Options=} opt_options Layer options.
|
||||
* @param {import("./BaseImage.js").Options=} opt_options Layer options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super(opt_options);
|
||||
|
||||
@@ -9,6 +9,8 @@ import {
|
||||
scale as scaleTransform
|
||||
} from './transform.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) {
|
||||
const frameState = event.frameState;
|
||||
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(
|
||||
event.context, frameState.pixelRatio, frameState.extent, transform,
|
||||
frameState.viewState.rotation);
|
||||
frameState.viewState.rotation, squaredTolerance, userTransform);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -204,11 +204,10 @@ class RenderFeature {
|
||||
* Get a transformed and simplified version of the geometry.
|
||||
* @abstract
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {import("../proj/Projection.js").default} sourceProjection The source projection.
|
||||
* @param {import("../proj/Projection.js").default} destProjection The destination projection.
|
||||
* @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.
|
||||
* @return {RenderFeature} Simplified geometry.
|
||||
*/
|
||||
simplifyTransformed(squaredTolerance, sourceProjection, destProjection) {
|
||||
simplifyTransformed(squaredTolerance, opt_transform) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -300,6 +300,9 @@ function getMeasureContext() {
|
||||
* @return {import("../size.js").Size} Measurement.
|
||||
*/
|
||||
export const measureTextHeight = (function() {
|
||||
/**
|
||||
* @type {HTMLDivElement}
|
||||
*/
|
||||
let div;
|
||||
const heights = textHeights;
|
||||
return function(font) {
|
||||
|
||||
@@ -31,8 +31,10 @@ class CanvasImmediateRenderer extends VectorContext {
|
||||
* @param {import("../../extent.js").Extent} extent Extent.
|
||||
* @param {import("../../transform.js").Transform} transform Transform.
|
||||
* @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();
|
||||
|
||||
/**
|
||||
@@ -65,6 +67,18 @@ class CanvasImmediateRenderer extends VectorContext {
|
||||
*/
|
||||
this.viewRotation_ = viewRotation;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.squaredTolerance_ = opt_squaredTolerance;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../../proj.js").TransformFunction}
|
||||
*/
|
||||
this.userTransform_ = opt_userTransform;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?import("../canvas.js").FillState}
|
||||
@@ -505,6 +519,9 @@ class CanvasImmediateRenderer extends VectorContext {
|
||||
* @override
|
||||
*/
|
||||
drawPoint(geometry) {
|
||||
if (this.squaredTolerance_) {
|
||||
geometry = /** @type {import("../../geom/Point.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
|
||||
}
|
||||
const flatCoordinates = geometry.getFlatCoordinates();
|
||||
const stride = geometry.getStride();
|
||||
if (this.image_) {
|
||||
@@ -523,6 +540,9 @@ class CanvasImmediateRenderer extends VectorContext {
|
||||
* @override
|
||||
*/
|
||||
drawMultiPoint(geometry) {
|
||||
if (this.squaredTolerance_) {
|
||||
geometry = /** @type {import("../../geom/MultiPoint.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
|
||||
}
|
||||
const flatCoordinates = geometry.getFlatCoordinates();
|
||||
const stride = geometry.getStride();
|
||||
if (this.image_) {
|
||||
@@ -541,6 +561,9 @@ class CanvasImmediateRenderer extends VectorContext {
|
||||
* @override
|
||||
*/
|
||||
drawLineString(geometry) {
|
||||
if (this.squaredTolerance_) {
|
||||
geometry = /** @type {import("../../geom/LineString.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
|
||||
}
|
||||
if (!intersects(this.extent_, geometry.getExtent())) {
|
||||
return;
|
||||
}
|
||||
@@ -567,6 +590,9 @@ class CanvasImmediateRenderer extends VectorContext {
|
||||
* @override
|
||||
*/
|
||||
drawMultiLineString(geometry) {
|
||||
if (this.squaredTolerance_) {
|
||||
geometry = /** @type {import("../../geom/MultiLineString.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
|
||||
}
|
||||
const geometryExtent = geometry.getExtent();
|
||||
if (!intersects(this.extent_, geometryExtent)) {
|
||||
return;
|
||||
@@ -598,6 +624,9 @@ class CanvasImmediateRenderer extends VectorContext {
|
||||
* @override
|
||||
*/
|
||||
drawPolygon(geometry) {
|
||||
if (this.squaredTolerance_) {
|
||||
geometry = /** @type {import("../../geom/Polygon.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
|
||||
}
|
||||
if (!intersects(this.extent_, geometry.getExtent())) {
|
||||
return;
|
||||
}
|
||||
@@ -632,6 +661,9 @@ class CanvasImmediateRenderer extends VectorContext {
|
||||
* @override
|
||||
*/
|
||||
drawMultiPolygon(geometry) {
|
||||
if (this.squaredTolerance_) {
|
||||
geometry = /** @type {import("../../geom/MultiPolygon.js").default} */ (geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_));
|
||||
}
|
||||
if (!intersects(this.extent_, geometry.getExtent())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import {getUid} from '../../util.js';
|
||||
import ViewHint from '../../ViewHint.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 ExecutorGroup, {replayDeclutter} from '../../render/canvas/ExecutorGroup.js';
|
||||
import CanvasLayerRenderer from './Layer.js';
|
||||
@@ -307,8 +307,10 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
||||
pixelRatio, vectorLayer.getDeclutter());
|
||||
|
||||
const userProjection = getUserProjection();
|
||||
let userTransform;
|
||||
if (userProjection) {
|
||||
vectorSource.loadFeatures(toUserExtent(extent, projection), resolution, userProjection);
|
||||
userTransform = getTransformFromProjections(userProjection, projection);
|
||||
} else {
|
||||
vectorSource.loadFeatures(extent, resolution, projection);
|
||||
}
|
||||
@@ -326,7 +328,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
||||
styles = styleFunction(feature, resolution);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}.bind(this);
|
||||
@@ -370,10 +372,10 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
||||
* @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("../../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.
|
||||
*/
|
||||
renderFeature(feature, squaredTolerance, styles, builderGroup, projection) {
|
||||
renderFeature(feature, squaredTolerance, styles, builderGroup, opt_transform) {
|
||||
if (!styles) {
|
||||
return false;
|
||||
}
|
||||
@@ -382,12 +384,12 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
||||
for (let i = 0, ii = styles.length; i < ii; ++i) {
|
||||
loading = renderFeature(
|
||||
builderGroup, feature, styles[i], squaredTolerance,
|
||||
this.boundHandleStyleImageChange_, projection) || loading;
|
||||
this.boundHandleStyleImageChange_, opt_transform) || loading;
|
||||
}
|
||||
} else {
|
||||
loading = renderFeature(
|
||||
builderGroup, feature, styles, squaredTolerance,
|
||||
this.boundHandleStyleImageChange_, projection);
|
||||
this.boundHandleStyleImageChange_, opt_transform);
|
||||
}
|
||||
return loading;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import {getUid} from '../util.js';
|
||||
import ImageState from '../ImageState.js';
|
||||
import GeometryType from '../geom/GeometryType.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 {number} squaredTolerance Squared tolerance.
|
||||
* @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.
|
||||
* @template T
|
||||
*/
|
||||
export function renderFeature(replayGroup, feature, style, squaredTolerance, listener, projection) {
|
||||
export function renderFeature(replayGroup, feature, style, squaredTolerance, listener, opt_transform) {
|
||||
let loading = false;
|
||||
const imageStyle = style.getImage();
|
||||
if (imageStyle) {
|
||||
@@ -113,7 +112,7 @@ export function renderFeature(replayGroup, feature, style, squaredTolerance, lis
|
||||
loading = true;
|
||||
}
|
||||
}
|
||||
renderFeatureInternal(replayGroup, feature, style, squaredTolerance, projection);
|
||||
renderFeatureInternal(replayGroup, feature, style, squaredTolerance, opt_transform);
|
||||
|
||||
return loading;
|
||||
}
|
||||
@@ -124,14 +123,14 @@ export function renderFeature(replayGroup, feature, style, squaredTolerance, lis
|
||||
* @param {import("../Feature.js").FeatureLike} feature Feature.
|
||||
* @param {import("../style/Style.js").default} style Style.
|
||||
* @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);
|
||||
if (!geometry) {
|
||||
return;
|
||||
}
|
||||
const simplifiedGeometry = geometry.simplifyTransformed(squaredTolerance, getUserProjection(), projection);
|
||||
const simplifiedGeometry = geometry.simplifyTransformed(squaredTolerance, opt_transform);
|
||||
const renderer = style.getRenderer();
|
||||
if (renderer) {
|
||||
renderGeometry(replayGroup, simplifiedGeometry, style, feature);
|
||||
|
||||
@@ -109,7 +109,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
||||
|
||||
/**
|
||||
* @param {import("../../layer/Layer.js").default} layer Layer.
|
||||
* @param {Options=} options Options.
|
||||
* @param {Options} options Options.
|
||||
*/
|
||||
constructor(layer, options) {
|
||||
const uniforms = options.uniforms || {};
|
||||
|
||||
@@ -104,7 +104,7 @@ class ReprojTile extends Tile {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<import("../events.js").EventsKey>}
|
||||
* @type {?Array<import("../events.js").EventsKey>}
|
||||
*/
|
||||
this.sourcesListenerKeys_ = null;
|
||||
|
||||
|
||||
@@ -127,10 +127,14 @@ export function createSnapToPower(power, maxResolution, opt_minResolution, opt_s
|
||||
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 zoomLevel = Math.floor(
|
||||
const cappedZoomLevel = Math.floor(
|
||||
Math.log(maxResolution / capped) / Math.log(power) + offset);
|
||||
const zoomLevel = Math.max(minZoomLevel, cappedZoomLevel);
|
||||
const newResolution = maxResolution / Math.pow(power, zoomLevel);
|
||||
return clamp(newResolution, minResolution, cappedMaxRes);
|
||||
} else {
|
||||
|
||||
@@ -81,7 +81,7 @@ class TileWMS extends TileImage {
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : /** @type {Options} */ ({});
|
||||
|
||||
const params = options.params || {};
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import UrlTile from './UrlTile.js';
|
||||
import {getKeyZXY, getKey} from '../tilecoord.js';
|
||||
import {createXYZ, extentFromProjection, createForProjection} from '../tilegrid.js';
|
||||
import {buffer as bufferExtent, getIntersection, intersects} from '../extent.js';
|
||||
import {listen, unlistenByKey} from '../events.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import {loadFeaturesXhr} from '../featureloader.js';
|
||||
import {isEmpty} from '../obj.js';
|
||||
@@ -200,11 +199,10 @@ class VectorTile extends UrlTile {
|
||||
const minZoom = sourceTileGrid.getMinZoom();
|
||||
|
||||
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) {
|
||||
sourceTiles = previousSourceTiles;
|
||||
covered = true;
|
||||
empty = false;
|
||||
loadedZ = sourceZ;
|
||||
} else {
|
||||
sourceTiles = [];
|
||||
@@ -212,7 +210,6 @@ class VectorTile extends UrlTile {
|
||||
do {
|
||||
--loadedZ;
|
||||
covered = true;
|
||||
empty = true;
|
||||
sourceTileGrid.forEachTileCoord(extent, loadedZ, function(sourceTileCoord) {
|
||||
const coordKey = getKey(sourceTileCoord);
|
||||
let sourceTile;
|
||||
@@ -220,7 +217,6 @@ class VectorTile extends UrlTile {
|
||||
sourceTile = this.sourceTileByCoordKey_[coordKey];
|
||||
const state = sourceTile.getState();
|
||||
if (state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) {
|
||||
empty = empty && state === TileState.EMPTY;
|
||||
sourceTiles.push(sourceTile);
|
||||
return;
|
||||
}
|
||||
@@ -233,28 +229,25 @@ class VectorTile extends UrlTile {
|
||||
sourceTile.projection = projection;
|
||||
sourceTile.resolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
|
||||
this.sourceTileByCoordKey_[coordKey] = sourceTile;
|
||||
empty = false;
|
||||
sourceTile.addEventListener(EventType.CHANGE, this.handleTileChange.bind(this));
|
||||
sourceTile.load();
|
||||
} else {
|
||||
sourceTile = null;
|
||||
}
|
||||
} else {
|
||||
empty = false;
|
||||
}
|
||||
covered = false;
|
||||
if (sourceTile === undefined) {
|
||||
if (!sourceTile) {
|
||||
return;
|
||||
}
|
||||
if (sourceTile !== null && tile.getState() === TileState.IDLE) {
|
||||
if (sourceTile.getState() !== TileState.EMPTY && tile.getState() === TileState.IDLE) {
|
||||
tile.loadingSourceTiles++;
|
||||
const key = listen(sourceTile, EventType.CHANGE, function() {
|
||||
const onSourceTileChange = function() {
|
||||
const state = sourceTile.getState();
|
||||
const sourceTileKey = sourceTile.getKey();
|
||||
if (state === TileState.LOADED || state === TileState.ERROR) {
|
||||
if (state === TileState.LOADED) {
|
||||
unlistenByKey(key);
|
||||
sourceTile.removeEventListener(EventType.CHANGE, onSourceTileChange);
|
||||
tile.loadingSourceTiles--;
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
tile.removeEventListener(EventType.CHANGE, onTileChange);
|
||||
delete tile.errorSourceTileKeys[sourceTileKey];
|
||||
} else if (state === TileState.ERROR) {
|
||||
tile.errorSourceTileKeys[sourceTileKey] = true;
|
||||
@@ -265,7 +258,15 @@ class VectorTile extends UrlTile {
|
||||
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));
|
||||
if (!covered) {
|
||||
@@ -274,14 +275,14 @@ class VectorTile extends UrlTile {
|
||||
} while (!covered && loadedZ > minZoom);
|
||||
}
|
||||
|
||||
if (!empty && tile.getState() === TileState.IDLE) {
|
||||
if (tile.getState() === TileState.IDLE) {
|
||||
tile.setState(TileState.LOADING);
|
||||
}
|
||||
if (covered || empty) {
|
||||
if (covered) {
|
||||
tile.hifi = sourceZ === loadedZ;
|
||||
tile.sourceZ = loadedZ;
|
||||
if (tile.getState() < TileState.LOADED) {
|
||||
tile.setState(empty ? TileState.EMPTY : TileState.LOADED);
|
||||
tile.setState(TileState.LOADED);
|
||||
} else if (!previousSourceTiles || !equals(sourceTiles, previousSourceTiles)) {
|
||||
this.removeSourceTiles(tile);
|
||||
this.addSourceTiles(tile, sourceTiles);
|
||||
@@ -336,8 +337,8 @@ class VectorTile extends UrlTile {
|
||||
const tileCoord = [z, x, y];
|
||||
let urlTileCoord = this.getTileCoordForTileUrlFunction(tileCoord, projection);
|
||||
const sourceExtent = this.getTileGrid().getExtent();
|
||||
const tileGrid = this.getTileGridForProjection(projection);
|
||||
if (urlTileCoord && sourceExtent) {
|
||||
const tileGrid = this.getTileGridForProjection(projection);
|
||||
const tileExtent = tileGrid.getTileCoordExtent(urlTileCoord);
|
||||
// make extent 1 pixel smaller so we don't load tiles for < 0.5 pixel render space
|
||||
bufferExtent(tileExtent, -tileGrid.getResolution(z), tileExtent);
|
||||
@@ -345,9 +346,21 @@ class VectorTile extends UrlTile {
|
||||
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(
|
||||
tileCoord,
|
||||
urlTileCoord !== null ? TileState.IDLE : TileState.EMPTY,
|
||||
empty ? TileState.EMPTY : TileState.IDLE,
|
||||
urlTileCoord,
|
||||
this.tileGrid,
|
||||
this.getSourceTiles.bind(this, pixelRatio, projection),
|
||||
|
||||
@@ -22,7 +22,7 @@ import EventType from '../events/EventType.js';
|
||||
* Object's properties (e.g. 'hasOwnProperty' is not allowed as a key). Expiring
|
||||
* items from the cache is the responsibility of the user.
|
||||
*
|
||||
* @fires import("../events/Event.js").Event
|
||||
* @fires import("../events/Event.js").default
|
||||
* @template T
|
||||
*/
|
||||
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
|
||||
* 3 arguments (the entry value, the entry key and the LRUCache object).
|
||||
* The return value is ignored.
|
||||
|
||||
@@ -53,7 +53,7 @@ class IconImage extends EventTarget {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {function():void}
|
||||
* @type {?function():void}
|
||||
*/
|
||||
this.unlisten_ = null;
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ const DEFAULT_FRAGMENT_SHADER = `
|
||||
class WebGLPostProcessingPass {
|
||||
|
||||
/**
|
||||
* @param {Options=} options Options.
|
||||
* @param {Options} options Options.
|
||||
*/
|
||||
constructor(options) {
|
||||
this.gl_ = options.webGlContext;
|
||||
|
||||
@@ -95,7 +95,7 @@ describe('ol.collection', function() {
|
||||
describe('on an empty collection', function() {
|
||||
it('does not call the callback', function() {
|
||||
collection.forEach(cb);
|
||||
expect(cb).to.not.be.called();
|
||||
expect(cb.called).to.be(false);
|
||||
});
|
||||
});
|
||||
describe('on a non-empty collection', function() {
|
||||
@@ -120,7 +120,7 @@ describe('ol.collection', function() {
|
||||
const cb = sinon.spy();
|
||||
listen(collection, CollectionEventType.REMOVE, cb);
|
||||
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);
|
||||
});
|
||||
it('does not remove more than one matching element', function() {
|
||||
@@ -216,21 +216,21 @@ describe('ol.collection', function() {
|
||||
describe('insertAt', function() {
|
||||
it('triggers change:length event', function() {
|
||||
collection.insertAt(2, 3);
|
||||
expect(cb).to.be.called();
|
||||
expect(cb.called).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeAt', function() {
|
||||
it('triggers change:length event', function() {
|
||||
collection.removeAt(0);
|
||||
expect(cb).to.be.called();
|
||||
expect(cb.called).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setAt', function() {
|
||||
it('does not trigger change:length event', function() {
|
||||
collection.setAt(1, 1);
|
||||
expect(cb).to.not.be.called();
|
||||
expect(cb.called).to.be(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,21 +2,6 @@
|
||||
|
||||
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() {
|
||||
|
||||
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() {
|
||||
|
||||
it('Test XML document with single root, different prefix', function() {
|
||||
|
||||
@@ -208,7 +208,7 @@ describe('ol.Feature', function() {
|
||||
expect(feature.getGeometry()).to.be(point2);
|
||||
|
||||
feature.on('change', function() {
|
||||
expect.fail();
|
||||
expect().fail();
|
||||
});
|
||||
point.setCoordinates([0, 2]);
|
||||
});
|
||||
|
||||
@@ -73,6 +73,12 @@ describe('ol.geom.LineString', function() {
|
||||
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() {
|
||||
|
||||
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() {
|
||||
|
||||
it('return the first point when fraction is 0', function() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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() {
|
||||
@@ -161,9 +161,10 @@ describe('ol.geom.Point', function() {
|
||||
const geom = new Point([1, 2]);
|
||||
const source = getProjection('EPSG:4326');
|
||||
const dest = getProjection('EPSG:3857');
|
||||
const transform = getTransformFromProjections(source, dest);
|
||||
const squaredTolerance = 0.5;
|
||||
const first = geom.simplifyTransformed(squaredTolerance, source, dest);
|
||||
const second = geom.simplifyTransformed(squaredTolerance, source, dest);
|
||||
const first = geom.simplifyTransformed(squaredTolerance, transform);
|
||||
const second = geom.simplifyTransformed(squaredTolerance, transform);
|
||||
expect(second).to.be(first);
|
||||
});
|
||||
|
||||
@@ -171,9 +172,10 @@ describe('ol.geom.Point', function() {
|
||||
const geom = new Point([1, 2]);
|
||||
const source = getProjection('EPSG:4326');
|
||||
const dest = getProjection('EPSG:3857');
|
||||
const transform = getTransformFromProjections(source, dest);
|
||||
const squaredTolerance = 0.5;
|
||||
const first = geom.simplifyTransformed(squaredTolerance, source, dest);
|
||||
const second = geom.simplifyTransformed(squaredTolerance * 2, source, dest);
|
||||
const first = geom.simplifyTransformed(squaredTolerance, transform);
|
||||
const second = geom.simplifyTransformed(squaredTolerance * 2, transform);
|
||||
expect(second).not.to.be(first);
|
||||
});
|
||||
|
||||
@@ -181,11 +183,12 @@ describe('ol.geom.Point', function() {
|
||||
const geom = new Point([1, 2]);
|
||||
const source = getProjection('EPSG:4326');
|
||||
const dest = getProjection('EPSG:3857');
|
||||
const transform = getTransformFromProjections(source, dest);
|
||||
const squaredTolerance = 0.5;
|
||||
const first = geom.simplifyTransformed(squaredTolerance, source, dest);
|
||||
const first = geom.simplifyTransformed(squaredTolerance, transform);
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ describe('HTML Image loading', function() {
|
||||
listenImage(img, handleLoad, handleError);
|
||||
|
||||
setTimeout(function() {
|
||||
expect(handleLoad).to.be.called();
|
||||
expect(handleError).not.to.be.called();
|
||||
expect(handleLoad.called).to.be(true);
|
||||
expect(handleError.called).to.be(false);
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
@@ -26,8 +26,8 @@ describe('HTML Image loading', function() {
|
||||
img.src = 'spec/ol/data/dot.png';
|
||||
|
||||
setTimeout(function() {
|
||||
expect(handleLoad).to.be.called();
|
||||
expect(handleError).not.to.be.called();
|
||||
expect(handleLoad.called).to.be(true);
|
||||
expect(handleError.called).to.be(false);
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
@@ -37,8 +37,8 @@ describe('HTML Image loading', function() {
|
||||
listenImage(img, handleLoad, handleError);
|
||||
|
||||
setTimeout(function() {
|
||||
expect(handleLoad).not.to.be.called();
|
||||
expect(handleError).to.be.called();
|
||||
expect(handleLoad.called).to.be(false);
|
||||
expect(handleError.called).to.be(true);
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
@@ -48,8 +48,8 @@ describe('HTML Image loading', function() {
|
||||
listenImage(img, handleLoad, handleError)();
|
||||
|
||||
setTimeout(function() {
|
||||
expect(handleLoad).not.to.be.called();
|
||||
expect(handleError).not.to.be.called();
|
||||
expect(handleLoad.called).to.be(false);
|
||||
expect(handleError.called).to.be(false);
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
@@ -216,8 +216,8 @@ describe('ol.interaction.Draw', function() {
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
expect(ds).to.be.called();
|
||||
expect(de).to.be.called();
|
||||
expect(ds.called).to.be(true);
|
||||
expect(de.called).to.be(true);
|
||||
simulateEvent('pointermove', 20, 20);
|
||||
expect(ds.callCount).to.be(1);
|
||||
expect(de.callCount).to.be(1);
|
||||
@@ -390,7 +390,6 @@ describe('ol.interaction.Draw', function() {
|
||||
simulateEvent('pointerup', 60, 70);
|
||||
|
||||
const features = source.getFeatures();
|
||||
// expect(features).to.have.length(1);
|
||||
const geometry = features[0].getGeometry();
|
||||
expect(geometry).to.be.a(LineString);
|
||||
expect(geometry.getCoordinates()).to.eql(
|
||||
@@ -478,9 +477,9 @@ describe('ol.interaction.Draw', function() {
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
|
||||
expect(ds).to.be.called();
|
||||
expect(ds.called).to.be(true);
|
||||
expect(ds.callCount).to.be(1);
|
||||
expect(de).to.be.called();
|
||||
expect(de.called).to.be(true);
|
||||
expect(de.callCount).to.be(1);
|
||||
});
|
||||
|
||||
@@ -801,9 +800,9 @@ describe('ol.interaction.Draw', function() {
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
expect(ds).to.be.called();
|
||||
expect(ds.called).to.be(true);
|
||||
expect(ds.callCount).to.be(1);
|
||||
expect(de).to.be.called();
|
||||
expect(de.called).to.be(true);
|
||||
expect(de.callCount).to.be(1);
|
||||
});
|
||||
|
||||
@@ -963,9 +962,9 @@ describe('ol.interaction.Draw', function() {
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
expect(ds).to.be.called();
|
||||
expect(ds.called).to.be(true);
|
||||
expect(ds.callCount).to.be(1);
|
||||
expect(de).to.be.called();
|
||||
expect(de.called).to.be(true);
|
||||
expect(de.callCount).to.be(1);
|
||||
});
|
||||
|
||||
|
||||
@@ -708,7 +708,7 @@ describe('ol.interaction.Modify', function() {
|
||||
collection.remove(features[0]);
|
||||
expect(function() {
|
||||
simulateEvent('pointerup', -10, -10, null, 0);
|
||||
}).to.not.throwError();
|
||||
}).to.not.throwException();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import Circle from '../../../../src/ol/geom/Circle.js';
|
||||
import Point from '../../../../src/ol/geom/Point.js';
|
||||
import LineString from '../../../../src/ol/geom/LineString.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() {
|
||||
@@ -190,6 +192,78 @@ describe('ol.interaction.Snap', function() {
|
||||
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);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ describe('ol.net', function() {
|
||||
};
|
||||
};
|
||||
function callback() {
|
||||
expect.fail();
|
||||
expect().fail();
|
||||
}
|
||||
function errback() {
|
||||
expect(window[key]).to.be(undefined);
|
||||
|
||||
@@ -156,7 +156,7 @@ describe('ol.Object', function() {
|
||||
|
||||
it('dispatches events to object', function() {
|
||||
o.set('k', 1);
|
||||
expect(listener1).to.be.called();
|
||||
expect(listener1.called).to.be(true);
|
||||
|
||||
expect(o.getKeys()).to.eql(['k']);
|
||||
});
|
||||
@@ -190,7 +190,7 @@ describe('ol.Object', function() {
|
||||
it('does not call the setter', function() {
|
||||
o.set('x', 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']);
|
||||
});
|
||||
@@ -206,7 +206,7 @@ describe('ol.Object', function() {
|
||||
|
||||
it('does not call the getter', function() {
|
||||
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() {
|
||||
o.set('K', 1);
|
||||
expect(listener1).to.not.be.called();
|
||||
expect(listener2).to.be.called();
|
||||
expect(listener1.called).to.be(false);
|
||||
expect(listener2.called).to.be(true);
|
||||
|
||||
expect(o.getKeys()).to.eql(['K']);
|
||||
});
|
||||
|
||||
@@ -30,15 +30,11 @@ describe('ol.obj.assign()', function() {
|
||||
});
|
||||
|
||||
it('throws a TypeError with `undefined` as target', function() {
|
||||
expect(assign).withArgs(undefined).to.throwException(function(e) {
|
||||
expect(e).to.be.a(TypeError);
|
||||
});
|
||||
expect(() => assign()).to.throwException(/Cannot convert undefined or null to object/);
|
||||
});
|
||||
|
||||
it('throws a TypeError with `null` as target', function() {
|
||||
expect(assign).withArgs(null).to.throwException(function(e) {
|
||||
expect(e).to.be.a(TypeError);
|
||||
});
|
||||
expect(() => assign(null)).to.throwException(/Cannot convert undefined or null to object/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -74,7 +74,8 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
|
||||
source = new VectorTileSource({
|
||||
format: new MVT(),
|
||||
tileClass: TileClass,
|
||||
tileGrid: createXYZ()
|
||||
tileGrid: createXYZ(),
|
||||
url: '{z}/{x}/{y}.pbf'
|
||||
});
|
||||
source.getSourceTiles = function() {
|
||||
return [new TileClass([0, 0, 0])];
|
||||
|
||||
@@ -17,7 +17,7 @@ import Feature from '../../../../src/ol/Feature.js';
|
||||
describe('ol.renderer.vector', function() {
|
||||
describe('#renderFeature', function() {
|
||||
let builderGroup;
|
||||
let feature, iconStyle, style, squaredTolerance, listener, listenerThis;
|
||||
let feature, iconStyle, style, squaredTolerance, listener;
|
||||
let iconStyleLoadSpy;
|
||||
|
||||
beforeEach(function() {
|
||||
@@ -33,7 +33,6 @@ describe('ol.renderer.vector', function() {
|
||||
});
|
||||
squaredTolerance = 1;
|
||||
listener = function() {};
|
||||
listenerThis = {};
|
||||
iconStyleLoadSpy = sinon.stub(iconStyle, 'load').callsFake(function() {
|
||||
iconStyle.iconImage_.imageState_ = 1; // LOADING
|
||||
});
|
||||
@@ -49,16 +48,14 @@ describe('ol.renderer.vector', function() {
|
||||
let listeners;
|
||||
|
||||
// call #1
|
||||
renderFeature(builderGroup, feature,
|
||||
style, squaredTolerance, listener, listenerThis);
|
||||
renderFeature(builderGroup, feature, style, squaredTolerance, listener);
|
||||
|
||||
expect(iconStyleLoadSpy.calledOnce).to.be.ok();
|
||||
listeners = iconStyle.iconImage_.listeners_['change'];
|
||||
expect(listeners.length).to.eql(1);
|
||||
|
||||
// call #2
|
||||
renderFeature(builderGroup, feature,
|
||||
style, squaredTolerance, listener, listenerThis);
|
||||
renderFeature(builderGroup, feature, style, squaredTolerance, listener);
|
||||
|
||||
expect(iconStyleLoadSpy.calledOnce).to.be.ok();
|
||||
listeners = iconStyle.iconImage_.listeners_['change'];
|
||||
@@ -75,8 +72,7 @@ describe('ol.renderer.vector', function() {
|
||||
style.getZIndex(), 'Image');
|
||||
const setImageStyleSpy = sinon.spy(imageReplay, 'setImageStyle');
|
||||
const drawPointSpy = sinon.stub(imageReplay, 'drawPoint').callsFake(VOID);
|
||||
renderFeature(builderGroup, feature,
|
||||
style, squaredTolerance, listener, listenerThis);
|
||||
renderFeature(builderGroup, feature, style, squaredTolerance, listener);
|
||||
expect(setImageStyleSpy.called).to.be(false);
|
||||
setImageStyleSpy.restore();
|
||||
drawPointSpy.restore();
|
||||
@@ -88,8 +84,7 @@ describe('ol.renderer.vector', function() {
|
||||
style.getZIndex(), 'Image');
|
||||
const setImageStyleSpy = sinon.spy(imageReplay, 'setImageStyle');
|
||||
const drawMultiPointSpy = sinon.stub(imageReplay, 'drawMultiPoint').callsFake(VOID);
|
||||
renderFeature(builderGroup, feature,
|
||||
style, squaredTolerance, listener, listenerThis);
|
||||
renderFeature(builderGroup, feature, style, squaredTolerance, listener);
|
||||
expect(setImageStyleSpy.called).to.be(false);
|
||||
setImageStyleSpy.restore();
|
||||
drawMultiPointSpy.restore();
|
||||
@@ -102,8 +97,7 @@ describe('ol.renderer.vector', function() {
|
||||
const setFillStrokeStyleSpy = sinon.spy(lineStringReplay,
|
||||
'setFillStrokeStyle');
|
||||
const drawLineStringSpy = sinon.stub(lineStringReplay, 'drawLineString').callsFake(VOID);
|
||||
renderFeature(builderGroup, feature,
|
||||
style, squaredTolerance, listener, listenerThis);
|
||||
renderFeature(builderGroup, feature, style, squaredTolerance, listener);
|
||||
expect(setFillStrokeStyleSpy.called).to.be(true);
|
||||
expect(drawLineStringSpy.called).to.be(true);
|
||||
setFillStrokeStyleSpy.restore();
|
||||
@@ -117,8 +111,7 @@ describe('ol.renderer.vector', function() {
|
||||
const setFillStrokeStyleSpy = sinon.spy(lineStringReplay,
|
||||
'setFillStrokeStyle');
|
||||
const drawMultiLineStringSpy = sinon.stub(lineStringReplay, 'drawMultiLineString').callsFake(VOID);
|
||||
renderFeature(builderGroup, feature,
|
||||
style, squaredTolerance, listener, listenerThis);
|
||||
renderFeature(builderGroup, feature, style, squaredTolerance, listener);
|
||||
expect(setFillStrokeStyleSpy.called).to.be(true);
|
||||
expect(drawMultiLineStringSpy.called).to.be(true);
|
||||
setFillStrokeStyleSpy.restore();
|
||||
@@ -133,8 +126,7 @@ describe('ol.renderer.vector', function() {
|
||||
const setFillStrokeStyleSpy = sinon.spy(polygonReplay,
|
||||
'setFillStrokeStyle');
|
||||
const drawPolygonSpy = sinon.stub(polygonReplay, 'drawPolygon').callsFake(VOID);
|
||||
renderFeature(builderGroup, feature,
|
||||
style, squaredTolerance, listener, listenerThis);
|
||||
renderFeature(builderGroup, feature, style, squaredTolerance, listener);
|
||||
expect(setFillStrokeStyleSpy.called).to.be(true);
|
||||
expect(drawPolygonSpy.called).to.be(true);
|
||||
setFillStrokeStyleSpy.restore();
|
||||
@@ -149,8 +141,7 @@ describe('ol.renderer.vector', function() {
|
||||
const setFillStrokeStyleSpy = sinon.spy(polygonReplay,
|
||||
'setFillStrokeStyle');
|
||||
const drawMultiPolygonSpy = sinon.stub(polygonReplay, 'drawMultiPolygon').callsFake(VOID);
|
||||
renderFeature(builderGroup, feature,
|
||||
style, squaredTolerance, listener, listenerThis);
|
||||
renderFeature(builderGroup, feature, style, squaredTolerance, listener);
|
||||
expect(setFillStrokeStyleSpy.called).to.be(true);
|
||||
expect(drawMultiPolygonSpy.called).to.be(true);
|
||||
setFillStrokeStyleSpy.restore();
|
||||
|
||||
@@ -211,7 +211,7 @@ describe('ol.source.ImageWMS', function() {
|
||||
const source = new ImageWMS(options);
|
||||
const image = source.getImage(extent, resolution, pixelRatio, projection);
|
||||
image.load();
|
||||
expect(imageLoadFunction).to.be.called();
|
||||
expect(imageLoadFunction.called).to.be(true);
|
||||
expect(imageLoadFunction.calledWith(image, image.src_)).to.be(true);
|
||||
});
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('ol.source.Vector', function() {
|
||||
it('does not call the callback', function() {
|
||||
const f = sinon.spy();
|
||||
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();
|
||||
listen(vectorSource, 'change', listener);
|
||||
vectorSource.addFeature(pointFeature);
|
||||
expect(listener).to.be.called();
|
||||
expect(listener.called).to.be(true);
|
||||
});
|
||||
|
||||
it('adds same id features only once', function() {
|
||||
@@ -249,9 +249,9 @@ describe('ol.source.Vector', function() {
|
||||
vectorSource.clear(true);
|
||||
expect(vectorSource.getFeatures()).to.eql([]);
|
||||
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(clearSourceSpy).to.be.called();
|
||||
expect(clearSourceSpy.called).to.be(true);
|
||||
expect(clearSourceSpy.callCount).to.be(1);
|
||||
});
|
||||
|
||||
@@ -263,9 +263,9 @@ describe('ol.source.Vector', function() {
|
||||
vectorSource.clear();
|
||||
expect(vectorSource.getFeatures()).to.eql([]);
|
||||
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(clearSourceSpy).to.be.called();
|
||||
expect(clearSourceSpy.called).to.be(true);
|
||||
expect(clearSourceSpy.callCount).to.be(1);
|
||||
});
|
||||
|
||||
@@ -323,14 +323,14 @@ describe('ol.source.Vector', function() {
|
||||
const listener = sinon.spy();
|
||||
listen(vectorSource, 'change', listener);
|
||||
vectorSource.removeFeature(features[0]);
|
||||
expect(listener).to.be.called();
|
||||
expect(listener.called).to.be(true);
|
||||
});
|
||||
|
||||
it('fires a removefeature event', function() {
|
||||
const listener = sinon.spy();
|
||||
listen(vectorSource, 'removefeature', listener);
|
||||
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();
|
||||
listen(vectorSource, 'change', listener);
|
||||
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() {
|
||||
@@ -427,7 +427,7 @@ describe('ol.source.Vector', function() {
|
||||
});
|
||||
vectorSource.on('changefeature', listener);
|
||||
feature.setStyle(null);
|
||||
expect(listener).to.be.called();
|
||||
expect(listener.called).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -71,19 +71,13 @@ describe('ol.source.VectorTile', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('handles empty tiles', function(done) {
|
||||
it('handles empty tiles', function() {
|
||||
const source = new VectorTileSource({
|
||||
format: new GeoJSON(),
|
||||
url: ''
|
||||
});
|
||||
const tile = source.getTile(0, 0, 0, 1, source.getProjection());
|
||||
|
||||
const key = listen(tile, 'change', function(e) {
|
||||
unlistenByKey(key);
|
||||
expect(tile.getState()).to.be(TileState.EMPTY);
|
||||
done();
|
||||
});
|
||||
tile.load();
|
||||
expect(tile.getState()).to.be(TileState.EMPTY);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
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() {
|
||||
const source = new VectorTileSource({});
|
||||
const source = new VectorTileSource({
|
||||
url: '{z}/{x}/{y}.pbf'
|
||||
});
|
||||
const tile = source.getTile(0, -1, 0, 1, source.getProjection());
|
||||
expect(tile.getState()).to.be(TileState.IDLE);
|
||||
});
|
||||
|
||||
it('creates non-empty tiles for overzoomed resolutions', function() {
|
||||
const source = new VectorTileSource({
|
||||
url: '{z}/{x}/{y}.pbf',
|
||||
tileLoadFunction: function(tile) {
|
||||
tile.setLoader(function() {});
|
||||
},
|
||||
maxZoom: 16
|
||||
});
|
||||
const tile = source.getTile(24, 9119385, 5820434, 1, source.getProjection());
|
||||
|
||||
@@ -454,7 +454,7 @@ describe('ol.View', function() {
|
||||
maxResolution: maxResolution,
|
||||
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() {
|
||||
|
||||
17
test/spec/util.js
Normal file
17
test/spec/util.js
Normal 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;
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import {equals} from '../src/ol/array.js';
|
||||
// avoid importing anything that results in an instanceof check
|
||||
// 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) {
|
||||
// check whitespace
|
||||
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) {
|
||||
const target = document.createElement('div');
|
||||
const style = target.style;
|
||||
|
||||
Reference in New Issue
Block a user