Compare commits

...

63 Commits

Author SHA1 Message Date
Tim Schaub
bd8a454df1 Updates for the 6.11.0 release 2022-01-08 16:17:52 -07:00
Andreas Hocevar
6de9c828ab Merge pull request #13195 from ahocevar/box-selection
Use getFeaturesInExtent
2022-01-08 21:53:16 +01:00
Tim Schaub
f13838470e Merge pull request #13200 from mike-000/sea-level
Use interpolate option in Sea Level example
2022-01-08 08:43:24 -07:00
Tim Schaub
a9210db25c Merge pull request #13201 from mike-000/typo
Fix typo in example description
2022-01-08 08:38:31 -07:00
Tim Schaub
85d5e5dfad Merge pull request #13177 from tschaub/ecoregions
Use ecoregions data
2022-01-08 08:32:46 -07:00
Tim Schaub
0e93a3118c Merge pull request #13198 from tschaub/no-color
Avoid failure if existing target has no background color
2022-01-08 08:31:47 -07:00
mike-000
449cfd15b1 Fix typo 2022-01-08 14:16:29 +00:00
mike-000
07ebc48516 Replace imageSmoothingEnabled with interpolate 2022-01-08 14:08:42 +00:00
Tim Schaub
a963ab7d1d Avoid failure if existing target has no background color 2022-01-07 15:05:31 -07:00
Tim Schaub
39b2de829e Remove countries from examples data 2022-01-07 13:58:31 -07:00
Tim Schaub
38d4a8f13f Update Sphere Mollweide example 2022-01-07 13:55:34 -07:00
Tim Schaub
197dd2e06d Update translate features example 2022-01-07 13:53:01 -07:00
Tim Schaub
4ce7f77749 Update label decluttering example 2022-01-07 13:50:43 -07:00
Tim Schaub
7f0b6b3f7a Update multi-select example 2022-01-07 13:47:08 -07:00
Tim Schaub
a64102f097 Update modify features example 2022-01-07 13:39:46 -07:00
Tim Schaub
22609f7a7d Update geographic editing example 2022-01-07 13:37:05 -07:00
Tim Schaub
35e1d29d6b Update canvas gradient example 2022-01-07 13:14:52 -07:00
Tim Schaub
eed400ca1c Update select on hover example 2022-01-07 13:00:35 -07:00
Tim Schaub
73f54c1e6c Update vector image layer example 2022-01-07 12:51:28 -07:00
Tim Schaub
71af0eee43 Update select features example 2022-01-07 12:45:27 -07:00
Tim Schaub
43e06a7d57 Update MapboxGL layer example 2022-01-07 12:45:27 -07:00
Tim Schaub
73f36adaaf Update hit detection example 2022-01-07 12:45:27 -07:00
Tim Schaub
2d96c92ac8 Update geojson-vt example 2022-01-07 12:45:27 -07:00
Tim Schaub
9024867893 Update extent interaction example 2022-01-07 12:45:27 -07:00
Tim Schaub
9aa3c00879 Update export map example 2022-01-07 12:45:27 -07:00
Tim Schaub
faddbf098b Update box selection example 2022-01-07 12:45:26 -07:00
Tim Schaub
539eae1398 Update vector layer example 2022-01-07 12:45:26 -07:00
Tim Schaub
e0aa161302 Merge pull request #13186 from mike-000/WebGL-getDataAtPixel
Add getDataAtPixel() method for WebGL
2022-01-07 12:05:10 -07:00
mike-000
9c955bc86d Update forEachLayerAtPixel description 2022-01-07 18:25:20 +00:00
Tim Schaub
ad7b95667f Merge pull request #13196 from bradh/contrast_typo_2022-01-07
typo fix for cog-stretch example
2022-01-06 21:22:47 -07:00
Brad
fc535ab4d0 typo fix for cog-stretch example 2022-01-07 13:29:51 +11:00
Andreas Hocevar
c785c2813b Filter for actual geometry intersection 2022-01-06 21:10:26 +01:00
Andreas Hocevar
a2388756f2 Use getFeaturesInExtent 2022-01-06 20:07:34 +01:00
Andreas Hocevar
69c02aa6c8 Merge pull request #13190 from ahocevar/basevector-type
Fix base vector layer template generics
2022-01-05 16:11:58 +01:00
Andreas Hocevar
f6496aa409 Fix base vector layer template generics 2022-01-04 18:04:53 +01:00
Tim Schaub
2893b78302 Merge pull request #13182 from openlayers/dependabot/npm_and_yarn/eslint-8.6.0
Bump eslint from 8.5.0 to 8.6.0
2022-01-03 07:34:36 -07:00
Tim Schaub
9553396c31 Merge pull request #13184 from openlayers/dependabot/npm_and_yarn/rollup/plugin-node-resolve-13.1.2
Bump @rollup/plugin-node-resolve from 13.1.1 to 13.1.2
2022-01-03 07:33:01 -07:00
Tim Schaub
13101e3ab4 Merge pull request #13183 from openlayers/dependabot/npm_and_yarn/babel/core-7.16.7
Bump @babel/core from 7.16.5 to 7.16.7
2022-01-03 07:32:23 -07:00
Tim Schaub
2dd4f71b51 Merge pull request #13185 from openlayers/dependabot/npm_and_yarn/webpack-dev-server-4.7.2
Bump webpack-dev-server from 4.7.1 to 4.7.2
2022-01-03 07:31:49 -07:00
Tim Schaub
9db298987b Merge pull request #13181 from openlayers/dependabot/npm_and_yarn/babel/preset-env-7.16.7
Bump @babel/preset-env from 7.16.5 to 7.16.7
2022-01-03 07:30:27 -07:00
mike-000
766a336650 Add getDataAtPixel() method for WebGL 2022-01-03 13:00:56 +00:00
mike-000
d85be48da2 Test getDataAtPixel() method for WebGL 2022-01-03 13:00:55 +00:00
dependabot[bot]
ae629301e9 Bump webpack-dev-server from 4.7.1 to 4.7.2
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.7.1 to 4.7.2.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.7.1...v4.7.2)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 10:02:05 +00:00
dependabot[bot]
7639eff49a Bump @rollup/plugin-node-resolve from 13.1.1 to 13.1.2
Bumps [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/HEAD/packages/node-resolve) from 13.1.1 to 13.1.2.
- [Release notes](https://github.com/rollup/plugins/releases)
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/node-resolve/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/node-resolve-v13.1.2/packages/node-resolve)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-node-resolve"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 10:01:52 +00:00
dependabot[bot]
654929bae2 Bump @babel/core from 7.16.5 to 7.16.7
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.16.5 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 10:01:42 +00:00
dependabot[bot]
7dd45c66ed Bump eslint from 8.5.0 to 8.6.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.5.0 to 8.6.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.5.0...v8.6.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 10:01:25 +00:00
dependabot[bot]
1193476442 Bump @babel/preset-env from 7.16.5 to 7.16.7
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.5 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 10:01:10 +00:00
Andreas Hocevar
83d3bbf0ab Merge pull request #13180 from ahocevar/geotiff-es
Always use ES modules from geotiff.js
2022-01-02 11:02:43 +01:00
Andreas Hocevar
665da47437 Merge pull request #13179 from ahocevar/blob-or-buffer
Use Buffer and data uri when Blob is not available
2022-01-02 11:01:40 +01:00
Andreas Hocevar
00b7bc60ac Use Buffer and data uri when Blob is not available 2022-01-01 22:47:22 +01:00
Andreas Hocevar
93abfe78a3 Always use ES modules from geotiff.js 2022-01-01 22:41:11 +01:00
Tim Schaub
3506176328 Merge pull request #13178 from tschaub/layer-background
Use background property for vector layers
2022-01-01 11:56:29 -07:00
Tim Schaub
275ecca473 Use background property for vector layers 2022-01-01 11:51:06 -07:00
MoonE
9b0878a94a Merge pull request #13175 from MoonE/nodejs-12-compatibility
Allow nodejs 12 to build the examples again
2021-12-31 23:00:24 +01:00
Tim Schaub
c500fdc4ad Merge pull request #13176 from mike-000/datatile-attributions
Add `attributions` and `attributionsCollapsible` options to `ol/source/DataTile`
2021-12-31 09:24:09 -07:00
mike-000
b1b09619bb Add attributions/attributionsCollapsible options 2021-12-31 14:20:33 +00:00
Maximilian Krög
d63a7ae497 Allow nodejs 12 to build the examples again 2021-12-31 11:06:43 +01:00
Andreas Hocevar
bc2969fd78 Merge pull request #13171 from mike-000/4326-scale-bar
Correct scale bar in EPSG:4326
2021-12-30 17:51:18 +01:00
mike-000
37f117b782 Test scalebar text in EPSG:4326 2021-12-29 23:55:50 +00:00
mike-000
c8a7a83e1f correct getScaleForResolution() 2021-12-29 22:43:53 +00:00
mike-000
e8b4011cf4 new example 2021-12-29 22:43:53 +00:00
Tim Schaub
d6d4b878c2 Merge pull request #13168 from openlayers/release-v6.10.0
Release 6.10.0
2021-12-28 15:59:06 -07:00
Tim Schaub
6570416343 Develop on 6.10.1-dev 2021-12-28 15:52:47 -07:00
55 changed files with 1848 additions and 1713 deletions

