Compare commits
157 Commits
docs
...
v6.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cc1ff0f45 | ||
|
|
2df5f85018 | ||
|
|
4a0d6ce43c | ||
|
|
187969cbb3 | ||
|
|
8cdfc6e17c | ||
|
|
9cd35d67a9 | ||
|
|
4d2fa476a3 | ||
|
|
f864c05070 | ||
|
|
3557271e5a | ||
|
|
8a49e06ebd | ||
|
|
6783f6adb9 | ||
|
|
5eb27f7704 | ||
|
|
df240fe905 | ||
|
|
300522e3cc | ||
|
|
3ede6e32be | ||
|
|
ce45a10063 | ||
|
|
2438ef167b | ||
|
|
d6dc7a926d | ||
|
|
6e6a2cae06 | ||
|
|
a6ebad008f | ||
|
|
ed5d4aaf6d | ||
|
|
f507efe77d | ||
|
|
83173cd385 | ||
|
|
b6b91abc27 | ||
|
|
05c791efcd | ||
|
|
2342626a57 | ||
|
|
7c0a0a4786 | ||
|
|
a35ca03e07 | ||
|
|
c522454af1 | ||
|
|
ef10834eb3 | ||
|
|
8efad7bcff | ||
|
|
51c8886d60 | ||
|
|
34a8702202 | ||
|
|
1f00da8d83 | ||
|
|
8d793ad6ec | ||
|
|
bd8a7bff16 | ||
|
|
d059689856 | ||
|
|
4ea28333f8 | ||
|
|
edebf35135 | ||
|
|
90b645daa5 | ||
|
|
9eac927b45 | ||
|
|
ec5e8bfa50 | ||
|
|
124e984a6d | ||
|
|
76f44efbb6 | ||
|
|
ddaaf6a860 | ||
|
|
92c16ecdf5 | ||
|
|
635d7a9189 | ||
|
|
fc6ca5eaf3 | ||
|
|
803f960ded | ||
|
|
ef1b672323 | ||
|
|
002dc34455 | ||
|
|
cc8389d588 | ||
|
|
a8e0e4e960 | ||
|
|
9ae7256048 | ||
|
|
e036767746 | ||
|
|
9a49c91fdd | ||
|
|
37ff7f547b | ||
|
|
c97a728531 | ||
|
|
811bff0430 | ||
|
|
2412fe0211 | ||
|
|
32084a7fce | ||
|
|
7817cf31c6 | ||
|
|
2e5aac8dba | ||
|
|
8b08996703 | ||
|
|
1fbbc56f93 | ||
|
|
8f77a300de | ||
|
|
91d49b26b5 | ||
|
|
02ce2f4bec | ||
|
|
d4f98c8e59 | ||
|
|
ab0860a22a | ||
|
|
dd478167a0 | ||
|
|
2df911e0a8 | ||
|
|
e9939ecc38 | ||
|
|
d058439756 | ||
|
|
8c21c9196d | ||
|
|
68b7831daf | ||
|
|
153e06e4d5 | ||
|
|
9bedfb7cb0 | ||
|
|
1bd23a0c32 | ||
|
|
50343afa61 | ||
|
|
a9e1ebccd3 | ||
|
|
9672142c1e | ||
|
|
6123be726a | ||
|
|
05d8517686 | ||
|
|
87d5f4c8bc | ||
|
|
06be00bbd5 | ||
|
|
7fb113c3dc | ||
|
|
98b0c65450 | ||
|
|
698816030e | ||
|
|
03e70bd10e | ||
|
|
e0983cb1c6 | ||
|
|
a366803cdd | ||
|
|
33d007ce01 | ||
|
|
8566cfc227 | ||
|
|
65be907095 | ||
|
|
532b8194b1 | ||
|
|
eb912d95ca | ||
|
|
245ded43d4 | ||
|
|
7c215b2532 | ||
|
|
579d05a0cb | ||
|
|
b42ee8ca0f | ||
|
|
ede864c823 | ||
|
|
a50ef05565 | ||
|
|
93a607d846 | ||
|
|
deb00f20fe | ||
|
|
c4e465dcf9 | ||
|
|
bfea858306 | ||
|
|
c92bf29677 | ||
|
|
6675f9be57 | ||
|
|
1a6d67776b | ||
|
|
889b6a9f43 | ||
|
|
970c1bcb66 | ||
|
|
2db953ceb1 | ||
|
|
051cc68f24 | ||
|
|
40c49a9ce5 | ||
|
|
442fa907ce | ||
|
|
7044e30529 | ||
|
|
7cfe047feb | ||
|
|
796f20385d | ||
|
|
c76aa76743 | ||
|
|
2969c9e8fb | ||
|
|
119c24faa2 | ||
|
|
93711ea806 | ||
|
|
96331c5d95 | ||
|
|
d8f41a9d73 | ||
|
|
311900e441 | ||
|
|
bdb87f06f9 | ||
|
|
ddb7da3733 | ||
|
|
a358521b2b | ||
|
|
4f833501d7 | ||
|
|
ace5c65ee5 | ||
|
|
ae47d3df58 | ||
|
|
4c8effe6fa | ||
|
|
c56ad4363d | ||
|
|
7895b16043 | ||
|
|
a45e704be2 | ||
|
|
d1f1b468b1 | ||
|
|
a55505b36a | ||
|
|
930318ab7a | ||
|
|
5fe9e06535 | ||
|
|
606443bc6d | ||
|
|
ec811bfa1f | ||
|
|
5e8d7f666e | ||
|
|
4f9057f066 | ||
|
|
4ed6413635 | ||
|
|
bb5ebaa1ab | ||
|
|
c9491ed023 | ||
|
|
3db13fa3bb | ||
|
|
7e4e113ac9 | ||
|
|
dc4ce62fab | ||
|
|
6288744d70 | ||
|
|
c0339f167b | ||
|
|
60007d8e3c | ||
|
|
f77b0941b8 | ||
|
|
b0fae46aa6 | ||
|
|
e69b15d33e | ||
|
|
9860699d5f |
8
.github/FUNDING.yml
vendored
Normal file
8
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: openlayers
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
custom: # Replace with a single custom sponsorship URL
|
||||||
17
.github/stale.yml
vendored
Normal file
17
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Number of days of inactivity before an issue becomes stale
|
||||||
|
daysUntilStale: 60
|
||||||
|
# Number of days of inactivity before a stale issue is closed
|
||||||
|
daysUntilClose: 7
|
||||||
|
# Issues with these labels will never be considered stale
|
||||||
|
exemptLabels:
|
||||||
|
- blocker
|
||||||
|
- regression
|
||||||
|
# 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
|
||||||
|
markComment: >
|
||||||
|
This issue has been automatically marked as stale because it has not had
|
||||||
|
recent activity. It will be closed if no further activity occurs. Thank you
|
||||||
|
for your contributions.
|
||||||
|
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||||
|
closeComment: false
|
||||||
@@ -4,9 +4,19 @@
|
|||||||
|
|
||||||
#### Backwards incompatible changes
|
#### Backwards incompatible changes
|
||||||
|
|
||||||
|
#### Removal of `TOUCH` constant from `ol/has`
|
||||||
|
|
||||||
|
If you were previously using this constant, you can check if `'ontouchstart'` is defined in `window` instead.
|
||||||
|
|
||||||
|
```js
|
||||||
|
if ('ontouchstart' in window) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### Removal of `GEOLOCATION` constant from `ol/has`
|
#### Removal of `GEOLOCATION` constant from `ol/has`
|
||||||
|
|
||||||
If you were previously using this constant, you can check if `'geolocation'` is define in `navigator` instead.
|
If you were previously using this constant, you can check if `'geolocation'` is defined in `navigator` instead.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
if ('geolocation' in navigator) {
|
if ('geolocation' in navigator) {
|
||||||
|
|||||||
@@ -59,7 +59,9 @@ function includeAugments(doclet) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
cls._hideConstructor = true;
|
cls._hideConstructor = true;
|
||||||
delete cls.undocumented;
|
if (!cls.undocumented) {
|
||||||
|
cls._documented = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,6 +152,9 @@ exports.handlers = {
|
|||||||
// Remove all other undocumented symbols
|
// Remove all other undocumented symbols
|
||||||
doclet.undocumented = true;
|
doclet.undocumented = true;
|
||||||
}
|
}
|
||||||
|
if (doclet._documented) {
|
||||||
|
delete doclet.undocumented;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,55 +214,39 @@ function buildNav(members) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function createEntry(type, v) {
|
||||||
|
return {
|
||||||
|
type: type,
|
||||||
|
longname: v.longname,
|
||||||
|
name: v.name,
|
||||||
|
classes: find({
|
||||||
|
kind: 'class',
|
||||||
|
memberof: v.longname
|
||||||
|
}).map(createEntry.bind(this, 'class')),
|
||||||
|
members: find({
|
||||||
|
kind: 'member',
|
||||||
|
memberof: v.longname
|
||||||
|
}),
|
||||||
|
methods: find({
|
||||||
|
kind: 'function',
|
||||||
|
memberof: v.longname
|
||||||
|
}),
|
||||||
|
typedefs: find({
|
||||||
|
kind: 'typedef',
|
||||||
|
memberof: v.longname
|
||||||
|
}),
|
||||||
|
events: find({
|
||||||
|
kind: 'event',
|
||||||
|
memberof: v.longname
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
_.each(merged, function(v) {
|
_.each(merged, function(v) {
|
||||||
// exclude interfaces from sidebar
|
// exclude interfaces from sidebar
|
||||||
if (v.interface !== true) {
|
if (v.interface !== true) {
|
||||||
if (v.kind == 'module') {
|
if (v.kind == 'module') {
|
||||||
nav.push({
|
nav.push(createEntry('module', v));
|
||||||
type: 'module',
|
|
||||||
longname: v.longname,
|
|
||||||
name: v.name,
|
|
||||||
members: find({
|
|
||||||
kind: 'member',
|
|
||||||
memberof: v.longname
|
|
||||||
}),
|
|
||||||
methods: find({
|
|
||||||
kind: 'function',
|
|
||||||
memberof: v.longname
|
|
||||||
}),
|
|
||||||
typedefs: find({
|
|
||||||
kind: 'typedef',
|
|
||||||
memberof: v.longname
|
|
||||||
}),
|
|
||||||
events: find({
|
|
||||||
kind: 'event',
|
|
||||||
memberof: v.longname
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (v.kind == 'class') {
|
|
||||||
nav.push({
|
|
||||||
type: 'class',
|
|
||||||
longname: v.longname,
|
|
||||||
name: v.name,
|
|
||||||
members: find({
|
|
||||||
kind: 'member',
|
|
||||||
memberof: v.longname
|
|
||||||
}),
|
|
||||||
methods: find({
|
|
||||||
kind: 'function',
|
|
||||||
memberof: v.longname
|
|
||||||
}),
|
|
||||||
typedefs: find({
|
|
||||||
kind: 'typedef',
|
|
||||||
memberof: v.longname
|
|
||||||
}),
|
|
||||||
fires: v.fires,
|
|
||||||
events: find({
|
|
||||||
kind: 'event',
|
|
||||||
memberof: v.longname
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,13 +12,18 @@ $(function () {
|
|||||||
var $item = $(v);
|
var $item = $(v);
|
||||||
|
|
||||||
if ($item.data('name') && regexp.test($item.data('name'))) {
|
if ($item.data('name') && regexp.test($item.data('name'))) {
|
||||||
|
const container = $item.parent().parent().parent();
|
||||||
|
container.show();
|
||||||
|
container.closest('.itemMembers').show();
|
||||||
|
container.closest('.item').show();
|
||||||
$item.show();
|
$item.show();
|
||||||
$item.closest('.itemMembers').show();
|
$item.closest('.itemMembers').show();
|
||||||
$item.closest('.item').show();
|
$item.closest('.item').show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$el.find('.item, .itemMembers').show();
|
$el.find('.item, .itemMembers').hide();
|
||||||
|
$('.navigation>ul>li').show();
|
||||||
}
|
}
|
||||||
|
|
||||||
$el.find('.list').scrollTop(0);
|
$el.find('.list').scrollTop(0);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<sup class="variation"><?js= doc.variation ?></sup>
|
<sup class="variation"><?js= doc.variation ?></sup>
|
||||||
<?js } ?></h2>
|
<?js } ?></h2>
|
||||||
<br>
|
<br>
|
||||||
<?js if (doc.stability || doc.kind == 'namespace') {
|
<?js if (doc.stability || doc.kind == 'namespace' || doc.kind == 'module') {
|
||||||
var ancestors = doc.ancestors.map(a => a.replace(/>\./g, '>').replace(/\.</g, '<')).join('/');
|
var ancestors = doc.ancestors.map(a => a.replace(/>\./g, '>').replace(/\.</g, '<')).join('/');
|
||||||
var parts = [];
|
var parts = [];
|
||||||
if (ancestors) {
|
if (ancestors) {
|
||||||
@@ -26,7 +26,20 @@
|
|||||||
}
|
}
|
||||||
var importPath = parts.join('/');
|
var importPath = parts.join('/');
|
||||||
?>
|
?>
|
||||||
<pre class="prettyprint source"><code>import <?js= doc.name ?> from '<?js= importPath ?>';</code></pre>
|
<?js
|
||||||
|
var nameParts = doc.name.split('/');
|
||||||
|
var moduleName = nameParts[nameParts.length - 1];
|
||||||
|
if(moduleName) {
|
||||||
|
var firstChar = moduleName.charAt(0);
|
||||||
|
moduleName = firstChar.toUpperCase() + moduleName.slice(1);
|
||||||
|
var isClassModule = firstChar.toUpperCase() === firstChar;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<?js if (doc.kind == 'module' && !isClassModule && nameParts.length < 3) {?>
|
||||||
|
<pre class="prettyprint source"><code>import * as ol<?js= moduleName ?> from '<?js= doc.name ?>';</code></pre>
|
||||||
|
<?js } else if(doc.kind !== 'module') { ?>
|
||||||
|
<pre class="prettyprint source"><code>import <?js= doc.name ?> from '<?js= importPath ?>';</code></pre>
|
||||||
|
<?js } ?>
|
||||||
<?js } ?>
|
<?js } ?>
|
||||||
<?js if (doc.classdesc) { ?>
|
<?js if (doc.classdesc) { ?>
|
||||||
<div class="class-description"><?js= doc.classdesc ?></div>
|
<div class="class-description"><?js= doc.classdesc ?></div>
|
||||||
@@ -143,6 +156,7 @@
|
|||||||
<h3 class="subsection-title">Methods</h3>
|
<h3 class="subsection-title">Methods</h3>
|
||||||
|
|
||||||
<dl><?js methods.forEach(function(m) { ?>
|
<dl><?js methods.forEach(function(m) { ?>
|
||||||
|
<?js m.parent = doc ?>
|
||||||
<?js= self.partial('method.tmpl', m) ?>
|
<?js= self.partial('method.tmpl', m) ?>
|
||||||
<?js }); ?></dl>
|
<?js }); ?></dl>
|
||||||
<?js } ?>
|
<?js } ?>
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ var self = this;
|
|||||||
</dt>
|
</dt>
|
||||||
<dd class="<?js= (data.stability && data.stability !== 'stable') ? 'unstable' : '' ?>">
|
<dd class="<?js= (data.stability && data.stability !== 'stable') ? 'unstable' : '' ?>">
|
||||||
|
|
||||||
|
<?js if (data.parent && data.parent.kind == 'module' && data.parent.name.split('ol/').length < 3) { ?>
|
||||||
|
<pre class="prettyprint source"><code>import {<?js= data.name ?>} from '<?js= data.parent.name ?>';</code></pre>
|
||||||
|
<?js } ?>
|
||||||
|
|
||||||
<?js if (data.description) { ?>
|
<?js if (data.description) { ?>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<?js= data.description ?>
|
<?js= data.description ?>
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ function toShortName(name) {
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list">
|
<ul class="list">
|
||||||
<?js
|
<?js
|
||||||
this.nav.forEach(function (item) {
|
let navbuilder;
|
||||||
|
this.nav.forEach(navbuilder = function (item) {
|
||||||
?>
|
?>
|
||||||
<li class="item" data-name="<?js= item.longname ?>">
|
<li class="item" data-name="<?js= item.longname ?>">
|
||||||
<span class="title">
|
<span class="title">
|
||||||
<?js= self.linkto(item.longname, item.longname.replace('module:', '')) ?>
|
<?js= self.linkto(item.longname, item.type === 'module' ? item.longname.replace('module:', '') : item.name) ?>
|
||||||
<?js if (item.type === 'namespace' &&
|
<?js if (item.type === 'namespace' &&
|
||||||
(item.members.length + item.typedefs.length + item.methods.length +
|
(item.members.length + item.typedefs.length + item.methods.length +
|
||||||
item.events.length > 0)) { ?>
|
item.events.length > 0)) { ?>
|
||||||
@@ -22,6 +23,18 @@ function toShortName(name) {
|
|||||||
</span>
|
</span>
|
||||||
<ul class="members itemMembers">
|
<ul class="members itemMembers">
|
||||||
<?js
|
<?js
|
||||||
|
if (item.classes.length) {
|
||||||
|
?>
|
||||||
|
<span class="subtitle">Classes</span>
|
||||||
|
<?js
|
||||||
|
item.classes.forEach(function (v) {
|
||||||
|
navbuilder(v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ul>
|
||||||
|
<ul class="members itemMembers">
|
||||||
|
<?js
|
||||||
if (item.members.length) {
|
if (item.members.length) {
|
||||||
?>
|
?>
|
||||||
<span class="subtitle">Members</span>
|
<span class="subtitle">Members</span>
|
||||||
|
|||||||
@@ -228,3 +228,11 @@ Missing or invalid `size`.
|
|||||||
### 61
|
### 61
|
||||||
|
|
||||||
Cannot determine IIIF Image API version from provided image information JSON.
|
Cannot determine IIIF Image API version from provided image information JSON.
|
||||||
|
|
||||||
|
### 62
|
||||||
|
|
||||||
|
A `WebGLArrayBuffer` must either be of type `ELEMENT_ARRAY_BUFFER` or `ARRAY_BUFFER`.
|
||||||
|
|
||||||
|
### 63
|
||||||
|
|
||||||
|
Support for the `OES_element_index_uint` WebGL extension is mandatory for WebGL layers.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
|||||||
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
||||||
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';
|
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';
|
||||||
|
|
||||||
|
/** @type {VectorSource<import("../src/ol/geom/SimpleGeometry.js").default>} */
|
||||||
const source = new VectorSource({
|
const source = new VectorSource({
|
||||||
url: 'data/geojson/switzerland.geojson',
|
url: 'data/geojson/switzerland.geojson',
|
||||||
format: new GeoJSON()
|
format: new GeoJSON()
|
||||||
@@ -51,21 +52,21 @@ const zoomtoswitzerland =
|
|||||||
document.getElementById('zoomtoswitzerland');
|
document.getElementById('zoomtoswitzerland');
|
||||||
zoomtoswitzerland.addEventListener('click', function() {
|
zoomtoswitzerland.addEventListener('click', function() {
|
||||||
const feature = source.getFeatures()[0];
|
const feature = source.getFeatures()[0];
|
||||||
const polygon = /** @type {import("../src/ol/geom/SimpleGeometry.js").default} */ (feature.getGeometry());
|
const polygon = feature.getGeometry();
|
||||||
view.fit(polygon, {padding: [170, 50, 30, 150]});
|
view.fit(polygon, {padding: [170, 50, 30, 150]});
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
const zoomtolausanne = document.getElementById('zoomtolausanne');
|
const zoomtolausanne = document.getElementById('zoomtolausanne');
|
||||||
zoomtolausanne.addEventListener('click', function() {
|
zoomtolausanne.addEventListener('click', function() {
|
||||||
const feature = source.getFeatures()[1];
|
const feature = source.getFeatures()[1];
|
||||||
const point = /** @type {import("../src/ol/geom/SimpleGeometry.js").default} */ (feature.getGeometry());
|
const point = feature.getGeometry();
|
||||||
view.fit(point, {padding: [170, 50, 30, 150], minResolution: 50});
|
view.fit(point, {padding: [170, 50, 30, 150], minResolution: 50});
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
const centerlausanne = document.getElementById('centerlausanne');
|
const centerlausanne = document.getElementById('centerlausanne');
|
||||||
centerlausanne.addEventListener('click', function() {
|
centerlausanne.addEventListener('click', function() {
|
||||||
const feature = source.getFeatures()[1];
|
const feature = source.getFeatures()[1];
|
||||||
const point = /** @type {import("../src/ol/geom/Point.js").default} */ (feature.getGeometry());
|
const point = feature.getGeometry();
|
||||||
const size = map.getSize();
|
const size = map.getSize();
|
||||||
view.centerOn(point.getCoordinates(), size, [570, 500]);
|
view.centerOn(point.getCoordinates(), size, [570, 500]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ const map = new Map({
|
|||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new TileJSON({
|
source: new TileJSON({
|
||||||
url: 'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure'
|
url: 'https://a.tiles.mapbox.com/v3/aj.1x1-degrees.json'
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
new VectorLayer({
|
new VectorLayer({
|
||||||
|
|||||||
2
examples/d3.js
vendored
2
examples/d3.js
vendored
@@ -2,7 +2,7 @@ import Map from '../src/ol/Map.js';
|
|||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import {getWidth, getCenter} from '../src/ol/extent.js';
|
import {getWidth, getCenter} from '../src/ol/extent.js';
|
||||||
import {Layer, Tile as TileLayer} from '../src/ol/layer.js';
|
import {Layer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||||
import SourceState from '../src/ol/source/State';
|
import SourceState from '../src/ol/source/State.js';
|
||||||
import {fromLonLat, toLonLat} from '../src/ol/proj.js';
|
import {fromLonLat, toLonLat} from '../src/ol/proj.js';
|
||||||
import Stamen from '../src/ol/source/Stamen.js';
|
import Stamen from '../src/ol/source/Stamen.js';
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import View from '../src/ol/View.js';
|
|||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import OSM from '../src/ol/source/OSM.js';
|
import OSM from '../src/ol/source/OSM.js';
|
||||||
import {defaults as defaultControls} from '../src/ol/control.js';
|
import {defaults as defaultControls} from '../src/ol/control.js';
|
||||||
import ZoomSlider from '../src/ol/control/ZoomSlider';
|
import ZoomSlider from '../src/ol/control/ZoomSlider.js';
|
||||||
|
|
||||||
const view = new View({
|
const view = new View({
|
||||||
center: [328627.563458, 5921296.662223],
|
center: [328627.563458, 5921296.662223],
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ const routeFeature = new Feature({
|
|||||||
type: 'route',
|
type: 'route',
|
||||||
geometry: route
|
geometry: route
|
||||||
});
|
});
|
||||||
const geoMarker = new Feature({
|
const geoMarker = /** @type Feature<import("../src/ol/geom/Point").default> */(new Feature({
|
||||||
type: 'geoMarker',
|
type: 'geoMarker',
|
||||||
geometry: new Point(routeCoords[0])
|
geometry: new Point(routeCoords[0])
|
||||||
});
|
}));
|
||||||
const startMarker = new Feature({
|
const startMarker = new Feature({
|
||||||
type: 'icon',
|
type: 'icon',
|
||||||
geometry: new Point(routeCoords[0])
|
geometry: new Point(routeCoords[0])
|
||||||
@@ -191,7 +191,7 @@ function stopAnimation(ended) {
|
|||||||
|
|
||||||
// if animation cancelled set the marker at the beginning
|
// if animation cancelled set the marker at the beginning
|
||||||
const coord = ended ? routeCoords[routeLength - 1] : routeCoords[0];
|
const coord = ended ? routeCoords[routeLength - 1] : routeCoords[0];
|
||||||
const geometry = /** @type {import("../src/ol/geom/Point").default} */ (geoMarker.getGeometry());
|
const geometry = geoMarker.getGeometry();
|
||||||
geometry.setCoordinates(coord);
|
geometry.setCoordinates(coord);
|
||||||
//remove listener
|
//remove listener
|
||||||
vectorLayer.un('postrender', moveFeature);
|
vectorLayer.un('postrender', moveFeature);
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import Feature from '../src/ol/Feature';
|
import Feature from '../src/ol/Feature.js';
|
||||||
import Point from '../src/ol/geom/Point';
|
import Point from '../src/ol/geom/Point.js';
|
||||||
import VectorLayer from '../src/ol/layer/Vector';
|
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||||
import {Vector} from '../src/ol/source';
|
import {Vector} from '../src/ol/source.js';
|
||||||
import {fromLonLat} from '../src/ol/proj';
|
import {fromLonLat} from '../src/ol/proj.js';
|
||||||
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer';
|
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer.js';
|
||||||
import {clamp, lerp} from '../src/ol/math';
|
import {clamp, lerp} from '../src/ol/math.js';
|
||||||
import Stamen from '../src/ol/source/Stamen';
|
import Stamen from '../src/ol/source/Stamen.js';
|
||||||
|
|
||||||
const vectorSource = new Vector({
|
const vectorSource = new Vector({
|
||||||
attributions: 'NASA'
|
attributions: 'NASA'
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import VectorTileSource from '../src/ol/source/VectorTile.js';
|
|||||||
import {Tile as TileLayer, VectorTile as VectorTileLayer} from '../src/ol/layer.js';
|
import {Tile as TileLayer, VectorTile as VectorTileLayer} from '../src/ol/layer.js';
|
||||||
import Projection from '../src/ol/proj/Projection.js';
|
import Projection from '../src/ol/proj/Projection.js';
|
||||||
|
|
||||||
|
// Converts geojson-vt data to GeoJSON
|
||||||
const replacer = function(key, value) {
|
const replacer = function(key, value) {
|
||||||
if (value.geometry) {
|
if (value.geometry) {
|
||||||
let type;
|
let type;
|
||||||
@@ -46,11 +46,6 @@ const replacer = function(key, value) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const tilePixels = new Projection({
|
|
||||||
code: 'TILE_PIXELS',
|
|
||||||
units: 'tile-pixels'
|
|
||||||
});
|
|
||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
@@ -73,23 +68,22 @@ fetch(url).then(function(response) {
|
|||||||
debug: 1
|
debug: 1
|
||||||
});
|
});
|
||||||
const vectorSource = new VectorTileSource({
|
const vectorSource = new VectorTileSource({
|
||||||
format: new GeoJSON(),
|
format: new GeoJSON({
|
||||||
tileLoadFunction: function(tile) {
|
// Data returned from geojson-vt is in tile pixel units
|
||||||
const format = tile.getFormat();
|
dataProjection: new Projection({
|
||||||
const tileCoord = tile.getTileCoord();
|
code: 'TILE_PIXELS',
|
||||||
|
units: 'tile-pixels',
|
||||||
|
extent: [0, 0, 4096, 4096]
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
tileUrlFunction: function(tileCoord) {
|
||||||
const data = tileIndex.getTile(tileCoord[0], tileCoord[1], tileCoord[2]);
|
const data = tileIndex.getTile(tileCoord[0], tileCoord[1], tileCoord[2]);
|
||||||
|
const geojson = JSON.stringify({
|
||||||
const features = format.readFeatures(
|
type: 'FeatureCollection',
|
||||||
JSON.stringify({
|
features: data ? data.features : []
|
||||||
type: 'FeatureCollection',
|
}, replacer);
|
||||||
features: data ? data.features : []
|
return 'data:application/json;charset=UTF-8,' + geojson;
|
||||||
}, replacer));
|
}
|
||||||
tile.setLoader(function() {
|
|
||||||
tile.setFeatures(features);
|
|
||||||
tile.setProjection(tilePixels);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
url: 'data:' // arbitrary url, we don't use it in the tileLoadFunction
|
|
||||||
});
|
});
|
||||||
const vectorLayer = new VectorTileLayer({
|
const vectorLayer = new VectorTileLayer({
|
||||||
source: vectorSource
|
source: vectorSource
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ const vectorLayer = new VectorLayer({
|
|||||||
|
|
||||||
const rasterLayer = new TileLayer({
|
const rasterLayer = new TileLayer({
|
||||||
source: new TileJSON({
|
source: new TileJSON({
|
||||||
url: 'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure',
|
url: 'https://a.tiles.mapbox.com/v3/aj.1x1-degrees.json',
|
||||||
crossOrigin: ''
|
crossOrigin: ''
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,5 +13,8 @@ docs: >
|
|||||||
|
|
||||||
The dataset contains around 80k points and can be found here: https://www.kaggle.com/NUFORC/ufo-sightings
|
The dataset contains around 80k points and can be found here: https://www.kaggle.com/NUFORC/ufo-sightings
|
||||||
tags: "webgl, icon, sprite, point, ufo"
|
tags: "webgl, icon, sprite, point, ufo"
|
||||||
|
cloak:
|
||||||
|
- key: pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg
|
||||||
|
value: Your Mapbox access token from https://mapbox.com/ here
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import TileJSON from '../src/ol/source/TileJSON';
|
import TileJSON from '../src/ol/source/TileJSON.js';
|
||||||
import Feature from '../src/ol/Feature';
|
import Feature from '../src/ol/Feature.js';
|
||||||
import Point from '../src/ol/geom/Point';
|
import Point from '../src/ol/geom/Point.js';
|
||||||
import VectorLayer from '../src/ol/layer/Vector';
|
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||||
import {Vector} from '../src/ol/source';
|
import {Vector} from '../src/ol/source.js';
|
||||||
import {fromLonLat} from '../src/ol/proj';
|
import {fromLonLat} from '../src/ol/proj.js';
|
||||||
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer';
|
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer.js';
|
||||||
import {lerp} from '../src/ol/math';
|
import {lerp} from '../src/ol/math.js';
|
||||||
|
|
||||||
|
const key = 'pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg';
|
||||||
|
|
||||||
const vectorSource = new Vector({
|
const vectorSource = new Vector({
|
||||||
features: [],
|
features: [],
|
||||||
@@ -105,7 +107,7 @@ new Map({
|
|||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new TileJSON({
|
source: new TileJSON({
|
||||||
url: 'https://api.tiles.mapbox.com/v3/mapbox.world-dark.json?secure',
|
url: 'https://api.tiles.mapbox.com/v4/mapbox.world-dark.json?access_token=' + key,
|
||||||
crossOrigin: 'anonymous'
|
crossOrigin: 'anonymous'
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const vectorLayer = new VectorLayer({
|
|||||||
|
|
||||||
const rasterLayer = new TileLayer({
|
const rasterLayer = new TileLayer({
|
||||||
source: new TileJSON({
|
source: new TileJSON({
|
||||||
url: 'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure',
|
url: 'https://a.tiles.mapbox.com/v3/aj.1x1-degrees.json',
|
||||||
crossOrigin: ''
|
crossOrigin: ''
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ layout: example.html
|
|||||||
title: Mapbox-gl Layer
|
title: Mapbox-gl Layer
|
||||||
shortdesc: Example of a Mapbox-gl-js layer integration.
|
shortdesc: Example of a Mapbox-gl-js layer integration.
|
||||||
docs: >
|
docs: >
|
||||||
Show how to add a mapbox-gl-js layer in an openlayers map. **Note**: Make sure to get your own Mapbox API key when using this example. No map will be visible when the API key has expired.
|
Show how to add a mapbox-gl-js layer in an openlayers map. **Note**: Make sure to get your own API key at https://www.maptiler.com/cloud/ when using this example. No map will be visible when the API key has expired.
|
||||||
tags: "simple, mapbox, vector, tiles"
|
tags: "simple, mapbox, vector, tiles, maptiler"
|
||||||
resources:
|
resources:
|
||||||
- https://unpkg.com/mapbox-gl@0.54.0/dist/mapbox-gl.js
|
- https://unpkg.com/mapbox-gl@0.54.0/dist/mapbox-gl.js
|
||||||
- https://unpkg.com/mapbox-gl@0.54.0/dist/mapbox-gl.css
|
- https://unpkg.com/mapbox-gl@0.54.0/dist/mapbox-gl.css
|
||||||
cloak:
|
cloak:
|
||||||
- key: ER67WIiPdCQvhgsUjoWK
|
- key: ER67WIiPdCQvhgsUjoWK
|
||||||
value: Your Mapbox access token from https://mapbox.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import Layer from '../src/ol/layer/Layer';
|
import Layer from '../src/ol/layer/Layer.js';
|
||||||
import {toLonLat, fromLonLat} from '../src/ol/proj';
|
import {toLonLat, fromLonLat} from '../src/ol/proj.js';
|
||||||
import {Stroke, Style} from '../src/ol/style.js';
|
import {Stroke, Style} from '../src/ol/style.js';
|
||||||
import VectorLayer from '../src/ol/layer/Vector.js';
|
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||||
import VectorSource from '../src/ol/source/Vector.js';
|
import VectorSource from '../src/ol/source/Vector.js';
|
||||||
@@ -11,7 +11,7 @@ const center = [-98.8, 37.9];
|
|||||||
const key = 'ER67WIiPdCQvhgsUjoWK';
|
const key = 'ER67WIiPdCQvhgsUjoWK';
|
||||||
|
|
||||||
const mbMap = new mapboxgl.Map({
|
const mbMap = new mapboxgl.Map({
|
||||||
style: 'https://maps.tilehosting.com/styles/bright/style.json?key=' + key,
|
style: 'https://api.maptiler.com/maps/bright/style.json?key=' + key,
|
||||||
attributionControl: false,
|
attributionControl: false,
|
||||||
boxZoom: false,
|
boxZoom: false,
|
||||||
center: center,
|
center: center,
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
layout: example-verbatim.html
|
layout: example-verbatim.html
|
||||||
title: Vector tiles created from a Mapbox Style object
|
title: Vector tiles created from a Mapbox Style object
|
||||||
shortdesc: Example of using ol-mapbox-style with tiles from tilehosting.com.
|
shortdesc: Example of using ol-mapbox-style with tiles from tilehosting.com.
|
||||||
tags: "vector tiles, mapbox style, ol-mapbox-style"
|
tags: "vector tiles, mapbox style, ol-mapbox-style, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: lirfd6Fegsjkvs0lshxe
|
- key: ER67WIiPdCQvhgsUjoWK
|
||||||
value: Your API key from http://tilehosting.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import apply from 'ol-mapbox-style';
|
import apply from 'ol-mapbox-style';
|
||||||
|
|
||||||
apply('map', 'https://maps.tilehosting.com/styles/topo/style.json?key=ER67WIiPdCQvhgsUjoWK');
|
apply('map', 'https://api.maptiler.com/maps/topo/style.json?key=ER67WIiPdCQvhgsUjoWK');
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ docs: >
|
|||||||
Click on the map to get a popup. The popup is composed of a few basic elements: a container, a close button, and a place for the content. To anchor the popup to the map, an <code>ol/Overlay</code> is created with the popup container. A listener is registered for the map's <code>click</code> event to display the popup, and another listener is set as the <code>click</code> handler for the close button to hide the popup.
|
Click on the map to get a popup. The popup is composed of a few basic elements: a container, a close button, and a place for the content. To anchor the popup to the map, an <code>ol/Overlay</code> is created with the popup container. A listener is registered for the map's <code>click</code> event to display the popup, and another listener is set as the <code>click</code> handler for the close button to hide the popup.
|
||||||
</p>
|
</p>
|
||||||
tags: "overlay, popup"
|
tags: "overlay, popup"
|
||||||
|
cloak:
|
||||||
|
- key: pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg
|
||||||
|
value: Your Mapbox access token from https://mapbox.com/ here
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
<div id="popup" class="ol-popup">
|
<div id="popup" class="ol-popup">
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import TileLayer from '../src/ol/layer/Tile.js';
|
|||||||
import {toLonLat} from '../src/ol/proj.js';
|
import {toLonLat} from '../src/ol/proj.js';
|
||||||
import TileJSON from '../src/ol/source/TileJSON.js';
|
import TileJSON from '../src/ol/source/TileJSON.js';
|
||||||
|
|
||||||
|
const key = 'pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Elements that make up the popup.
|
* Elements that make up the popup.
|
||||||
@@ -45,7 +46,7 @@ const map = new Map({
|
|||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new TileJSON({
|
source: new TileJSON({
|
||||||
url: 'https://api.tiles.mapbox.com/v3/mapbox.natural-earth-hypso-bathy.json?secure',
|
url: 'https://api.tiles.mapbox.com/v4/mapbox.natural-earth-hypso-bathy.json?access_token=' + key,
|
||||||
crossOrigin: 'anonymous'
|
crossOrigin: 'anonymous'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const map = new Map({
|
|||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new TileJSON({
|
source: new TileJSON({
|
||||||
url: 'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure',
|
url: 'https://a.tiles.mapbox.com/v3/aj.1x1-degrees.json',
|
||||||
crossOrigin: 'anonymous'
|
crossOrigin: 'anonymous'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: UTFGrid
|
|||||||
shortdesc: This example shows how to read data from a UTFGrid source.
|
shortdesc: This example shows how to read data from a UTFGrid source.
|
||||||
docs: >
|
docs: >
|
||||||
<p>Point to a country to see its name and flag.</p>
|
<p>Point to a country to see its name and flag.</p>
|
||||||
Tiles made with [TileMill](http://tilemill.com). Hosting on MapBox.com or with open-source [TileServer](https://github.com/klokantech/tileserver-php/).
|
Tiles made with <a href="http://tilemill.com">TileMill</a>. Hosting on <a href="mapbox.com">mapbox.com</a> or with open-source <a href="https://github.com/klokantech/tileserver-php/">TileServer</a>.
|
||||||
tags: "utfgrid, tilejson"
|
tags: "utfgrid, tilejson"
|
||||||
cloak:
|
cloak:
|
||||||
- key: pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiY2pzbmg0Nmk5MGF5NzQzbzRnbDNoeHJrbiJ9.7_-_gL8ur7ZtEiNwRfCy7Q
|
- key: pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiY2pzbmg0Nmk5MGF5NzQzbzRnbDNoeHJrbiJ9.7_-_gL8ur7ZtEiNwRfCy7Q
|
||||||
|
|||||||
@@ -2,14 +2,7 @@ const build = require('../../tasks/serialize-workers').build;
|
|||||||
|
|
||||||
function loader() {
|
function loader() {
|
||||||
const callback = this.async();
|
const callback = this.async();
|
||||||
|
const minify = this.mode === 'production';
|
||||||
let minify = false;
|
|
||||||
|
|
||||||
// TODO: remove when https://github.com/webpack/webpack/issues/6496 is addressed
|
|
||||||
const compilation = this._compilation;
|
|
||||||
if (compilation) {
|
|
||||||
minify = compilation.compiler.options.mode === 'production';
|
|
||||||
}
|
|
||||||
|
|
||||||
build(this.resource, {minify})
|
build(this.resource, {minify})
|
||||||
.then(chunk => {
|
.then(chunk => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Map from '../src/ol/Map.js';
|
|||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import OSM from '../src/ol/source/OSM.js';
|
import OSM from '../src/ol/source/OSM.js';
|
||||||
import {create as createVersionWorker} from '../src/ol/worker/version';
|
import {create as createVersionWorker} from '../src/ol/worker/version.js';
|
||||||
|
|
||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
|
|||||||
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ol",
|
"name": "ol",
|
||||||
"version": "6.0.0-beta.8",
|
"version": "6.0.0-beta.10",
|
||||||
"description": "OpenLayers mapping library",
|
"description": "OpenLayers mapping library",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"map",
|
"map",
|
||||||
@@ -54,9 +54,9 @@
|
|||||||
"chaikin-smooth": "^1.0.4",
|
"chaikin-smooth": "^1.0.4",
|
||||||
"clean-css-cli": "4.3.0",
|
"clean-css-cli": "4.3.0",
|
||||||
"copy-webpack-plugin": "^5.0.3",
|
"copy-webpack-plugin": "^5.0.3",
|
||||||
"coveralls": "3.0.3",
|
"coveralls": "3.0.4",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^6.0.0",
|
||||||
"eslint-config-openlayers": "^11.0.0",
|
"eslint-config-openlayers": "^12.0.0",
|
||||||
"expect.js": "0.3.1",
|
"expect.js": "0.3.1",
|
||||||
"front-matter": "^3.0.2",
|
"front-matter": "^3.0.2",
|
||||||
"fs-extra": "^8.0.0",
|
"fs-extra": "^8.0.0",
|
||||||
@@ -81,15 +81,15 @@
|
|||||||
"marked": "0.6.2",
|
"marked": "0.6.2",
|
||||||
"mocha": "6.1.4",
|
"mocha": "6.1.4",
|
||||||
"ol-mapbox-style": "^5.0.0-beta.2",
|
"ol-mapbox-style": "^5.0.0-beta.2",
|
||||||
"pixelmatch": "^4.0.2",
|
"pixelmatch": "^5.0.0",
|
||||||
"pngjs": "^3.4.0",
|
"pngjs": "^3.4.0",
|
||||||
"proj4": "2.5.0",
|
"proj4": "2.5.0",
|
||||||
"puppeteer": "~1.16.0",
|
"puppeteer": "~1.18.0",
|
||||||
"rollup": "^1.12.0",
|
"rollup": "^1.12.0",
|
||||||
"rollup-plugin-babel": "^4.3.2",
|
"rollup-plugin-babel": "^4.3.2",
|
||||||
"rollup-plugin-commonjs": "^10.0.0",
|
"rollup-plugin-commonjs": "^10.0.0",
|
||||||
"rollup-plugin-node-resolve": "^5.0.0",
|
"rollup-plugin-node-resolve": "^5.0.0",
|
||||||
"rollup-plugin-terser": "^4.0.4",
|
"rollup-plugin-terser": "^5.0.0",
|
||||||
"serve-static": "^1.14.0",
|
"serve-static": "^1.14.0",
|
||||||
"shx": "^0.3.2",
|
"shx": "^0.3.2",
|
||||||
"sinon": "^7.3.2",
|
"sinon": "^7.3.2",
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
"typescript": "^3.4.5",
|
"typescript": "^3.4.5",
|
||||||
"url-polyfill": "^1.1.5",
|
"url-polyfill": "^1.1.5",
|
||||||
"walk": "^2.3.9",
|
"walk": "^2.3.9",
|
||||||
"webpack": "4.31.0",
|
"webpack": "4.35.0",
|
||||||
"webpack-cli": "^3.3.2",
|
"webpack-cli": "^3.3.2",
|
||||||
"webpack-dev-middleware": "^3.6.2",
|
"webpack-dev-middleware": "^3.6.2",
|
||||||
"webpack-dev-server": "^3.3.1",
|
"webpack-dev-server": "^3.3.1",
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import TileLayer from '../../../src/ol/layer/Tile.js';
|
import TileLayer from '../../../src/ol/layer/Tile.js';
|
||||||
import XYZ from '../../../src/ol/source/XYZ';
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
import {Heatmap as HeatmapLayer} from '../../../src/ol/layer';
|
import {Heatmap as HeatmapLayer} from '../../../src/ol/layer.js';
|
||||||
import VectorSource from '../../../src/ol/source/Vector';
|
import VectorSource from '../../../src/ol/source/Vector.js';
|
||||||
import KML from '../../../src/ol/format/KML';
|
import KML from '../../../src/ol/format/KML.js';
|
||||||
|
|
||||||
const vector = new HeatmapLayer({
|
const vector = new HeatmapLayer({
|
||||||
source: new VectorSource({
|
source: new VectorSource({
|
||||||
|
|||||||
BIN
rendering/cases/layer-group/expected.png
Normal file
BIN
rendering/cases/layer-group/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
30
rendering/cases/layer-group/main.js
Normal file
30
rendering/cases/layer-group/main.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import Map from '../../../src/ol/Map.js';
|
||||||
|
import View from '../../../src/ol/View.js';
|
||||||
|
import {Group as LayerGroup, Tile as TileLayer} from '../../../src/ol/layer.js';
|
||||||
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
|
new Map({
|
||||||
|
target: 'map',
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 3
|
||||||
|
}),
|
||||||
|
layers: new LayerGroup({
|
||||||
|
opacity: 0.75,
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
opacity: 0.25,
|
||||||
|
source: new XYZ({
|
||||||
|
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg'
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
new TileLayer({
|
||||||
|
source: new XYZ({
|
||||||
|
url: '/data/tiles/stamen-labels/{z}/{x}/{y}.png'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
render();
|
||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
get as getProjection,
|
get as getProjection,
|
||||||
transform,
|
transform,
|
||||||
transformExtent
|
transformExtent
|
||||||
} from '../../../src/ol/proj';
|
} from '../../../src/ol/proj.js';
|
||||||
import ImageLayer from '../../../src/ol/layer/Image.js';
|
import ImageLayer from '../../../src/ol/layer/Image.js';
|
||||||
const center = transform([-122.416667, 37.783333], 'EPSG:4326', 'EPSG:3857');
|
const center = transform([-122.416667, 37.783333], 'EPSG:4326', 'EPSG:3857');
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import TileLayer from '../../../src/ol/layer/Tile.js';
|
import TileLayer from '../../../src/ol/layer/Tile.js';
|
||||||
import {fromLonLat} from '../../../src/ol/proj';
|
import {fromLonLat} from '../../../src/ol/proj.js';
|
||||||
import {transformExtent} from '../../../src/ol/proj.js';
|
import {transformExtent} from '../../../src/ol/proj.js';
|
||||||
import XYZ from '../../../src/ol/source/XYZ';
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
const center = fromLonLat([7, 50]);
|
const center = fromLonLat([7, 50]);
|
||||||
const extent = transformExtent([2, 47, 10, 53], 'EPSG:4326', 'EPSG:3857');
|
const extent = transformExtent([2, 47, 10, 53], 'EPSG:4326', 'EPSG:3857');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import TileLayer from '../../../src/ol/layer/Tile.js';
|
import TileLayer from '../../../src/ol/layer/Tile.js';
|
||||||
import XYZ from '../../../src/ol/source/XYZ';
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
import {createXYZ} from '../../../src/ol/tilegrid.js';
|
import {createXYZ} from '../../../src/ol/tilegrid.js';
|
||||||
|
|
||||||
const center = [-10997148, 4569099];
|
const center = [-10997148, 4569099];
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import TileLayer from '../../../src/ol/layer/Tile.js';
|
import TileLayer from '../../../src/ol/layer/Tile.js';
|
||||||
import {fromLonLat} from '../../../src/ol/proj';
|
import {fromLonLat} from '../../../src/ol/proj.js';
|
||||||
import XYZ from '../../../src/ol/source/XYZ';
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
const center = fromLonLat([8.6, 50.1]);
|
const center = fromLonLat([8.6, 50.1]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import TileLayer from '../../../src/ol/layer/Tile.js';
|
import TileLayer from '../../../src/ol/layer/Tile.js';
|
||||||
import {fromLonLat} from '../../../src/ol/proj';
|
import {fromLonLat} from '../../../src/ol/proj.js';
|
||||||
import XYZ from '../../../src/ol/source/XYZ';
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
const center = fromLonLat([8.6, 50.1]);
|
const center = fromLonLat([8.6, 50.1]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import TileLayer from '../../../src/ol/layer/Tile.js';
|
import TileLayer from '../../../src/ol/layer/Tile.js';
|
||||||
import {fromLonLat} from '../../../src/ol/proj';
|
import {fromLonLat} from '../../../src/ol/proj.js';
|
||||||
import XYZ from '../../../src/ol/source/XYZ';
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
const center = fromLonLat([8.6, 50.1]);
|
const center = fromLonLat([8.6, 50.1]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import TileLayer from '../../../src/ol/layer/Tile.js';
|
import TileLayer from '../../../src/ol/layer/Tile.js';
|
||||||
import {fromLonLat} from '../../../src/ol/proj';
|
import {fromLonLat} from '../../../src/ol/proj.js';
|
||||||
import XYZ from '../../../src/ol/source/XYZ';
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
const center = fromLonLat([8.6, 50.1]);
|
const center = fromLonLat([8.6, 50.1]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import VectorTileSource from '../../../src/ol/source/VectorTile';
|
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
|
||||||
import MVT from '../../../src/ol/format/MVT';
|
import MVT from '../../../src/ol/format/MVT.js';
|
||||||
import {createXYZ} from '../../../src/ol/tilegrid';
|
import {createXYZ} from '../../../src/ol/tilegrid.js';
|
||||||
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
|
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
|
||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
pixelRatio: 2,
|
pixelRatio: 2,
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import VectorTileSource from '../../../src/ol/source/VectorTile';
|
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
|
||||||
import MVT from '../../../src/ol/format/MVT';
|
import MVT from '../../../src/ol/format/MVT.js';
|
||||||
import {createXYZ} from '../../../src/ol/tilegrid';
|
import {createXYZ} from '../../../src/ol/tilegrid.js';
|
||||||
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
|
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
|
||||||
import VectorSource from '../../../src/ol/source/Vector';
|
import VectorSource from '../../../src/ol/source/Vector.js';
|
||||||
import Feature from '../../../src/ol/Feature';
|
import Feature from '../../../src/ol/Feature.js';
|
||||||
import Point from '../../../src/ol/geom/Point';
|
import Point from '../../../src/ol/geom/Point.js';
|
||||||
import VectorLayer from '../../../src/ol/layer/Vector';
|
import VectorLayer from '../../../src/ol/layer/Vector.js';
|
||||||
import Style from '../../../src/ol/style/Style';
|
import Style from '../../../src/ol/style/Style.js';
|
||||||
import CircleStyle from '../../../src/ol/style/Circle';
|
import CircleStyle from '../../../src/ol/style/Circle.js';
|
||||||
import Fill from '../../../src/ol/style/Fill';
|
import Fill from '../../../src/ol/style/Fill.js';
|
||||||
|
|
||||||
const vectorSource = new VectorSource({
|
const vectorSource = new VectorSource({
|
||||||
features: [
|
features: [
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import VectorTileSource from '../../../src/ol/source/VectorTile';
|
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
|
||||||
import MVT from '../../../src/ol/format/MVT';
|
import MVT from '../../../src/ol/format/MVT.js';
|
||||||
import {createXYZ} from '../../../src/ol/tilegrid';
|
import {createXYZ} from '../../../src/ol/tilegrid.js';
|
||||||
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
|
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
|
||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
layers: [
|
layers: [
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import VectorTileSource from '../../../src/ol/source/VectorTile';
|
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
|
||||||
import MVT from '../../../src/ol/format/MVT';
|
import MVT from '../../../src/ol/format/MVT.js';
|
||||||
import {createXYZ} from '../../../src/ol/tilegrid';
|
import {createXYZ} from '../../../src/ol/tilegrid.js';
|
||||||
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
|
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
|
||||||
|
|
||||||
new Map({
|
new Map({
|
||||||
layers: [
|
layers: [
|
||||||
|
|||||||
@@ -9,12 +9,6 @@ import Point from '../../../src/ol/geom/Point.js';
|
|||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
|
||||||
source: new XYZ({
|
|
||||||
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
|
|
||||||
maxZoom: 3
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
new VectorLayer({
|
new VectorLayer({
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
style: new Style({
|
style: new Style({
|
||||||
@@ -27,6 +21,12 @@ const map = new Map({
|
|||||||
url: '/data/countries.json',
|
url: '/data/countries.json',
|
||||||
format: new GeoJSON()
|
format: new GeoJSON()
|
||||||
})
|
})
|
||||||
|
}),
|
||||||
|
new TileLayer({
|
||||||
|
source: new XYZ({
|
||||||
|
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
|
||||||
|
maxZoom: 3
|
||||||
|
})
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
target: 'map',
|
target: 'map',
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import Map from '../../../src/ol/Map.js';
|
import Map from '../../../src/ol/Map.js';
|
||||||
import View from '../../../src/ol/View.js';
|
import View from '../../../src/ol/View.js';
|
||||||
import TileLayer from '../../../src/ol/layer/Tile.js';
|
import TileLayer from '../../../src/ol/layer/Tile.js';
|
||||||
import XYZ from '../../../src/ol/source/XYZ';
|
import XYZ from '../../../src/ol/source/XYZ.js';
|
||||||
import {Vector as VectorLayer} from '../../../src/ol/layer';
|
import {Vector as VectorLayer} from '../../../src/ol/layer.js';
|
||||||
import VectorSource from '../../../src/ol/source/Vector';
|
import VectorSource from '../../../src/ol/source/Vector.js';
|
||||||
import KML from '../../../src/ol/format/KML';
|
import KML from '../../../src/ol/format/KML.js';
|
||||||
import WebGLPointsLayerRenderer from '../../../src/ol/renderer/webgl/PointsLayer';
|
import WebGLPointsLayerRenderer from '../../../src/ol/renderer/webgl/PointsLayer.js';
|
||||||
|
|
||||||
class CustomLayer extends VectorLayer {
|
class CustomLayer extends VectorLayer {
|
||||||
createRenderer() {
|
createRenderer() {
|
||||||
|
|||||||
@@ -22,5 +22,16 @@ module.exports = {
|
|||||||
context: __dirname,
|
context: __dirname,
|
||||||
target: 'web',
|
target: 'web',
|
||||||
entry: entry,
|
entry: entry,
|
||||||
devtool: 'source-map'
|
devtool: 'source-map',
|
||||||
|
module: {
|
||||||
|
rules: [{
|
||||||
|
test: /\.js$/,
|
||||||
|
use: {
|
||||||
|
loader: path.join(__dirname, '../examples/webpack/worker-loader.js')
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src/ol/worker')
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,10 +57,11 @@ import BaseObject, {getChangeEventType} from './Object.js';
|
|||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
|
* @template {import("./geom/Geometry.js").default} Geometry
|
||||||
*/
|
*/
|
||||||
class Feature extends BaseObject {
|
class Feature extends BaseObject {
|
||||||
/**
|
/**
|
||||||
* @param {import("./geom/Geometry.js").default|Object<string, *>=} opt_geometryOrProperties
|
* @param {Geometry|Object<string, *>=} opt_geometryOrProperties
|
||||||
* You may pass a Geometry object directly, or an object literal containing
|
* You may pass a Geometry object directly, or an object literal containing
|
||||||
* properties. If you pass an object literal, you may include a Geometry
|
* properties. If you pass an object literal, you may include a Geometry
|
||||||
* associated with a `geometry` key.
|
* associated with a `geometry` key.
|
||||||
@@ -106,7 +107,7 @@ class Feature extends BaseObject {
|
|||||||
|
|
||||||
if (opt_geometryOrProperties) {
|
if (opt_geometryOrProperties) {
|
||||||
if (typeof /** @type {?} */ (opt_geometryOrProperties).getSimplifiedGeometry === 'function') {
|
if (typeof /** @type {?} */ (opt_geometryOrProperties).getSimplifiedGeometry === 'function') {
|
||||||
const geometry = /** @type {import("./geom/Geometry.js").default} */ (opt_geometryOrProperties);
|
const geometry = /** @type {Geometry} */ (opt_geometryOrProperties);
|
||||||
this.setGeometry(geometry);
|
this.setGeometry(geometry);
|
||||||
} else {
|
} else {
|
||||||
/** @type {Object<string, *>} */
|
/** @type {Object<string, *>} */
|
||||||
@@ -140,13 +141,13 @@ class Feature extends BaseObject {
|
|||||||
* Get the feature's default geometry. A feature may have any number of named
|
* Get the feature's default geometry. A feature may have any number of named
|
||||||
* geometries. The "default" geometry (the one that is rendered by default) is
|
* geometries. The "default" geometry (the one that is rendered by default) is
|
||||||
* set when calling {@link module:ol/Feature~Feature#setGeometry}.
|
* set when calling {@link module:ol/Feature~Feature#setGeometry}.
|
||||||
* @return {import("./geom/Geometry.js").default|undefined} The default geometry for the feature.
|
* @return {Geometry|undefined} The default geometry for the feature.
|
||||||
* @api
|
* @api
|
||||||
* @observable
|
* @observable
|
||||||
*/
|
*/
|
||||||
getGeometry() {
|
getGeometry() {
|
||||||
return (
|
return (
|
||||||
/** @type {import("./geom/Geometry.js").default|undefined} */ (this.get(this.geometryName_))
|
/** @type {Geometry|undefined} */ (this.get(this.geometryName_))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +219,7 @@ class Feature extends BaseObject {
|
|||||||
/**
|
/**
|
||||||
* Set the default geometry for the feature. This will update the property
|
* Set the default geometry for the feature. This will update the property
|
||||||
* with the name returned by {@link module:ol/Feature~Feature#getGeometryName}.
|
* with the name returned by {@link module:ol/Feature~Feature#getGeometryName}.
|
||||||
* @param {import("./geom/Geometry.js").default|undefined} geometry The new geometry.
|
* @param {Geometry|undefined} geometry The new geometry.
|
||||||
* @api
|
* @api
|
||||||
* @observable
|
* @observable
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import ImageState from './ImageState.js';
|
|||||||
import {listenOnce, unlistenByKey} from './events.js';
|
import {listenOnce, unlistenByKey} from './events.js';
|
||||||
import EventType from './events/EventType.js';
|
import EventType from './events/EventType.js';
|
||||||
import {getHeight} from './extent.js';
|
import {getHeight} from './extent.js';
|
||||||
|
import {IMAGE_DECODE} from './has.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,7 +158,8 @@ class ImageWrapper extends ImageBase {
|
|||||||
*/
|
*/
|
||||||
export function listenImage(image, loadHandler, errorHandler) {
|
export function listenImage(image, loadHandler, errorHandler) {
|
||||||
const img = /** @type {HTMLImageElement} */ (image);
|
const img = /** @type {HTMLImageElement} */ (image);
|
||||||
if (img.decode) {
|
|
||||||
|
if (IMAGE_DECODE) {
|
||||||
const promise = img.decode();
|
const promise = img.decode();
|
||||||
let listening = true;
|
let listening = true;
|
||||||
const unlisten = function() {
|
const unlisten = function() {
|
||||||
@@ -169,7 +171,13 @@ export function listenImage(image, loadHandler, errorHandler) {
|
|||||||
}
|
}
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
if (listening) {
|
if (listening) {
|
||||||
errorHandler();
|
// FIXME: Unconditionally call errorHandler() when this bug is fixed upstream:
|
||||||
|
// https://bugs.webkit.org/show_bug.cgi?id=198527
|
||||||
|
if (error.name === 'EncodingError' && error.message === 'Invalid image type.') {
|
||||||
|
loadHandler();
|
||||||
|
} else {
|
||||||
|
errorHandler();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return unlisten;
|
return unlisten;
|
||||||
|
|||||||
@@ -260,12 +260,6 @@ class MapBrowserEventHandler extends EventTarget {
|
|||||||
this.dragging_);
|
this.dragging_);
|
||||||
this.dispatchEvent(newEvent);
|
this.dispatchEvent(newEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some native android browser triggers mousemove events during small period
|
|
||||||
// of time. See: https://code.google.com/p/android/issues/detail?id=5491 or
|
|
||||||
// https://code.google.com/p/android/issues/detail?id=19827
|
|
||||||
// ex: Galaxy Tab P3110 + Android 4.1.1
|
|
||||||
pointerEvent.preventDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {listen, unlistenByKey, unlisten} from './events.js';
|
|||||||
import EventType from './events/EventType.js';
|
import EventType from './events/EventType.js';
|
||||||
import {createEmpty, clone, createOrUpdateEmpty, equals, getForViewAndSize, isEmpty} from './extent.js';
|
import {createEmpty, clone, createOrUpdateEmpty, equals, getForViewAndSize, isEmpty} from './extent.js';
|
||||||
import {TRUE} from './functions.js';
|
import {TRUE} from './functions.js';
|
||||||
import {DEVICE_PIXEL_RATIO, TOUCH} from './has.js';
|
import {DEVICE_PIXEL_RATIO, IMAGE_DECODE} from './has.js';
|
||||||
import LayerGroup from './layer/Group.js';
|
import LayerGroup from './layer/Group.js';
|
||||||
import {hasArea} from './size.js';
|
import {hasArea} from './size.js';
|
||||||
import {DROP} from './structs/PriorityQueue.js';
|
import {DROP} from './structs/PriorityQueue.js';
|
||||||
@@ -39,10 +39,11 @@ import {create as createTransform, apply as applyTransform} from './transform.js
|
|||||||
* @property {boolean} animate
|
* @property {boolean} animate
|
||||||
* @property {import("./transform.js").Transform} coordinateToPixelTransform
|
* @property {import("./transform.js").Transform} coordinateToPixelTransform
|
||||||
* @property {null|import("./extent.js").Extent} extent
|
* @property {null|import("./extent.js").Extent} extent
|
||||||
* @property {Array<*>} declutterItems
|
* @property {Array<DeclutterItems>} declutterItems
|
||||||
* @property {import("./coordinate.js").Coordinate} focus
|
* @property {import("./coordinate.js").Coordinate} focus
|
||||||
* @property {number} index
|
* @property {number} index
|
||||||
* @property {Array<import("./layer/Layer.js").State>} layerStatesArray
|
* @property {Array<import("./layer/Layer.js").State>} layerStatesArray
|
||||||
|
* @property {number} layerIndex
|
||||||
* @property {import("./transform.js").Transform} pixelToCoordinateTransform
|
* @property {import("./transform.js").Transform} pixelToCoordinateTransform
|
||||||
* @property {Array<PostRenderFunction>} postRenderFunctions
|
* @property {Array<PostRenderFunction>} postRenderFunctions
|
||||||
* @property {import("./size.js").Size} size
|
* @property {import("./size.js").Size} size
|
||||||
@@ -54,6 +55,13 @@ import {create as createTransform, apply as applyTransform} from './transform.js
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} DeclutterItems
|
||||||
|
* @property {Array<*>} items Declutter items of an executor.
|
||||||
|
* @property {number} opacity Layer opacity.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {function(PluggableMap, ?FrameState): any} PostRenderFunction
|
* @typedef {function(PluggableMap, ?FrameState): any} PostRenderFunction
|
||||||
*/
|
*/
|
||||||
@@ -222,7 +230,7 @@ class PluggableMap extends BaseObject {
|
|||||||
* @type {!HTMLElement}
|
* @type {!HTMLElement}
|
||||||
*/
|
*/
|
||||||
this.viewport_ = document.createElement('div');
|
this.viewport_ = document.createElement('div');
|
||||||
this.viewport_.className = 'ol-viewport' + (TOUCH ? ' ol-touch' : '');
|
this.viewport_.className = 'ol-viewport' + ('ontouchstart' in window ? ' ol-touch' : '');
|
||||||
this.viewport_.style.position = 'relative';
|
this.viewport_.style.position = 'relative';
|
||||||
this.viewport_.style.overflow = 'hidden';
|
this.viewport_.style.overflow = 'hidden';
|
||||||
this.viewport_.style.width = '100%';
|
this.viewport_.style.width = '100%';
|
||||||
@@ -293,6 +301,11 @@ class PluggableMap extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
this.interactions = optionsInternal.interactions || new Collection();
|
this.interactions = optionsInternal.interactions || new Collection();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import("./events/Target.js").default}
|
||||||
|
*/
|
||||||
|
this.labelCache_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {import("./events.js").EventsKey}
|
* @type {import("./events.js").EventsKey}
|
||||||
*/
|
*/
|
||||||
@@ -315,7 +328,7 @@ class PluggableMap extends BaseObject {
|
|||||||
* @type {import("./renderer/Map.js").default}
|
* @type {import("./renderer/Map.js").default}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.renderer_ = this.createRenderer();
|
this.renderer_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {function(Event): void|undefined}
|
* @type {function(Event): void|undefined}
|
||||||
@@ -503,24 +516,6 @@ class PluggableMap extends BaseObject {
|
|||||||
overlay.setMap(this);
|
overlay.setMap(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Attach a label cache for listening to font changes.
|
|
||||||
* @param {import("./events/Target.js").default} labelCache Label cache.
|
|
||||||
*/
|
|
||||||
attachLabelCache(labelCache) {
|
|
||||||
this.detachLabelCache();
|
|
||||||
this.labelCacheListenerKey_ = listen(labelCache, EventType.CLEAR, this.redrawText.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detach the label cache, i.e. no longer listen to font changes.
|
|
||||||
*/
|
|
||||||
detachLabelCache() {
|
|
||||||
if (this.labelCacheListenerKey_) {
|
|
||||||
unlistenByKey(this.labelCacheListenerKey_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
@@ -534,11 +529,6 @@ class PluggableMap extends BaseObject {
|
|||||||
removeEventListener(EventType.RESIZE, this.handleResize_, false);
|
removeEventListener(EventType.RESIZE, this.handleResize_, false);
|
||||||
this.handleResize_ = undefined;
|
this.handleResize_ = undefined;
|
||||||
}
|
}
|
||||||
if (this.animationDelayKey_) {
|
|
||||||
cancelAnimationFrame(this.animationDelayKey_);
|
|
||||||
this.animationDelayKey_ = undefined;
|
|
||||||
}
|
|
||||||
this.detachLabelCache();
|
|
||||||
this.setTarget(null);
|
this.setTarget(null);
|
||||||
super.disposeInternal();
|
super.disposeInternal();
|
||||||
}
|
}
|
||||||
@@ -977,7 +967,7 @@ class PluggableMap extends BaseObject {
|
|||||||
if (frameState) {
|
if (frameState) {
|
||||||
const hints = frameState.viewHints;
|
const hints = frameState.viewHints;
|
||||||
if (hints[ViewHint.ANIMATING] || hints[ViewHint.INTERACTING]) {
|
if (hints[ViewHint.ANIMATING] || hints[ViewHint.INTERACTING]) {
|
||||||
const lowOnFrameBudget = Date.now() - frameState.time > 8;
|
const lowOnFrameBudget = !IMAGE_DECODE && Date.now() - frameState.time > 8;
|
||||||
maxTotalLoading = lowOnFrameBudget ? 0 : 8;
|
maxTotalLoading = lowOnFrameBudget ? 0 : 8;
|
||||||
maxNewLoads = lowOnFrameBudget ? 0 : 2;
|
maxNewLoads = lowOnFrameBudget ? 0 : 2;
|
||||||
}
|
}
|
||||||
@@ -1033,6 +1023,14 @@ class PluggableMap extends BaseObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!targetElement) {
|
if (!targetElement) {
|
||||||
|
if (this.renderer_) {
|
||||||
|
this.renderer_.dispose();
|
||||||
|
this.renderer_ = null;
|
||||||
|
}
|
||||||
|
if (this.animationDelayKey_) {
|
||||||
|
cancelAnimationFrame(this.animationDelayKey_);
|
||||||
|
this.animationDelayKey_ = undefined;
|
||||||
|
}
|
||||||
removeNode(this.viewport_);
|
removeNode(this.viewport_);
|
||||||
if (this.handleResize_ !== undefined) {
|
if (this.handleResize_ !== undefined) {
|
||||||
removeEventListener(EventType.RESIZE, this.handleResize_, false);
|
removeEventListener(EventType.RESIZE, this.handleResize_, false);
|
||||||
@@ -1040,6 +1038,9 @@ class PluggableMap extends BaseObject {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
targetElement.appendChild(this.viewport_);
|
targetElement.appendChild(this.viewport_);
|
||||||
|
if (!this.renderer_) {
|
||||||
|
this.renderer_ = this.createRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
const keyboardEventTarget = !this.keyboardEventTarget_ ?
|
const keyboardEventTarget = !this.keyboardEventTarget_ ?
|
||||||
targetElement : this.keyboardEventTarget_;
|
targetElement : this.keyboardEventTarget_;
|
||||||
@@ -1050,7 +1051,7 @@ class PluggableMap extends BaseObject {
|
|||||||
|
|
||||||
if (!this.handleResize_) {
|
if (!this.handleResize_) {
|
||||||
this.handleResize_ = this.updateSize.bind(this);
|
this.handleResize_ = this.updateSize.bind(this);
|
||||||
addEventListener(EventType.RESIZE, this.handleResize_, false);
|
window.addEventListener(EventType.RESIZE, this.handleResize_, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1158,7 +1159,7 @@ class PluggableMap extends BaseObject {
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
if (this.animationDelayKey_ === undefined) {
|
if (this.renderer_ && this.animationDelayKey_ === undefined) {
|
||||||
this.animationDelayKey_ = requestAnimationFrame(this.animationDelay_);
|
this.animationDelayKey_ = requestAnimationFrame(this.animationDelay_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1224,13 +1225,14 @@ class PluggableMap extends BaseObject {
|
|||||||
if (size !== undefined && hasArea(size) && view && view.isDef()) {
|
if (size !== undefined && hasArea(size) && view && view.isDef()) {
|
||||||
const viewHints = view.getHints(this.frameState_ ? this.frameState_.viewHints : undefined);
|
const viewHints = view.getHints(this.frameState_ ? this.frameState_.viewHints : undefined);
|
||||||
viewState = view.getState(this.pixelRatio_);
|
viewState = view.getState(this.pixelRatio_);
|
||||||
frameState = /** @type {FrameState} */ ({
|
frameState = {
|
||||||
animate: false,
|
animate: false,
|
||||||
coordinateToPixelTransform: this.coordinateToPixelTransform_,
|
coordinateToPixelTransform: this.coordinateToPixelTransform_,
|
||||||
declutterItems: previousFrameState ? previousFrameState.declutterItems : [],
|
declutterItems: previousFrameState ? previousFrameState.declutterItems : [],
|
||||||
extent: extent,
|
extent: extent,
|
||||||
focus: this.focus_ ? this.focus_ : viewState.center,
|
focus: this.focus_ ? this.focus_ : viewState.center,
|
||||||
index: this.frameIndex_++,
|
index: this.frameIndex_++,
|
||||||
|
layerIndex: 0,
|
||||||
layerStatesArray: this.getLayerGroup().getLayerStatesArray(),
|
layerStatesArray: this.getLayerGroup().getLayerStatesArray(),
|
||||||
pixelRatio: this.pixelRatio_,
|
pixelRatio: this.pixelRatio_,
|
||||||
pixelToCoordinateTransform: this.pixelToCoordinateTransform_,
|
pixelToCoordinateTransform: this.pixelToCoordinateTransform_,
|
||||||
@@ -1243,7 +1245,7 @@ class PluggableMap extends BaseObject {
|
|||||||
viewState: viewState,
|
viewState: viewState,
|
||||||
viewHints: viewHints,
|
viewHints: viewHints,
|
||||||
wantedTiles: {}
|
wantedTiles: {}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frameState) {
|
if (frameState) {
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ import {clamp, modulo} from './math.js';
|
|||||||
import {assign} from './obj.js';
|
import {assign} from './obj.js';
|
||||||
import {createProjection, METERS_PER_UNIT} from './proj.js';
|
import {createProjection, METERS_PER_UNIT} from './proj.js';
|
||||||
import Units from './proj/Units.js';
|
import Units from './proj/Units.js';
|
||||||
import {equals} from './coordinate';
|
import {equals} from './coordinate.js';
|
||||||
import {easeOut} from './easing';
|
import {easeOut} from './easing.js';
|
||||||
import {createMinMaxResolution} from './resolutionconstraint';
|
import {createMinMaxResolution} from './resolutionconstraint.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ class ControlledMap extends PluggableMap {
|
|||||||
* @property {boolean} [collapsible=true] Whether the control can be collapsed or not.
|
* @property {boolean} [collapsible=true] Whether the control can be collapsed or not.
|
||||||
* @property {string|HTMLElement} [label='»'] Text label to use for the collapsed
|
* @property {string|HTMLElement} [label='»'] Text label to use for the collapsed
|
||||||
* overviewmap button. Instead of text, also an element (e.g. a `span` element) can be used.
|
* overviewmap button. Instead of text, also an element (e.g. a `span` element) can be used.
|
||||||
* @property {Array<import("../layer/Layer.js").default>|import("../Collection.js").default<import("../layer/Layer.js").default>} layers
|
* @property {Array<import("../layer/Layer.js").default>|import("../Collection.js").default<import("../layer/Layer.js").default>} [layers]
|
||||||
* Layers for the overview map (mandatory).
|
* Layers for the overview map.
|
||||||
* @property {function(import("../MapEvent.js").default)} [render] Function called when the control
|
* @property {function(import("../MapEvent.js").default)} [render] Function called when the control
|
||||||
* should be re-rendered. This is called in a `requestAnimationFrame` callback.
|
* should be re-rendered. This is called in a `requestAnimationFrame` callback.
|
||||||
* @property {HTMLElement|string} [target] Specify a target if you want the control
|
* @property {HTMLElement|string} [target] Specify a target if you want the control
|
||||||
@@ -159,13 +159,9 @@ class OverviewMap extends Control {
|
|||||||
const ovmap = this.ovmap_;
|
const ovmap = this.ovmap_;
|
||||||
|
|
||||||
if (options.layers) {
|
if (options.layers) {
|
||||||
/** @type {Array<import("../layer/Layer.js").default>} */ (options.layers).forEach(
|
options.layers.forEach(function(layer) {
|
||||||
/**
|
ovmap.addLayer(layer);
|
||||||
* @param {import("../layer/Layer.js").default} layer Layer.
|
});
|
||||||
*/
|
|
||||||
(function(layer) {
|
|
||||||
ovmap.addLayer(layer);
|
|
||||||
}).bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const box = document.createElement('div');
|
const box = document.createElement('div');
|
||||||
|
|||||||
@@ -13,8 +13,10 @@ import {get as getProjection, equivalent as equivalentProjection, transformExten
|
|||||||
* the `dataProjection` of the format is assigned (where set). If the projection
|
* the `dataProjection` of the format is assigned (where set). If the projection
|
||||||
* can not be derived from the data and if no `dataProjection` is set for a format,
|
* can not be derived from the data and if no `dataProjection` is set for a format,
|
||||||
* the features will not be reprojected.
|
* the features will not be reprojected.
|
||||||
* @property {import("../extent.js").Extent} [extent] Tile extent of the tile being read. This is only used and
|
* @property {import("../extent.js").Extent} [extent] Tile extent in map units of the tile being read.
|
||||||
* required for {@link module:ol/format/MVT}.
|
* This is only required when reading data with tile pixels as geometry units. When configured,
|
||||||
|
* a `dataProjection` with `TILE_PIXELS` as `units` and the tile's pixel extent as `extent` needs to be
|
||||||
|
* provided.
|
||||||
* @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
|
* @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
|
||||||
* created by the format reader. If not provided, features will be returned in the
|
* created by the format reader. If not provided, features will be returned in the
|
||||||
* `dataProjection`.
|
* `dataProjection`.
|
||||||
@@ -86,9 +88,14 @@ class FeatureFormat {
|
|||||||
getReadOptions(source, opt_options) {
|
getReadOptions(source, opt_options) {
|
||||||
let options;
|
let options;
|
||||||
if (opt_options) {
|
if (opt_options) {
|
||||||
|
let dataProjection = opt_options.dataProjection ?
|
||||||
|
opt_options.dataProjection : this.readProjection(source);
|
||||||
|
if (opt_options.extent) {
|
||||||
|
dataProjection = getProjection(dataProjection);
|
||||||
|
dataProjection.setWorldExtent(opt_options.extent);
|
||||||
|
}
|
||||||
options = {
|
options = {
|
||||||
dataProjection: opt_options.dataProjection ?
|
dataProjection: dataProjection,
|
||||||
opt_options.dataProjection : this.readProjection(source),
|
|
||||||
featureProjection: opt_options.featureProjection
|
featureProjection: opt_options.featureProjection
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,9 +174,8 @@ class Geometry extends BaseObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a simplified version of this geometry. For linestrings, this uses
|
* Create a simplified version of this geometry. For linestrings, this uses
|
||||||
* the the {@link
|
* the [Douglas Peucker](https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm)
|
||||||
* https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
|
* algorithm. For polygons, a quantization-based
|
||||||
* Douglas Peucker} algorithm. For polygons, a quantization-based
|
|
||||||
* simplification is used to preserve topology.
|
* simplification is used to preserve topology.
|
||||||
* @param {number} tolerance The tolerance distance for simplification.
|
* @param {number} tolerance The tolerance distance for simplification.
|
||||||
* @return {Geometry} A new, simplified version of the original geometry.
|
* @return {Geometry} A new, simplified version of the original geometry.
|
||||||
|
|||||||
@@ -39,30 +39,8 @@ export const MAC = ua.indexOf('macintosh') !== -1;
|
|||||||
*/
|
*/
|
||||||
export const DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;
|
export const DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if browser supports touch events.
|
* Image.prototype.decode() is supported.
|
||||||
* @const
|
|
||||||
* @type {boolean}
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
export const TOUCH = 'ontouchstart' in window;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if browser supports pointer events.
|
|
||||||
* @const
|
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
export const POINTER = 'PointerEvent' in window;
|
export const IMAGE_DECODE = typeof Image !== 'undefined' && Image.prototype.decode;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if browser supports ms pointer events (IE 10).
|
|
||||||
* @const
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
export const MSPOINTER = !!(navigator.msPointerEnabled);
|
|
||||||
|
|
||||||
|
|
||||||
export {HAS as WEBGL} from './webgl.js';
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
import {scale as scaleCoordinate, rotate as rotateCoordinate} from '../coordinate.js';
|
import {scale as scaleCoordinate, rotate as rotateCoordinate} from '../coordinate.js';
|
||||||
import {easeOut} from '../easing.js';
|
import {easeOut} from '../easing.js';
|
||||||
import {noModifierKeys} from '../events/condition.js';
|
import {noModifierKeys, primaryAction} from '../events/condition.js';
|
||||||
import {FALSE} from '../functions.js';
|
import {FALSE} from '../functions.js';
|
||||||
import PointerInteraction, {centroid as centroidFromPointers} from './Pointer.js';
|
import PointerInteraction, {centroid as centroidFromPointers} from './Pointer.js';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ import PointerInteraction, {centroid as centroidFromPointers} from './Pointer.js
|
|||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
* @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
|
* @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
|
||||||
* to indicate whether that event should be handled.
|
* to indicate whether that event should be handled.
|
||||||
* Default is {@link module:ol/events/condition~noModifierKeys}.
|
* Default is {@link module:ol/events/condition~noModifierKeys} and {@link module:ol/events/condition~primaryAction}.
|
||||||
* @property {import("../Kinetic.js").default} [kinetic] Kinetic inertia to apply to the pan.
|
* @property {import("../Kinetic.js").default} [kinetic] Kinetic inertia to apply to the pan.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ class DragPan extends PointerInteraction {
|
|||||||
* @private
|
* @private
|
||||||
* @type {import("../events/condition.js").Condition}
|
* @type {import("../events/condition.js").Condition}
|
||||||
*/
|
*/
|
||||||
this.condition_ = options.condition ? options.condition : noModifierKeys;
|
this.condition_ = options.condition ? options.condition : defaultCondition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -166,4 +166,12 @@ class DragPan extends PointerInteraction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Browser event.
|
||||||
|
* @return {boolean} Combined condition result.
|
||||||
|
*/
|
||||||
|
function defaultCondition(mapBrowserEvent) {
|
||||||
|
return noModifierKeys(mapBrowserEvent) && primaryAction(mapBrowserEvent);
|
||||||
|
}
|
||||||
|
|
||||||
export default DragPan;
|
export default DragPan;
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ class Draw extends PointerInteraction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sketch point.
|
* Sketch point.
|
||||||
* @type {Feature}
|
* @type {Feature<Point>}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.sketchPoint_ = null;
|
this.sketchPoint_ = null;
|
||||||
@@ -387,7 +387,7 @@ class Draw extends PointerInteraction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sketch line. Used when drawing polygon.
|
* Sketch line. Used when drawing polygon.
|
||||||
* @type {Feature}
|
* @type {Feature<LineString>}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.sketchLine_ = null;
|
this.sketchLine_ = null;
|
||||||
@@ -669,7 +669,7 @@ class Draw extends PointerInteraction {
|
|||||||
this.sketchPoint_ = new Feature(new Point(coordinates));
|
this.sketchPoint_ = new Feature(new Point(coordinates));
|
||||||
this.updateSketchFeatures_();
|
this.updateSketchFeatures_();
|
||||||
} else {
|
} else {
|
||||||
const sketchPointGeom = /** @type {Point} */ (this.sketchPoint_.getGeometry());
|
const sketchPointGeom = this.sketchPoint_.getGeometry();
|
||||||
sketchPointGeom.setCoordinates(coordinates);
|
sketchPointGeom.setCoordinates(coordinates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -711,7 +711,7 @@ class Draw extends PointerInteraction {
|
|||||||
*/
|
*/
|
||||||
modifyDrawing_(event) {
|
modifyDrawing_(event) {
|
||||||
let coordinate = event.coordinate;
|
let coordinate = event.coordinate;
|
||||||
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
|
const geometry = this.sketchFeature_.getGeometry();
|
||||||
let coordinates, last;
|
let coordinates, last;
|
||||||
if (this.mode_ === Mode.POINT) {
|
if (this.mode_ === Mode.POINT) {
|
||||||
last = this.sketchCoords_;
|
last = this.sketchCoords_;
|
||||||
@@ -730,7 +730,7 @@ class Draw extends PointerInteraction {
|
|||||||
last[1] = coordinate[1];
|
last[1] = coordinate[1];
|
||||||
this.geometryFunction_(/** @type {!LineCoordType} */ (this.sketchCoords_), geometry);
|
this.geometryFunction_(/** @type {!LineCoordType} */ (this.sketchCoords_), geometry);
|
||||||
if (this.sketchPoint_) {
|
if (this.sketchPoint_) {
|
||||||
const sketchPointGeom = /** @type {Point} */ (this.sketchPoint_.getGeometry());
|
const sketchPointGeom = this.sketchPoint_.getGeometry();
|
||||||
sketchPointGeom.setCoordinates(coordinate);
|
sketchPointGeom.setCoordinates(coordinate);
|
||||||
}
|
}
|
||||||
/** @type {LineString} */
|
/** @type {LineString} */
|
||||||
@@ -740,8 +740,8 @@ class Draw extends PointerInteraction {
|
|||||||
if (!this.sketchLine_) {
|
if (!this.sketchLine_) {
|
||||||
this.sketchLine_ = new Feature();
|
this.sketchLine_ = new Feature();
|
||||||
}
|
}
|
||||||
const ring = /** @type {Polygon} */ (geometry).getLinearRing(0);
|
const ring = geometry.getLinearRing(0);
|
||||||
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
|
sketchLineGeom = this.sketchLine_.getGeometry();
|
||||||
if (!sketchLineGeom) {
|
if (!sketchLineGeom) {
|
||||||
sketchLineGeom = new LineString(ring.getFlatCoordinates(), ring.getLayout());
|
sketchLineGeom = new LineString(ring.getFlatCoordinates(), ring.getLayout());
|
||||||
this.sketchLine_.setGeometry(sketchLineGeom);
|
this.sketchLine_.setGeometry(sketchLineGeom);
|
||||||
@@ -751,7 +751,7 @@ class Draw extends PointerInteraction {
|
|||||||
sketchLineGeom.changed();
|
sketchLineGeom.changed();
|
||||||
}
|
}
|
||||||
} else if (this.sketchLineCoords_) {
|
} else if (this.sketchLineCoords_) {
|
||||||
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
|
sketchLineGeom = this.sketchLine_.getGeometry();
|
||||||
sketchLineGeom.setCoordinates(this.sketchLineCoords_);
|
sketchLineGeom.setCoordinates(this.sketchLineCoords_);
|
||||||
}
|
}
|
||||||
this.updateSketchFeatures_();
|
this.updateSketchFeatures_();
|
||||||
@@ -764,7 +764,7 @@ class Draw extends PointerInteraction {
|
|||||||
*/
|
*/
|
||||||
addToDrawing_(event) {
|
addToDrawing_(event) {
|
||||||
const coordinate = event.coordinate;
|
const coordinate = event.coordinate;
|
||||||
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
|
const geometry = this.sketchFeature_.getGeometry();
|
||||||
let done;
|
let done;
|
||||||
let coordinates;
|
let coordinates;
|
||||||
if (this.mode_ === Mode.LINE_STRING) {
|
if (this.mode_ === Mode.LINE_STRING) {
|
||||||
@@ -808,7 +808,7 @@ class Draw extends PointerInteraction {
|
|||||||
if (!this.sketchFeature_) {
|
if (!this.sketchFeature_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
|
const geometry = this.sketchFeature_.getGeometry();
|
||||||
let coordinates;
|
let coordinates;
|
||||||
/** @type {LineString} */
|
/** @type {LineString} */
|
||||||
let sketchLineGeom;
|
let sketchLineGeom;
|
||||||
@@ -822,7 +822,7 @@ class Draw extends PointerInteraction {
|
|||||||
} else if (this.mode_ === Mode.POLYGON) {
|
} else if (this.mode_ === Mode.POLYGON) {
|
||||||
coordinates = /** @type {PolyCoordType} */ (this.sketchCoords_)[0];
|
coordinates = /** @type {PolyCoordType} */ (this.sketchCoords_)[0];
|
||||||
coordinates.splice(-2, 1);
|
coordinates.splice(-2, 1);
|
||||||
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
|
sketchLineGeom = this.sketchLine_.getGeometry();
|
||||||
sketchLineGeom.setCoordinates(coordinates);
|
sketchLineGeom.setCoordinates(coordinates);
|
||||||
this.geometryFunction_(this.sketchCoords_, geometry);
|
this.geometryFunction_(this.sketchCoords_, geometry);
|
||||||
}
|
}
|
||||||
@@ -846,7 +846,7 @@ class Draw extends PointerInteraction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let coordinates = this.sketchCoords_;
|
let coordinates = this.sketchCoords_;
|
||||||
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (sketchFeature.getGeometry());
|
const geometry = sketchFeature.getGeometry();
|
||||||
if (this.mode_ === Mode.LINE_STRING) {
|
if (this.mode_ === Mode.LINE_STRING) {
|
||||||
// remove the redundant last point
|
// remove the redundant last point
|
||||||
coordinates.pop();
|
coordinates.pop();
|
||||||
@@ -900,12 +900,12 @@ class Draw extends PointerInteraction {
|
|||||||
* Extend an existing geometry by adding additional points. This only works
|
* Extend an existing geometry by adding additional points. This only works
|
||||||
* on features with `LineString` geometries, where the interaction will
|
* on features with `LineString` geometries, where the interaction will
|
||||||
* extend lines by adding points to the end of the coordinates array.
|
* extend lines by adding points to the end of the coordinates array.
|
||||||
* @param {!Feature} feature Feature to be extended.
|
* @param {!Feature<LineString>} feature Feature to be extended.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
extend(feature) {
|
extend(feature) {
|
||||||
const geometry = feature.getGeometry();
|
const geometry = feature.getGeometry();
|
||||||
const lineString = /** @type {LineString} */ (geometry);
|
const lineString = geometry;
|
||||||
this.sketchFeature_ = feature;
|
this.sketchFeature_ = feature;
|
||||||
this.sketchCoords_ = lineString.getCoordinates();
|
this.sketchCoords_ = lineString.getCoordinates();
|
||||||
const last = this.sketchCoords_[this.sketchCoords_.length - 1];
|
const last = this.sketchCoords_[this.sketchCoords_.length - 1];
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ class Extent extends PointerInteraction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Feature for displaying the visible pointer
|
* Feature for displaying the visible pointer
|
||||||
* @type {Feature}
|
* @type {Feature<Point>}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.vertexFeature_ = null;
|
this.vertexFeature_ = null;
|
||||||
@@ -265,7 +265,7 @@ class Extent extends PointerInteraction {
|
|||||||
this.vertexFeature_ = vertexFeature;
|
this.vertexFeature_ = vertexFeature;
|
||||||
this.vertexOverlay_.getSource().addFeature(vertexFeature);
|
this.vertexOverlay_.getSource().addFeature(vertexFeature);
|
||||||
} else {
|
} else {
|
||||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
const geometry = vertexFeature.getGeometry();
|
||||||
geometry.setCoordinates(vertex);
|
geometry.setCoordinates(vertex);
|
||||||
}
|
}
|
||||||
return vertexFeature;
|
return vertexFeature;
|
||||||
|
|||||||
@@ -660,7 +660,7 @@ class Modify extends PointerInteraction {
|
|||||||
this.vertexFeature_ = vertexFeature;
|
this.vertexFeature_ = vertexFeature;
|
||||||
this.overlay_.getSource().addFeature(vertexFeature);
|
this.overlay_.getSource().addFeature(vertexFeature);
|
||||||
} else {
|
} else {
|
||||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
const geometry = vertexFeature.getGeometry();
|
||||||
geometry.setCoordinates(coordinates);
|
geometry.setCoordinates(coordinates);
|
||||||
}
|
}
|
||||||
return vertexFeature;
|
return vertexFeature;
|
||||||
@@ -785,7 +785,7 @@ class Modify extends PointerInteraction {
|
|||||||
const vertexFeature = this.vertexFeature_;
|
const vertexFeature = this.vertexFeature_;
|
||||||
if (vertexFeature) {
|
if (vertexFeature) {
|
||||||
const insertVertices = [];
|
const insertVertices = [];
|
||||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
const geometry = vertexFeature.getGeometry();
|
||||||
const vertex = geometry.getCoordinates();
|
const vertex = geometry.getCoordinates();
|
||||||
const vertexExtent = boundingExtent([vertex]);
|
const vertexExtent = boundingExtent([vertex]);
|
||||||
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
|
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
|
||||||
|
|||||||
@@ -35,6 +35,13 @@ const TranslateEventType = {
|
|||||||
TRANSLATEEND: 'translateend'
|
TRANSLATEEND: 'translateend'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that takes an {@link module:ol/Feature} or
|
||||||
|
* {@link module:ol/render/Feature} and an
|
||||||
|
* {@link module:ol/layer/Layer} and returns `true` if the feature may be
|
||||||
|
* translated or `false` otherwise.
|
||||||
|
* @typedef {function(import("../Feature.js").FeatureLike, import("../layer/Layer.js").default):boolean} FilterFunction
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} Options
|
* @typedef {Object} Options
|
||||||
@@ -45,6 +52,10 @@ const TranslateEventType = {
|
|||||||
* function will be called for each layer in the map and should return
|
* function will be called for each layer in the map and should return
|
||||||
* `true` for layers that you want to be translatable. If the option is
|
* `true` for layers that you want to be translatable. If the option is
|
||||||
* absent, all visible layers will be considered translatable.
|
* absent, all visible layers will be considered translatable.
|
||||||
|
* @property {FilterFunction} [filter] A function
|
||||||
|
* that takes an {@link module:ol/Feature} and an
|
||||||
|
* {@link module:ol/layer/Layer} and returns `true` if the feature may be
|
||||||
|
* translated or `false` otherwise.
|
||||||
* @property {number} [hitTolerance=0] Hit-detection tolerance. Pixels inside the radius around the given position
|
* @property {number} [hitTolerance=0] Hit-detection tolerance. Pixels inside the radius around the given position
|
||||||
* will be checked for features.
|
* will be checked for features.
|
||||||
*/
|
*/
|
||||||
@@ -136,6 +147,12 @@ class Translate extends PointerInteraction {
|
|||||||
*/
|
*/
|
||||||
this.layerFilter_ = layerFilter;
|
this.layerFilter_ = layerFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {FilterFunction}
|
||||||
|
*/
|
||||||
|
this.filter_ = options.filter ? options.filter : TRUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {number}
|
* @type {number}
|
||||||
@@ -245,9 +262,11 @@ class Translate extends PointerInteraction {
|
|||||||
*/
|
*/
|
||||||
featuresAtPixel_(pixel, map) {
|
featuresAtPixel_(pixel, map) {
|
||||||
return map.forEachFeatureAtPixel(pixel,
|
return map.forEachFeatureAtPixel(pixel,
|
||||||
function(feature) {
|
function(feature, layer) {
|
||||||
if (!this.features_ || includes(this.features_.getArray(), feature)) {
|
if (this.filter_(feature, layer)) {
|
||||||
return feature;
|
if (!this.features_ || includes(this.features_.getArray(), feature)) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this), {
|
}.bind(this), {
|
||||||
layerFilter: this.layerFilter_,
|
layerFilter: this.layerFilter_,
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ class BaseLayer extends BaseObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This method is not meant to be called by layers or layer renderers because the state
|
||||||
|
* is incorrect if the layer is included in a layer group.
|
||||||
|
*
|
||||||
* @param {boolean=} opt_managed Layer is managed.
|
* @param {boolean=} opt_managed Layer is managed.
|
||||||
* @return {import("./Layer.js").State} Layer state.
|
* @return {import("./Layer.js").State} Layer state.
|
||||||
*/
|
*/
|
||||||
@@ -90,7 +93,8 @@ class BaseLayer extends BaseObject {
|
|||||||
/** @type {import("./Layer.js").State} */
|
/** @type {import("./Layer.js").State} */
|
||||||
const state = this.state_ || /** @type {?} */ ({
|
const state = this.state_ || /** @type {?} */ ({
|
||||||
layer: this,
|
layer: this,
|
||||||
managed: opt_managed === undefined ? true : opt_managed
|
managed: opt_managed === undefined ? true : opt_managed,
|
||||||
|
hasOverlay: false
|
||||||
});
|
});
|
||||||
state.opacity = clamp(Math.round(this.getOpacity() * 100) / 100, 0, 1);
|
state.opacity = clamp(Math.round(this.getOpacity() * 100) / 100, 0, 1);
|
||||||
state.sourceState = this.getSourceState();
|
state.sourceState = this.getSourceState();
|
||||||
|
|||||||
@@ -72,8 +72,7 @@ class BaseVectorLayer extends Layer {
|
|||||||
* @param {Options=} opt_options Options.
|
* @param {Options=} opt_options Options.
|
||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
const options = opt_options ?
|
const options = opt_options ? opt_options : {};
|
||||||
opt_options : /** @type {Options} */ ({});
|
|
||||||
|
|
||||||
const baseOptions = assign({}, options);
|
const baseOptions = assign({}, options);
|
||||||
|
|
||||||
|
|||||||
@@ -3,27 +3,27 @@
|
|||||||
*/
|
*/
|
||||||
import VectorLayer from './Vector.js';
|
import VectorLayer from './Vector.js';
|
||||||
import {assign} from '../obj.js';
|
import {assign} from '../obj.js';
|
||||||
import {degreesToStringHDMS} from '../coordinate';
|
import {degreesToStringHDMS} from '../coordinate.js';
|
||||||
import Text from '../style/Text';
|
import Text from '../style/Text.js';
|
||||||
import Fill from '../style/Fill';
|
import Fill from '../style/Fill.js';
|
||||||
import Stroke from '../style/Stroke';
|
import Stroke from '../style/Stroke.js';
|
||||||
import LineString from '../geom/LineString.js';
|
import LineString from '../geom/LineString.js';
|
||||||
import VectorSource from '../source/Vector';
|
import VectorSource from '../source/Vector.js';
|
||||||
import {
|
import {
|
||||||
equivalent as equivalentProjection,
|
equivalent as equivalentProjection,
|
||||||
get as getProjection,
|
get as getProjection,
|
||||||
getTransform,
|
getTransform,
|
||||||
transformExtent
|
transformExtent
|
||||||
} from '../proj';
|
} from '../proj.js';
|
||||||
import {getCenter, intersects, equals, getIntersection, isEmpty} from '../extent';
|
import {getCenter, intersects, equals, getIntersection, isEmpty} from '../extent.js';
|
||||||
import {clamp} from '../math';
|
import {clamp} from '../math.js';
|
||||||
import Style from '../style/Style';
|
import Style from '../style/Style.js';
|
||||||
import Feature from '../Feature';
|
import Feature from '../Feature.js';
|
||||||
import {bbox} from '../loadingstrategy';
|
import {bbox} from '../loadingstrategy.js';
|
||||||
import {meridian, parallel} from '../geom/flat/geodesic';
|
import {meridian, parallel} from '../geom/flat/geodesic.js';
|
||||||
import GeometryLayout from '../geom/GeometryLayout';
|
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||||
import Point from '../geom/Point';
|
import Point from '../geom/Point.js';
|
||||||
import Collection from '../Collection';
|
import Collection from '../Collection.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {getChangeEventType} from '../Object.js';
|
|||||||
import {createCanvasContext2D} from '../dom.js';
|
import {createCanvasContext2D} from '../dom.js';
|
||||||
import VectorLayer from './Vector.js';
|
import VectorLayer from './Vector.js';
|
||||||
import {assign} from '../obj.js';
|
import {assign} from '../obj.js';
|
||||||
import WebGLPointsLayerRenderer from '../renderer/webgl/PointsLayer';
|
import WebGLPointsLayerRenderer from '../renderer/webgl/PointsLayer.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import SourceState from '../source/State.js';
|
|||||||
* @property {SourceState} sourceState
|
* @property {SourceState} sourceState
|
||||||
* @property {boolean} visible
|
* @property {boolean} visible
|
||||||
* @property {boolean} managed
|
* @property {boolean} managed
|
||||||
|
* @property {boolean} hasOverlay Set by the renderer when an overlay for points and text is used.
|
||||||
* @property {import("../extent.js").Extent} [extent]
|
* @property {import("../extent.js").Extent} [extent]
|
||||||
* @property {number} zIndex
|
* @property {number} zIndex
|
||||||
* @property {number} maxResolution
|
* @property {number} maxResolution
|
||||||
@@ -189,13 +190,15 @@ class Layer extends BaseLayer {
|
|||||||
* In charge to manage the rendering of the layer. One layer type is
|
* In charge to manage the rendering of the layer. One layer type is
|
||||||
* bounded with one layer renderer.
|
* bounded with one layer renderer.
|
||||||
* @param {?import("../PluggableMap.js").FrameState} frameState Frame state.
|
* @param {?import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||||
|
* @param {HTMLElement} target Target which the renderer may (but need not) use
|
||||||
|
* for rendering its content.
|
||||||
* @return {HTMLElement} The rendered element.
|
* @return {HTMLElement} The rendered element.
|
||||||
*/
|
*/
|
||||||
render(frameState) {
|
render(frameState, target) {
|
||||||
const layerRenderer = this.getRenderer();
|
const layerRenderer = this.getRenderer();
|
||||||
const layerState = this.getLayerState();
|
|
||||||
if (layerRenderer.prepareFrame(frameState, layerState)) {
|
if (layerRenderer.prepareFrame(frameState)) {
|
||||||
return layerRenderer.renderFrame(frameState, layerState);
|
return layerRenderer.renderFrame(frameState, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,6 @@ import BaseTileLayer from './BaseTile.js';
|
|||||||
import CanvasTileLayerRenderer from '../renderer/canvas/TileLayer.js';
|
import CanvasTileLayerRenderer from '../renderer/canvas/TileLayer.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import("./BaseTile.js").Options} Options
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* For layer sources that provide pre-rendered, tiled images in grids that are
|
* For layer sources that provide pre-rendered, tiled images in grids that are
|
||||||
@@ -23,7 +18,7 @@ import CanvasTileLayerRenderer from '../renderer/canvas/TileLayer.js';
|
|||||||
class TileLayer extends BaseTileLayer {
|
class TileLayer extends BaseTileLayer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Options=} opt_options Tile layer options.
|
* @param {import("./BaseTile.js").Options=} opt_options Tile layer options.
|
||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
super(opt_options);
|
super(opt_options);
|
||||||
|
|||||||
@@ -5,11 +5,6 @@ import BaseVectorLayer from './BaseVector.js';
|
|||||||
import CanvasVectorLayerRenderer from '../renderer/canvas/VectorLayer.js';
|
import CanvasVectorLayerRenderer from '../renderer/canvas/VectorLayer.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import("./BaseVector.js").Options} Options
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* Vector data that is rendered client-side.
|
* Vector data that is rendered client-side.
|
||||||
@@ -22,7 +17,7 @@ import CanvasVectorLayerRenderer from '../renderer/canvas/VectorLayer.js';
|
|||||||
*/
|
*/
|
||||||
class VectorLayer extends BaseVectorLayer {
|
class VectorLayer extends BaseVectorLayer {
|
||||||
/**
|
/**
|
||||||
* @param {Options=} opt_options Options.
|
* @param {import("./BaseVector.js").Options=} opt_options Options.
|
||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
super(opt_options);
|
super(opt_options);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class VectorImageLayer extends BaseVectorLayer {
|
|||||||
* @param {Options=} opt_options Options.
|
* @param {Options=} opt_options Options.
|
||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
const options = opt_options ? opt_options : /** @type {Options} */ ({});
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
const baseOptions = assign({}, options);
|
const baseOptions = assign({}, options);
|
||||||
delete baseOptions.imageRatio;
|
delete baseOptions.imageRatio;
|
||||||
|
|||||||
@@ -86,12 +86,12 @@ class VectorTileLayer extends BaseVectorLayer {
|
|||||||
delete baseOptions.preload;
|
delete baseOptions.preload;
|
||||||
delete baseOptions.useInterimTilesOnError;
|
delete baseOptions.useInterimTilesOnError;
|
||||||
|
|
||||||
super(/** @type {import("./Vector.js").Options} */ (baseOptions));
|
super(/** @type {import("./BaseVector.js").Options} */ (baseOptions));
|
||||||
|
|
||||||
const renderMode = options.renderMode || VectorTileRenderType.HYBRID;
|
const renderMode = options.renderMode || VectorTileRenderType.HYBRID;
|
||||||
assert(renderMode == undefined ||
|
assert(renderMode == undefined ||
|
||||||
renderMode == VectorTileRenderType.IMAGE ||
|
renderMode == VectorTileRenderType.IMAGE ||
|
||||||
renderMode == VectorTileRenderType.HYBRID,
|
renderMode == VectorTileRenderType.HYBRID,
|
||||||
28); // `renderMode` must be `'image'` or `'hybrid'`
|
28); // `renderMode` must be `'image'` or `'hybrid'`
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -63,10 +63,6 @@
|
|||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ol-overlay-container {
|
|
||||||
will-change: left,right,top,bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ol-unsupported {
|
.ol-unsupported {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
|
|
||||||
import {listen, unlisten} from '../events.js';
|
import {listen, unlisten} from '../events.js';
|
||||||
import EventTarget from '../events/Target.js';
|
import EventTarget from '../events/Target.js';
|
||||||
import {POINTER, MSPOINTER, TOUCH} from '../has.js';
|
|
||||||
import PointerEventType from './EventType.js';
|
import PointerEventType from './EventType.js';
|
||||||
import MouseSource, {prepareEvent as prepareMouseEvent} from './MouseSource.js';
|
import MouseSource, {prepareEvent as prepareMouseEvent} from './MouseSource.js';
|
||||||
import MsSource from './MsSource.js';
|
import MsSource from './MsSource.js';
|
||||||
@@ -124,15 +123,15 @@ class PointerEventHandler extends EventTarget {
|
|||||||
* that generate pointer events.
|
* that generate pointer events.
|
||||||
*/
|
*/
|
||||||
registerSources() {
|
registerSources() {
|
||||||
if (POINTER) {
|
if ('PointerEvent' in window) {
|
||||||
this.registerSource('native', new NativeSource(this));
|
this.registerSource('native', new NativeSource(this));
|
||||||
} else if (MSPOINTER) {
|
} else if (window.navigator.msPointerEnabled) {
|
||||||
this.registerSource('ms', new MsSource(this));
|
this.registerSource('ms', new MsSource(this));
|
||||||
} else {
|
} else {
|
||||||
const mouseSource = new MouseSource(this);
|
const mouseSource = new MouseSource(this);
|
||||||
this.registerSource('mouse', mouseSource);
|
this.registerSource('mouse', mouseSource);
|
||||||
|
|
||||||
if (TOUCH) {
|
if ('ontouchstart' in window) {
|
||||||
this.registerSource('touch', new TouchSource(this, mouseSource));
|
this.registerSource('touch', new TouchSource(this, mouseSource));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ import {toEPSG4326, fromEPSG4326, PROJECTIONS as EPSG3857_PROJECTIONS} from './p
|
|||||||
import {PROJECTIONS as EPSG4326_PROJECTIONS} from './proj/epsg4326.js';
|
import {PROJECTIONS as EPSG4326_PROJECTIONS} from './proj/epsg4326.js';
|
||||||
import Projection from './proj/Projection.js';
|
import Projection from './proj/Projection.js';
|
||||||
import Units, {METERS_PER_UNIT} from './proj/Units.js';
|
import Units, {METERS_PER_UNIT} from './proj/Units.js';
|
||||||
import * as projections from './proj/projections.js';
|
|
||||||
import {add as addTransformFunc, clear as clearTransformFuncs, get as getTransformFunc} from './proj/transforms.js';
|
import {add as addTransformFunc, clear as clearTransformFuncs, get as getTransformFunc} from './proj/transforms.js';
|
||||||
|
import {add as addProj, clear as clearProj, get as getProj} from './proj/projections.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +133,7 @@ export function identityTransform(input, opt_output, opt_dimension) {
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
export function addProjection(projection) {
|
export function addProjection(projection) {
|
||||||
projections.add(projection.getCode(), projection);
|
addProj(projection.getCode(), projection);
|
||||||
addTransformFunc(projection, projection, cloneTransform);
|
addTransformFunc(projection, projection, cloneTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ export function addProjections(projections) {
|
|||||||
*/
|
*/
|
||||||
export function get(projectionLike) {
|
export function get(projectionLike) {
|
||||||
return typeof projectionLike === 'string' ?
|
return typeof projectionLike === 'string' ?
|
||||||
projections.get(/** @type {string} */ (projectionLike)) :
|
getProj(/** @type {string} */ (projectionLike)) :
|
||||||
(/** @type {Projection} */ (projectionLike) || null);
|
(/** @type {Projection} */ (projectionLike) || null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ export function addEquivalentTransforms(projections1, projections2, forwardTrans
|
|||||||
* Clear all cached projections and transforms.
|
* Clear all cached projections and transforms.
|
||||||
*/
|
*/
|
||||||
export function clearAllProjections() {
|
export function clearAllProjections() {
|
||||||
projections.clear();
|
clearProj();
|
||||||
clearTransformFuncs();
|
clearTransformFuncs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,9 +122,10 @@ export function renderDeclutterItems(frameState, declutterTree) {
|
|||||||
}
|
}
|
||||||
const items = frameState.declutterItems;
|
const items = frameState.declutterItems;
|
||||||
for (let z = items.length - 1; z >= 0; --z) {
|
for (let z = items.length - 1; z >= 0; --z) {
|
||||||
const zIndexItems = items[z];
|
const item = items[z];
|
||||||
|
const zIndexItems = item.items;
|
||||||
for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) {
|
for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) {
|
||||||
declutterTree = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], declutterTree);
|
declutterTree = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], item.opacity, declutterTree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
items.length = 0;
|
items.length = 0;
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ class RenderEvent extends Event {
|
|||||||
* CSS pixels to rendered pixels.
|
* CSS pixels to rendered pixels.
|
||||||
* @param {import("../PluggableMap.js").FrameState=} opt_frameState Frame state.
|
* @param {import("../PluggableMap.js").FrameState=} opt_frameState Frame state.
|
||||||
* @param {?CanvasRenderingContext2D=} opt_context Context.
|
* @param {?CanvasRenderingContext2D=} opt_context Context.
|
||||||
* @param {?import("../webgl/Helper.js").default=} opt_glContext WebGL Context.
|
|
||||||
*/
|
*/
|
||||||
constructor(type, opt_inversePixelTransform, opt_frameState, opt_context, opt_glContext) {
|
constructor(type, opt_inversePixelTransform, opt_frameState, opt_context) {
|
||||||
|
|
||||||
super(type);
|
super(type);
|
||||||
|
|
||||||
@@ -41,14 +40,6 @@ class RenderEvent extends Event {
|
|||||||
*/
|
*/
|
||||||
this.context = opt_context;
|
this.context = opt_context;
|
||||||
|
|
||||||
/**
|
|
||||||
* WebGL context. Only available when a WebGL renderer is used, null
|
|
||||||
* otherwise.
|
|
||||||
* @type {import("../webgl/Helper.js").default|null|undefined}
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
this.glContext = opt_glContext;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ export function drawImage(context,
|
|||||||
|
|
||||||
context.drawImage(image, originX, originY, w, h, x, y, w * scale, h * scale);
|
context.drawImage(image, originX, originY, w, h, x, y, w * scale, h * scale);
|
||||||
|
|
||||||
if (alpha) {
|
if (opacity != 1) {
|
||||||
context.globalAlpha = alpha;
|
context.globalAlpha = alpha;
|
||||||
}
|
}
|
||||||
if (transform) {
|
if (transform) {
|
||||||
|
|||||||
@@ -362,10 +362,12 @@ class Executor extends Disposable {
|
|||||||
const declutterArgs = intersects ?
|
const declutterArgs = intersects ?
|
||||||
[context, transform ? transform.slice(0) : null, opacity, image, originX, originY, w, h, x, y, scale] :
|
[context, transform ? transform.slice(0) : null, opacity, image, originX, originY, w, h, x, y, scale] :
|
||||||
null;
|
null;
|
||||||
if (declutterArgs && fillStroke) {
|
if (declutterArgs) {
|
||||||
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
|
if (fillStroke) {
|
||||||
|
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
|
||||||
|
}
|
||||||
|
declutterGroup.push(declutterArgs);
|
||||||
}
|
}
|
||||||
declutterGroup.push(declutterArgs);
|
|
||||||
} else if (intersects) {
|
} else if (intersects) {
|
||||||
if (fillStroke) {
|
if (fillStroke) {
|
||||||
this.replayTextBackground_(context, p1, p2, p3, p4,
|
this.replayTextBackground_(context, p1, p2, p3, p4,
|
||||||
@@ -414,10 +416,11 @@ class Executor extends Disposable {
|
|||||||
/**
|
/**
|
||||||
* @param {import("../canvas.js").DeclutterGroup} declutterGroup Declutter group.
|
* @param {import("../canvas.js").DeclutterGroup} declutterGroup Declutter group.
|
||||||
* @param {import("../../Feature.js").FeatureLike} feature Feature.
|
* @param {import("../../Feature.js").FeatureLike} feature Feature.
|
||||||
|
* @param {number} opacity Layer opacity.
|
||||||
* @param {?} declutterTree Declutter tree.
|
* @param {?} declutterTree Declutter tree.
|
||||||
* @return {?} Declutter tree.
|
* @return {?} Declutter tree.
|
||||||
*/
|
*/
|
||||||
renderDeclutter(declutterGroup, feature, declutterTree) {
|
renderDeclutter(declutterGroup, feature, opacity, declutterTree) {
|
||||||
if (declutterGroup && declutterGroup.length > 5) {
|
if (declutterGroup && declutterGroup.length > 5) {
|
||||||
const groupCount = declutterGroup[4];
|
const groupCount = declutterGroup[4];
|
||||||
if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
|
if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
|
||||||
@@ -436,13 +439,19 @@ class Executor extends Disposable {
|
|||||||
declutterTree.insert(box);
|
declutterTree.insert(box);
|
||||||
for (let j = 5, jj = declutterGroup.length; j < jj; ++j) {
|
for (let j = 5, jj = declutterGroup.length; j < jj; ++j) {
|
||||||
const declutterData = /** @type {Array} */ (declutterGroup[j]);
|
const declutterData = /** @type {Array} */ (declutterGroup[j]);
|
||||||
if (declutterData) {
|
const context = declutterData[0];
|
||||||
if (declutterData.length > 11) {
|
const currentAlpha = context.globalAlpha;
|
||||||
this.replayTextBackground_(declutterData[0],
|
if (currentAlpha !== opacity) {
|
||||||
declutterData[13], declutterData[14], declutterData[15], declutterData[16],
|
context.globalAlpha = opacity;
|
||||||
declutterData[11], declutterData[12]);
|
}
|
||||||
}
|
if (declutterData.length > 11) {
|
||||||
drawImage.apply(undefined, declutterData);
|
this.replayTextBackground_(declutterData[0],
|
||||||
|
declutterData[13], declutterData[14], declutterData[15], declutterData[16],
|
||||||
|
declutterData[11], declutterData[12]);
|
||||||
|
}
|
||||||
|
drawImage.apply(undefined, declutterData);
|
||||||
|
if (currentAlpha !== opacity) {
|
||||||
|
context.globalAlpha = currentAlpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -430,10 +430,11 @@ export function getCircleArray(radius) {
|
|||||||
* @param {!Object<string, Array<*>>} declutterReplays Declutter replays.
|
* @param {!Object<string, Array<*>>} declutterReplays Declutter replays.
|
||||||
* @param {CanvasRenderingContext2D} context Context.
|
* @param {CanvasRenderingContext2D} context Context.
|
||||||
* @param {number} rotation Rotation.
|
* @param {number} rotation Rotation.
|
||||||
|
* @param {number} opacity Opacity.
|
||||||
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
|
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
|
||||||
* @param {Array<Array<*>>} declutterItems Declutter items.
|
* @param {Array<import("../../PluggableMap.js").DeclutterItems>} declutterItems Declutter items.
|
||||||
*/
|
*/
|
||||||
export function replayDeclutter(declutterReplays, context, rotation, snapToPixel, declutterItems) {
|
export function replayDeclutter(declutterReplays, context, rotation, opacity, snapToPixel, declutterItems) {
|
||||||
const zs = Object.keys(declutterReplays).map(Number).sort(numberSafeCompareFunction);
|
const zs = Object.keys(declutterReplays).map(Number).sort(numberSafeCompareFunction);
|
||||||
const skippedFeatureUids = {};
|
const skippedFeatureUids = {};
|
||||||
for (let z = 0, zz = zs.length; z < zz; ++z) {
|
for (let z = 0, zz = zs.length; z < zz; ++z) {
|
||||||
@@ -443,7 +444,10 @@ export function replayDeclutter(declutterReplays, context, rotation, snapToPixel
|
|||||||
const executor = executorData[i++];
|
const executor = executorData[i++];
|
||||||
if (executor !== currentExecutor) {
|
if (executor !== currentExecutor) {
|
||||||
currentExecutor = executor;
|
currentExecutor = executor;
|
||||||
declutterItems.push(executor.declutterItems);
|
declutterItems.push({
|
||||||
|
items: executor.declutterItems,
|
||||||
|
opacity: opacity
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const transform = executorData[i++];
|
const transform = executorData[i++];
|
||||||
executor.execute(context, transform, rotation, skippedFeatureUids, snapToPixel);
|
executor.execute(context, transform, rotation, skippedFeatureUids, snapToPixel);
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import MapRenderer from './Map.js';
|
|||||||
import SourceState from '../source/State.js';
|
import SourceState from '../source/State.js';
|
||||||
import {replaceChildren} from '../dom.js';
|
import {replaceChildren} from '../dom.js';
|
||||||
import {labelCache} from '../render/canvas.js';
|
import {labelCache} from '../render/canvas.js';
|
||||||
|
import EventType from '../events/EventType.js';
|
||||||
|
import {listen, unlistenByKey} from '../events.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,7 +25,11 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
*/
|
*/
|
||||||
constructor(map) {
|
constructor(map) {
|
||||||
super(map);
|
super(map);
|
||||||
map.attachLabelCache(labelCache);
|
|
||||||
|
/**
|
||||||
|
* @type {import("../events.js").EventsKey}
|
||||||
|
*/
|
||||||
|
this.labelCacheKey_ = listen(labelCache, EventType.CLEAR, map.redrawText.bind(map));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -66,6 +72,11 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disposeInternal() {
|
||||||
|
unlistenByKey(this.labelCacheKey_);
|
||||||
|
super.disposeInternal();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
@@ -81,25 +92,35 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
this.calculateMatrices2D(frameState);
|
this.calculateMatrices2D(frameState);
|
||||||
this.dispatchRenderEvent(RenderEventType.PRECOMPOSE, frameState);
|
this.dispatchRenderEvent(RenderEventType.PRECOMPOSE, frameState);
|
||||||
|
|
||||||
const layerStatesArray = frameState.layerStatesArray;
|
const layerStatesArray = frameState.layerStatesArray.sort(function(a, b) {
|
||||||
|
return a.zIndex - b.zIndex;
|
||||||
|
});
|
||||||
const viewResolution = frameState.viewState.resolution;
|
const viewResolution = frameState.viewState.resolution;
|
||||||
|
|
||||||
this.children_.length = 0;
|
this.children_.length = 0;
|
||||||
|
let hasOverlay = false;
|
||||||
|
let previousElement = null;
|
||||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||||
const layerState = layerStatesArray[i];
|
const layerState = layerStatesArray[i];
|
||||||
|
hasOverlay = hasOverlay || layerState.hasOverlay;
|
||||||
|
frameState.layerIndex = i;
|
||||||
if (!visibleAtResolution(layerState, viewResolution) ||
|
if (!visibleAtResolution(layerState, viewResolution) ||
|
||||||
(layerState.sourceState != SourceState.READY && layerState.sourceState != SourceState.UNDEFINED)) {
|
(layerState.sourceState != SourceState.READY && layerState.sourceState != SourceState.UNDEFINED)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const layer = layerState.layer;
|
const layer = layerState.layer;
|
||||||
const element = layer.render(frameState);
|
const element = layer.render(frameState, previousElement);
|
||||||
if (element) {
|
if (!element) {
|
||||||
const zIndex = layerState.zIndex;
|
continue;
|
||||||
if (zIndex !== element.style.zIndex) {
|
}
|
||||||
element.style.zIndex = zIndex === Infinity ? Number.MAX_SAFE_INTEGER : zIndex;
|
if ((element !== previousElement || i == ii - 1) && element.childElementCount === 2 && !hasOverlay) {
|
||||||
}
|
element.removeChild(element.lastElementChild);
|
||||||
|
}
|
||||||
|
if (element !== previousElement) {
|
||||||
this.children_.push(element);
|
this.children_.push(element);
|
||||||
|
hasOverlay = false;
|
||||||
|
previousElement = element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.renderFrame(frameState);
|
super.renderFrame(frameState);
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ class LayerRenderer extends Observable {
|
|||||||
* Determine whether render should be called.
|
* Determine whether render should be called.
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||||
* @param {import("../layer/Layer.js").State} layerState Layer state.
|
|
||||||
* @return {boolean} Layer is ready to be rendered.
|
* @return {boolean} Layer is ready to be rendered.
|
||||||
*/
|
*/
|
||||||
prepareFrame(frameState, layerState) {
|
prepareFrame(frameState) {
|
||||||
return abstract();
|
return abstract();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,10 +39,10 @@ class LayerRenderer extends Observable {
|
|||||||
* Render the layer.
|
* Render the layer.
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||||
* @param {import("../layer/Layer.js").State} layerState Layer state.
|
* @param {HTMLElement} target Target that may be used to render content to.
|
||||||
* @return {HTMLElement} The rendered element.
|
* @return {HTMLElement} The rendered element.
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
renderFrame(frameState, target) {
|
||||||
return abstract();
|
return abstract();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
prepareFrame(frameState, layerState) {
|
prepareFrame(frameState) {
|
||||||
|
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||||
const pixelRatio = frameState.pixelRatio;
|
const pixelRatio = frameState.pixelRatio;
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const viewResolution = viewState.resolution;
|
const viewResolution = viewState.resolution;
|
||||||
@@ -72,11 +73,12 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
renderFrame(frameState, target) {
|
||||||
const image = this.image_;
|
const image = this.image_;
|
||||||
const imageExtent = image.getExtent();
|
const imageExtent = image.getExtent();
|
||||||
const imageResolution = image.getResolution();
|
const imageResolution = image.getResolution();
|
||||||
const imagePixelRatio = image.getPixelRatio();
|
const imagePixelRatio = image.getPixelRatio();
|
||||||
|
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||||
const pixelRatio = frameState.pixelRatio;
|
const pixelRatio = frameState.pixelRatio;
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const viewCenter = viewState.center;
|
const viewCenter = viewState.center;
|
||||||
@@ -93,13 +95,15 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set forward and inverse pixel transforms
|
// set forward and inverse pixel transforms
|
||||||
composeTransform(this.pixelTransform_,
|
composeTransform(this.pixelTransform,
|
||||||
frameState.size[0] / 2, frameState.size[1] / 2,
|
frameState.size[0] / 2, frameState.size[1] / 2,
|
||||||
1 / pixelRatio, 1 / pixelRatio,
|
1 / pixelRatio, 1 / pixelRatio,
|
||||||
rotation,
|
rotation,
|
||||||
-width / 2, -height / 2
|
-width / 2, -height / 2
|
||||||
);
|
);
|
||||||
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
|
makeInverse(this.inversePixelTransform, this.pixelTransform);
|
||||||
|
|
||||||
|
this.useContainer(target, this.pixelTransform, layerState.opacity);
|
||||||
|
|
||||||
const context = this.context;
|
const context = this.context;
|
||||||
const canvas = context.canvas;
|
const canvas = context.canvas;
|
||||||
@@ -107,7 +111,7 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
|
|||||||
if (canvas.width != width || canvas.height != height) {
|
if (canvas.width != width || canvas.height != height) {
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
} else {
|
} else if (!this.containerReused) {
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +142,17 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
|
|||||||
|
|
||||||
this.preRender(context, frameState);
|
this.preRender(context, frameState);
|
||||||
if (dw >= 0.5 && dh >= 0.5) {
|
if (dw >= 0.5 && dh >= 0.5) {
|
||||||
|
const opacity = layerState.opacity;
|
||||||
|
let previousAlpha;
|
||||||
|
if (opacity !== 1) {
|
||||||
|
previousAlpha = this.context.globalAlpha;
|
||||||
|
this.context.globalAlpha = opacity;
|
||||||
|
}
|
||||||
this.context.drawImage(img, 0, 0, +img.width, +img.height,
|
this.context.drawImage(img, 0, 0, +img.width, +img.height,
|
||||||
Math.round(dx), Math.round(dy), Math.round(dw), Math.round(dh));
|
Math.round(dx), Math.round(dy), Math.round(dw), Math.round(dh));
|
||||||
|
if (opacity !== 1) {
|
||||||
|
this.context.globalAlpha = previousAlpha;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.postRender(context, frameState);
|
this.postRender(context, frameState);
|
||||||
|
|
||||||
@@ -147,17 +160,12 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
|
|||||||
context.restore();
|
context.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
const opacity = layerState.opacity;
|
const canvasTransform = transformToString(this.pixelTransform);
|
||||||
if (opacity !== parseFloat(canvas.style.opacity)) {
|
|
||||||
canvas.style.opacity = opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
const canvasTransform = transformToString(this.pixelTransform_);
|
|
||||||
if (canvasTransform !== canvas.style.transform) {
|
if (canvasTransform !== canvas.style.transform) {
|
||||||
canvas.style.transform = canvasTransform;
|
canvas.style.transform = canvasTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
return canvas;
|
return this.container;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import RenderEvent from '../../render/Event.js';
|
|||||||
import RenderEventType from '../../render/EventType.js';
|
import RenderEventType from '../../render/EventType.js';
|
||||||
import {rotateAtOffset} from '../../render/canvas.js';
|
import {rotateAtOffset} from '../../render/canvas.js';
|
||||||
import LayerRenderer from '../Layer.js';
|
import LayerRenderer from '../Layer.js';
|
||||||
import {create as createTransform, apply as applyTransform, compose as composeTransform} from '../../transform.js';
|
import {create as createTransform, apply as applyTransform, compose as composeTransform, toString as transformToString} from '../../transform.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract
|
* @abstract
|
||||||
@@ -21,6 +21,12 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
|
|
||||||
super(layer);
|
super(layer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*/
|
||||||
|
this.container = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {number}
|
* @type {number}
|
||||||
@@ -38,37 +44,74 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* The transform for rendered pixels to viewport CSS pixels. This transform must
|
* The transform for rendered pixels to viewport CSS pixels. This transform must
|
||||||
* be set when rendering a frame and may be used by other functions after rendering.
|
* be set when rendering a frame and may be used by other functions after rendering.
|
||||||
* @private
|
* @protected
|
||||||
* @type {import("../../transform.js").Transform}
|
* @type {import("../../transform.js").Transform}
|
||||||
*/
|
*/
|
||||||
this.pixelTransform_ = createTransform();
|
this.pixelTransform = createTransform();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The transform for viewport CSS pixels to rendered pixels. This transform must
|
* The transform for viewport CSS pixels to rendered pixels. This transform must
|
||||||
* be set when rendering a frame and may be used by other functions after rendering.
|
* be set when rendering a frame and may be used by other functions after rendering.
|
||||||
* @private
|
* @protected
|
||||||
* @type {import("../../transform.js").Transform}
|
* @type {import("../../transform.js").Transform}
|
||||||
*/
|
*/
|
||||||
this.inversePixelTransform_ = createTransform();
|
this.inversePixelTransform = createTransform();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @type {CanvasRenderingContext2D}
|
* @type {CanvasRenderingContext2D}
|
||||||
*/
|
*/
|
||||||
this.context = createCanvasContext2D();
|
this.context = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.containerReused = false;
|
||||||
|
|
||||||
const canvas = this.context.canvas;
|
|
||||||
canvas.style.position = 'absolute';
|
|
||||||
canvas.style.transformOrigin = 'top left';
|
|
||||||
canvas.className = this.getLayer().getClassName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* Get a rendering container from an existing target, if compatible.
|
||||||
|
* @param {HTMLElement} target Potential render target.
|
||||||
|
* @param {import("../../transform").Transform} transform Transform.
|
||||||
|
* @param {number} opacity Opacity.
|
||||||
*/
|
*/
|
||||||
disposeInternal() {
|
useContainer(target, transform, opacity) {
|
||||||
this.context.canvas.width = this.context.canvas.height = 0;
|
const layerClassName = this.getLayer().getClassName();
|
||||||
super.disposeInternal();
|
let container, context;
|
||||||
|
if (target && target.style.opacity === '' && target.className === layerClassName) {
|
||||||
|
const canvas = target.firstElementChild;
|
||||||
|
if (canvas instanceof HTMLCanvasElement) {
|
||||||
|
context = canvas.getContext('2d');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (context && context.canvas.style.transform === transformToString(transform)) {
|
||||||
|
// Container of the previous layer renderer can be used.
|
||||||
|
this.container = target;
|
||||||
|
this.context = context;
|
||||||
|
this.containerReused = true;
|
||||||
|
} else if (this.containerReused) {
|
||||||
|
// Previously reused container cannot be used any more.
|
||||||
|
this.container = null;
|
||||||
|
this.context = null;
|
||||||
|
this.containerReused = false;
|
||||||
|
}
|
||||||
|
if (!this.container) {
|
||||||
|
container = document.createElement('div');
|
||||||
|
container.className = layerClassName;
|
||||||
|
let style = container.style;
|
||||||
|
style.position = 'absolute';
|
||||||
|
style.width = '100%';
|
||||||
|
style.height = '100%';
|
||||||
|
context = createCanvasContext2D();
|
||||||
|
const canvas = context.canvas;
|
||||||
|
container.appendChild(canvas);
|
||||||
|
style = canvas.style;
|
||||||
|
style.position = 'absolute';
|
||||||
|
style.transformOrigin = 'top left';
|
||||||
|
this.container = container;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,7 +163,7 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
applyTransform(frameState.coordinateToPixelTransform, bottomRight);
|
applyTransform(frameState.coordinateToPixelTransform, bottomRight);
|
||||||
applyTransform(frameState.coordinateToPixelTransform, bottomLeft);
|
applyTransform(frameState.coordinateToPixelTransform, bottomLeft);
|
||||||
|
|
||||||
const inverted = this.inversePixelTransform_;
|
const inverted = this.inversePixelTransform;
|
||||||
applyTransform(inverted, topLeft);
|
applyTransform(inverted, topLeft);
|
||||||
applyTransform(inverted, topRight);
|
applyTransform(inverted, topRight);
|
||||||
applyTransform(inverted, bottomRight);
|
applyTransform(inverted, bottomRight);
|
||||||
@@ -144,7 +187,7 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
dispatchRenderEvent_(type, context, frameState) {
|
dispatchRenderEvent_(type, context, frameState) {
|
||||||
const layer = this.getLayer();
|
const layer = this.getLayer();
|
||||||
if (layer.hasListener(type)) {
|
if (layer.hasListener(type)) {
|
||||||
const event = new RenderEvent(type, this.inversePixelTransform_, frameState, context, null);
|
const event = new RenderEvent(type, this.inversePixelTransform, frameState, context);
|
||||||
layer.dispatchEvent(event);
|
layer.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,7 +240,7 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
* returned, and empty array will be returned.
|
* returned, and empty array will be returned.
|
||||||
*/
|
*/
|
||||||
getDataAtPixel(pixel, frameState, hitTolerance) {
|
getDataAtPixel(pixel, frameState, hitTolerance) {
|
||||||
const renderPixel = applyTransform(this.inversePixelTransform_, pixel.slice());
|
const renderPixel = applyTransform(this.inversePixelTransform, pixel.slice());
|
||||||
const context = this.context;
|
const context = this.context;
|
||||||
|
|
||||||
let data;
|
let data;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import TileState from '../../TileState.js';
|
|||||||
import {createEmpty, equals, getIntersection, getTopLeft} from '../../extent.js';
|
import {createEmpty, equals, getIntersection, getTopLeft} from '../../extent.js';
|
||||||
import CanvasLayerRenderer from './Layer.js';
|
import CanvasLayerRenderer from './Layer.js';
|
||||||
import {apply as applyTransform, compose as composeTransform, makeInverse, toString as transformToString} from '../../transform.js';
|
import {apply as applyTransform, compose as composeTransform, makeInverse, toString as transformToString} from '../../transform.js';
|
||||||
|
import {numberSafeCompareFunction} from '../../array.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
@@ -125,7 +126,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
prepareFrame(frameState, layerState) {
|
prepareFrame(frameState) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,8 +138,8 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
* @returns {HTMLElement} The rendered element.
|
* @returns {HTMLElement} The rendered element.
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
renderFrame(frameState, target) {
|
||||||
const context = this.context;
|
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const projection = viewState.projection;
|
const projection = viewState.projection;
|
||||||
const viewResolution = viewState.resolution;
|
const viewResolution = viewState.resolution;
|
||||||
@@ -224,17 +225,21 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const canvas = context.canvas;
|
|
||||||
const canvasScale = tileResolution / viewResolution;
|
const canvasScale = tileResolution / viewResolution;
|
||||||
|
|
||||||
// set forward and inverse pixel transforms
|
// set forward and inverse pixel transforms
|
||||||
composeTransform(this.pixelTransform_,
|
composeTransform(this.pixelTransform,
|
||||||
frameState.size[0] / 2, frameState.size[1] / 2,
|
frameState.size[0] / 2, frameState.size[1] / 2,
|
||||||
1 / tilePixelRatio, 1 / tilePixelRatio,
|
1 / tilePixelRatio, 1 / tilePixelRatio,
|
||||||
rotation,
|
rotation,
|
||||||
-width / 2, -height / 2
|
-width / 2, -height / 2
|
||||||
);
|
);
|
||||||
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
|
|
||||||
|
this.useContainer(target, this.pixelTransform, layerState.opacity);
|
||||||
|
const context = this.context;
|
||||||
|
const canvas = context.canvas;
|
||||||
|
|
||||||
|
makeInverse(this.inversePixelTransform, this.pixelTransform);
|
||||||
|
|
||||||
// set scale transform for calculating tile positions on the canvas
|
// set scale transform for calculating tile positions on the canvas
|
||||||
composeTransform(this.tempTransform_,
|
composeTransform(this.tempTransform_,
|
||||||
@@ -247,7 +252,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
if (canvas.width != width || canvas.height != height) {
|
if (canvas.width != width || canvas.height != height) {
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
} else {
|
} else if (!this.containerReused) {
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,18 +264,17 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
|
|
||||||
this.renderedTiles.length = 0;
|
this.renderedTiles.length = 0;
|
||||||
/** @type {Array<number>} */
|
/** @type {Array<number>} */
|
||||||
const zs = Object.keys(tilesToDrawByZ).map(Number);
|
let zs = Object.keys(tilesToDrawByZ).map(Number);
|
||||||
zs.sort(function(a, b) {
|
zs.sort(numberSafeCompareFunction);
|
||||||
if (a === z) {
|
|
||||||
return 1;
|
|
||||||
} else if (b === z) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return a > b ? 1 : a < b ? -1 : 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let i = 0, ii = zs.length; i < ii; ++i) {
|
let clips, clipZs, currentClip;
|
||||||
|
if (layerState.opacity === 1 && (!this.containerReused || tileSource.getOpaque(frameState.viewState.projection))) {
|
||||||
|
zs = zs.reverse();
|
||||||
|
} else {
|
||||||
|
clips = [];
|
||||||
|
clipZs = [];
|
||||||
|
}
|
||||||
|
for (let i = zs.length - 1; i >= 0; --i) {
|
||||||
const currentZ = zs[i];
|
const currentZ = zs[i];
|
||||||
const currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
|
const currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
|
||||||
const currentResolution = tileGrid.getResolution(currentZ);
|
const currentResolution = tileGrid.getResolution(currentZ);
|
||||||
@@ -298,8 +302,41 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
const y = Math.round(floatY);
|
const y = Math.round(floatY);
|
||||||
const w = nextX - x;
|
const w = nextX - x;
|
||||||
const h = nextY - y;
|
const h = nextY - y;
|
||||||
|
const transition = z === currentZ;
|
||||||
|
|
||||||
this.drawTileImage(tile, frameState, x, y, w, h, tileGutter, z === currentZ);
|
const inTransition = transition && tile.getAlpha(getUid(this), frameState.time) !== 1;
|
||||||
|
if (!inTransition) {
|
||||||
|
if (clips) {
|
||||||
|
// Clip mask for regions in this tile that already filled by a higher z tile
|
||||||
|
context.save();
|
||||||
|
currentClip = [x, y, x + w, y, x + w, y + h, x, y + h];
|
||||||
|
for (let i = 0, ii = clips.length; i < ii; ++i) {
|
||||||
|
if (z !== currentZ && currentZ < clipZs[i]) {
|
||||||
|
const clip = clips[i];
|
||||||
|
context.beginPath();
|
||||||
|
// counter-clockwise (outer ring) for current tile
|
||||||
|
context.moveTo(currentClip[0], currentClip[1]);
|
||||||
|
context.lineTo(currentClip[2], currentClip[3]);
|
||||||
|
context.lineTo(currentClip[4], currentClip[5]);
|
||||||
|
context.lineTo(currentClip[6], currentClip[7]);
|
||||||
|
// clockwise (inner ring) for higher z tile
|
||||||
|
context.moveTo(clip[6], clip[7]);
|
||||||
|
context.lineTo(clip[4], clip[5]);
|
||||||
|
context.lineTo(clip[2], clip[3]);
|
||||||
|
context.lineTo(clip[0], clip[1]);
|
||||||
|
context.clip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clips.push(currentClip);
|
||||||
|
clipZs.push(currentZ);
|
||||||
|
} else {
|
||||||
|
context.clearRect(x, y, w, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.drawTileImage(tile, frameState, x, y, w, h, tileGutter, transition, layerState.opacity);
|
||||||
|
if (clips && !inTransition) {
|
||||||
|
context.restore();
|
||||||
|
}
|
||||||
this.renderedTiles.push(tile);
|
this.renderedTiles.push(tile);
|
||||||
this.updateUsedTiles(frameState.usedTiles, tileSource, tile);
|
this.updateUsedTiles(frameState.usedTiles, tileSource, tile);
|
||||||
}
|
}
|
||||||
@@ -322,17 +359,12 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
context.restore();
|
context.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
const opacity = layerState.opacity;
|
const canvasTransform = transformToString(this.pixelTransform);
|
||||||
if (opacity !== parseFloat(canvas.style.opacity)) {
|
|
||||||
canvas.style.opacity = opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
const canvasTransform = transformToString(this.pixelTransform_);
|
|
||||||
if (canvasTransform !== canvas.style.transform) {
|
if (canvasTransform !== canvas.style.transform) {
|
||||||
canvas.style.transform = canvasTransform;
|
canvas.style.transform = canvasTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
return canvas;
|
return this.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -344,19 +376,15 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
* @param {number} h Height of the tile.
|
* @param {number} h Height of the tile.
|
||||||
* @param {number} gutter Tile gutter.
|
* @param {number} gutter Tile gutter.
|
||||||
* @param {boolean} transition Apply an alpha transition.
|
* @param {boolean} transition Apply an alpha transition.
|
||||||
|
* @param {number} opacity Opacity.
|
||||||
*/
|
*/
|
||||||
drawTileImage(tile, frameState, x, y, w, h, gutter, transition) {
|
drawTileImage(tile, frameState, x, y, w, h, gutter, transition, opacity) {
|
||||||
const image = this.getTileImage(tile);
|
const image = this.getTileImage(tile);
|
||||||
if (!image) {
|
if (!image) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const uid = getUid(this);
|
const uid = getUid(this);
|
||||||
const alpha = transition ? tile.getAlpha(uid, frameState.time) : 1;
|
const alpha = opacity * (transition ? tile.getAlpha(uid, frameState.time) : 1);
|
||||||
const tileLayer = /** @type {import("../../layer/Tile.js").default} */ (this.getLayer());
|
|
||||||
const tileSource = tileLayer.getSource();
|
|
||||||
if (alpha === 1 && !tileSource.getOpaque(frameState.viewState.projection)) {
|
|
||||||
this.context.clearRect(x, y, w, h);
|
|
||||||
}
|
|
||||||
const alphaChanged = alpha !== this.context.globalAlpha;
|
const alphaChanged = alpha !== this.context.globalAlpha;
|
||||||
if (alphaChanged) {
|
if (alphaChanged) {
|
||||||
this.context.save();
|
this.context.save();
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
prepareFrame(frameState, layerState) {
|
prepareFrame(frameState) {
|
||||||
const pixelRatio = frameState.pixelRatio;
|
const pixelRatio = frameState.pixelRatio;
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const viewResolution = viewState.resolution;
|
const viewResolution = viewState.resolution;
|
||||||
@@ -78,6 +78,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
|
|||||||
|
|
||||||
if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] && !isEmpty(renderedExtent)) {
|
if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] && !isEmpty(renderedExtent)) {
|
||||||
let skippedFeatures = this.skippedFeatures_;
|
let skippedFeatures = this.skippedFeatures_;
|
||||||
|
vectorRenderer.useContainer(null, null, 1);
|
||||||
const context = vectorRenderer.context;
|
const context = vectorRenderer.context;
|
||||||
const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, {
|
const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, {
|
||||||
declutterItems: [],
|
declutterItems: [],
|
||||||
@@ -91,10 +92,10 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
|
|||||||
}));
|
}));
|
||||||
const newSkippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
|
const newSkippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
|
||||||
const image = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas, function(callback) {
|
const image = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas, function(callback) {
|
||||||
if (vectorRenderer.prepareFrame(imageFrameState, layerState) &&
|
if (vectorRenderer.prepareFrame(imageFrameState) &&
|
||||||
(vectorRenderer.replayGroupChanged ||
|
(vectorRenderer.replayGroupChanged ||
|
||||||
!equals(skippedFeatures, newSkippedFeatures))) {
|
!equals(skippedFeatures, newSkippedFeatures))) {
|
||||||
vectorRenderer.renderFrame(imageFrameState, layerState);
|
vectorRenderer.renderFrame(imageFrameState, null);
|
||||||
renderDeclutterItems(imageFrameState, null);
|
renderDeclutterItems(imageFrameState, null);
|
||||||
skippedFeatures = newSkippedFeatures;
|
skippedFeatures = newSkippedFeatures;
|
||||||
callback();
|
callback();
|
||||||
|
|||||||
@@ -70,35 +70,48 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
useContainer(target, transform, opacity) {
|
||||||
|
if (opacity < 1) {
|
||||||
|
target = null;
|
||||||
|
}
|
||||||
|
super.useContainer(target, transform, opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
renderFrame(frameState, target) {
|
||||||
|
|
||||||
|
const pixelRatio = frameState.pixelRatio;
|
||||||
|
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||||
|
|
||||||
|
// set forward and inverse pixel transforms
|
||||||
|
makeScale(this.pixelTransform, 1 / pixelRatio, 1 / pixelRatio);
|
||||||
|
makeInverse(this.inversePixelTransform, this.pixelTransform);
|
||||||
|
|
||||||
|
this.useContainer(target, this.pixelTransform, layerState.opacity);
|
||||||
const context = this.context;
|
const context = this.context;
|
||||||
const canvas = context.canvas;
|
const canvas = context.canvas;
|
||||||
|
|
||||||
const replayGroup = this.replayGroup_;
|
const replayGroup = this.replayGroup_;
|
||||||
if (!replayGroup || replayGroup.isEmpty()) {
|
if (!replayGroup || replayGroup.isEmpty()) {
|
||||||
if (canvas.width > 0) {
|
if (!this.containerReused && canvas.width > 0) {
|
||||||
canvas.width = 0;
|
canvas.width = 0;
|
||||||
}
|
}
|
||||||
return canvas;
|
return this.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pixelRatio = frameState.pixelRatio;
|
|
||||||
|
|
||||||
// set forward and inverse pixel transforms
|
|
||||||
makeScale(this.pixelTransform_, 1 / pixelRatio, 1 / pixelRatio);
|
|
||||||
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
|
|
||||||
|
|
||||||
// resize and clear
|
// resize and clear
|
||||||
const width = Math.round(frameState.size[0] * pixelRatio);
|
const width = Math.round(frameState.size[0] * pixelRatio);
|
||||||
const height = Math.round(frameState.size[1] * pixelRatio);
|
const height = Math.round(frameState.size[1] * pixelRatio);
|
||||||
if (canvas.width != width || canvas.height != height) {
|
if (canvas.width != width || canvas.height != height) {
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
const canvasTransform = transformToString(this.pixelTransform_);
|
const canvasTransform = transformToString(this.pixelTransform);
|
||||||
if (canvas.style.transform !== canvasTransform) {
|
if (canvas.style.transform !== canvasTransform) {
|
||||||
canvas.style.transform = canvasTransform;
|
canvas.style.transform = canvasTransform;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!this.containerReused) {
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +165,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
if (declutterReplays) {
|
if (declutterReplays) {
|
||||||
const viewHints = frameState.viewHints;
|
const viewHints = frameState.viewHints;
|
||||||
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
|
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
|
||||||
replayDeclutter(declutterReplays, context, rotation, hifi, frameState.declutterItems);
|
replayDeclutter(declutterReplays, context, rotation, 1, hifi, frameState.declutterItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clipped) {
|
if (clipped) {
|
||||||
@@ -162,11 +175,12 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
this.postRender(context, frameState);
|
this.postRender(context, frameState);
|
||||||
|
|
||||||
const opacity = layerState.opacity;
|
const opacity = layerState.opacity;
|
||||||
if (opacity !== parseFloat(canvas.style.opacity)) {
|
const container = this.container;
|
||||||
canvas.style.opacity = opacity;
|
if (opacity !== parseFloat(container.style.opacity)) {
|
||||||
|
container.style.opacity = opacity === 1 ? '' : opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return canvas;
|
return this.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,7 +233,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
prepareFrame(frameState, layerState) {
|
prepareFrame(frameState) {
|
||||||
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
||||||
const vectorSource = vectorLayer.getSource();
|
const vectorSource = vectorLayer.getSource();
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import {
|
|||||||
makeInverse
|
makeInverse
|
||||||
} from '../../transform.js';
|
} from '../../transform.js';
|
||||||
import CanvasExecutorGroup, {replayDeclutter} from '../../render/canvas/ExecutorGroup.js';
|
import CanvasExecutorGroup, {replayDeclutter} from '../../render/canvas/ExecutorGroup.js';
|
||||||
import {clear, isEmpty} from '../../obj.js';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,32 +58,16 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
constructor(layer) {
|
constructor(layer) {
|
||||||
super(layer);
|
super(layer);
|
||||||
|
|
||||||
const baseCanvas = this.context.canvas;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {CanvasRenderingContext2D}
|
* @type {CanvasRenderingContext2D}
|
||||||
*/
|
*/
|
||||||
this.overlayContext_ = createCanvasContext2D();
|
this.overlayContext_ = null;
|
||||||
|
|
||||||
const overlayCanvas = this.overlayContext_.canvas;
|
|
||||||
overlayCanvas.style.position = 'absolute';
|
|
||||||
overlayCanvas.style.transformOrigin = 'top left';
|
|
||||||
|
|
||||||
const container = document.createElement('div');
|
|
||||||
const style = container.style;
|
|
||||||
style.position = 'absolute';
|
|
||||||
style.width = '100%';
|
|
||||||
style.height = '100%';
|
|
||||||
|
|
||||||
container.appendChild(baseCanvas);
|
|
||||||
container.appendChild(overlayCanvas);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @type {string}
|
||||||
* @type {HTMLElement}
|
|
||||||
*/
|
*/
|
||||||
this.container_ = container;
|
this.overlayContextUid_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The transform for rendered pixels to viewport CSS pixels for the overlay canvas.
|
* The transform for rendered pixels to viewport CSS pixels for the overlay canvas.
|
||||||
@@ -136,17 +119,42 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
disposeInternal() {
|
useContainer(target, transform, opacity) {
|
||||||
this.overlayContext_.canvas.width = this.overlayContext_.canvas.height = 0;
|
let overlayContext;
|
||||||
super.disposeInternal();
|
if (target && target.childElementCount === 2) {
|
||||||
|
overlayContext = target.lastElementChild.getContext('2d');
|
||||||
|
if (!overlayContext) {
|
||||||
|
target = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const containerReused = this.containerReused;
|
||||||
|
super.useContainer(target, transform, opacity);
|
||||||
|
if (containerReused) {
|
||||||
|
this.overlayContext_ = overlayContext || null;
|
||||||
|
this.overlayContextUid_ = overlayContext ? getUid(overlayContext) : undefined;
|
||||||
|
}
|
||||||
|
if (!this.overlayContext_) {
|
||||||
|
const overlayContext = createCanvasContext2D();
|
||||||
|
const style = overlayContext.canvas.style;
|
||||||
|
style.position = 'absolute';
|
||||||
|
style.transformOrigin = 'top left';
|
||||||
|
this.overlayContext_ = overlayContext;
|
||||||
|
this.overlayContextUid_ = getUid(overlayContext);
|
||||||
|
}
|
||||||
|
if (this.container.childElementCount === 1) {
|
||||||
|
this.container.appendChild(this.overlayContext_.canvas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../../VectorRenderTile.js").default} tile Tile.
|
* @param {import("../../VectorRenderTile.js").default} tile Tile.
|
||||||
* @param {number} pixelRatio Pixel ratio.
|
* @param {number} pixelRatio Pixel ratio.
|
||||||
* @param {import("../../proj/Projection").default} projection Projection.
|
* @param {import("../../proj/Projection").default} projection Projection.
|
||||||
|
* @param {boolean} queue Queue tile for rendering.
|
||||||
|
* @return {boolean} Tile needs to be rendered.
|
||||||
*/
|
*/
|
||||||
prepareTile(tile, pixelRatio, projection) {
|
prepareTile(tile, pixelRatio, projection, queue) {
|
||||||
|
let render = false;
|
||||||
const tileUid = getUid(tile);
|
const tileUid = getUid(tile);
|
||||||
const state = tile.getState();
|
const state = tile.getState();
|
||||||
if (((state === TileState.LOADED && tile.hifi) ||
|
if (((state === TileState.LOADED && tile.hifi) ||
|
||||||
@@ -158,9 +166,13 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
if (state === TileState.LOADED || state === TileState.ERROR) {
|
if (state === TileState.LOADED || state === TileState.ERROR) {
|
||||||
this.updateExecutorGroup_(tile, pixelRatio, projection);
|
this.updateExecutorGroup_(tile, pixelRatio, projection);
|
||||||
if (this.tileImageNeedsRender_(tile, pixelRatio, projection)) {
|
if (this.tileImageNeedsRender_(tile, pixelRatio, projection)) {
|
||||||
this.renderTileImageQueue_[tileUid] = tile;
|
render = true;
|
||||||
|
if (queue) {
|
||||||
|
this.renderTileImageQueue_[tileUid] = tile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return render;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,7 +188,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
tile.wantedResolution = resolution;
|
tile.wantedResolution = resolution;
|
||||||
const tileUid = getUid(tile);
|
const tileUid = getUid(tile);
|
||||||
if (!(tileUid in this.tileListenerKeys_)) {
|
if (!(tileUid in this.tileListenerKeys_)) {
|
||||||
const listenerKey = listen(tile, EventType.CHANGE, this.prepareTile.bind(this, tile, pixelRatio, projection));
|
const listenerKey = listen(tile, EventType.CHANGE, this.prepareTile.bind(this, tile, pixelRatio, projection, true));
|
||||||
this.tileListenerKeys_[tileUid] = listenerKey;
|
this.tileListenerKeys_[tileUid] = listenerKey;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -185,7 +197,10 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
if (hifi || !tile.wantedResolution) {
|
if (hifi || !tile.wantedResolution) {
|
||||||
tile.wantedResolution = resolution;
|
tile.wantedResolution = resolution;
|
||||||
}
|
}
|
||||||
this.prepareTile(tile, pixelRatio, projection);
|
const render = this.prepareTile(tile, pixelRatio, projection, false);
|
||||||
|
if (render) {
|
||||||
|
this.renderTileImage_(tile, frameState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
@@ -207,13 +222,15 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
prepareFrame(frameState, layerState) {
|
prepareFrame(frameState) {
|
||||||
|
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||||
|
layerState.hasOverlay = true;
|
||||||
const layerRevision = this.getLayer().getRevision();
|
const layerRevision = this.getLayer().getRevision();
|
||||||
if (this.renderedLayerRevision_ != layerRevision) {
|
if (this.renderedLayerRevision_ != layerRevision) {
|
||||||
this.renderedTiles.length = 0;
|
this.renderedTiles.length = 0;
|
||||||
}
|
}
|
||||||
this.renderedLayerRevision_ = layerRevision;
|
this.renderedLayerRevision_ = layerRevision;
|
||||||
return super.prepareFrame(frameState, layerState);
|
return super.prepareFrame(frameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -379,26 +396,30 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
renderFrame(frameState, target) {
|
||||||
super.renderFrame(frameState, layerState);
|
|
||||||
|
|
||||||
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
|
|
||||||
const viewHints = frameState.viewHints;
|
const viewHints = frameState.viewHints;
|
||||||
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
|
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
|
||||||
|
this.renderQueuedTileImages_(hifi, frameState);
|
||||||
|
|
||||||
|
super.renderFrame(frameState, target);
|
||||||
|
|
||||||
|
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
|
||||||
const renderMode = layer.getRenderMode();
|
const renderMode = layer.getRenderMode();
|
||||||
if (renderMode === VectorTileRenderType.IMAGE) {
|
if (renderMode === VectorTileRenderType.IMAGE) {
|
||||||
this.renderTileImages_(hifi, frameState);
|
return this.container;
|
||||||
return this.container_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmpty(this.renderTileImageQueue_) && !this.extentChanged) {
|
const source = layer.getSource();
|
||||||
this.renderTileImages_(hifi, frameState);
|
// Unqueue tiles from the image queue when we don't need any more
|
||||||
return this.container_;
|
const usedTiles = frameState.usedTiles[getUid(source)];
|
||||||
|
for (const tileUid in this.renderTileImageQueue_) {
|
||||||
|
if (!usedTiles || !(tileUid in usedTiles)) {
|
||||||
|
delete this.renderTileImageQueue_[tileUid];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = this.overlayContext_;
|
const context = this.overlayContext_;
|
||||||
const declutterReplays = layer.getDeclutter() ? {} : null;
|
const declutterReplays = layer.getDeclutter() ? {} : null;
|
||||||
const source = layer.getSource();
|
|
||||||
const replayTypes = VECTOR_REPLAYS[renderMode];
|
const replayTypes = VECTOR_REPLAYS[renderMode];
|
||||||
const pixelRatio = frameState.pixelRatio;
|
const pixelRatio = frameState.pixelRatio;
|
||||||
const rotation = frameState.viewState.rotation;
|
const rotation = frameState.viewState.rotation;
|
||||||
@@ -419,13 +440,14 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
if (canvas.style.transform !== canvasTransform) {
|
if (canvas.style.transform !== canvasTransform) {
|
||||||
canvas.style.transform = canvasTransform;
|
canvas.style.transform = canvasTransform;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (getUid(context) === this.overlayContextUid_) {
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tiles = this.renderedTiles;
|
const tiles = this.renderedTiles;
|
||||||
const tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
const tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
||||||
const clips = [];
|
const clips = [];
|
||||||
|
const clipZs = [];
|
||||||
for (let i = tiles.length - 1; i >= 0; --i) {
|
for (let i = tiles.length - 1; i >= 0; --i) {
|
||||||
const tile = /** @type {import("../../VectorRenderTile.js").default} */ (tiles[i]);
|
const tile = /** @type {import("../../VectorRenderTile.js").default} */ (tiles[i]);
|
||||||
if (tile.getState() == TileState.ABORT) {
|
if (tile.getState() == TileState.ABORT) {
|
||||||
@@ -436,6 +458,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
const worldOffset = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent)[0] - tileExtent[0];
|
const worldOffset = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent)[0] - tileExtent[0];
|
||||||
const transform = this.getRenderTransform(frameState, width, height, worldOffset);
|
const transform = this.getRenderTransform(frameState, width, height, worldOffset);
|
||||||
const executorGroups = tile.executorGroups[getUid(layer)];
|
const executorGroups = tile.executorGroups[getUid(layer)];
|
||||||
|
let clipped = false;
|
||||||
for (let t = 0, tt = executorGroups.length; t < tt; ++t) {
|
for (let t = 0, tt = executorGroups.length; t < tt; ++t) {
|
||||||
const executorGroup = executorGroups[t];
|
const executorGroup = executorGroups[t];
|
||||||
if (!executorGroup.hasExecutors(replayTypes)) {
|
if (!executorGroup.hasExecutors(replayTypes)) {
|
||||||
@@ -443,9 +466,8 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const currentZ = tile.tileCoord[0];
|
const currentZ = tile.tileCoord[0];
|
||||||
let zs, currentClip;
|
let currentClip;
|
||||||
if (!declutterReplays) {
|
if (!declutterReplays && !clipped) {
|
||||||
zs = [];
|
|
||||||
currentClip = executorGroup.getClipCoords(transform);
|
currentClip = executorGroup.getClipCoords(transform);
|
||||||
context.save();
|
context.save();
|
||||||
|
|
||||||
@@ -453,7 +475,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
// already filled by a higher resolution tile
|
// already filled by a higher resolution tile
|
||||||
for (let j = 0, jj = clips.length; j < jj; ++j) {
|
for (let j = 0, jj = clips.length; j < jj; ++j) {
|
||||||
const clip = clips[j];
|
const clip = clips[j];
|
||||||
if (currentZ < zs[j]) {
|
if (currentZ < clipZs[j]) {
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
// counter-clockwise (outer ring) for current tile
|
// counter-clockwise (outer ring) for current tile
|
||||||
context.moveTo(currentClip[0], currentClip[1]);
|
context.moveTo(currentClip[0], currentClip[1]);
|
||||||
@@ -470,51 +492,38 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
executorGroup.execute(context, transform, rotation, {}, hifi, replayTypes, declutterReplays);
|
executorGroup.execute(context, transform, rotation, {}, hifi, replayTypes, declutterReplays);
|
||||||
if (!declutterReplays) {
|
if (!declutterReplays && !clipped) {
|
||||||
context.restore();
|
context.restore();
|
||||||
clips.push(currentClip);
|
clips.push(currentClip);
|
||||||
zs.push(currentZ);
|
clipZs.push(currentZ);
|
||||||
|
clipped = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (declutterReplays) {
|
if (declutterReplays) {
|
||||||
replayDeclutter(declutterReplays, context, rotation, hifi, frameState.declutterItems);
|
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||||
|
replayDeclutter(declutterReplays, context, rotation, layerState.opacity, hifi, frameState.declutterItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
const opacity = layerState.opacity;
|
return this.container;
|
||||||
if (opacity !== parseFloat(canvas.style.opacity)) {
|
|
||||||
canvas.style.opacity = opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that we have rendered the tiles we have already, let's prepare new tile images
|
|
||||||
// for the next frame
|
|
||||||
this.renderTileImages_(hifi, frameState);
|
|
||||||
|
|
||||||
return this.container_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {boolean} hifi We have time to render a high fidelity map image.
|
* @param {boolean} hifi We have time to render a high fidelity map image.
|
||||||
* @param {import('../../PluggableMap.js').FrameState} frameState Frame state.
|
* @param {import('../../PluggableMap.js').FrameState} frameState Frame state.
|
||||||
*/
|
*/
|
||||||
renderTileImages_(hifi, frameState) {
|
renderQueuedTileImages_(hifi, frameState) {
|
||||||
// When we don't have time to render hifi, only render tiles until we have used up
|
// When we don't have time to render hifi, only render tiles until we have used up
|
||||||
// half of the frame budget of 16 ms
|
// half of the frame budget of 16 ms
|
||||||
for (const uid in this.renderTileImageQueue_) {
|
for (const uid in this.renderTileImageQueue_) {
|
||||||
if (!hifi && Date.now() - frameState.time > 8) {
|
if (!hifi && Date.now() - frameState.time > 8) {
|
||||||
|
frameState.animate = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const tile = this.renderTileImageQueue_[uid];
|
const tile = this.renderTileImageQueue_[uid];
|
||||||
frameState.animate = true;
|
|
||||||
delete this.renderTileImageQueue_[uid];
|
delete this.renderTileImageQueue_[uid];
|
||||||
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
|
this.renderTileImage_(tile, frameState);
|
||||||
const viewState = frameState.viewState;
|
|
||||||
const tileGrid = layer.getSource().getTileGridForProjection(viewState.projection);
|
|
||||||
const tileResolution = tileGrid.getResolution(tile.tileCoord[0]);
|
|
||||||
const renderPixelRatio = frameState.pixelRatio / tile.wantedResolution * tileResolution;
|
|
||||||
this.renderTileImage_(tile, frameState.pixelRatio, renderPixelRatio, viewState.projection);
|
|
||||||
}
|
}
|
||||||
clear(this.renderTileImageQueue_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -561,24 +570,29 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../../VectorRenderTile.js").default} tile Tile.
|
* @param {import("../../VectorRenderTile.js").default} tile Tile.
|
||||||
* @param {number} pixelRatio Pixel ratio.
|
* @param {import("../../PluggableMap").FrameState} frameState Frame state.
|
||||||
* @param {number} renderPixelRatio Render pixel ratio.
|
|
||||||
* @param {import("../../proj/Projection.js").default} projection Projection.
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
renderTileImage_(tile, pixelRatio, renderPixelRatio, projection) {
|
renderTileImage_(tile, frameState) {
|
||||||
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
|
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
|
||||||
const replayState = tile.getReplayState(layer);
|
const replayState = tile.getReplayState(layer);
|
||||||
const revision = layer.getRevision();
|
const revision = layer.getRevision();
|
||||||
const executorGroups = tile.executorGroups[getUid(layer)];
|
const executorGroups = tile.executorGroups[getUid(layer)];
|
||||||
replayState.renderedTileRevision = revision;
|
replayState.renderedTileRevision = revision;
|
||||||
replayState.renderedTileZ = tile.sourceZ;
|
replayState.renderedTileZ = tile.sourceZ;
|
||||||
|
|
||||||
const tileCoord = tile.wrappedTileCoord;
|
const tileCoord = tile.wrappedTileCoord;
|
||||||
const z = tileCoord[0];
|
const z = tileCoord[0];
|
||||||
const source = layer.getSource();
|
const source = layer.getSource();
|
||||||
|
let pixelRatio = frameState.pixelRatio;
|
||||||
|
const viewState = frameState.viewState;
|
||||||
|
const projection = viewState.projection;
|
||||||
const tileGrid = source.getTileGridForProjection(projection);
|
const tileGrid = source.getTileGridForProjection(projection);
|
||||||
|
const tileResolution = tileGrid.getResolution(tile.tileCoord[0]);
|
||||||
|
const renderPixelRatio = frameState.pixelRatio / tile.wantedResolution * tileResolution;
|
||||||
const resolution = tileGrid.getResolution(z);
|
const resolution = tileGrid.getResolution(z);
|
||||||
const context = tile.getContext(layer);
|
const context = tile.getContext(layer);
|
||||||
|
|
||||||
// Increase tile size when overzooming for low pixel ratio, to avoid blurry tiles
|
// Increase tile size when overzooming for low pixel ratio, to avoid blurry tiles
|
||||||
pixelRatio = Math.max(pixelRatio, renderPixelRatio / pixelRatio);
|
pixelRatio = Math.max(pixelRatio, renderPixelRatio / pixelRatio);
|
||||||
const size = source.getTilePixelSize(z, pixelRatio, projection);
|
const size = source.getTilePixelSize(z, pixelRatio, projection);
|
||||||
|
|||||||
@@ -2,9 +2,29 @@
|
|||||||
* @module ol/renderer/webgl/Layer
|
* @module ol/renderer/webgl/Layer
|
||||||
*/
|
*/
|
||||||
import LayerRenderer from '../Layer.js';
|
import LayerRenderer from '../Layer.js';
|
||||||
import WebGLHelper from '../../webgl/Helper';
|
import WebGLHelper from '../../webgl/Helper.js';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
export const WebGLWorkerMessageType = {
|
||||||
|
GENERATE_BUFFERS: 'GENERATE_BUFFERS'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} WebGLWorkerGenerateBuffersMessage
|
||||||
|
* This message will trigger the generation of a vertex and an index buffer based on the given render instructions.
|
||||||
|
* When the buffers are generated, the worked will send a message of the same type to the main thread, with
|
||||||
|
* the generated buffers in it.
|
||||||
|
* Note that any addition properties present in the message *will* be sent back to the main thread.
|
||||||
|
* @property {WebGLWorkerMessageType} type Message type
|
||||||
|
* @property {ArrayBuffer} renderInstructions Render instructions raw binary buffer.
|
||||||
|
* @property {ArrayBuffer} [vertexBuffer] Vertices array raw binary buffer (sent by the worker).
|
||||||
|
* @property {ArrayBuffer} [indexBuffer] Indices array raw binary buffer (sent by the worker).
|
||||||
|
* @property {number} [customAttributesCount] Amount of custom attributes count in the render instructions.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} PostProcessesOptions
|
* @typedef {Object} PostProcessesOptions
|
||||||
* @property {number} [scaleRatio] Scale ratio; if < 1, the post process will render to a texture smaller than
|
* @property {number} [scaleRatio] Scale ratio; if < 1, the post process will render to a texture smaller than
|
||||||
@@ -36,7 +56,11 @@ class WebGLLayerRenderer extends LayerRenderer {
|
|||||||
|
|
||||||
const options = opt_options || {};
|
const options = opt_options || {};
|
||||||
|
|
||||||
this.helper_ = new WebGLHelper({
|
/**
|
||||||
|
* @type {WebGLHelper}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.helper = new WebGLHelper({
|
||||||
postProcesses: options.postProcesses,
|
postProcesses: options.postProcesses,
|
||||||
uniforms: options.uniforms
|
uniforms: options.uniforms
|
||||||
});
|
});
|
||||||
@@ -55,96 +79,151 @@ class WebGLLayerRenderer extends LayerRenderer {
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
getShaderCompileErrors() {
|
getShaderCompileErrors() {
|
||||||
return this.helper_.getShaderCompileErrors();
|
return this.helper.getShaderCompileErrors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes vertices and indices to the given buffers using the geometry coordinates and the following properties
|
* @param {Float32Array} instructions Instructons array in which to write.
|
||||||
* from the feature:
|
* @param {number} elementIndex Index from which render instructions will be written.
|
||||||
* - `color`
|
* @param {number} x Point center X coordinate
|
||||||
* - `opacity`
|
* @param {number} y Point center Y coordinate
|
||||||
* - `size` (for points)
|
* @param {number} u0 Left texture coordinate
|
||||||
* - `u0`, `v0`, `u1`, `v1` (for points)
|
* @param {number} v0 Bottom texture coordinate
|
||||||
* - `rotateWithView` (for points)
|
* @param {number} u1 Right texture coordinate
|
||||||
* - `width` (for lines)
|
* @param {number} v1 Top texture coordinate
|
||||||
* Custom attributes can be designated using the `opt_attributes` argument, otherwise other properties on the
|
* @param {number} size Radius of the point
|
||||||
* feature will be ignored.
|
* @param {number} opacity Opacity
|
||||||
* @param {import("../../webgl/Buffer").default} vertexBuffer WebGL buffer in which new vertices will be pushed.
|
* @param {boolean} rotateWithView If true, the point will stay aligned with the view
|
||||||
* @param {import("../../webgl/Buffer").default} indexBuffer WebGL buffer in which new indices will be pushed.
|
* @param {Array<number>} color Array holding red, green, blue, alpha values
|
||||||
* @param {import("../../format/GeoJSON").GeoJSONFeature} geojsonFeature Feature in geojson format, coordinates
|
* @return {number} Index from which the next element should be written
|
||||||
* expressed in EPSG:4326.
|
* @private
|
||||||
* @param {Array<string>} [opt_attributes] Custom attributes. An array of properties which will be read from the
|
|
||||||
* feature and pushed in the buffer in the given order. Note: attributes can only be numerical! Any other type or
|
|
||||||
* NaN will result in `0` being pushed in the buffer.
|
|
||||||
*/
|
*/
|
||||||
export function pushFeatureToBuffer(vertexBuffer, indexBuffer, geojsonFeature, opt_attributes) {
|
export function writePointFeatureInstructions(instructions, elementIndex, x, y, u0, v0, u1, v1, size, opacity, rotateWithView, color) {
|
||||||
if (!geojsonFeature.geometry) {
|
let i = elementIndex;
|
||||||
return;
|
instructions[i++] = x;
|
||||||
}
|
instructions[i++] = y;
|
||||||
switch (geojsonFeature.geometry.type) {
|
instructions[i++] = u0;
|
||||||
case 'Point':
|
instructions[i++] = v0;
|
||||||
pushPointFeatureToBuffer_(vertexBuffer, indexBuffer, geojsonFeature, opt_attributes);
|
instructions[i++] = u1;
|
||||||
return;
|
instructions[i++] = v1;
|
||||||
default:
|
instructions[i++] = size;
|
||||||
return;
|
instructions[i++] = opacity;
|
||||||
}
|
instructions[i++] = rotateWithView ? 1 : 0;
|
||||||
|
instructions[i++] = color[0];
|
||||||
|
instructions[i++] = color[1];
|
||||||
|
instructions[i++] = color[2];
|
||||||
|
instructions[i++] = color[3];
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tmpArray_ = [];
|
const tmpArray_ = [];
|
||||||
|
const bufferPositions_ = {vertexPosition: 0, indexPosition: 0};
|
||||||
|
|
||||||
|
export const POINT_INSTRUCTIONS_COUNT = 13;
|
||||||
|
export const POINT_VERTEX_STRIDE = 12;
|
||||||
|
|
||||||
|
function writePointVertex(buffer, pos, x, y, offsetX, offsetY, u, v, opacity, rotateWithView, red, green, blue, alpha) {
|
||||||
|
buffer[pos + 0] = x;
|
||||||
|
buffer[pos + 1] = y;
|
||||||
|
buffer[pos + 2] = offsetX;
|
||||||
|
buffer[pos + 3] = offsetY;
|
||||||
|
buffer[pos + 4] = u;
|
||||||
|
buffer[pos + 5] = v;
|
||||||
|
buffer[pos + 6] = opacity;
|
||||||
|
buffer[pos + 7] = rotateWithView;
|
||||||
|
buffer[pos + 8] = red;
|
||||||
|
buffer[pos + 9] = green;
|
||||||
|
buffer[pos + 10] = blue;
|
||||||
|
buffer[pos + 11] = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeCustomAttrs(buffer, pos, customAttrs) {
|
||||||
|
if (customAttrs.length) {
|
||||||
|
buffer.set(customAttrs, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object holding positions both in an index and a vertex buffer.
|
||||||
|
* @typedef {Object} BufferPositions
|
||||||
|
* @property {number} vertexPosition Position in the vertex buffer
|
||||||
|
* @property {number} indexPosition Position in the index buffer
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes a quad (two triangles) based on a point geometry
|
* Pushes a quad (two triangles) based on a point geometry
|
||||||
* @param {import("../../webgl/Buffer").default} vertexBuffer WebGL buffer
|
* @param {Float32Array} instructions Array of render instructions for points.
|
||||||
* @param {import("../../webgl/Buffer").default} indexBuffer WebGL buffer
|
* @param {number} elementIndex Index from which render instructions will be read.
|
||||||
* @param {import("../../format/GeoJSON").GeoJSONFeature} geojsonFeature Feature
|
* @param {Float32Array} vertexBuffer Buffer in the form of a typed array.
|
||||||
* @param {Array<string>} [opt_attributes] Custom attributes
|
* @param {Uint32Array} indexBuffer Buffer in the form of a typed array.
|
||||||
|
* @param {BufferPositions} [bufferPositions] Buffer write positions; if not specified, positions will be set at 0.
|
||||||
|
* @param {number} [count] Amount of render instructions that will be read. Default value is POINT_INSTRUCTIONS_COUNT
|
||||||
|
* but a higher value can be provided; all values beyond the default count will be put in the vertices buffer as
|
||||||
|
* is, thus allowing specifying custom attributes. Please note: this value should not vary inside the same buffer or
|
||||||
|
* rendering will break.
|
||||||
|
* @return {BufferPositions} New buffer positions where to write next
|
||||||
|
* @property {number} vertexPosition New position in the vertex buffer where future writes should start.
|
||||||
|
* @property {number} indexPosition New position in the index buffer where future writes should start.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function pushPointFeatureToBuffer_(vertexBuffer, indexBuffer, geojsonFeature, opt_attributes) {
|
export function writePointFeatureToBuffers(instructions, elementIndex, vertexBuffer, indexBuffer, bufferPositions, count) {
|
||||||
const stride = 12 + (opt_attributes !== undefined ? opt_attributes.length : 0);
|
const count_ = count > POINT_INSTRUCTIONS_COUNT ? count : POINT_INSTRUCTIONS_COUNT;
|
||||||
|
|
||||||
const x = geojsonFeature.geometry.coordinates[0];
|
const x = instructions[elementIndex + 0];
|
||||||
const y = geojsonFeature.geometry.coordinates[1];
|
const y = instructions[elementIndex + 1];
|
||||||
const u0 = geojsonFeature.properties.u0;
|
const u0 = instructions[elementIndex + 2];
|
||||||
const v0 = geojsonFeature.properties.v0;
|
const v0 = instructions[elementIndex + 3];
|
||||||
const u1 = geojsonFeature.properties.u1;
|
const u1 = instructions[elementIndex + 4];
|
||||||
const v1 = geojsonFeature.properties.v1;
|
const v1 = instructions[elementIndex + 5];
|
||||||
const size = geojsonFeature.properties.size;
|
const size = instructions[elementIndex + 6];
|
||||||
const opacity = geojsonFeature.properties.opacity;
|
const opacity = instructions[elementIndex + 7];
|
||||||
const rotateWithView = geojsonFeature.properties.rotateWithView;
|
const rotateWithView = instructions[elementIndex + 8];
|
||||||
const color = geojsonFeature.properties.color;
|
const red = instructions[elementIndex + 9];
|
||||||
const red = color[0];
|
const green = instructions[elementIndex + 10];
|
||||||
const green = color[1];
|
const blue = instructions[elementIndex + 11];
|
||||||
const blue = color[2];
|
const alpha = instructions[elementIndex + 12];
|
||||||
const alpha = color[3];
|
|
||||||
const baseIndex = vertexBuffer.getArray().length / stride;
|
// the default vertex buffer stride is 12, plus additional custom values if any
|
||||||
|
const baseStride = POINT_VERTEX_STRIDE;
|
||||||
|
const stride = baseStride + count_ - POINT_INSTRUCTIONS_COUNT;
|
||||||
|
|
||||||
// read custom numerical attributes on the feature
|
// read custom numerical attributes on the feature
|
||||||
const customAttributeValues = tmpArray_;
|
const customAttrs = tmpArray_;
|
||||||
customAttributeValues.length = opt_attributes ? opt_attributes.length : 0;
|
customAttrs.length = count_ - POINT_INSTRUCTIONS_COUNT;
|
||||||
for (let i = 0; i < customAttributeValues.length; i++) {
|
for (let i = 0; i < customAttrs.length; i++) {
|
||||||
customAttributeValues[i] = parseFloat(geojsonFeature.properties[opt_attributes[i]]) || 0;
|
customAttrs[i] = instructions[elementIndex + POINT_INSTRUCTIONS_COUNT + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let vPos = bufferPositions ? bufferPositions.vertexPosition : 0;
|
||||||
|
let iPos = bufferPositions ? bufferPositions.indexPosition : 0;
|
||||||
|
const baseIndex = vPos / stride;
|
||||||
|
|
||||||
// push vertices for each of the four quad corners (first standard then custom attributes)
|
// push vertices for each of the four quad corners (first standard then custom attributes)
|
||||||
vertexBuffer.getArray().push(x, y, -size / 2, -size / 2, u0, v0, opacity, rotateWithView, red, green, blue, alpha);
|
writePointVertex(vertexBuffer, vPos, x, y, -size / 2, -size / 2, u0, v0, opacity, rotateWithView, red, green, blue, alpha);
|
||||||
Array.prototype.push.apply(vertexBuffer.getArray(), customAttributeValues);
|
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
||||||
|
vPos += stride;
|
||||||
|
|
||||||
vertexBuffer.getArray().push(x, y, +size / 2, -size / 2, u1, v0, opacity, rotateWithView, red, green, blue, alpha);
|
writePointVertex(vertexBuffer, vPos, x, y, +size / 2, -size / 2, u1, v0, opacity, rotateWithView, red, green, blue, alpha);
|
||||||
Array.prototype.push.apply(vertexBuffer.getArray(), customAttributeValues);
|
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
||||||
|
vPos += stride;
|
||||||
|
|
||||||
vertexBuffer.getArray().push(x, y, +size / 2, +size / 2, u1, v1, opacity, rotateWithView, red, green, blue, alpha);
|
writePointVertex(vertexBuffer, vPos, x, y, +size / 2, +size / 2, u1, v1, opacity, rotateWithView, red, green, blue, alpha);
|
||||||
Array.prototype.push.apply(vertexBuffer.getArray(), customAttributeValues);
|
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
||||||
|
vPos += stride;
|
||||||
|
|
||||||
vertexBuffer.getArray().push(x, y, -size / 2, +size / 2, u0, v1, opacity, rotateWithView, red, green, blue, alpha);
|
writePointVertex(vertexBuffer, vPos, x, y, -size / 2, +size / 2, u0, v1, opacity, rotateWithView, red, green, blue, alpha);
|
||||||
Array.prototype.push.apply(vertexBuffer.getArray(), customAttributeValues);
|
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
||||||
|
vPos += stride;
|
||||||
|
|
||||||
indexBuffer.getArray().push(
|
indexBuffer[iPos++] = baseIndex; indexBuffer[iPos++] = baseIndex + 1; indexBuffer[iPos++] = baseIndex + 3;
|
||||||
baseIndex, baseIndex + 1, baseIndex + 3,
|
indexBuffer[iPos++] = baseIndex + 1; indexBuffer[iPos++] = baseIndex + 2; indexBuffer[iPos++] = baseIndex + 3;
|
||||||
baseIndex + 1, baseIndex + 2, baseIndex + 3
|
|
||||||
);
|
bufferPositions_.vertexPosition = vPos;
|
||||||
|
bufferPositions_.indexPosition = iPos;
|
||||||
|
|
||||||
|
return bufferPositions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/renderer/webgl/PointsLayer
|
* @module ol/renderer/webgl/PointsLayer
|
||||||
*/
|
*/
|
||||||
import WebGLArrayBuffer from '../../webgl/Buffer';
|
import WebGLArrayBuffer from '../../webgl/Buffer.js';
|
||||||
import {DYNAMIC_DRAW, ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, FLOAT} from '../../webgl';
|
import {DYNAMIC_DRAW, ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, FLOAT} from '../../webgl.js';
|
||||||
import {DefaultAttrib, DefaultUniform} from '../../webgl/Helper';
|
import {DefaultAttrib, DefaultUniform} from '../../webgl/Helper.js';
|
||||||
import GeometryType from '../../geom/GeometryType';
|
import GeometryType from '../../geom/GeometryType.js';
|
||||||
import WebGLLayerRenderer, {getBlankTexture, pushFeatureToBuffer} from './Layer';
|
import WebGLLayerRenderer, {
|
||||||
import GeoJSON from '../../format/GeoJSON';
|
getBlankTexture,
|
||||||
import {getUid} from '../../util';
|
POINT_INSTRUCTIONS_COUNT, POINT_VERTEX_STRIDE, WebGLWorkerMessageType,
|
||||||
import ViewHint from '../../ViewHint';
|
writePointFeatureInstructions
|
||||||
import {createEmpty, equals} from '../../extent';
|
} from './Layer.js';
|
||||||
|
import ViewHint from '../../ViewHint.js';
|
||||||
|
import {createEmpty, equals} from '../../extent.js';
|
||||||
import {
|
import {
|
||||||
create as createTransform,
|
create as createTransform,
|
||||||
makeInverse as makeInverseTransform,
|
makeInverse as makeInverseTransform,
|
||||||
multiply as multiplyTransform,
|
multiply as multiplyTransform,
|
||||||
apply as applyTransform
|
apply as applyTransform
|
||||||
} from '../../transform';
|
} from '../../transform.js';
|
||||||
|
import {create as createWebGLWorker} from '../../worker/webgl.js';
|
||||||
|
|
||||||
const VERTEX_SHADER = `
|
const VERTEX_SHADER = `
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
@@ -208,21 +211,21 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
|
|
||||||
this.sourceRevision_ = -1;
|
this.sourceRevision_ = -1;
|
||||||
|
|
||||||
this.verticesBuffer_ = new WebGLArrayBuffer([], DYNAMIC_DRAW);
|
this.verticesBuffer_ = new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW);
|
||||||
this.indicesBuffer_ = new WebGLArrayBuffer([], DYNAMIC_DRAW);
|
this.indicesBuffer_ = new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, DYNAMIC_DRAW);
|
||||||
|
|
||||||
this.program_ = this.helper_.getProgram(
|
this.program_ = this.helper.getProgram(
|
||||||
options.fragmentShader || FRAGMENT_SHADER,
|
options.fragmentShader || FRAGMENT_SHADER,
|
||||||
options.vertexShader || VERTEX_SHADER
|
options.vertexShader || VERTEX_SHADER
|
||||||
);
|
);
|
||||||
|
|
||||||
this.helper_.useProgram(this.program_);
|
this.helper.useProgram(this.program_);
|
||||||
|
|
||||||
this.sizeCallback_ = options.sizeCallback || function() {
|
this.sizeCallback_ = options.sizeCallback || function() {
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
this.coordCallback_ = options.coordCallback || function(feature, index) {
|
this.coordCallback_ = options.coordCallback || function(feature, index) {
|
||||||
const geom = /** @type {import("../../geom/Point").default} */ (feature.getGeometry());
|
const geom = feature.getGeometry();
|
||||||
return geom.getCoordinates()[index];
|
return geom.getCoordinates()[index];
|
||||||
};
|
};
|
||||||
this.opacityCallback_ = options.opacityCallback || function() {
|
this.opacityCallback_ = options.opacityCallback || function() {
|
||||||
@@ -241,14 +244,6 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.geojsonFormat_ = new GeoJSON();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Object<string, import("../../format/GeoJSON").GeoJSONFeature>}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.geojsonFeatureCache_ = {};
|
|
||||||
|
|
||||||
this.previousExtent_ = createEmpty();
|
this.previousExtent_ = createEmpty();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -272,6 +267,30 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.invertRenderTransform_ = createTransform();
|
this.invertRenderTransform_ = createTransform();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Float32Array}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.renderInstructions_ = new Float32Array(0);
|
||||||
|
|
||||||
|
this.worker_ = createWebGLWorker();
|
||||||
|
this.worker_.addEventListener('message', function(event) {
|
||||||
|
const received = event.data;
|
||||||
|
if (received.type === WebGLWorkerMessageType.GENERATE_BUFFERS) {
|
||||||
|
const projectionTransform = received.projectionTransform;
|
||||||
|
this.verticesBuffer_.fromArrayBuffer(received.vertexBuffer);
|
||||||
|
this.indicesBuffer_.fromArrayBuffer(received.indexBuffer);
|
||||||
|
this.helper.flushBufferData(this.verticesBuffer_);
|
||||||
|
this.helper.flushBufferData(this.indicesBuffer_);
|
||||||
|
|
||||||
|
// saves the projection transform for the current frame state
|
||||||
|
this.renderTransform_ = projectionTransform;
|
||||||
|
makeInverseTransform(this.invertRenderTransform_, this.renderTransform_);
|
||||||
|
|
||||||
|
this.renderInstructions_ = new Float32Array(event.data.renderInstructions);
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -284,11 +303,13 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
renderFrame(frameState) {
|
||||||
this.helper_.drawElements(0, this.indicesBuffer_.getArray().length);
|
const renderCount = this.indicesBuffer_.getArray() ? this.indicesBuffer_.getArray().length : 0;
|
||||||
this.helper_.finalizeDraw(frameState);
|
this.helper.drawElements(0, renderCount);
|
||||||
const canvas = this.helper_.getCanvas();
|
this.helper.finalizeDraw(frameState);
|
||||||
|
const canvas = this.helper.getCanvas();
|
||||||
|
|
||||||
|
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||||
const opacity = layerState.opacity;
|
const opacity = layerState.opacity;
|
||||||
if (opacity !== parseFloat(canvas.style.opacity)) {
|
if (opacity !== parseFloat(canvas.style.opacity)) {
|
||||||
canvas.style.opacity = opacity;
|
canvas.style.opacity = opacity;
|
||||||
@@ -305,8 +326,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
const vectorSource = vectorLayer.getSource();
|
const vectorSource = vectorLayer.getSource();
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
|
|
||||||
// TODO: get this from somewhere...
|
const stride = POINT_VERTEX_STRIDE;
|
||||||
const stride = 12;
|
|
||||||
|
|
||||||
// the source has changed: clear the feature cache & reload features
|
// the source has changed: clear the feature cache & reload features
|
||||||
const sourceChanged = this.sourceRevision_ < vectorSource.getRevision();
|
const sourceChanged = this.sourceRevision_ < vectorSource.getRevision();
|
||||||
@@ -327,22 +347,22 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// apply the current projection transform with the invert of the one used to fill buffers
|
// apply the current projection transform with the invert of the one used to fill buffers
|
||||||
this.helper_.makeProjectionTransform(frameState, this.currentTransform_);
|
this.helper.makeProjectionTransform(frameState, this.currentTransform_);
|
||||||
multiplyTransform(this.currentTransform_, this.invertRenderTransform_);
|
multiplyTransform(this.currentTransform_, this.invertRenderTransform_);
|
||||||
|
|
||||||
this.helper_.prepareDraw(frameState);
|
this.helper.prepareDraw(frameState);
|
||||||
|
|
||||||
// write new data
|
// write new data
|
||||||
this.helper_.bindBuffer(ARRAY_BUFFER, this.verticesBuffer_);
|
this.helper.bindBuffer(this.verticesBuffer_);
|
||||||
this.helper_.bindBuffer(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
this.helper.bindBuffer(this.indicesBuffer_);
|
||||||
|
|
||||||
const bytesPerFloat = Float32Array.BYTES_PER_ELEMENT;
|
const bytesPerFloat = Float32Array.BYTES_PER_ELEMENT;
|
||||||
this.helper_.enableAttributeArray(DefaultAttrib.POSITION, 2, FLOAT, bytesPerFloat * stride, 0);
|
this.helper.enableAttributeArray(DefaultAttrib.POSITION, 2, FLOAT, bytesPerFloat * stride, 0);
|
||||||
this.helper_.enableAttributeArray(DefaultAttrib.OFFSETS, 2, FLOAT, bytesPerFloat * stride, bytesPerFloat * 2);
|
this.helper.enableAttributeArray(DefaultAttrib.OFFSETS, 2, FLOAT, bytesPerFloat * stride, bytesPerFloat * 2);
|
||||||
this.helper_.enableAttributeArray(DefaultAttrib.TEX_COORD, 2, FLOAT, bytesPerFloat * stride, bytesPerFloat * 4);
|
this.helper.enableAttributeArray(DefaultAttrib.TEX_COORD, 2, FLOAT, bytesPerFloat * stride, bytesPerFloat * 4);
|
||||||
this.helper_.enableAttributeArray(DefaultAttrib.OPACITY, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 6);
|
this.helper.enableAttributeArray(DefaultAttrib.OPACITY, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 6);
|
||||||
this.helper_.enableAttributeArray(DefaultAttrib.ROTATE_WITH_VIEW, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 7);
|
this.helper.enableAttributeArray(DefaultAttrib.ROTATE_WITH_VIEW, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 7);
|
||||||
this.helper_.enableAttributeArray(DefaultAttrib.COLOR, 4, FLOAT, bytesPerFloat * stride, bytesPerFloat * 8);
|
this.helper.enableAttributeArray(DefaultAttrib.COLOR, 4, FLOAT, bytesPerFloat * stride, bytesPerFloat * 8);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -356,47 +376,59 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
||||||
const vectorSource = vectorLayer.getSource();
|
const vectorSource = vectorLayer.getSource();
|
||||||
|
|
||||||
this.verticesBuffer_.getArray().length = 0;
|
|
||||||
this.indicesBuffer_.getArray().length = 0;
|
|
||||||
|
|
||||||
// saves the projection transform for the current frame state
|
// saves the projection transform for the current frame state
|
||||||
this.helper_.makeProjectionTransform(frameState, this.renderTransform_);
|
const projectionTransform = createTransform();
|
||||||
makeInverseTransform(this.invertRenderTransform_, this.renderTransform_);
|
this.helper.makeProjectionTransform(frameState, projectionTransform);
|
||||||
|
|
||||||
|
const features = vectorSource.getFeatures();
|
||||||
|
const totalInstructionsCount = POINT_INSTRUCTIONS_COUNT * features.length;
|
||||||
|
if (!this.renderInstructions_ || this.renderInstructions_.length !== totalInstructionsCount) {
|
||||||
|
this.renderInstructions_ = new Float32Array(totalInstructionsCount);
|
||||||
|
}
|
||||||
|
|
||||||
// loop on features to fill the buffer
|
// loop on features to fill the buffer
|
||||||
const features = vectorSource.getFeatures();
|
|
||||||
let feature;
|
let feature;
|
||||||
|
const tmpCoords = [];
|
||||||
|
let elementIndex = 0;
|
||||||
for (let i = 0; i < features.length; i++) {
|
for (let i = 0; i < features.length; i++) {
|
||||||
feature = features[i];
|
feature = features[i];
|
||||||
if (!feature.getGeometry() || feature.getGeometry().getType() !== GeometryType.POINT) {
|
if (!feature.getGeometry() || feature.getGeometry().getType() !== GeometryType.POINT) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let geojsonFeature = this.geojsonFeatureCache_[getUid(feature)];
|
tmpCoords[0] = this.coordCallback_(feature, 0);
|
||||||
if (!geojsonFeature) {
|
tmpCoords[1] = this.coordCallback_(feature, 1);
|
||||||
geojsonFeature = this.geojsonFormat_.writeFeatureObject(feature);
|
applyTransform(projectionTransform, tmpCoords);
|
||||||
this.geojsonFeatureCache_[getUid(feature)] = geojsonFeature;
|
|
||||||
}
|
|
||||||
|
|
||||||
geojsonFeature.geometry.coordinates[0] = this.coordCallback_(feature, 0);
|
elementIndex = writePointFeatureInstructions(
|
||||||
geojsonFeature.geometry.coordinates[1] = this.coordCallback_(feature, 1);
|
this.renderInstructions_,
|
||||||
applyTransform(this.renderTransform_, geojsonFeature.geometry.coordinates);
|
elementIndex,
|
||||||
geojsonFeature.properties = geojsonFeature.properties || {};
|
tmpCoords[0],
|
||||||
geojsonFeature.properties.color = this.colorCallback_(feature, this.colorArray_);
|
tmpCoords[1],
|
||||||
geojsonFeature.properties.u0 = this.texCoordCallback_(feature, 0);
|
this.texCoordCallback_(feature, 0),
|
||||||
geojsonFeature.properties.v0 = this.texCoordCallback_(feature, 1);
|
this.texCoordCallback_(feature, 1),
|
||||||
geojsonFeature.properties.u1 = this.texCoordCallback_(feature, 2);
|
this.texCoordCallback_(feature, 2),
|
||||||
geojsonFeature.properties.v1 = this.texCoordCallback_(feature, 3);
|
this.texCoordCallback_(feature, 3),
|
||||||
geojsonFeature.properties.size = this.sizeCallback_(feature);
|
this.sizeCallback_(feature),
|
||||||
geojsonFeature.properties.opacity = this.opacityCallback_(feature);
|
this.opacityCallback_(feature),
|
||||||
geojsonFeature.properties.rotateWithView = this.rotateWithViewCallback_(feature) ? 1 : 0;
|
this.rotateWithViewCallback_(feature),
|
||||||
|
this.colorCallback_(feature, this.colorArray_)
|
||||||
pushFeatureToBuffer(this.verticesBuffer_, this.indicesBuffer_, geojsonFeature);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.helper_.flushBufferData(ARRAY_BUFFER, this.verticesBuffer_);
|
/** @type import('./Layer').WebGLWorkerGenerateBuffersMessage */
|
||||||
this.helper_.flushBufferData(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
const message = {
|
||||||
|
type: WebGLWorkerMessageType.GENERATE_BUFFERS,
|
||||||
|
renderInstructions: this.renderInstructions_.buffer
|
||||||
|
};
|
||||||
|
// additional properties will be sent back as-is by the worker
|
||||||
|
message['projectionTransform'] = projectionTransform;
|
||||||
|
|
||||||
|
this.worker_.postMessage(message, [this.renderInstructions_.buffer]);
|
||||||
|
this.renderInstructions_ = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WebGLPointsLayerRenderer;
|
export default WebGLPointsLayerRenderer;
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
* @module ol/resolutionconstraint
|
* @module ol/resolutionconstraint
|
||||||
*/
|
*/
|
||||||
import {linearFindNearest} from './array.js';
|
import {linearFindNearest} from './array.js';
|
||||||
import {getHeight, getWidth} from './extent';
|
import {getHeight, getWidth} from './extent.js';
|
||||||
import {clamp} from './math';
|
import {clamp} from './math.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class Cluster extends VectorSource {
|
|||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
this.geometryFunction = options.geometryFunction || function(feature) {
|
this.geometryFunction = options.geometryFunction || function(feature) {
|
||||||
const geometry = /** @type {Point} */ (feature.getGeometry());
|
const geometry = feature.getGeometry();
|
||||||
assert(geometry.getType() == GeometryType.POINT,
|
assert(geometry.getType() == GeometryType.POINT,
|
||||||
10); // The default `geometryFunction` can only handle `Point` geometries
|
10); // The default `geometryFunction` can only handle `Point` geometries
|
||||||
return geometry;
|
return geometry;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import TileImage from './TileImage.js';
|
|||||||
* for version 1, 'default' for versions 2 and 3.
|
* for version 1, 'default' for versions 2 and 3.
|
||||||
* @property {number} [reprojectionErrorThreshold=0.5] Maximum allowed reprojection error (in pixels).
|
* @property {number} [reprojectionErrorThreshold=0.5] Maximum allowed reprojection error (in pixels).
|
||||||
* Higher values can increase reprojection performance, but decrease precision.
|
* Higher values can increase reprojection performance, but decrease precision.
|
||||||
|
* @property {Array<number>} [resolutions] Supported resolutions as given in IIIF 'scaleFactors'
|
||||||
* @property {import("../size.js").Size} size Size of the image [width, height].
|
* @property {import("../size.js").Size} size Size of the image [width, height].
|
||||||
* @property {import("../size.js").Size[]} [sizes] Supported scaled image sizes.
|
* @property {import("../size.js").Size[]} [sizes] Supported scaled image sizes.
|
||||||
* Content of the IIIF info.json 'sizes' property, but as array of Size objects.
|
* Content of the IIIF info.json 'sizes' property, but as array of Size objects.
|
||||||
@@ -37,7 +38,7 @@ import TileImage from './TileImage.js';
|
|||||||
* are supported), the default tilesize is 256.
|
* are supported), the default tilesize is 256.
|
||||||
* @property {number} [transition]
|
* @property {number} [transition]
|
||||||
* @property {string} [url] Base URL of the IIIF Image service.
|
* @property {string} [url] Base URL of the IIIF Image service.
|
||||||
* This should be the same as the IIIF Image @id.
|
* This should be the same as the IIIF Image ID.
|
||||||
* @property {Versions} [version=Versions.VERSION2] Service's IIIF Image API version.
|
* @property {Versions} [version=Versions.VERSION2] Service's IIIF Image API version.
|
||||||
* @property {number} [zDirection] Indicate which resolution should be used
|
* @property {number} [zDirection] Indicate which resolution should be used
|
||||||
* by a renderer if the views resolution does not match any resolution of the tile source.
|
* by a renderer if the views resolution does not match any resolution of the tile source.
|
||||||
@@ -63,6 +64,9 @@ class IIIF extends TileImage {
|
|||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Partial<Options>} options
|
||||||
|
*/
|
||||||
const options = opt_options || {};
|
const options = opt_options || {};
|
||||||
|
|
||||||
let baseUrl = options.url || '';
|
let baseUrl = options.url || '';
|
||||||
@@ -75,6 +79,7 @@ class IIIF extends TileImage {
|
|||||||
const width = size[0];
|
const width = size[0];
|
||||||
const height = size[1];
|
const height = size[1];
|
||||||
const tileSize = options.tileSize;
|
const tileSize = options.tileSize;
|
||||||
|
const tilePixelRatio = options.tilePixelRatio || 1;
|
||||||
const format = options.format || 'jpg';
|
const format = options.format || 'jpg';
|
||||||
const quality = options.quality || (options.version == Versions.VERSION1 ? 'native' : 'default');
|
const quality = options.quality || (options.version == Versions.VERSION1 ? 'native' : 'default');
|
||||||
let resolutions = options.resolutions || [];
|
let resolutions = options.resolutions || [];
|
||||||
@@ -82,7 +87,7 @@ class IIIF extends TileImage {
|
|||||||
const extent = options.extent || [0, -height, width, 0];
|
const extent = options.extent || [0, -height, width, 0];
|
||||||
|
|
||||||
const supportsListedSizes = sizes != undefined && Array.isArray(sizes) && sizes.length > 0;
|
const supportsListedSizes = sizes != undefined && Array.isArray(sizes) && sizes.length > 0;
|
||||||
const supportsListedTiles = tileSize != undefined && (Number.isInteger(tileSize) && tileSize > 0 || Array.isArray(tileSize) && tileSize.length > 0);
|
const supportsListedTiles = tileSize != undefined && (typeof tileSize === 'number' && Number.isInteger(tileSize) && tileSize > 0 || Array.isArray(tileSize) && tileSize.length > 0);
|
||||||
const supportsArbitraryTiling = supports != undefined && Array.isArray(supports) &&
|
const supportsArbitraryTiling = supports != undefined && Array.isArray(supports) &&
|
||||||
(supports.includes('regionByPx') || supports.includes('regionByPct')) &&
|
(supports.includes('regionByPx') || supports.includes('regionByPct')) &&
|
||||||
(supports.includes('sizeByWh') || supports.includes('sizeByH') ||
|
(supports.includes('sizeByWh') || supports.includes('sizeByH') ||
|
||||||
@@ -98,7 +103,7 @@ class IIIF extends TileImage {
|
|||||||
|
|
||||||
if (supportsListedTiles || supportsArbitraryTiling) {
|
if (supportsListedTiles || supportsArbitraryTiling) {
|
||||||
if (tileSize != undefined) {
|
if (tileSize != undefined) {
|
||||||
if (Number.isInteger(tileSize) && tileSize > 0) {
|
if (typeof tileSize === 'number' && Number.isInteger(tileSize) && tileSize > 0) {
|
||||||
tileWidth = tileSize;
|
tileWidth = tileSize;
|
||||||
tileHeight = tileSize;
|
tileHeight = tileSize;
|
||||||
} else if (Array.isArray(tileSize) && tileSize.length > 0) {
|
} else if (Array.isArray(tileSize) && tileSize.length > 0) {
|
||||||
@@ -130,7 +135,7 @@ class IIIF extends TileImage {
|
|||||||
resolutions.push(Math.pow(2, i));
|
resolutions.push(Math.pow(2, i));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const maxScaleFactor = Math.max([...resolutions]);
|
const maxScaleFactor = Math.max(...resolutions);
|
||||||
// TODO maxScaleFactor might not be a power to 2
|
// TODO maxScaleFactor might not be a power to 2
|
||||||
maxZoom = Math.round(Math.log(maxScaleFactor) / Math.LN2);
|
maxZoom = Math.round(Math.log(maxScaleFactor) / Math.LN2);
|
||||||
}
|
}
|
||||||
@@ -260,7 +265,7 @@ class IIIF extends TileImage {
|
|||||||
return baseUrl + regionParam + '/' + sizeParam + '/0/' + quality + '.' + format;
|
return baseUrl + regionParam + '/' + sizeParam + '/0/' + quality + '.' + format;
|
||||||
};
|
};
|
||||||
|
|
||||||
const IiifTileClass = CustomTile.bind(null, tileGrid);
|
const IiifTileClass = CustomTile.bind(null, tilePixelRatio, tileGrid);
|
||||||
|
|
||||||
super({
|
super({
|
||||||
attributions: options.attributions,
|
attributions: options.attributions,
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class ImageArcGISRest extends ImageSource {
|
|||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
|
|
||||||
const options = opt_options || /** @type {Options} */ ({});
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
super({
|
super({
|
||||||
attributions: options.attributions,
|
attributions: options.attributions,
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class ImageCanvasSource extends ImageSource {
|
|||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
|
|
||||||
const options = opt_options || /** @type {Options} */ ({});
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
super({
|
super({
|
||||||
attributions: options.attributions,
|
attributions: options.attributions,
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class ImageWMS extends ImageSource {
|
|||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
|
|
||||||
const options = opt_options || /** @type {Options} */ ({});
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
super({
|
super({
|
||||||
attributions: options.attributions,
|
attributions: options.attributions,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {createCanvasContext2D} from '../dom.js';
|
|||||||
import {listen} from '../events.js';
|
import {listen} from '../events.js';
|
||||||
import Event from '../events/Event.js';
|
import Event from '../events/Event.js';
|
||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import {Processor} from 'pixelworks/lib/index';
|
import {Processor} from 'pixelworks/lib/index.js';
|
||||||
import {equals, getCenter, getHeight, getWidth} from '../extent.js';
|
import {equals, getCenter, getHeight, getWidth} from '../extent.js';
|
||||||
import ImageLayer from '../layer/Image.js';
|
import ImageLayer from '../layer/Image.js';
|
||||||
import TileLayer from '../layer/Tile.js';
|
import TileLayer from '../layer/Tile.js';
|
||||||
@@ -214,6 +214,7 @@ class RasterSource extends ImageSource {
|
|||||||
extent: null,
|
extent: null,
|
||||||
focus: null,
|
focus: null,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
layerIndex: 0,
|
||||||
layerStatesArray: getLayerStatesArray(this.layers_),
|
layerStatesArray: getLayerStatesArray(this.layers_),
|
||||||
pixelRatio: 1,
|
pixelRatio: 1,
|
||||||
pixelToCoordinateTransform: createTransform(),
|
pixelToCoordinateTransform: createTransform(),
|
||||||
@@ -358,7 +359,8 @@ class RasterSource extends ImageSource {
|
|||||||
const len = this.layers_.length;
|
const len = this.layers_.length;
|
||||||
const imageDatas = new Array(len);
|
const imageDatas = new Array(len);
|
||||||
for (let i = 0; i < len; ++i) {
|
for (let i = 0; i < len; ++i) {
|
||||||
const imageData = getImageData(this.layers_[i], frameState, frameState.layerStatesArray[i]);
|
frameState.layerIndex = i;
|
||||||
|
const imageData = getImageData(this.layers_[i], frameState);
|
||||||
if (imageData) {
|
if (imageData) {
|
||||||
imageDatas[i] = imageData;
|
imageDatas[i] = imageData;
|
||||||
} else {
|
} else {
|
||||||
@@ -430,21 +432,24 @@ let sharedContext = null;
|
|||||||
* Get image data from a layer.
|
* Get image data from a layer.
|
||||||
* @param {import("../layer/Layer.js").default} layer Layer to render.
|
* @param {import("../layer/Layer.js").default} layer Layer to render.
|
||||||
* @param {import("../PluggableMap.js").FrameState} frameState The frame state.
|
* @param {import("../PluggableMap.js").FrameState} frameState The frame state.
|
||||||
* @param {import("../layer/Layer.js").State} layerState The layer state.
|
|
||||||
* @return {ImageData} The image data.
|
* @return {ImageData} The image data.
|
||||||
*/
|
*/
|
||||||
function getImageData(layer, frameState, layerState) {
|
function getImageData(layer, frameState) {
|
||||||
const renderer = layer.getRenderer();
|
const renderer = layer.getRenderer();
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
throw new Error('Unsupported layer type: ' + layer);
|
throw new Error('Unsupported layer type: ' + layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!renderer.prepareFrame(frameState, layerState)) {
|
if (!renderer.prepareFrame(frameState)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const width = frameState.size[0];
|
const width = frameState.size[0];
|
||||||
const height = frameState.size[1];
|
const height = frameState.size[1];
|
||||||
const element = renderer.renderFrame(frameState, layerState);
|
const container = renderer.renderFrame(frameState, null);
|
||||||
|
let element;
|
||||||
|
if (container) {
|
||||||
|
element = container.firstElementChild;
|
||||||
|
}
|
||||||
if (!(element instanceof HTMLCanvasElement)) {
|
if (!(element instanceof HTMLCanvasElement)) {
|
||||||
throw new Error('Unsupported rendered element: ' + element);
|
throw new Error('Unsupported rendered element: ' + element);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class TileSource extends Source {
|
|||||||
if (tileGrid) {
|
if (tileGrid) {
|
||||||
toSize(tileGrid.getTileSize(tileGrid.getMinZoom()), tileSize);
|
toSize(tileGrid.getTileSize(tileGrid.getMinZoom()), tileSize);
|
||||||
}
|
}
|
||||||
const canUseScreen = 'screen' in self;
|
const canUseScreen = typeof screen !== 'undefined';
|
||||||
const width = canUseScreen ? (screen.availWidth || screen.width) : 1920;
|
const width = canUseScreen ? (screen.availWidth || screen.width) : 1920;
|
||||||
const height = canUseScreen ? (screen.availHeight || screen.height) : 1080;
|
const height = canUseScreen ? (screen.availHeight || screen.height) : 1080;
|
||||||
cacheSize = 4 * Math.ceil(width / tileSize[0]) * Math.ceil(height / tileSize[1]);
|
cacheSize = 4 * Math.ceil(width / tileSize[0]) * Math.ceil(height / tileSize[1]);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class TileArcGISRest extends TileImage {
|
|||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
|
|
||||||
const options = opt_options || /** @type {Options} */ ({});
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
super({
|
super({
|
||||||
attributions: options.attributions,
|
attributions: options.attributions,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class TileWMS extends TileImage {
|
|||||||
*/
|
*/
|
||||||
constructor(opt_options) {
|
constructor(opt_options) {
|
||||||
|
|
||||||
const options = opt_options || /** @type {Options} */ ({});
|
const options = opt_options ? opt_options : {};
|
||||||
|
|
||||||
const params = options.params || {};
|
const params = options.params || {};
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user