Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd8a454df1 | ||
|
|
6de9c828ab | ||
|
|
f13838470e | ||
|
|
a9210db25c | ||
|
|
85d5e5dfad | ||
|
|
0e93a3118c | ||
|
|
449cfd15b1 | ||
|
|
07ebc48516 | ||
|
|
a963ab7d1d | ||
|
|
39b2de829e | ||
|
|
38d4a8f13f | ||
|
|
197dd2e06d | ||
|
|
4ce7f77749 | ||
|
|
7f0b6b3f7a | ||
|
|
a64102f097 | ||
|
|
22609f7a7d | ||
|
|
35e1d29d6b | ||
|
|
eed400ca1c | ||
|
|
73f54c1e6c | ||
|
|
71af0eee43 | ||
|
|
43e06a7d57 | ||
|
|
73f36adaaf | ||
|
|
2d96c92ac8 | ||
|
|
9024867893 | ||
|
|
9aa3c00879 | ||
|
|
faddbf098b | ||
|
|
539eae1398 | ||
|
|
e0aa161302 | ||
|
|
9c955bc86d | ||
|
|
ad7b95667f | ||
|
|
fc535ab4d0 | ||
|
|
c785c2813b | ||
|
|
a2388756f2 | ||
|
|
69c02aa6c8 | ||
|
|
f6496aa409 | ||
|
|
2893b78302 | ||
|
|
9553396c31 | ||
|
|
13101e3ab4 | ||
|
|
2dd4f71b51 | ||
|
|
9db298987b | ||
|
|
766a336650 | ||
|
|
d85be48da2 | ||
|
|
ae629301e9 | ||
|
|
7639eff49a | ||
|
|
654929bae2 | ||
|
|
7dd45c66ed | ||
|
|
1193476442 | ||
|
|
83d3bbf0ab | ||
|
|
665da47437 | ||
|
|
00b7bc60ac | ||
|
|
93abfe78a3 | ||
|
|
3506176328 | ||
|
|
275ecca473 | ||
|
|
9b0878a94a | ||
|
|
c500fdc4ad | ||
|
|
b1b09619bb | ||
|
|
d63a7ae497 | ||
|
|
bc2969fd78 | ||
|
|
37f117b782 | ||
|
|
c8a7a83e1f | ||
|
|
e8b4011cf4 | ||
|
|
d6d4b878c2 | ||
|
|
6570416343 |
@@ -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
32
changelog/v6.11.0.md
Normal 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>
|
||||
@@ -1,4 +0,0 @@
|
||||
.ol-dragbox {
|
||||
background-color: rgba(255,255,255,0.4);
|
||||
border-color: rgba(100,150,0,1);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -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
@@ -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,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 = ' ';
|
||||
}
|
||||
|
||||
@@ -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 = ' ';
|
||||
}
|
||||
const info = document.getElementById('info');
|
||||
if (feature) {
|
||||
info.innerHTML = feature.get('ECO_NAME') || ' ';
|
||||
} else {
|
||||
info.innerHTML = ' ';
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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],
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
});
|
||||
|
||||
18
examples/projection-and-scale.html
Normal file
18
examples/projection-and-scale.html
Normal 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>
|
||||
68
examples/projection-and-scale.js
Normal file
68
examples/projection-and-scale.js
Normal 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);
|
||||
@@ -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
|
||||
|
||||
@@ -26,18 +26,14 @@ const attributions =
|
||||
'<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> ' +
|
||||
'<a href="https://www.openstreetmap.org/copyright" target="_blank">© 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({
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -7,4 +7,4 @@ docs: >
|
||||
tags: "select, vector"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
<span id="status"></span>
|
||||
<span id="status"> </span>
|
||||
|
||||
@@ -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 = ' Hovering: ' + selected.get('name');
|
||||
status.innerHTML = selected.get('ECO_NAME');
|
||||
} else {
|
||||
status.innerHTML = ' ';
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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') || ' ';
|
||||
} else {
|
||||
info.innerHTML = ' ';
|
||||
}
|
||||
|
||||
@@ -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
1870
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ol",
|
||||
"version": "6.10.0",
|
||||
"version": "6.11.0",
|
||||
"description": "OpenLayers mapping library",
|
||||
"keywords": [
|
||||
"map",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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_ = [];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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'})));
|
||||
}
|
||||
`;
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
BIN
test/rendering/cases/layer-vector-background-over/expected.png
Normal file
BIN
test/rendering/cases/layer-vector-background-over/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
41
test/rendering/cases/layer-vector-background-over/main.js
Normal file
41
test/rendering/cases/layer-vector-background-over/main.js
Normal 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();
|
||||
BIN
test/rendering/cases/layer-vector-background/expected.png
Normal file
BIN
test/rendering/cases/layer-vector-background/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
33
test/rendering/cases/layer-vector-background/main.js
Normal file
33
test/rendering/cases/layer-vector-background/main.js
Normal 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();
|
||||
BIN
test/rendering/cases/layer-vectorimage-background/expected.png
Normal file
BIN
test/rendering/cases/layer-vectorimage-background/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
33
test/rendering/cases/layer-vectorimage-background/main.js
Normal file
33
test/rendering/cases/layer-vectorimage-background/main.js
Normal 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();
|
||||
Reference in New Issue
Block a user