View File

@@ -1,5 +1,9 @@
## Upgrade notes
### v6.11.0
No special changes are required when upgrading to the 6.11.0 release.
### v6.10.0
#### New `interpolate` option for sources

32
changelog/v6.11.0.md Normal file
View File

@@ -0,0 +1,32 @@
# 6.11.0
This release follows up on the 6.10 release with a fix for Mapbox vector layers rendered over other layers. A handful of other fixes and features are included. See below for more detail.
* [#13195](https://github.com/openlayers/openlayers/pull/13195) - Use getFeaturesInExtent ([@ahocevar](https://github.com/ahocevar))
* [#13200](https://github.com/openlayers/openlayers/pull/13200) - Use interpolate option in Sea Level example ([@mike-000](https://github.com/mike-000))
* [#13201](https://github.com/openlayers/openlayers/pull/13201) - Fix typo in example description ([@mike-000](https://github.com/mike-000))
* [#13177](https://github.com/openlayers/openlayers/pull/13177) - Use ecoregions data ([@tschaub](https://github.com/tschaub))
* [#13198](https://github.com/openlayers/openlayers/pull/13198) - Avoid failure if existing target has no background color ([@tschaub](https://github.com/tschaub))
* [#13186](https://github.com/openlayers/openlayers/pull/13186) - Add getDataAtPixel() method for WebGL ([@mike-000](https://github.com/mike-000))
* [#13196](https://github.com/openlayers/openlayers/pull/13196) - typo fix for cog-stretch example ([@bradh](https://github.com/bradh))
* [#13190](https://github.com/openlayers/openlayers/pull/13190) - Fix base vector layer template generics ([@ahocevar](https://github.com/ahocevar))
* [#13180](https://github.com/openlayers/openlayers/pull/13180) - Always use ES modules from geotiff.js ([@ahocevar](https://github.com/ahocevar))
* [#13179](https://github.com/openlayers/openlayers/pull/13179) - Use Buffer and data uri when Blob is not available ([@ahocevar](https://github.com/ahocevar))
* [#13178](https://github.com/openlayers/openlayers/pull/13178) - Use background property for vector layers ([@tschaub](https://github.com/tschaub))
* [#13175](https://github.com/openlayers/openlayers/pull/13175) - Allow nodejs 12 to build the examples again ([@MoonE](https://github.com/MoonE))
* [#13176](https://github.com/openlayers/openlayers/pull/13176) - Add `attributions` and `attributionsCollapsible` options to `ol/source/DataTile` ([@mike-000](https://github.com/mike-000))
* [#13171](https://github.com/openlayers/openlayers/pull/13171) - Correct scale bar in EPSG:4326 ([@mike-000](https://github.com/mike-000))
* [#13168](https://github.com/openlayers/openlayers/pull/13168) - Release 6.10.0 ([@openlayers](https://github.com/openlayers))
<details>
<summary>Dependency Updates</summary>
* [#13182](https://github.com/openlayers/openlayers/pull/13182) - Bump eslint from 8.5.0 to 8.6.0 ([@openlayers](https://github.com/openlayers))
* [#13184](https://github.com/openlayers/openlayers/pull/13184) - Bump @rollup/plugin-node-resolve from 13.1.1 to 13.1.2 ([@openlayers](https://github.com/openlayers))
* [#13183](https://github.com/openlayers/openlayers/pull/13183) - Bump @babel/core from 7.16.5 to 7.16.7 ([@openlayers](https://github.com/openlayers))
* [#13185](https://github.com/openlayers/openlayers/pull/13185) - Bump webpack-dev-server from 4.7.1 to 4.7.2 ([@openlayers](https://github.com/openlayers))
* [#13181](https://github.com/openlayers/openlayers/pull/13181) - Bump @babel/preset-env from 7.16.5 to 7.16.7 ([@openlayers](https://github.com/openlayers))
</details>

View File

@@ -1,4 +0,0 @@
.ol-dragbox {
background-color: rgba(255,255,255,0.4);
border-color: rgba(100,150,0,1);
}

View File

@@ -9,4 +9,4 @@ docs: >
tags: "DragBox, feature, selection, box"
---
<div id="map" class="map"></div>
<div id="info">No countries selected</div>
<div>Selected regions: <span id="info">None</span></div>

View File

@@ -1,23 +1,33 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {DragBox, Select} from '../src/ol/interaction.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {Fill, Stroke, Style} from '../src/ol/style.js';
import {platformModifierKeyOnly} from '../src/ol/events/condition.js';
const vectorSource = new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
});
const style = new Style({
fill: new Fill({
color: '#eeeeee',
}),
});
const map = new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
new VectorLayer({
source: vectorSource,
background: '#1a2b39',
style: function (feature) {
const color = feature.get('COLOR_BIO') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
}),
],
target: 'map',
@@ -28,8 +38,24 @@ const map = new Map({
}),
});
const selectedStyle = new Style({
fill: new Fill({
color: 'rgba(255, 255, 255, 0.6)',
}),
stroke: new Stroke({
color: 'rgba(255, 255, 255, 0.7)',
width: 2,
}),
});
// a normal select interaction to handle click
const select = new Select();
const select = new Select({
style: function (feature) {
const color = feature.get('COLOR_BIO') || '#eeeeee';
selectedStyle.getFill().setColor(color);
return selectedStyle;
},
});
map.addInteraction(select);
const selectedFeatures = select.getFeatures();
@@ -42,6 +68,11 @@ const dragBox = new DragBox({
map.addInteraction(dragBox);
dragBox.on('boxend', function () {
const extent = dragBox.getGeometry().getExtent();
const boxFeatures = vectorSource
.getFeaturesInExtent(extent)
.filter((feature) => feature.getGeometry().intersectsExtent(extent));
// features that intersect the box geometry are added to the
// collection of selected features
@@ -50,11 +81,6 @@ dragBox.on('boxend', function () {
// be added directly to the collection
const rotation = map.getView().getRotation();
const oblique = rotation % (Math.PI / 2) !== 0;
const candidateFeatures = oblique ? [] : selectedFeatures;
const extent = dragBox.getGeometry().getExtent();
vectorSource.forEachFeatureIntersectingExtent(extent, function (feature) {
candidateFeatures.push(feature);
});
// when the view is obliquely rotated the box extent will
// exceed its geometry so both the box and the candidate
@@ -66,13 +92,15 @@ dragBox.on('boxend', function () {
const geometry = dragBox.getGeometry().clone();
geometry.rotate(-rotation, anchor);
const extent = geometry.getExtent();
candidateFeatures.forEach(function (feature) {
boxFeatures.forEach(function (feature) {
const geometry = feature.getGeometry().clone();
geometry.rotate(-rotation, anchor);
if (geometry.intersectsExtent(extent)) {
selectedFeatures.push(feature);
}
});
} else {
selectedFeatures.extend(boxFeatures);
}
});
@@ -85,11 +113,11 @@ const infoBox = document.getElementById('info');
selectedFeatures.on(['add', 'remove'], function () {
const names = selectedFeatures.getArray().map(function (feature) {
return feature.get('name');
return feature.get('ECO_NAME');
});
if (names.length > 0) {
infoBox.innerHTML = names.join(', ');
} else {
infoBox.innerHTML = 'No countries selected';
infoBox.innerHTML = 'None';
}
});

File diff suppressed because one or more lines are too long

View File

@@ -1,13 +1,11 @@
---
layout: example.html
title: Styling feature with CanvasGradient or CanvasPattern
shortdesc: Example showing the countries vector layer styled with patterns and gradients.
shortdesc: Example showing a vector layer styled with a gradient.
docs: >
This example creates a [`CanvasPattern`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern)
and a [`CanvasGradient`](https://developer.mozilla.org/en/docs/Web/API/CanvasGradient). The countries are loaded from
a GeoJSON file. A style function determines for each country whether to use a fill with the
CanvasGradient (rainbow colors) or a CanvasPattern (repeating stacked circles). **Note**: For seamless repeat patterns,
image width and height of the pattern image must be a factor of two (2, 4, 8, ..., 512).
This example creates a [`CanvasGradient`](https://developer.mozilla.org/en/docs/Web/API/CanvasGradient).
The vector data is loaded from a file and features are filled with the gradient.
The same technique can be used with a [`CanvasPattern`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern).
tags: "canvas, gradient, pattern, style"
---
<div id="map" class="map"></div>

View File

@@ -1,4 +1,4 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import KML from '../src/ol/format/KML.js';
import Map from '../src/ol/Map.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
@@ -7,84 +7,42 @@ import {DEVICE_PIXEL_RATIO} from '../src/ol/has.js';
import {Fill, Stroke, Style} from '../src/ol/style.js';
import {fromLonLat} from '../src/ol/proj.js';
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
// Gradient and pattern are in canvas pixel space, so we adjust for the
// renderer's pixel ratio
const pixelRatio = DEVICE_PIXEL_RATIO;
// Generate a rainbow gradient
const gradient = (function () {
const grad = context.createLinearGradient(0, 0, 512 * pixelRatio, 0);
grad.addColorStop(0, 'red');
grad.addColorStop(1 / 6, 'orange');
grad.addColorStop(2 / 6, 'yellow');
grad.addColorStop(3 / 6, 'green');
grad.addColorStop(4 / 6, 'aqua');
grad.addColorStop(5 / 6, 'blue');
grad.addColorStop(1, 'purple');
return grad;
})();
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const gradient = context.createLinearGradient(0, 0, 1024 * pixelRatio, 0);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1 / 6, 'orange');
gradient.addColorStop(2 / 6, 'yellow');
gradient.addColorStop(3 / 6, 'green');
gradient.addColorStop(4 / 6, 'aqua');
gradient.addColorStop(5 / 6, 'blue');
gradient.addColorStop(1, 'purple');
// Generate a canvasPattern with two circles on white background
const pattern = (function () {
canvas.width = 8 * pixelRatio;
canvas.height = 8 * pixelRatio;
// white background
context.fillStyle = 'white';
context.fillRect(0, 0, canvas.width, canvas.height);
// outer circle
context.fillStyle = 'rgba(102, 0, 102, 0.5)';
context.beginPath();
context.arc(4 * pixelRatio, 4 * pixelRatio, 3 * pixelRatio, 0, 2 * Math.PI);
context.fill();
// inner circle
context.fillStyle = 'rgb(55, 0, 170)';
context.beginPath();
context.arc(4 * pixelRatio, 4 * pixelRatio, 1.5 * pixelRatio, 0, 2 * Math.PI);
context.fill();
return context.createPattern(canvas, 'repeat');
})();
// Generate style for gradient or pattern fill
const fill = new Fill();
const style = new Style({
fill: fill,
stroke: new Stroke({
color: '#333',
width: 2,
}),
});
/**
* The styling function for the vector layer, will return an array of styles
* which either contains the aboove gradient or pattern.
*
* @param {import("../src/ol/Feature.js").default} feature The feature to style.
* @return {Style} The style to use for the feature.
*/
const getStackedStyle = function (feature) {
const id = feature.getId();
fill.setColor(id > 'J' ? gradient : pattern);
return style;
};
// Create a vector layer that makes use of the style function above…
const vectorLayer = new VectorLayer({
background: 'white',
source: new VectorSource({
url: 'data/geojson/countries.geojson',
format: new GeoJSON(),
url: 'data/kml/states.kml',
format: new KML({extractStyles: false}),
}),
style: new Style({
fill: new Fill({color: gradient}),
stroke: new Stroke({
color: '#333',
width: 1,
}),
}),
style: getStackedStyle,
});
// … finally create a map with that layer.
const map = new Map({
layers: [vectorLayer],
target: 'map',
view: new View({
center: fromLonLat([16, 48]),
zoom: 3,
center: fromLonLat([-100, 38.5]),
zoom: 4,
}),
});

View File

@@ -1,7 +1,7 @@
---
layout: example.html
title: Band Constrast Stretch
shortdesc: Choosing bands and applying constrast stretch
title: Band Contrast Stretch
shortdesc: Choosing bands and applying contrast stretch
docs: >
This example uses the `layer.updateStyleVariables()` method to update the rendering
of a GeoTIFF based on user selected bands and contrast stretch parameters.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,30 +1,28 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import {Draw, Modify, Select, Snap} from '../src/ol/interaction.js';
import {Map, View} from '../src/ol/index.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {useGeographic} from '../src/ol/proj.js';
useGeographic();
const source = new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/us-states.json',
format: new GeoJSON(),
});
const map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new OSM(),
}),
new VectorLayer({
background: 'white',
source: source,
}),
],
view: new View({
center: [0, 0],
zoom: 2,
center: [-100, 38.5],
zoom: 4,
}),
});

View File

@@ -1,24 +1,34 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Fill, Style} from '../src/ol/style.js';
import {
Heatmap as HeatmapLayer,
Tile as TileLayer,
Vector as VectorLayer,
} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {asArray} from '../src/ol/color.js';
const style = new Style({
fill: new Fill({
color: '#eeeeee',
}),
});
const map = new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
new VectorLayer({
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
}),
opacity: 0.5,
background: 'white',
style: function (feature) {
const color = asArray(feature.get('COLOR_NNH') || '#eeeeee');
color[3] = 0.75;
style.getFill().setColor(color);
return style;
},
}),
new HeatmapLayer({
source: new VectorSource({
@@ -30,7 +40,7 @@ const map = new Map({
},
radius: 15,
blur: 15,
opacity: 0.5,
opacity: 0.75,
}),
],
target: 'map',
@@ -54,6 +64,13 @@ document.getElementById('export-png').addEventListener('click', function () {
const opacity =
canvas.parentNode.style.opacity || canvas.style.opacity;
mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
const backgroundColor = canvas.parentNode.style.backgroundColor;
if (backgroundColor) {
mapContext.fillStyle = backgroundColor;
mapContext.fillRect(0, 0, canvas.width, canvas.height);
}
let matrix;
const transform = canvas.style.transform;
if (transform) {

View File

@@ -1,24 +1,15 @@
import ExtentInteraction from '../src/ol/interaction/Extent.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import OSM from '../src/ol/source/OSM.js';
import TileLayer from '../src/ol/layer/Tile.js';
import View from '../src/ol/View.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {shiftKeyOnly} from '../src/ol/events/condition.js';
const vectorSource = new VectorSource({
url: 'data/geojson/countries.geojson',
format: new GeoJSON(),
});
const map = new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
new VectorLayer({
source: vectorSource,
}),
],
target: 'map',
view: new View({

View File

@@ -1,60 +1,67 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import OSM from '../src/ol/source/OSM.js';
import Projection from '../src/ol/proj/Projection.js';
import VectorTileLayer from '../src/ol/layer/VectorTile.js';
import VectorTileSource from '../src/ol/source/VectorTile.js';
import View from '../src/ol/View.js';
import {
Tile as TileLayer,
VectorTile as VectorTileLayer,
} from '../src/ol/layer.js';
import {Fill, Style} from '../src/ol/style.js';
// Converts geojson-vt data to GeoJSON
const replacer = function (key, value) {
if (value.geometry) {
let type;
const rawType = value.type;
let geometry = value.geometry;
if (rawType === 1) {
type = 'MultiPoint';
if (geometry.length == 1) {
type = 'Point';
geometry = geometry[0];
}
} else if (rawType === 2) {
type = 'MultiLineString';
if (geometry.length == 1) {
type = 'LineString';
geometry = geometry[0];
}
} else if (rawType === 3) {
type = 'Polygon';
if (geometry.length > 1) {
type = 'MultiPolygon';
geometry = [geometry];
}
}
return {
'type': 'Feature',
'geometry': {
'type': type,
'coordinates': geometry,
},
'properties': value.tags,
};
} else {
if (!value || !value.geometry) {
return value;
}
let type;
const rawType = value.type;
let geometry = value.geometry;
if (rawType === 1) {
type = 'MultiPoint';
if (geometry.length == 1) {
type = 'Point';
geometry = geometry[0];
}
} else if (rawType === 2) {
type = 'MultiLineString';
if (geometry.length == 1) {
type = 'LineString';
geometry = geometry[0];
}
} else if (rawType === 3) {
type = 'Polygon';
if (geometry.length > 1) {
type = 'MultiPolygon';
geometry = [geometry];
}
}
return {
'type': 'Feature',
'geometry': {
'type': type,
'coordinates': geometry,
},
'properties': value.tags,
};
};
const style = new Style({
fill: new Fill({
color: '#eeeeee',
}),
});
const layer = new VectorTileLayer({
background: '#1a2b39',
style: function (feature) {
const color = feature.get('COLOR') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
});
const map = new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
],
layers: [layer],
target: 'map',
view: new View({
center: [0, 0],
@@ -62,7 +69,7 @@ const map = new Map({
}),
});
const url = 'data/geojson/countries.geojson';
const url = 'https://openlayers.org/data/vector/ecoregions.json';
fetch(url)
.then(function (response) {
return response.json();
@@ -106,8 +113,5 @@ fetch(url)
tile.setFeatures(features);
},
});
const vectorLayer = new VectorTileLayer({
source: vectorSource,
});
map.addLayer(vectorLayer);
layer.setSource(vectorSource);
});

View File

@@ -1,12 +1,12 @@
---
layout: example.html
title: Vector Layer Hit Detection
shortdesc: Example of hit detection on a countries vector layer with country information.
shortdesc: Example of hit detection on an ecoregions vector layer with protection status.
docs: >
The countries are loaded from a GeoJSON file. Information about countries is
on hover and click is retrieved using the layer's `getFeatures()` method. For
The ecoregions are loaded from a GeoJSON file. Information about features is
retrieved using the layer's `getFeatures()` method on hover and click. For
vector layers, this function resolves with an array of only the topmost
feature. It uses a very efficient hit detection algorithm, at the cost of
feature. It uses an efficient hit detection algorithm, at the cost of
accuracy. For pixel exact hit detection, when performance is not a concern,
use the map's `getFeaturesAtPixel()` or `forEachFeatureAtPixel()` methods.
tags: "vector, geojson, click, hover, hit detection"

View File

@@ -3,35 +3,23 @@ import Map from '../src/ol/Map.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Fill, Stroke, Style, Text} from '../src/ol/style.js';
import {Fill, Stroke, Style} from '../src/ol/style.js';
const style = new Style({
fill: new Fill({
color: 'rgba(255, 255, 255, 0.6)',
}),
stroke: new Stroke({
color: '#319FD3',
width: 1,
}),
text: new Text({
font: '12px Calibri,sans-serif',
fill: new Fill({
color: '#000',
}),
stroke: new Stroke({
color: '#fff',
width: 3,
}),
color: '#eeeeee',
}),
});
const vectorLayer = new VectorLayer({
background: '#1a2b39',
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
}),
style: function (feature) {
style.getText().setText(feature.get('name'));
const color = feature.get('COLOR_NNH') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
});
@@ -47,31 +35,15 @@ const map = new Map({
const highlightStyle = new Style({
stroke: new Stroke({
color: '#f00',
width: 1,
}),
fill: new Fill({
color: 'rgba(255,0,0,0.1)',
}),
text: new Text({
font: '12px Calibri,sans-serif',
fill: new Fill({
color: '#000',
}),
stroke: new Stroke({
color: '#f00',
width: 3,
}),
color: 'rgba(255, 255, 255, 0.7)',
width: 2,
}),
});
const featureOverlay = new VectorLayer({
source: new VectorSource(),
map: map,
style: function (feature) {
highlightStyle.getText().setText(feature.get('name'));
return highlightStyle;
},
style: highlightStyle,
});
let highlight;
@@ -80,7 +52,7 @@ const displayFeatureInfo = function (pixel) {
const feature = features.length ? features[0] : undefined;
const info = document.getElementById('info');
if (features.length) {
info.innerHTML = feature.getId() + ': ' + feature.get('name');
info.innerHTML = feature.get('ECO_NAME') + ': ' + feature.get('NNH_NAME');
} else {
info.innerHTML = '&nbsp;';
}

View File

@@ -4,33 +4,30 @@ import VectorImageLayer from '../src/ol/layer/VectorImage.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Fill, Stroke, Style, Text} from '../src/ol/style.js';
import {Fill, Stroke, Style} from '../src/ol/style.js';
const style = new Style({
fill: new Fill({
color: 'rgba(255, 255, 255, 0.6)',
color: '#eeeeee',
}),
stroke: new Stroke({
color: '#319FD3',
width: 1,
});
const vectorLayer = new VectorImageLayer({
background: '#1a2b39',
imageRatio: 2,
source: new VectorSource({
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
}),
text: new Text(),
style: function (feature) {
const color = feature.get('COLOR') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
});
const map = new Map({
layers: [
new VectorImageLayer({
imageRatio: 2,
source: new VectorSource({
url: 'data/geojson/countries.geojson',
format: new GeoJSON(),
}),
style: function (feature) {
style.getText().setText(feature.get('name'));
return style;
},
}),
],
layers: [vectorLayer],
target: 'map',
view: new View({
center: [0, 0],
@@ -43,47 +40,42 @@ const featureOverlay = new VectorLayer({
map: map,
style: new Style({
stroke: new Stroke({
color: '#f00',
width: 1,
}),
fill: new Fill({
color: 'rgba(255,0,0,0.1)',
color: 'rgba(255, 255, 255, 0.7)',
width: 2,
}),
}),
});
let highlight;
const displayFeatureInfo = function (pixel) {
map
.getLayers()
.item(0)
.getFeatures(pixel)
.then(function (features) {
const feature = features.length > 0 ? features[0] : undefined;
const feature = map.forEachFeatureAtPixel(pixel, function (feature) {
return feature;
});
const info = document.getElementById('info');
if (feature) {
info.innerHTML = feature.getId() + ': ' + feature.get('name');
} else {
info.innerHTML = '&nbsp;';
}
const info = document.getElementById('info');
if (feature) {
info.innerHTML = feature.get('ECO_NAME') || '&nbsp;';
} else {
info.innerHTML = '&nbsp;';
}
if (feature !== highlight) {
if (highlight) {
featureOverlay.getSource().removeFeature(highlight);
}
if (feature) {
featureOverlay.getSource().addFeature(feature);
}
highlight = feature;
}
});
if (feature !== highlight) {
if (highlight) {
featureOverlay.getSource().removeFeature(highlight);
}
if (feature) {
featureOverlay.getSource().addFeature(feature);
}
highlight = feature;
}
};
map.on('pointermove', function (evt) {
if (!evt.dragging) {
displayFeatureInfo(evt.pixel);
if (evt.dragging) {
return;
}
const pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
});
map.on('click', function (evt) {

View File

@@ -7,7 +7,7 @@ docs: >
The <code>interpolate: false</code> setting is used to disable interpolation of data values during
reprojection and rendering. Elevation data is
calculated from the pixel value returned by <b>forEachLayerAtPixel</b>. For comparison a second map
with interpolation enabled returns inaccuate elevations which are very noticeable close to 3107 meters
with interpolation enabled returns inaccurate elevations which are very noticeable close to 3107 meters
due to how elevation is calculated from the pixel value.
tags: "disable image interpolation, xyz, maptiler, reprojection"
cloak:

View File

@@ -1,11 +1,10 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import HeatmapLayer from '../src/ol/layer/Heatmap.js';
import Layer from '../src/ol/layer/Layer.js';
import Map from '../src/ol/Map.js';
import Source from '../src/ol/source/Source.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Stroke, Style} from '../src/ol/style.js';
import {fromLonLat, toLonLat} from '../src/ol/proj.js';
const center = [-98.8, 37.9];
@@ -34,6 +33,7 @@ const mbLayer = new Layer({
const visible = mbLayer.getVisible();
canvas.style.display = visible ? 'block' : 'none';
canvas.style.position = 'absolute';
const opacity = mbLayer.getOpacity();
canvas.style.opacity = opacity;
@@ -66,19 +66,16 @@ const mbLayer = new Layer({
}),
});
const style = new Style({
stroke: new Stroke({
color: '#319FD3',
width: 2,
}),
});
const vectorLayer = new VectorLayer({
const cities = new HeatmapLayer({
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'data/geojson/world-cities.geojson',
format: new GeoJSON(),
}),
style: style,
weight: function (feature) {
return feature.get('population') / 1e7;
},
radius: 15,
blur: 15,
});
const map = new Map({
@@ -87,5 +84,5 @@ const map = new Map({
center: fromLonLat(center),
zoom: 4,
}),
layers: [mbLayer, vectorLayer],
layers: [mbLayer, cities],
});

View File

@@ -1,21 +1,19 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {
Modify,
Select,
defaults as defaultInteractions,
} from '../src/ol/interaction.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
const raster = new TileLayer({
source: new OSM(),
});
import {fromLonLat} from '../src/ol/proj.js';
const vector = new VectorLayer({
background: 'white',
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/us-states.json',
format: new GeoJSON(),
wrapX: false,
}),
@@ -31,10 +29,10 @@ const modify = new Modify({
const map = new Map({
interactions: defaultInteractions().extend([select, modify]),
layers: [raster, vector],
layers: [vector],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2,
center: fromLonLat([-100, 38.5]),
zoom: 4,
}),
});

View File

@@ -0,0 +1,18 @@
---
layout: example.html
title: Projection and Scale
shortdesc: Example of maintaining scale when changing projection.
docs: >
Example of maintaining scale when changing projection.
`getPointResolution()` is used to calculate the resolution for the
new projection which corresponds to that for the old projection.
tags: "projection, scale"
---
<div id="map" class="map"></div>
<div>
<label for="view-projection">View projection</label>
<select id="view-projection">
<option value="EPSG:3857">Spherical Mercator (EPSG:3857)</option>
<option value="EPSG:4326" selected>WGS 84 (EPSG:4326)</option>
</select>
</div>

View File

@@ -0,0 +1,68 @@
import Map from '../src/ol/Map.js';
import OSM from '../src/ol/source/OSM.js';
import TileLayer from '../src/ol/layer/Tile.js';
import View from '../src/ol/View.js';
import {ScaleLine, defaults as defaultControls} from '../src/ol/control.js';
import {
getPointResolution,
get as getProjection,
transform,
} from '../src/ol/proj.js';
const viewProjSelect = document.getElementById('view-projection');
const projection = getProjection(viewProjSelect.value);
const scaleControl = new ScaleLine({
units: 'metric',
bar: true,
steps: 4,
text: true,
minWidth: 140,
});
const map = new Map({
controls: defaultControls().extend([scaleControl]),
layers: [
new TileLayer({
source: new OSM(),
}),
],
target: 'map',
view: new View({
center: transform([0, 52], 'EPSG:4326', projection),
zoom: 6,
projection: projection,
}),
});
function onChangeProjection() {
const currentView = map.getView();
const currentProjection = currentView.getProjection();
const newProjection = getProjection(viewProjSelect.value);
const currentResolution = currentView.getResolution();
const currentCenter = currentView.getCenter();
const currentRotation = currentView.getRotation();
const newCenter = transform(currentCenter, currentProjection, newProjection);
const currentPointResolution = getPointResolution(
currentProjection,
1,
currentCenter,
'm'
);
const newPointResolution = getPointResolution(
newProjection,
1,
newCenter,
'm'
);
const newResolution =
(currentResolution * currentPointResolution) / newPointResolution;
const newView = new View({
center: newCenter,
resolution: newResolution,
rotation: currentRotation,
projection: newProjection,
});
map.setView(newView);
}
viewProjSelect.addEventListener('change', onChangeProjection);

View File

@@ -8,11 +8,6 @@ docs: >
<a href="https://blog.mapbox.com/styling-mapbox-terrain-rgb-c75d1cd71471">Mapbox Terrain-RGB tiles</a>
to "flood" areas below the elevation shown on the sea level slider.
</p>
<p>
<code>ol/source/Raster</code> can take either a tile source or layer.
In this case a layer is used to allow disabling at the <code>prerender</code> event
of image smoothing which would change the precise elevation values set in the pixels.
</p>
tags: "raster, pixel operation, flood"
cloak:
- key: get_your_own_D6rA4zTHduk6KOKTXzGB

View File

@@ -26,18 +26,14 @@ const attributions =
'<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
'<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>';
const elevation = new TileLayer({
source: new XYZ({
url:
'https://api.maptiler.com/tiles/terrain-rgb/{z}/{x}/{y}.png?key=' + key,
tileSize: 512,
maxZoom: 12,
crossOrigin: '',
}),
});
elevation.on('prerender', function (evt) {
evt.context.imageSmoothingEnabled = false;
evt.context.msImageSmoothingEnabled = false;
const elevation = new XYZ({
// The RGB values in the source collectively represent elevation.
// Interpolation of individual colors would produce incorrect evelations and is disabled.
url: 'https://api.maptiler.com/tiles/terrain-rgb/{z}/{x}/{y}.png?key=' + key,
tileSize: 512,
maxZoom: 12,
crossOrigin: '',
interpolate: false,
});
const raster = new RasterSource({

View File

@@ -1,25 +1,33 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import OSM from '../src/ol/source/OSM.js';
import Select from '../src/ol/interaction/Select.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {Fill, Stroke, Style} from '../src/ol/style.js';
import {altKeyOnly, click, pointerMove} from '../src/ol/events/condition.js';
const raster = new TileLayer({
source: new OSM(),
const style = new Style({
fill: new Fill({
color: '#eeeeee',
}),
});
const vector = new VectorLayer({
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
}),
background: 'white',
style: function (feature) {
const color = feature.get('COLOR') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
});
const map = new Map({
layers: [raster, vector],
layers: [vector],
target: 'map',
view: new View({
center: [0, 0],
@@ -29,20 +37,39 @@ const map = new Map({
let select = null; // ref to currently selected interaction
const selected = new Style({
fill: new Fill({
color: '#eeeeee',
}),
stroke: new Stroke({
color: 'rgba(255, 255, 255, 0.7)',
width: 2,
}),
});
function selectStyle(feature) {
const color = feature.get('COLOR') || '#eeeeee';
selected.getFill().setColor(color);
return selected;
}
// select interaction working on "singleclick"
const selectSingleClick = new Select();
const selectSingleClick = new Select({style: selectStyle});
// select interaction working on "click"
const selectClick = new Select({
condition: click,
style: selectStyle,
});
// select interaction working on "pointermove"
const selectPointerMove = new Select({
condition: pointerMove,
style: selectStyle,
});
const selectAltClick = new Select({
style: selectStyle,
condition: function (mapBrowserEvent) {
return click(mapBrowserEvent) && altKeyOnly(mapBrowserEvent);
},

View File

@@ -7,4 +7,4 @@ docs: >
tags: "select, vector"
---
<div id="map" class="map"></div>
<span id="status"></span>
<span id="status">&nbsp;</span>

View File

@@ -1,36 +1,33 @@
import Fill from '../src/ol/style/Fill.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import OSM from '../src/ol/source/OSM.js';
import Stroke from '../src/ol/style/Stroke.js';
import Style from '../src/ol/style/Style.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
const raster = new TileLayer({
source: new OSM(),
});
const highlightStyle = new Style({
const style = new Style({
fill: new Fill({
color: 'rgba(255,255,255,0.7)',
}),
stroke: new Stroke({
color: '#3399CC',
width: 3,
color: '#eeeeee',
}),
});
const vector = new VectorLayer({
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
}),
background: 'white',
style: function (feature) {
const color = feature.get('COLOR') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
});
const map = new Map({
layers: [raster, vector],
layers: [vector],
target: 'map',
view: new View({
center: [0, 0],
@@ -38,9 +35,19 @@ const map = new Map({
}),
});
let selected = null;
const selectStyle = new Style({
fill: new Fill({
color: '#eeeeee',
}),
stroke: new Stroke({
color: 'rgba(255, 255, 255, 0.7)',
width: 2,
}),
});
const status = document.getElementById('status');
let selected = null;
map.on('pointermove', function (e) {
if (selected !== null) {
selected.setStyle(undefined);
@@ -49,12 +56,13 @@ map.on('pointermove', function (e) {
map.forEachFeatureAtPixel(e.pixel, function (f) {
selected = f;
f.setStyle(highlightStyle);
selectStyle.getFill().setColor(f.get('COLOR') || '#eeeeee');
f.setStyle(selectStyle);
return true;
});
if (selected) {
status.innerHTML = '&nbsp;Hovering: ' + selected.get('name');
status.innerHTML = selected.get('ECO_NAME');
} else {
status.innerHTML = '&nbsp;';
}

View File

@@ -1,40 +1,37 @@
import Fill from '../src/ol/style/Fill.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import OSM from '../src/ol/source/OSM.js';
import Stroke from '../src/ol/style/Stroke.js';
import Style from '../src/ol/style/Style.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
const raster = new TileLayer({
source: new OSM(),
});
import {fromLonLat} from '../src/ol/proj.js';
const highlightStyle = new Style({
fill: new Fill({
color: 'rgba(255,255,255,0.7)',
color: '#EEE',
}),
stroke: new Stroke({
color: '#3399CC',
width: 3,
width: 2,
}),
});
const vector = new VectorLayer({
background: 'white',
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/us-states.json',
format: new GeoJSON(),
}),
});
const map = new Map({
layers: [raster, vector],
layers: [vector],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2,
center: fromLonLat([-100, 38.5]),
zoom: 4,
multiWorld: true,
}),
});

View File

@@ -6,6 +6,7 @@ import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import proj4 from 'proj4';
import {Fill, Style} from '../src/ol/style.js';
import {register} from '../src/ol/proj/proj4.js';
proj4.defs(
@@ -26,14 +27,25 @@ const sphereMollweideProjection = new Projection({
worldExtent: [-179, -89.99, 179, 89.99],
});
const style = new Style({
fill: new Fill({
color: '#eeeeee',
}),
});
const map = new Map({
keyboardEventTarget: document,
layers: [
new VectorLayer({
source: new VectorSource({
url: 'data/geojson/countries-110m.geojson',
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
}),
style: function (feature) {
const color = feature.get('COLOR_BIO') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
}),
new Graticule(),
],
@@ -41,6 +53,6 @@ const map = new Map({
view: new View({
center: [0, 0],
projection: sphereMollweideProjection,
zoom: 1,
zoom: 2,
}),
});

View File

@@ -1,6 +1,6 @@
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Map from '../src/ol/Map.js';
import OSM from '../src/ol/source/OSM.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {
@@ -8,15 +8,12 @@ import {
Translate,
defaults as defaultInteractions,
} from '../src/ol/interaction.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
const raster = new TileLayer({
source: new OSM(),
});
import {fromLonLat} from '../src/ol/proj.js';
const vector = new VectorLayer({
background: 'white',
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/us-states.json',
format: new GeoJSON(),
}),
});
@@ -29,10 +26,10 @@ const translate = new Translate({
const map = new Map({
interactions: defaultInteractions().extend([select, translate]),
layers: [raster, vector],
layers: [vector],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2,
center: fromLonLat([-100, 38.5]),
zoom: 4,
}),
});

View File

@@ -4,12 +4,13 @@ import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Fill, Stroke, Style, Text} from '../src/ol/style.js';
import {fromLonLat} from '../src/ol/proj.js';
const map = new Map({
target: 'map',
view: new View({
center: [0, 0],
zoom: 1,
center: fromLonLat([-100, 38.5]),
zoom: 4,
}),
});
@@ -38,12 +39,14 @@ const countryStyle = new Style({
const style = [countryStyle, labelStyle];
const vectorLayer = new VectorLayer({
background: 'white',
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/us-states.json',
format: new GeoJSON(),
}),
style: function (feature) {
labelStyle.getText().setText(feature.get('name'));
const label = feature.get('name').split(' ').join('\n');
labelStyle.getText().setText(label);
return style;
},
declutter: true,

View File

@@ -3,35 +3,23 @@ import Map from '../src/ol/Map.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import View from '../src/ol/View.js';
import {Fill, Stroke, Style, Text} from '../src/ol/style.js';
import {Fill, Stroke, Style} from '../src/ol/style.js';
const style = new Style({
fill: new Fill({
color: 'rgba(255, 255, 255, 0.6)',
}),
stroke: new Stroke({
color: '#319FD3',
width: 1,
}),
text: new Text({
font: '12px Calibri,sans-serif',
fill: new Fill({
color: '#000',
}),
stroke: new Stroke({
color: '#fff',
width: 3,
}),
color: '#eeeeee',
}),
});
const vectorLayer = new VectorLayer({
background: '#1a2b39',
source: new VectorSource({
url: 'data/geojson/countries.geojson',
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
}),
style: function (feature) {
style.getText().setText(feature.get('name'));
const color = feature.get('COLOR') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
});
@@ -45,33 +33,15 @@ const map = new Map({
}),
});
const highlightStyle = new Style({
stroke: new Stroke({
color: '#f00',
width: 1,
}),
fill: new Fill({
color: 'rgba(255,0,0,0.1)',
}),
text: new Text({
font: '12px Calibri,sans-serif',
fill: new Fill({
color: '#000',
}),
stroke: new Stroke({
color: '#f00',
width: 3,
}),
}),
});
const featureOverlay = new VectorLayer({
source: new VectorSource(),
map: map,
style: function (feature) {
highlightStyle.getText().setText(feature.get('name'));
return highlightStyle;
},
style: new Style({
stroke: new Stroke({
color: 'rgba(255, 255, 255, 0.7)',
width: 2,
}),
}),
});
let highlight;
@@ -82,7 +52,7 @@ const displayFeatureInfo = function (pixel) {
const info = document.getElementById('info');
if (feature) {
info.innerHTML = feature.getId() + ': ' + feature.get('name');
info.innerHTML = feature.get('ECO_NAME') || '&nbsp;';
} else {
info.innerHTML = '&nbsp;';
}

View File

@@ -329,7 +329,7 @@ export default class ExampleBuilder {
source = this.cloakSource(source, data.cloak);
assets[fileName] = source;
return {
name: sourceConfig.as ?? fileName,
name: sourceConfig.as || fileName,
source: source,
type: ext,
};

1870
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "ol",
"version": "6.10.0",
"version": "6.11.0",
"description": "OpenLayers mapping library",
"keywords": [
"map",

View File

@@ -688,8 +688,11 @@ class PluggableMap extends BaseObject {
* execute a callback with each matching layer. Layers included in the
* detection can be configured through `opt_layerFilter`.
*
* Note: this may give false positives unless the map layers have had different `className`
* properties assigned to them.
* Note: In maps with more than one layer, this method will typically return pixel data
* representing the composed image of all layers visible at the given pixel because layers
* will generally share the same rendering context. To force layers to render separately, and
* to get pixel data representing only one layer at a time, you can assign each layer a unique
* `className` in its constructor.
*
* @param {import("./pixel.js").Pixel} pixel Pixel.
* @param {function(this: S, import("./layer/Layer.js").default, (Uint8ClampedArray|Uint8Array)): T} callback

View File

@@ -484,12 +484,12 @@ class ScaleLine extends Control {
const resolution = getPointResolution(
this.viewState_.projection,
this.viewState_.resolution,
this.viewState_.center
this.viewState_.center,
ProjUnits.METERS
);
const dpi = this.dpi_ || DEFAULT_DPI;
const mpu = this.viewState_.projection.getMetersPerUnit();
const inchesPerMeter = 1000 / 25.4;
return parseFloat(resolution.toString()) * mpu * inchesPerMeter * dpi;
return parseFloat(resolution.toString()) * inchesPerMeter * dpi;
}
/**

View File

@@ -75,7 +75,7 @@ const Property = {
* options means that `title` is observable, and has get/set accessors.
*
* @template {import("../source/Vector.js").default|import("../source/VectorTile.js").default} VectorSourceType
* @template {import("../renderer/Layer.js").default} RendererType
* @template {import("../renderer/canvas/VectorLayer.js").default|import("../renderer/canvas/VectorTileLayer.js").default|import("../renderer/canvas/VectorImageLayer.js").default|import("../renderer/webgl/PointsLayer.js").default} RendererType
* @extends {Layer<VectorSourceType, RendererType>}
* @api
*/

View File

@@ -135,7 +135,12 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
const canvasTransform = toTransformString(this.pixelTransform);
this.useContainer(target, canvasTransform, layerState.opacity);
this.useContainer(
target,
canvasTransform,
layerState.opacity,
this.getBackground(frameState)
);
const context = this.context;
const canvas = context.canvas;

View File

@@ -114,10 +114,11 @@ class CanvasLayerRenderer extends LayerRenderer {
target.style.opacity === '' &&
opacity === 1 &&
(!opt_backgroundColor ||
equals(
asArray(target.style.backgroundColor),
asArray(opt_backgroundColor)
))
(target.style.backgroundColor &&
equals(
asArray(target.style.backgroundColor),
asArray(opt_backgroundColor)
)))
) {
const canvas = target.firstElementChild;
if (canvas instanceof HTMLCanvasElement) {

View File

@@ -233,7 +233,12 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
const canvasTransform = transformToString(this.pixelTransform);
this.useContainer(target, canvasTransform, layerState.opacity);
this.useContainer(
target,
canvasTransform,
layerState.opacity,
this.getBackground(frameState)
);
const context = this.context;
const canvas = context.canvas;

View File

@@ -7,9 +7,11 @@ import RenderEvent from '../../render/Event.js';
import RenderEventType from '../../render/EventType.js';
import WebGLHelper from '../../webgl/Helper.js';
import {
apply as applyTransform,
compose as composeTransform,
create as createTransform,
} from '../../transform.js';
import {containsCoordinate} from '../../extent.js';
/**
* @enum {string}
@@ -71,6 +73,12 @@ class WebGLLayerRenderer extends LayerRenderer {
*/
this.inversePixelTransform_ = createTransform();
/**
* @private
* @type {CanvasRenderingContext2D}
*/
this.pixelContext_ = null;
/**
* @private
*/
@@ -270,6 +278,68 @@ class WebGLLayerRenderer extends LayerRenderer {
postRender(context, frameState) {
this.dispatchRenderEvent_(RenderEventType.POSTRENDER, context, frameState);
}
/**
* @param {import("../../pixel.js").Pixel} pixel Pixel.
* @param {import("../../PluggableMap.js").FrameState} frameState FrameState.
* @param {number} hitTolerance Hit tolerance in pixels.
* @return {Uint8ClampedArray|Uint8Array} The result. If there is no data at the pixel
* location, null will be returned. If there is data, but pixel values cannot be
* returned, and empty array will be returned.
*/
getDataAtPixel(pixel, frameState, hitTolerance) {
const renderPixel = applyTransform(
[frameState.pixelRatio, 0, 0, frameState.pixelRatio, 0, 0],
pixel.slice()
);
const gl = this.helper.getGL();
if (!gl) {
return null;
}
const layer = this.getLayer();
const layerExtent = layer.getExtent();
if (layerExtent) {
const renderCoordinate = applyTransform(
frameState.pixelToCoordinateTransform,
pixel.slice()
);
/** get only data inside of the layer extent */
if (!containsCoordinate(layerExtent, renderCoordinate)) {
return null;
}
}
const attributes = gl.getContextAttributes();
if (!attributes || !attributes.preserveDrawingBuffer) {
// we assume there is data at the given pixel (although there might not be)
return new Uint8Array();
}
const x = Math.round(renderPixel[0]);
const y = Math.round(renderPixel[1]);
let pixelContext = this.pixelContext_;
if (!pixelContext) {
const pixelCanvas = document.createElement('canvas');
pixelCanvas.width = 1;
pixelCanvas.height = 1;
pixelContext = pixelCanvas.getContext('2d');
this.pixelContext_ = pixelContext;
}
pixelContext.clearRect(0, 0, 1, 1);
let data;
try {
pixelContext.drawImage(gl.canvas, x, y, 1, 1, 0, 0, 1, 1);
data = pixelContext.getImageData(0, 0, 1, 1).data;
} catch (err) {
return data;
}
if (data[3] === 0) {
return null;
}
return data;
}
}
const tmpArray_ = [];

View File

@@ -22,6 +22,8 @@ import {toPromise} from '../functions.js';
* @typedef {Object} Options
* @property {Loader} [loader] Data loader. Called with z, x, and y tile coordinates.
* Returns {@link import("../DataTile.js").Data data} for a tile or a promise for the same.
* @property {import("./Source.js").AttributionLike} [attributions] Attributions.
* @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.
* @property {number} [maxZoom=42] Optional max zoom level. Not used if `tileGrid` is provided.
* @property {number} [minZoom=0] Optional min zoom level. Not used if `tileGrid` is provided.
* @property {number|import("../size.js").Size} [tileSize=[256, 256]] The pixel width and height of the tiles.
@@ -66,6 +68,8 @@ class DataTileSource extends TileSource {
super({
cacheSize: 0.1, // don't cache on the source
attributions: options.attributions,
attributionsCollapsible: options.attributionsCollapsible,
projection: projection,
tileGrid: tileGrid,
opaque: options.opaque,

View File

@@ -4,7 +4,11 @@
import DataTile from './DataTile.js';
import State from './State.js';
import TileGrid from '../tilegrid/TileGrid.js';
import {Pool, fromUrl as tiffFromUrl, fromUrls as tiffFromUrls} from 'geotiff';
import {
Pool,
fromUrl as tiffFromUrl,
fromUrls as tiffFromUrls,
} from 'geotiff/src/geotiff.js';
import {
Projection,
get as getCachedProjection,

View File

@@ -151,9 +151,12 @@ function createWorker(config, onMessage) {
'});',
]);
const blob = new Blob(lines, {type: 'text/javascript'});
const source = URL.createObjectURL(blob);
const worker = new Worker(source);
const worker = new Worker(
typeof Blob === 'undefined'
? 'data:text/javascript;base64,' +
Buffer.from(lines.join('\n'), 'binary').toString('base64')
: URL.createObjectURL(new Blob(lines, {type: 'text/javascript'}))
);
worker.addEventListener('message', onMessage);
return worker;
}

View File

@@ -45,9 +45,9 @@ async function build(input, {minify = true} = {}) {
return `
export function create() {
const source = ${JSON.stringify(code)};
const blob = new Blob([source], {type: 'application/javascript'});
const url = URL.createObjectURL(blob);
return new Worker(url);
return new Worker(typeof Blob === 'undefined'
? 'data:application/javascript;base64,' + Buffer.from(source, 'binary').toString('base64')
: URL.createObjectURL(new Blob([source], {type: 'application/javascript'})));
}
`;
},

View File

@@ -640,5 +640,49 @@ describe('ol.control.ScaleLine', function () {
expect(text.slice(0, 4)).to.be('1 : ');
expect(text.replace(/^1|\D/g, '')).to.eql(69885283);
});
it('it corresponds to the resolution in EPSG:4326', function () {
const ctrl = new ScaleLine({
bar: true,
text: true,
});
ctrl.setMap(map);
map.setView(
new View({
center: [0, 0],
zoom: 2,
multiWorld: true,
projection: 'EPSG:4326',
})
);
map.renderSync();
const element = document.querySelector('.ol-scale-text', map.getTarget());
expect(element).to.not.be(null);
expect(element).to.be.a(HTMLDivElement);
const text = element.innerText;
expect(text.slice(0, 4)).to.be('1 : ');
expect(text.replace(/^1|\D/g, '')).to.eql(139614359);
});
it('it changes with latitude in EPSG:4326', function () {
const ctrl = new ScaleLine({
bar: true,
text: true,
});
ctrl.setMap(map);
map.setView(
new View({
center: [0, 60],
zoom: 2,
multiWorld: true,
projection: 'EPSG:4326',
})
);
map.renderSync();
const element = document.querySelector('.ol-scale-text', map.getTarget());
expect(element).to.not.be(null);
expect(element).to.be.a(HTMLDivElement);
const text = element.innerText;
expect(text.slice(0, 4)).to.be('1 : ');
expect(text.replace(/^1|\D/g, '')).to.eql(104710728);
});
});
});

View File

@@ -1,6 +1,7 @@
import DataTileSource from '../../../../../../src/ol/source/DataTile.js';
import Layer from '../../../../../../src/ol/layer/Layer.js';
import Map from '../../../../../../src/ol/Map.js';
import Projection from '../../../../../../src/ol/proj/Projection.js';
import TileLayer from '../../../../../../src/ol/layer/WebGLTile.js';
import VectorLayer from '../../../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../../../src/ol/source/Vector.js';
@@ -434,4 +435,176 @@ describe('ol/renderer/webgl/Layer', function () {
dispose(map);
});
});
describe('#getDataAtPixel (preserveDrawingBuffer false)', function () {
let map, target, source, layer, getContextOriginal;
beforeEach(function (done) {
getContextOriginal = HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext = function (type, attributes) {
if (attributes && attributes.preserveDrawingBuffer) {
attributes.preserveDrawingBuffer = false;
}
return getContextOriginal.call(this, type, attributes);
};
const projection = new Projection({
code: 'custom-image',
units: 'pixels',
extent: [0, 0, 200, 200],
});
target = document.createElement('div');
target.style.width = '100px';
target.style.height = '100px';
document.body.appendChild(target);
source = new DataTileSource({
loader: function (z, x, y) {
return new Uint8Array(x == 0 ? [255, 0, 0, 255] : [0, 0, 0, 0]);
},
projection: projection,
maxZoom: 0,
tileSize: 1,
maxResolution: 100,
});
layer = new TileLayer({
source: source,
extent: [50, 0, 150, 100],
});
map = new Map({
pixelRatio: 1,
target: target,
layers: [layer],
view: new View({
projection: projection,
center: [100, 100],
zoom: 0,
}),
});
map.once('rendercomplete', function () {
done();
});
});
afterEach(function () {
HTMLCanvasElement.prototype.getContext = getContextOriginal;
map.setLayers([]);
map.setTarget(null);
document.body.removeChild(target);
});
it('should not detect pixels outside of the layer extent', function () {
const pixel = [10, 10];
const frameState = map.frameState_;
const hitTolerance = 0;
const layerRenderer = layer.getRenderer();
const data = layerRenderer.getDataAtPixel(
pixel,
frameState,
hitTolerance
);
expect(data).to.be(null);
});
it('should handle unreadable pixels in the layer extent', function () {
const pixel = [10, 60];
const frameState = map.frameState_;
const hitTolerance = 0;
const layerRenderer = layer.getRenderer();
const data = layerRenderer.getDataAtPixel(
pixel,
frameState,
hitTolerance
);
expect(data.length).to.be(0);
});
});
describe('#getDataAtPixel (preserveDrawingBuffer true)', function () {
let map, target, source, layer;
beforeEach(function (done) {
const projection = new Projection({
code: 'custom-image',
units: 'pixels',
extent: [0, 0, 200, 200],
});
target = document.createElement('div');
target.style.width = '100px';
target.style.height = '100px';
document.body.appendChild(target);
source = new DataTileSource({
loader: function (z, x, y) {
return new Uint8Array(x == 0 ? [255, 0, 0, 255] : [0, 0, 0, 0]);
},
projection: projection,
maxZoom: 0,
tileSize: 1,
maxResolution: 100,
});
layer = new TileLayer({
source: source,
extent: [50, 0, 150, 100],
});
map = new Map({
pixelRatio: 1,
target: target,
layers: [layer],
view: new View({
projection: projection,
center: [100, 100],
zoom: 0,
}),
});
map.once('rendercomplete', function () {
done();
});
});
afterEach(function () {
map.setLayers([]);
map.setTarget(null);
document.body.removeChild(target);
});
it('should not detect pixels outside of the layer extent', function () {
const pixel = [10, 10];
const frameState = map.frameState_;
const hitTolerance = 0;
const layerRenderer = layer.getRenderer();
const data = layerRenderer.getDataAtPixel(
pixel,
frameState,
hitTolerance
);
expect(data).to.be(null);
});
it('should detect pixels in the layer extent', function () {
const pixel = [10, 60];
const frameState = map.frameState_;
const hitTolerance = 0;
const layerRenderer = layer.getRenderer();
const data = layerRenderer.getDataAtPixel(
pixel,
frameState,
hitTolerance
);
expect(data.length > 0).to.be(true);
expect(data[0]).to.be(255);
expect(data[1]).to.be(0);
expect(data[2]).to.be(0);
expect(data[3]).to.be(255);
});
it('should handle no data in the layer extent', function () {
const pixel = [60, 60];
const frameState = map.frameState_;
const hitTolerance = 0;
const layerRenderer = layer.getRenderer();
const data = layerRenderer.getDataAtPixel(
pixel,
frameState,
hitTolerance
);
expect(data).to.be(null);
});
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,41 @@
import GeoJSON from '../../../../src/ol/format/GeoJSON.js';
import Map from '../../../../src/ol/Map.js';
import TileLayer from '../../../../src/ol/layer/Tile.js';
import VectorLayer from '../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../src/ol/source/Vector.js';
import View from '../../../../src/ol/View.js';
import XYZ from '../../../../src/ol/source/XYZ.js';
import {Fill, Stroke, Style} from '../../../../src/ol/style.js';
new Map({
target: 'map',
view: new View({
center: [0, 0],
zoom: 1,
}),
layers: [
new TileLayer({
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
transition: 0,
}),
}),
new VectorLayer({
background: '#a9d3df',
source: new VectorSource({
url: '/data/countries.json',
format: new GeoJSON(),
}),
style: new Style({
stroke: new Stroke({
color: '#ccc',
}),
fill: new Fill({
color: 'white',
}),
}),
}),
],
});
render();

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,33 @@
import GeoJSON from '../../../../src/ol/format/GeoJSON.js';
import Map from '../../../../src/ol/Map.js';
import VectorLayer from '../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../src/ol/source/Vector.js';
import View from '../../../../src/ol/View.js';
import {Fill, Stroke, Style} from '../../../../src/ol/style.js';
new Map({
target: 'map',
view: new View({
center: [0, 0],
zoom: 1,
}),
layers: [
new VectorLayer({
background: '#a9d3df',
source: new VectorSource({
url: '/data/countries.json',
format: new GeoJSON(),
}),
style: new Style({
stroke: new Stroke({
color: '#ccc',
}),
fill: new Fill({
color: 'white',
}),
}),
}),
],
});
render();

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,33 @@
import GeoJSON from '../../../../src/ol/format/GeoJSON.js';
import Map from '../../../../src/ol/Map.js';
import VectorImageLayer from '../../../../src/ol/layer/VectorImage.js';
import VectorSource from '../../../../src/ol/source/Vector.js';
import View from '../../../../src/ol/View.js';
import {Fill, Stroke, Style} from '../../../../src/ol/style.js';
new Map({
target: 'map',
view: new View({
center: [0, 0],
zoom: 1,
}),
layers: [
new VectorImageLayer({
background: '#a9d3df',
source: new VectorSource({
url: '/data/countries.json',
format: new GeoJSON(),
}),
style: new Style({
stroke: new Stroke({
color: '#ccc',
}),
fill: new Fill({
color: 'white',
}),
}),
}),
],
});
render();