Merge remote-tracking branch 'origin/master' into fix_triangulation
Conflicts: src/ol/TileCache.js
@@ -34,7 +34,7 @@ Interactions for <a href="module-ol_Feature-Feature.html">vector features</a>
|
|||||||
<tr><th>Projections</th><th>Observable objects</th><th>Other components</th></tr>
|
<tr><th>Projections</th><th>Observable objects</th><th>Other components</th></tr>
|
||||||
<tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use <a href="module-ol_proj.html#.transform">ol/proj#transform()</a> and <a href="module-ol_proj.html#.transformExtent">ol/proj#transformExtent()</a>.</p>
|
<tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use <a href="module-ol_proj.html#.transform">ol/proj#transform()</a> and <a href="module-ol_proj.html#.transformExtent">ol/proj#transformExtent()</a>.</p>
|
||||||
<a href="module-ol_proj.html">ol/proj</a></td>
|
<a href="module-ol_proj.html">ol/proj</a></td>
|
||||||
<td><p>Changes to all <a href="module-ol_Object-BaseObject.html">ol/Object</a>s can be observed by calling the <a href="module-ol_Object-BaseObject.html#on">object.on('propertychange')</a> method. Listeners receive an <a href="module-ol_Object-ObjectEvent.html">ol/Object.ObjectEvent</a> with information on the changed property and old value.</p>
|
<td><p>Changes to all <a href="module-ol_Object-BaseObject.html">ol/Object</a>s can be observed by calling the <a href="module-ol_Object-BaseObject.html#on">object.on('propertychange')</a> method. Listeners receive an <a href="module-ol_Object.ObjectEvent.html">ol/Object.ObjectEvent</a> with information on the changed property and old value.</p>
|
||||||
<td>
|
<td>
|
||||||
<a href="module-ol_Geolocation.html">ol/Geolocation</a><br>
|
<a href="module-ol_Geolocation.html">ol/Geolocation</a><br>
|
||||||
<a href="module-ol_Overlay-Overlay.html">ol/Overlay</a><br></td>
|
<a href="module-ol_Overlay-Overlay.html">ol/Overlay</a><br></td>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Settable</th>
|
<th>Settable</th>
|
||||||
<th><a href="module-ol_Object-ObjectEvent.html">ol/Object.ObjectEvent</a> type</th>
|
<th><a href="module-ol_Object.ObjectEvent.html">ol/Object.ObjectEvent</a> type</th>
|
||||||
<th class="last">Description</th>
|
<th class="last">Description</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ Features for `updates` must have an id set by the feature reader or `ol.Feature#
|
|||||||
|
|
||||||
### 28
|
### 28
|
||||||
|
|
||||||
`renderMode` must be `'image'` or `'hybrid'`.
|
`renderMode` must be `'image'`, `'hybrid'` or `'vector'`.
|
||||||
|
|
||||||
### 29
|
### 29
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 3.2 MiB |
@@ -6,10 +6,10 @@ docs: >
|
|||||||
This example shows how to use <b>postrender</b> events and a <b>vector context</b> to
|
This example shows how to use <b>postrender</b> events and a <b>vector context</b> to
|
||||||
animate a marker feature along a line. In this example an encoded polyline
|
animate a marker feature along a line. In this example an encoded polyline
|
||||||
is being used.
|
is being used.
|
||||||
tags: "animation, feature, postrender, polyline"
|
tags: "animation, feature, postrender, polyline, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
<label for="speed">
|
<label for="speed">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import View from '../src/ol/View.js';
|
|||||||
import Polyline from '../src/ol/format/Polyline.js';
|
import Polyline from '../src/ol/format/Polyline.js';
|
||||||
import Point from '../src/ol/geom/Point.js';
|
import Point from '../src/ol/geom/Point.js';
|
||||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
import VectorSource from '../src/ol/source/Vector.js';
|
import VectorSource from '../src/ol/source/Vector.js';
|
||||||
import {Circle as CircleStyle, Fill, Icon, Stroke, Style} from '../src/ol/style.js';
|
import {Circle as CircleStyle, Fill, Icon, Stroke, Style} from '../src/ol/style.js';
|
||||||
import {getVectorContext} from '../src/ol/render.js';
|
import {getVectorContext} from '../src/ol/render.js';
|
||||||
@@ -121,6 +121,10 @@ const vectorLayer = new VectorLayer({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 center = [-5639523.95, -3501274.52];
|
const center = [-5639523.95, -3501274.52];
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
target: document.getElementById('map'),
|
target: document.getElementById('map'),
|
||||||
@@ -132,9 +136,10 @@ const map = new Map({
|
|||||||
}),
|
}),
|
||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new BingMaps({
|
source: new XYZ({
|
||||||
imagerySet: 'AerialWithLabelsOnDemand',
|
attributions: attributions,
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
|
url: 'https://api.maptiler.com/maps/hybrid/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
tileSize: 512
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
vectorLayer
|
vectorLayer
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ shortdesc: Example of drag rotate and zoom control with full screen effect.
|
|||||||
docs: >
|
docs: >
|
||||||
<p>Hold down <code>Shift+Drag</code> to rotate and zoom. Click the button in the top right corner to go full screen. Then do the <code>Shift+Drag</code> thing again.</p>
|
<p>Hold down <code>Shift+Drag</code> to rotate and zoom. Click the button in the top right corner to go full screen. Then do the <code>Shift+Drag</code> thing again.</p>
|
||||||
<p>If there is no button on the map, your browser does not support the <a href="http://caniuse.com/#feat=fullscreen">Full Screen API</a>.</p>
|
<p>If there is no button on the map, your browser does not support the <a href="http://caniuse.com/#feat=fullscreen">Full Screen API</a>.</p>
|
||||||
tags: "full-screen, drag, rotate, zoom, bing, bing-maps"
|
tags: "full-screen, drag, rotate, zoom, xyz, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -3,9 +3,13 @@ import View from '../src/ol/View.js';
|
|||||||
import {defaults as defaultControls, FullScreen} from '../src/ol/control.js';
|
import {defaults as defaultControls, FullScreen} from '../src/ol/control.js';
|
||||||
import {defaults as defaultInteractions, DragRotateAndZoom} from '../src/ol/interaction.js';
|
import {defaults as defaultInteractions, DragRotateAndZoom} from '../src/ol/interaction.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
|
|
||||||
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 map = new Map({
|
const map = new Map({
|
||||||
controls: defaultControls().extend([
|
controls: defaultControls().extend([
|
||||||
new FullScreen()
|
new FullScreen()
|
||||||
@@ -15,13 +19,13 @@ const map = new Map({
|
|||||||
]),
|
]),
|
||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new BingMaps({
|
source: new XYZ({
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
attributions: attributions,
|
||||||
imagerySet: 'Aerial'
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
// Use the canvas renderer because it's currently the fastest
|
|
||||||
target: 'map',
|
target: 'map',
|
||||||
view: new View({
|
view: new View({
|
||||||
center: [-33519607, 5616436],
|
center: [-33519607, 5616436],
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ shortdesc: Example of a full screen control.
|
|||||||
docs: >
|
docs: >
|
||||||
<p>Click the control in the top right corner to go full screen. Click it again to exit full screen.</p>
|
<p>Click the control in the top right corner to go full screen. Click it again to exit full screen.</p>
|
||||||
<p>If there is no button on the map, your browser does not support the <a href="http://caniuse.com/#feat=fullscreen">Full Screen API</a>.</p>
|
<p>If there is no button on the map, your browser does not support the <a href="http://caniuse.com/#feat=fullscreen">Full Screen API</a>.</p>
|
||||||
tags: "full-screen, bing, bing-maps"
|
tags: "full-screen, xyz, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Map from '../src/ol/Map.js';
|
|||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import {defaults as defaultControls, FullScreen} from '../src/ol/control.js';
|
import {defaults as defaultControls, FullScreen} from '../src/ol/control.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
|
|
||||||
const view = new View({
|
const view = new View({
|
||||||
@@ -10,15 +10,20 @@ const view = new View({
|
|||||||
zoom: 14
|
zoom: 14
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 map = new Map({
|
const map = new Map({
|
||||||
controls: defaultControls().extend([
|
controls: defaultControls().extend([
|
||||||
new FullScreen()
|
new FullScreen()
|
||||||
]),
|
]),
|
||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new BingMaps({
|
source: new XYZ({
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
attributions: attributions,
|
||||||
imagerySet: 'Aerial'
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ title: GPX Data
|
|||||||
shortdesc: Example of using the GPX source.
|
shortdesc: Example of using the GPX source.
|
||||||
docs: >
|
docs: >
|
||||||
Example of using the GPX source.
|
Example of using the GPX source.
|
||||||
tags: "GPX"
|
tags: "GPX, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
<div id="info"> </div>
|
<div id="info"> </div>
|
||||||
|
|||||||
@@ -2,14 +2,19 @@ import Map from '../src/ol/Map.js';
|
|||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import GPX from '../src/ol/format/GPX.js';
|
import GPX from '../src/ol/format/GPX.js';
|
||||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
import VectorSource from '../src/ol/source/Vector.js';
|
import VectorSource from '../src/ol/source/Vector.js';
|
||||||
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';
|
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';
|
||||||
|
|
||||||
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 raster = new TileLayer({
|
const raster = new TileLayer({
|
||||||
source: new BingMaps({
|
source: new XYZ({
|
||||||
imagerySet: 'Aerial',
|
attributions: attributions,
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ docs: >
|
|||||||
<p>Layer rendering can be manipulated in <code>prerender</code> and <code>postrender</code> event listeners.
|
<p>Layer rendering can be manipulated in <code>prerender</code> and <code>postrender</code> event listeners.
|
||||||
These listeners get an event with a reference to the Canvas rendering context.
|
These listeners get an event with a reference to the Canvas rendering context.
|
||||||
In this example, the <code>postrender</code> listener applies a filter to the image data.</p>
|
In this example, the <code>postrender</code> listener applies a filter to the image data.</p>
|
||||||
tags: "filter, image manipulation"
|
tags: "filter, image manipulation, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
<select id="kernel" name="kernel">
|
<select id="kernel" name="kernel">
|
||||||
|
|||||||
@@ -2,12 +2,19 @@ import Map from '../src/ol/Map.js';
|
|||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import {fromLonLat} from '../src/ol/proj.js';
|
import {fromLonLat} from '../src/ol/proj.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
const key = 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5';
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 imagery = new TileLayer({
|
const imagery = new TileLayer({
|
||||||
source: new BingMaps({key: key, imagerySet: 'Aerial'})
|
source: new XYZ({
|
||||||
|
attributions: attributions,
|
||||||
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20,
|
||||||
|
crossOrigin: ''
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
layout: example.html
|
|
||||||
title: Interaction Options
|
|
||||||
shortdesc: Shows interaction options for custom scroll and zoom behavior.
|
|
||||||
docs: >
|
|
||||||
This example uses a custom `ol/interaction/defaults` configuration:
|
|
||||||
by default, wheel/trackpad zoom and drag panning is always active, which
|
|
||||||
can be unexpected on pages with a lot of scrollable content and an embedded
|
|
||||||
map. To perform wheel/trackpad zoom and drag-pan actions only when the map
|
|
||||||
has the focus, set `onFocusOnly: true` as option. This requires a map div
|
|
||||||
with a `tabindex` attribute set.
|
|
||||||
tags: "trackpad, mousewheel, zoom, scroll, interaction, fractional"
|
|
||||||
---
|
|
||||||
<div tabindex="1" id="map" class="map"></div>
|
|
||||||
@@ -18,11 +18,17 @@ const map = new Map({
|
|||||||
|
|
||||||
osm.on('prerender', function(event) {
|
osm.on('prerender', function(event) {
|
||||||
const ctx = event.context;
|
const ctx = event.context;
|
||||||
|
|
||||||
|
// calculate the pixel ratio and rotation of the canvas
|
||||||
|
const matrix = event.inversePixelTransform;
|
||||||
|
const canvasPixelRatio = Math.sqrt(matrix[0] * matrix[0] + matrix[1] * matrix[1]);
|
||||||
|
const canvasRotation = -Math.atan2(matrix[1], matrix[0]);
|
||||||
ctx.save();
|
ctx.save();
|
||||||
const pixelRatio = event.frameState.pixelRatio;
|
// center the canvas and remove rotation to position clipping
|
||||||
const size = map.getSize();
|
ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2);
|
||||||
ctx.translate(size[0] / 2 * pixelRatio, size[1] / 2 * pixelRatio);
|
ctx.rotate(-canvasRotation);
|
||||||
ctx.scale(3 * pixelRatio, 3 * pixelRatio);
|
|
||||||
|
ctx.scale(3 * canvasPixelRatio, 3 * canvasPixelRatio);
|
||||||
ctx.translate(-75, -80);
|
ctx.translate(-75, -80);
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(75, 40);
|
ctx.moveTo(75, 40);
|
||||||
@@ -34,8 +40,11 @@ osm.on('prerender', function(event) {
|
|||||||
ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
|
ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
|
||||||
ctx.clip();
|
ctx.clip();
|
||||||
ctx.translate(75, 80);
|
ctx.translate(75, 80);
|
||||||
ctx.scale(1 / 3 / pixelRatio, 1 / 3 / pixelRatio);
|
ctx.scale(1 / 3 / canvasPixelRatio, 1 / 3 / canvasPixelRatio);
|
||||||
ctx.translate(-size[0] / 2 * pixelRatio, -size[1] / 2 * pixelRatio);
|
|
||||||
|
// reapply canvas rotation and position
|
||||||
|
ctx.rotate(canvasRotation);
|
||||||
|
ctx.translate(-ctx.canvas.width / 2, -ctx.canvas.height / 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
osm.on('postrender', function(event) {
|
osm.on('postrender', function(event) {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ docs: >
|
|||||||
In this example, the <code>prerender</code> listener sets a clipping mask around the most
|
In this example, the <code>prerender</code> listener sets a clipping mask around the most
|
||||||
recent mouse position, giving you a spyglass effect for viewing one layer over another.</p>
|
recent mouse position, giving you a spyglass effect for viewing one layer over another.</p>
|
||||||
<p>Move around the map to see the effect. Use the ↑ up and ↓ down arrow keys to adjust the spyglass size.</p>
|
<p>Move around the map to see the effect. Use the ↑ up and ↓ down arrow keys to adjust the spyglass size.</p>
|
||||||
tags: "spy, image manipulation"
|
tags: "spy, image manipulation, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -2,16 +2,28 @@ import Map from '../src/ol/Map.js';
|
|||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import {fromLonLat} from '../src/ol/proj.js';
|
import {fromLonLat} from '../src/ol/proj.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
|
import {getRenderPixel} from '../src/ol/render.js';
|
||||||
|
|
||||||
const key = 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5';
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 roads = new TileLayer({
|
const roads = new TileLayer({
|
||||||
source: new BingMaps({key: key, imagerySet: 'RoadOnDemand'})
|
source: new XYZ({
|
||||||
|
attributions: attributions,
|
||||||
|
url: 'https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=' + key,
|
||||||
|
tileSize: 512,
|
||||||
|
maxZoom: 22
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const imagery = new TileLayer({
|
const imagery = new TileLayer({
|
||||||
source: new BingMaps({key: key, imagerySet: 'Aerial'})
|
source: new XYZ({
|
||||||
|
attributions: attributions,
|
||||||
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const container = document.getElementById('map');
|
const container = document.getElementById('map');
|
||||||
@@ -54,14 +66,15 @@ container.addEventListener('mouseout', function() {
|
|||||||
// before rendering the layer, do some clipping
|
// before rendering the layer, do some clipping
|
||||||
imagery.on('prerender', function(event) {
|
imagery.on('prerender', function(event) {
|
||||||
const ctx = event.context;
|
const ctx = event.context;
|
||||||
const pixelRatio = event.frameState.pixelRatio;
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
if (mousePosition) {
|
if (mousePosition) {
|
||||||
// only show a circle around the mouse
|
// only show a circle around the mouse
|
||||||
ctx.arc(mousePosition[0] * pixelRatio, mousePosition[1] * pixelRatio,
|
const pixel = getRenderPixel(event, mousePosition);
|
||||||
radius * pixelRatio, 0, 2 * Math.PI);
|
const offset = getRenderPixel(event, [mousePosition[0] + radius, mousePosition[1]]);
|
||||||
ctx.lineWidth = 5 * pixelRatio;
|
const canvasRadius = Math.sqrt(Math.pow(offset[0] - pixel[0], 2) + Math.pow(offset[1] - pixel[1], 2));
|
||||||
|
ctx.arc(pixel[0], pixel[1], canvasRadius, 0, 2 * Math.PI);
|
||||||
|
ctx.lineWidth = 5 * canvasRadius / radius;
|
||||||
ctx.strokeStyle = 'rgba(0,0,0,0.5)';
|
ctx.strokeStyle = 'rgba(0,0,0,0.5)';
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ title: Layer Swipe
|
|||||||
shortdesc: Example of a Layer swipe map.
|
shortdesc: Example of a Layer swipe map.
|
||||||
docs: >
|
docs: >
|
||||||
Example of a Layer swipe map.
|
Example of a Layer swipe map.
|
||||||
tags: "swipe, openstreetmap"
|
tags: "swipe, openstreetmap, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
<input id="swipe" type="range" style="width: 100%">
|
<input id="swipe" type="range" style="width: 100%">
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
|
||||||
import OSM from '../src/ol/source/OSM.js';
|
import OSM from '../src/ol/source/OSM.js';
|
||||||
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
|
import {getRenderPixel} from '../src/ol/render.js';
|
||||||
|
|
||||||
const osm = new TileLayer({
|
const osm = new TileLayer({
|
||||||
source: new OSM()
|
source: new OSM()
|
||||||
});
|
});
|
||||||
const bing = new TileLayer({
|
|
||||||
source: new BingMaps({
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> ' +
|
||||||
imagerySet: 'Aerial'
|
'<a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>';
|
||||||
|
|
||||||
|
const aerial = new TileLayer({
|
||||||
|
source: new XYZ({
|
||||||
|
attributions: attributions,
|
||||||
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
layers: [osm, bing],
|
layers: [osm, aerial],
|
||||||
target: 'map',
|
target: 'map',
|
||||||
view: new View({
|
view: new View({
|
||||||
center: [0, 0],
|
center: [0, 0],
|
||||||
@@ -25,17 +32,26 @@ const map = new Map({
|
|||||||
|
|
||||||
const swipe = document.getElementById('swipe');
|
const swipe = document.getElementById('swipe');
|
||||||
|
|
||||||
bing.on('prerender', function(event) {
|
aerial.on('prerender', function(event) {
|
||||||
const ctx = event.context;
|
const ctx = event.context;
|
||||||
const width = ctx.canvas.width * (swipe.value / 100);
|
const mapSize = map.getSize();
|
||||||
|
const width = mapSize[0] * (swipe.value / 100);
|
||||||
|
const tl = getRenderPixel(event, [width, 0]);
|
||||||
|
const tr = getRenderPixel(event, [mapSize[0], 0]);
|
||||||
|
const bl = getRenderPixel(event, [width, mapSize[1]]);
|
||||||
|
const br = getRenderPixel(event, mapSize);
|
||||||
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.rect(width, 0, ctx.canvas.width - width, ctx.canvas.height);
|
ctx.moveTo(tl[0], tl[1]);
|
||||||
|
ctx.lineTo(bl[0], bl[1]);
|
||||||
|
ctx.lineTo(br[0], br[1]);
|
||||||
|
ctx.lineTo(tr[0], tr[1]);
|
||||||
|
ctx.closePath();
|
||||||
ctx.clip();
|
ctx.clip();
|
||||||
});
|
});
|
||||||
|
|
||||||
bing.on('postrender', function(event) {
|
aerial.on('postrender', function(event) {
|
||||||
const ctx = event.context;
|
const ctx = event.context;
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ docs: >
|
|||||||
<p>This example makes use of the <code>postrender</code> event listener to
|
<p>This example makes use of the <code>postrender</code> event listener to
|
||||||
oversample imagery in a circle around the pointer location. Listeners for this event have access to the Canvas context and can manipulate image data.</p>
|
oversample imagery in a circle around the pointer location. Listeners for this event have access to the Canvas context and can manipulate image data.</p>
|
||||||
<p>Move around the map to see the effect. Use the ↑ up and ↓ down arrow keys to adjust the magnified circle size.</p>
|
<p>Move around the map to see the effect. Use the ↑ up and ↓ down arrow keys to adjust the magnified circle size.</p>
|
||||||
tags: "magnify, image manipulation"
|
tags: "magnify, image manipulation, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -2,13 +2,20 @@ import Map from '../src/ol/Map.js';
|
|||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import {fromLonLat} from '../src/ol/proj.js';
|
import {fromLonLat} from '../src/ol/proj.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
import {getRenderPixel} from '../src/ol/render.js';
|
import {getRenderPixel} from '../src/ol/render.js';
|
||||||
|
|
||||||
const key = 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5';
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 imagery = new TileLayer({
|
const imagery = new TileLayer({
|
||||||
source: new BingMaps({key: key, imagerySet: 'Aerial'})
|
source: new XYZ({
|
||||||
|
attributions: attributions,
|
||||||
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20,
|
||||||
|
crossOrigin: ''
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const container = document.getElementById('map');
|
const container = document.getElementById('map');
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
layout: example.html
|
||||||
|
title: Page Scrolling
|
||||||
|
shortdesc: Shows a map that does not interrupt page scrolling.
|
||||||
|
docs: >
|
||||||
|
To perform wheel/trackpad zoom and drag-pan actions only when the map
|
||||||
|
has the focus, configure your map div with a `tabindex` attribute.
|
||||||
|
tags: "trackpad, mousewheel, zoom, scroll, page"
|
||||||
|
---
|
||||||
|
<div tabindex="1" id="map" class="map"></div>
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import {defaults as defaultInteractions} from '../src/ol/interaction.js';
|
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import OSM from '../src/ol/source/OSM.js';
|
import OSM from '../src/ol/source/OSM.js';
|
||||||
|
|
||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
interactions: defaultInteractions({
|
|
||||||
onFocusOnly: true
|
|
||||||
}),
|
|
||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new OSM()
|
source: new OSM()
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
.ol-popup {
|
.ol-popup {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
-webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
|
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
|
||||||
filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
|
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border: 1px solid #cccccc;
|
border: 1px solid #cccccc;
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ docs: >
|
|||||||
those pixels based on a threshold value (values above the
|
those pixels based on a threshold value (values above the
|
||||||
threshold are green and those below are transparent).
|
threshold are green and those below are transparent).
|
||||||
</p>
|
</p>
|
||||||
tags: "raster, pixel"
|
tags: "raster, pixel, maptiler"
|
||||||
resources:
|
resources:
|
||||||
- https://unpkg.com/d3@4.12.0/build/d3.js
|
- https://unpkg.com/d3@4.12.0/build/d3.js
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div class="rel">
|
<div class="rel">
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
import RasterSource from '../src/ol/source/Raster.js';
|
import RasterSource from '../src/ol/source/Raster.js';
|
||||||
|
|
||||||
const minVgi = 0;
|
const minVgi = 0;
|
||||||
@@ -46,9 +46,16 @@ function summarize(value, counts) {
|
|||||||
/**
|
/**
|
||||||
* Use aerial imagery as the input data for the raster source.
|
* Use aerial imagery as the input data for the raster source.
|
||||||
*/
|
*/
|
||||||
const bing = new BingMaps({
|
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
imagerySet: 'Aerial'
|
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 aerial = new XYZ({
|
||||||
|
attributions: attributions,
|
||||||
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20,
|
||||||
|
crossOrigin: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -57,7 +64,7 @@ const bing = new BingMaps({
|
|||||||
* be colored green.
|
* be colored green.
|
||||||
*/
|
*/
|
||||||
const raster = new RasterSource({
|
const raster = new RasterSource({
|
||||||
sources: [bing],
|
sources: [aerial],
|
||||||
/**
|
/**
|
||||||
* Run calculations on pixel data.
|
* Run calculations on pixel data.
|
||||||
* @param {Array} pixels List of pixels (one per source).
|
* @param {Array} pixels List of pixels (one per source).
|
||||||
@@ -110,7 +117,7 @@ raster.on('afteroperations', function(event) {
|
|||||||
const map = new Map({
|
const map = new Map({
|
||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: bing
|
source: aerial
|
||||||
}),
|
}),
|
||||||
new ImageLayer({
|
new ImageLayer({
|
||||||
source: raster
|
source: raster
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ docs: >
|
|||||||
This example also shows how an additional function can be made available
|
This example also shows how an additional function can be made available
|
||||||
to the operation.
|
to the operation.
|
||||||
</p>
|
</p>
|
||||||
tags: "raster, region growing"
|
tags: "raster, region growing, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map" style="cursor: pointer"></div>
|
<div id="map" class="map" style="cursor: pointer"></div>
|
||||||
<table class="controls">
|
<table class="controls">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Map from '../src/ol/Map.js';
|
|||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||||
import {fromLonLat} from '../src/ol/proj.js';
|
import {fromLonLat} from '../src/ol/proj.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
import RasterSource from '../src/ol/source/Raster.js';
|
import RasterSource from '../src/ol/source/Raster.js';
|
||||||
|
|
||||||
function growRegion(inputs, data) {
|
function growRegion(inputs, data) {
|
||||||
@@ -72,10 +72,17 @@ function next4Edges(edge) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5';
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 imagery = new TileLayer({
|
const imagery = new TileLayer({
|
||||||
source: new BingMaps({key: key, imagerySet: 'Aerial'})
|
source: new XYZ({
|
||||||
|
attributions: attributions,
|
||||||
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20,
|
||||||
|
crossOrigin: ''
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const raster = new RasterSource({
|
const raster = new RasterSource({
|
||||||
|
|||||||
@@ -55,15 +55,6 @@ proj54009.setExtent([-18e6, -9e6, 18e6, 9e6]);
|
|||||||
|
|
||||||
const layers = {};
|
const layers = {};
|
||||||
|
|
||||||
layers['bng'] = new TileLayer({
|
|
||||||
source: new XYZ({
|
|
||||||
projection: 'EPSG:27700',
|
|
||||||
url: 'https://tileserver.maptiler.com/miniscale/{z}/{x}/{y}.png',
|
|
||||||
crossOrigin: '',
|
|
||||||
maxZoom: 6
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
layers['osm'] = new TileLayer({
|
layers['osm'] = new TileLayer({
|
||||||
source: new OSM()
|
source: new OSM()
|
||||||
});
|
});
|
||||||
@@ -95,9 +86,11 @@ layers['wms21781'] = new TileLayer({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const parser = new WMTSCapabilities();
|
const parser = new WMTSCapabilities();
|
||||||
const url = 'https://map1.vis.earthdata.nasa.gov/wmts-arctic/' +
|
|
||||||
|
layers['wmts3413'] = new TileLayer();
|
||||||
|
const urlA = 'https://map1.vis.earthdata.nasa.gov/wmts-arctic/' +
|
||||||
'wmts.cgi?SERVICE=WMTS&request=GetCapabilities';
|
'wmts.cgi?SERVICE=WMTS&request=GetCapabilities';
|
||||||
fetch(url).then(function(response) {
|
fetch(urlA).then(function(response) {
|
||||||
return response.text();
|
return response.text();
|
||||||
}).then(function(text) {
|
}).then(function(text) {
|
||||||
const result = parser.read(text);
|
const result = parser.read(text);
|
||||||
@@ -108,9 +101,23 @@ fetch(url).then(function(response) {
|
|||||||
options.crossOrigin = '';
|
options.crossOrigin = '';
|
||||||
options.projection = 'EPSG:3413';
|
options.projection = 'EPSG:3413';
|
||||||
options.wrapX = false;
|
options.wrapX = false;
|
||||||
layers['wmts3413'] = new TileLayer({
|
layers['wmts3413'].setSource(new WMTS(options));
|
||||||
source: new WMTS(options)
|
});
|
||||||
|
|
||||||
|
layers['bng'] = new TileLayer();
|
||||||
|
const urlB = 'https://tiles.arcgis.com/tiles/qHLhLQrcvEnxjtPr/arcgis/rest/services/OS_Open_Raster/MapServer/WMTS';
|
||||||
|
fetch(urlB).then(function(response) {
|
||||||
|
return response.text();
|
||||||
|
}).then(function(text) {
|
||||||
|
const result = parser.read(text);
|
||||||
|
const options = optionsFromCapabilities(result, {
|
||||||
|
layer: 'OS_Open_Raster'
|
||||||
});
|
});
|
||||||
|
options.attributions = 'Contains OS data © Crown Copyright and database right 2019';
|
||||||
|
options.crossOrigin = '';
|
||||||
|
options.projection = 'EPSG:27700';
|
||||||
|
options.wrapX = false;
|
||||||
|
layers['bng'].setSource(new WMTS(options));
|
||||||
});
|
});
|
||||||
|
|
||||||
layers['grandcanyon'] = new TileLayer({
|
layers['grandcanyon'] = new TileLayer({
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ docs: >
|
|||||||
<a href="https://www.mapbox.com/blog/terrain-rgb/">Mapbox Terrain-RGB tiles</a>
|
<a href="https://www.mapbox.com/blog/terrain-rgb/">Mapbox Terrain-RGB tiles</a>
|
||||||
to "flood" areas below the elevation shown on the sea level slider.
|
to "flood" areas below the elevation shown on the sea level slider.
|
||||||
</p>
|
</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"
|
tags: "raster, pixel operation, flood"
|
||||||
cloak:
|
cloak:
|
||||||
- key: pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg
|
- key: pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg
|
||||||
|
|||||||
@@ -22,9 +22,15 @@ function flood(pixels, data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const key = 'pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg';
|
const key = 'pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg';
|
||||||
const elevation = new XYZ({
|
const elevation = new TileLayer({
|
||||||
url: 'https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=' + key,
|
source: new XYZ({
|
||||||
crossOrigin: 'anonymous'
|
url: 'https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=' + key,
|
||||||
|
crossOrigin: 'anonymous'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
elevation.on('prerender', function(evt) {
|
||||||
|
evt.context.imageSmoothingEnabled = false;
|
||||||
|
evt.context.msImageSmoothingEnabled = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
const raster = new RasterSource({
|
const raster = new RasterSource({
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ title: Shared Views
|
|||||||
shortdesc: Two maps share view properties
|
shortdesc: Two maps share view properties
|
||||||
docs: >
|
docs: >
|
||||||
Two maps (one Road, one Aerial) share the same center, resolution and rotation.
|
Two maps (one Road, one Aerial) share the same center, resolution and rotation.
|
||||||
tags: "side-by-side, bing, bing-maps"
|
tags: "side-by-side, xyz, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="half">
|
<div class="half">
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 roadLayer = new TileLayer({
|
const roadLayer = new TileLayer({
|
||||||
source: new BingMaps({
|
source: new XYZ({
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
attributions: attributions,
|
||||||
imagerySet: 'RoadOnDemand',
|
url: 'https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=' + key,
|
||||||
maxZoom: 19
|
tileSize: 512,
|
||||||
|
maxZoom: 22
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const aerialLayer = new TileLayer({
|
const aerialLayer = new TileLayer({
|
||||||
source: new BingMaps({
|
source: new XYZ({
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
attributions: attributions,
|
||||||
imagerySet: 'Aerial',
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
maxZoom: 19
|
maxZoom: 20
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ title: Street Labels
|
|||||||
shortdesc: Render street names.
|
shortdesc: Render street names.
|
||||||
docs: >
|
docs: >
|
||||||
Example showing the use of a text style with `placement: 'line'` to render text along a path.
|
Example showing the use of a text style with `placement: 'line'` to render text along a path.
|
||||||
tags: "vector, label, streets"
|
tags: "vector, label, streets, maptiler"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import View from '../src/ol/View.js';
|
|||||||
import {getCenter} from '../src/ol/extent.js';
|
import {getCenter} from '../src/ol/extent.js';
|
||||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
import VectorSource from '../src/ol/source/Vector.js';
|
import VectorSource from '../src/ol/source/Vector.js';
|
||||||
import {Fill, Style, Text} from '../src/ol/style.js';
|
import {Fill, Style, Text} from '../src/ol/style.js';
|
||||||
|
|
||||||
@@ -17,12 +17,17 @@ const style = new Style({
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 viewExtent = [1817379, 6139595, 1827851, 6143616];
|
const viewExtent = [1817379, 6139595, 1827851, 6143616];
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
layers: [new TileLayer({
|
layers: [new TileLayer({
|
||||||
source: new BingMaps({
|
source: new XYZ({
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
attributions: attributions,
|
||||||
imagerySet: 'Aerial'
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||||
|
maxZoom: 20
|
||||||
})
|
})
|
||||||
}), new VectorLayer({
|
}), new VectorLayer({
|
||||||
declutter: true,
|
declutter: true,
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#map {
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg-layer path:hover {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
layout: example.html
|
||||||
|
title: SVG Layer
|
||||||
|
shortdesc: Example of a map with an interactive svg layer.
|
||||||
|
docs: >
|
||||||
|
With a plain `ol/Layer` and a `render` function, we can use an interactive svg as layer. Hover over countries to see the interactivity that is defined purely with a css `:hover` pseudo-class.
|
||||||
|
tags: "svg, layer, render, transform"
|
||||||
|
---
|
||||||
|
<div id="map" class="map"></div>
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import Map from '../src/ol/Map.js';
|
||||||
|
import View from '../src/ol/View.js';
|
||||||
|
import Layer from '../src/ol/layer/Layer.js';
|
||||||
|
import {composeCssTransform} from '../src/ol/transform.js';
|
||||||
|
|
||||||
|
const map = new Map({
|
||||||
|
target: 'map',
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
extent: [-180, -90, 180, 90],
|
||||||
|
projection: 'EPSG:4326',
|
||||||
|
zoom: 2
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const svgContainer = document.createElement('div');
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', 'data/world.svg');
|
||||||
|
xhr.addEventListener('load', function() {
|
||||||
|
const svg = xhr.responseXML.documentElement;
|
||||||
|
svgContainer.ownerDocument.importNode(svg);
|
||||||
|
svgContainer.appendChild(svg);
|
||||||
|
});
|
||||||
|
xhr.send();
|
||||||
|
|
||||||
|
const width = 2560;
|
||||||
|
const height = 1280;
|
||||||
|
const svgResolution = 360 / width;
|
||||||
|
svgContainer.style.width = width + 'px';
|
||||||
|
svgContainer.style.height = height + 'px';
|
||||||
|
svgContainer.style.transformOrigin = 'top left';
|
||||||
|
svgContainer.className = 'svg-layer';
|
||||||
|
|
||||||
|
map.addLayer(new Layer({
|
||||||
|
render: function(frameState) {
|
||||||
|
const scale = svgResolution / frameState.viewState.resolution;
|
||||||
|
const center = frameState.viewState.center;
|
||||||
|
const size = frameState.size;
|
||||||
|
const cssTransform = composeCssTransform(
|
||||||
|
size[0] / 2, size[1] / 2,
|
||||||
|
scale, scale,
|
||||||
|
frameState.viewState.rotation,
|
||||||
|
-center[0] / svgResolution - width / 2, center[1] / svgResolution - height / 2);
|
||||||
|
svgContainer.style.transform = cssTransform;
|
||||||
|
svgContainer.style.opacity = this.getOpacity();
|
||||||
|
return svgContainer;
|
||||||
|
}
|
||||||
|
}));
|
||||||
@@ -108,7 +108,14 @@
|
|||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<a class="codepen-button pull-right"><i class="fa fa-codepen"></i> Edit</a>
|
<a class="codepen-button pull-right"><i class="fa fa-codepen"></i> Edit</a>
|
||||||
<div class="span12">
|
<div class="span12">
|
||||||
<h4 id="title">{{ title }}</h4>
|
<h4 id="title">
|
||||||
|
{{ title }}
|
||||||
|
</h4>
|
||||||
|
<p class="tags">
|
||||||
|
{{#each tags}}
|
||||||
|
<a href="./index.html?q={{.}}" class="label label-primary">{{.}}</a>
|
||||||
|
{{/each}}
|
||||||
|
</p>
|
||||||
{{{ contents }}}
|
{{{ contents }}}
|
||||||
</div>
|
</div>
|
||||||
<form method="POST" id="codepen-form" target="_blank" action="https://codesandbox.io/api/v1/sandboxes/define">
|
<form method="POST" id="codepen-form" target="_blank" action="https://codesandbox.io/api/v1/sandboxes/define">
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
layout: example.html
|
||||||
|
title: Panning and page scrolling
|
||||||
|
shortdesc: Shows a map that allows page scrolling unless two fingers or Cmd/Ctrl are used to pan the map.
|
||||||
|
docs: >
|
||||||
|
This example shows a common behavior for page scrolling: on touch devices, when one finger
|
||||||
|
is placed on the map, it can be used to scroll the page. Only two fingers will perform drag pan.
|
||||||
|
For mouse or trackpad devices, the platform modifier key (Cmd or Ctrl) will enable drag pan on
|
||||||
|
the map, otherwise the page will scroll.
|
||||||
|
tags: "trackpad, mousewheel, zoom, scroll, page"
|
||||||
|
---
|
||||||
|
<div id="map" class="map"></div>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import Map from '../src/ol/Map.js';
|
||||||
|
import View from '../src/ol/View.js';
|
||||||
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
|
import OSM from '../src/ol/source/OSM.js';
|
||||||
|
import {defaults, DragPan, MouseWheelZoom} from '../src/ol/interaction.js';
|
||||||
|
import {platformModifierKeyOnly} from '../src/ol/events/condition.js';
|
||||||
|
|
||||||
|
const map = new Map({
|
||||||
|
interactions: defaults({dragPan: false, mouseWheelZoom: false}).extend([
|
||||||
|
new DragPan({
|
||||||
|
condition: function(event) {
|
||||||
|
return this.getPointerCount() === 2 || platformModifierKeyOnly(event);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new MouseWheelZoom({
|
||||||
|
condition: platformModifierKeyOnly
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
source: new OSM()
|
||||||
|
})
|
||||||
|
],
|
||||||
|
target: 'map',
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 2
|
||||||
|
})
|
||||||
|
});
|
||||||
@@ -5,7 +5,11 @@ shortdesc: Select features from vector tiles.
|
|||||||
docs: >
|
docs: >
|
||||||
<p>
|
<p>
|
||||||
Click a rendered vector-tile feature to highlight it on the map. Click on an empty spot (ocean) to reset the selection.
|
Click a rendered vector-tile feature to highlight it on the map. Click on an empty spot (ocean) to reset the selection.
|
||||||
By changing the action type to "Multi Select" you can select multiple features at a time.
|
By changing the action type to "Multi Select" you can select multiple features at a time. With "Single Select on hover",
|
||||||
|
features will be higlighted when the pointer is above them.
|
||||||
|
</p><p>
|
||||||
|
The selection layer is configured with `renderMode: 'vector'` for better performance on frequent redraws,
|
||||||
|
i.e. when 'Single select on hover' is selected.
|
||||||
</p>
|
</p>
|
||||||
tags: "vector tiles, selection"
|
tags: "vector tiles, selection"
|
||||||
---
|
---
|
||||||
@@ -15,5 +19,6 @@ tags: "vector tiles, selection"
|
|||||||
<select id="type" class="form-control">
|
<select id="type" class="form-control">
|
||||||
<option value="singleselect" selected>Single Select</option>
|
<option value="singleselect" selected>Single Select</option>
|
||||||
<option value="multiselect">Multi Select</option>
|
<option value="multiselect">Multi Select</option>
|
||||||
|
<option value="singleselect-hover">Single Select on hover</option>
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -8,6 +8,25 @@ import {Fill, Stroke, Style} from '../src/ol/style.js';
|
|||||||
// lookup for selection objects
|
// lookup for selection objects
|
||||||
let selection = {};
|
let selection = {};
|
||||||
|
|
||||||
|
const country = new Style({
|
||||||
|
stroke: new Stroke({
|
||||||
|
color: 'gray',
|
||||||
|
width: 1
|
||||||
|
}),
|
||||||
|
fill: new Fill({
|
||||||
|
color: 'rgba(20,20,20,0.9)'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const selectedCountry = new Style({
|
||||||
|
stroke: new Stroke({
|
||||||
|
color: 'rgba(200,20,20,0.8)',
|
||||||
|
width: 2
|
||||||
|
}),
|
||||||
|
fill: new Fill({
|
||||||
|
color: 'rgba(200,20,20,0.4)'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
const vtLayer = new VectorTileLayer({
|
const vtLayer = new VectorTileLayer({
|
||||||
declutter: true,
|
declutter: true,
|
||||||
source: new VectorTileSource({
|
source: new VectorTileSource({
|
||||||
@@ -18,18 +37,7 @@ const vtLayer = new VectorTileLayer({
|
|||||||
url: 'https://ahocevar.com/geoserver/gwc/service/tms/1.0.0/' +
|
url: 'https://ahocevar.com/geoserver/gwc/service/tms/1.0.0/' +
|
||||||
'ne:ne_10m_admin_0_countries@EPSG%3A900913@pbf/{z}/{x}/{-y}.pbf'
|
'ne:ne_10m_admin_0_countries@EPSG%3A900913@pbf/{z}/{x}/{-y}.pbf'
|
||||||
}),
|
}),
|
||||||
style: function(feature) {
|
style: country
|
||||||
const selected = !!selection[feature.getId()];
|
|
||||||
return new Style({
|
|
||||||
stroke: new Stroke({
|
|
||||||
color: selected ? 'rgba(200,20,20,0.8)' : 'gray',
|
|
||||||
width: selected ? 2 : 1
|
|
||||||
}),
|
|
||||||
fill: new Fill({
|
|
||||||
color: selected ? 'rgba(200,20,20,0.2)' : 'rgba(20,20,20,0.9)'
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const map = new Map({
|
const map = new Map({
|
||||||
@@ -39,18 +47,34 @@ const map = new Map({
|
|||||||
target: 'map',
|
target: 'map',
|
||||||
view: new View({
|
view: new View({
|
||||||
center: [0, 0],
|
center: [0, 0],
|
||||||
zoom: 2
|
zoom: 2,
|
||||||
|
multiWorld: true
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Selection
|
||||||
|
const selectionLayer = new VectorTileLayer({
|
||||||
|
map: map,
|
||||||
|
renderMode: 'vector',
|
||||||
|
source: vtLayer.getSource(),
|
||||||
|
style: function(feature) {
|
||||||
|
if (feature.getId() in selection) {
|
||||||
|
return selectedCountry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const selectElement = document.getElementById('type');
|
const selectElement = document.getElementById('type');
|
||||||
|
|
||||||
map.on('click', function(event) {
|
map.on(['click', 'pointermove'], function(event) {
|
||||||
|
if (selectElement.value === 'singleselect-hover' && event.type !== 'pointermove' ||
|
||||||
|
selectElement.value !== 'singleselect-hover' && event.type === 'pointermove') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
vtLayer.getFeatures(event.pixel).then(function(features) {
|
vtLayer.getFeatures(event.pixel).then(function(features) {
|
||||||
if (!features.length) {
|
if (!features.length) {
|
||||||
selection = {};
|
selection = {};
|
||||||
// force redraw of layer style
|
selectionLayer.changed();
|
||||||
vtLayer.setStyle(vtLayer.getStyle());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const feature = features[0];
|
const feature = features[0];
|
||||||
@@ -59,14 +83,12 @@ map.on('click', function(event) {
|
|||||||
}
|
}
|
||||||
const fid = feature.getId();
|
const fid = feature.getId();
|
||||||
|
|
||||||
if (selectElement.value === 'singleselect') {
|
if (selectElement.value.startsWith('singleselect')) {
|
||||||
selection = {};
|
selection = {};
|
||||||
}
|
}
|
||||||
// add selected feature to lookup
|
// add selected feature to lookup
|
||||||
selection[fid] = feature;
|
selection[fid] = feature;
|
||||||
|
|
||||||
// force redraw of layer style
|
selectionLayer.changed();
|
||||||
vtLayer.setStyle(vtLayer.getStyle());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,19 +3,67 @@ layout: example.html
|
|||||||
title: WebGL points layer
|
title: WebGL points layer
|
||||||
shortdesc: Using a WebGL-optimized layer to render a large quantities of points
|
shortdesc: Using a WebGL-optimized layer to render a large quantities of points
|
||||||
docs: >
|
docs: >
|
||||||
<p>This example shows how to use a <code>WebGLPointsLayer</code> to show a large amount of points on the map.</p>
|
This example shows how to use a `WebGLPointsLayer` to show a large amount of points on the map.
|
||||||
<p>The layer is given a style in JSON format which allows a certain level of customization of the final reprensentation.</p>
|
The layer is given a style in JSON format which allows a certain level of customization of the final reprensentation.
|
||||||
<p>
|
|
||||||
The following operators can be used for numerical values:
|
The following operators can be used:
|
||||||
<ul>
|
|
||||||
<li><code>["get", "attributeName"]</code> fetches a numeric attribute value for each feature</li>
|
* Reading operators:
|
||||||
<li><code>["+", value, value]</code> adds two values (which an either be numeric, or the result of another operator)</li>
|
* `['get', 'attributeName']` fetches a feature attribute (it will be prefixed by `a_` in the shader)
|
||||||
<li><code>["*", value, value]</code> multiplies two values</li>
|
Note: those will be taken from the attributes provided to the renderer
|
||||||
<li><code>["clamp", value, min, max]</code> outputs a value between <code>min</code> and <code>max</code></li>
|
* `['var', 'varName']` fetches a value from the style variables, or 0 if undefined
|
||||||
<li><code>["stretch", value, low1, high1, low2, high2]</code> outputs a value which has been mapped from the
|
* `['time']` returns the time in seconds since the creation of the layer
|
||||||
<code>low1..high1</code> range to the <code>low2..high2</code> range</li>
|
* `['zoom']` returns the current zoom level
|
||||||
</ul>
|
* `['resolution']` returns the current resolution
|
||||||
</p>
|
|
||||||
|
* Math operators:
|
||||||
|
* `['*', value1, value2]` multiplies `value1` by `value2`
|
||||||
|
* `['/', value1, value2]` divides `value1` by `value2`
|
||||||
|
* `['+', value1, value2]` adds `value1` and `value2`
|
||||||
|
* `['-', value1, value2]` subtracts `value2` from `value1`
|
||||||
|
* `['clamp', value, low, high]` clamps `value` between `low` and `high`
|
||||||
|
* `['%', value1, value2]` returns the result of `value1 % value2` (modulo)
|
||||||
|
* `['^', value1, value2]` returns the value of `value1` raised to the `value2` power
|
||||||
|
|
||||||
|
* Transform operators:
|
||||||
|
* `['case', condition1, output1, ...conditionN, outputN, fallback]` selects the first output whose corresponding
|
||||||
|
condition evaluates to `true`. If no match is found, returns the `fallback` value.
|
||||||
|
All conditions should be `boolean`, output and fallback can be any kind.
|
||||||
|
* `['match', input, match1, output1, ...matchN, outputN, fallback]` compares the `input` value against all
|
||||||
|
provided `matchX` values, returning the output associated with the first valid match. If no match is found,
|
||||||
|
returns the `fallback` value.
|
||||||
|
`input` and `matchX` values must all be of the same type, and can be `number` or `string`. `outputX` and
|
||||||
|
`fallback` values must be of the same type, and can be of any kind.
|
||||||
|
* `['interpolate', interpolation, input, stop1, output1, ...stopN, outputN]` returns a value by interpolating between
|
||||||
|
pairs of inputs and outputs; `interpolation` can either be `['linear']` or `['exponential', base]` where `base` is
|
||||||
|
the rate of increase from stop A to stop B (i.e. power to which the interpolation ratio is raised); a value
|
||||||
|
of 1 is equivalent to `['linear']`.
|
||||||
|
`input` and `stopX` values must all be of type `number`. `outputX` values can be `number` or `color` values.
|
||||||
|
Note: `input` will be clamped between `stop1` and `stopN`, meaning that all output values will be comprised
|
||||||
|
between `output1` and `outputN`.
|
||||||
|
|
||||||
|
* Logical operators:
|
||||||
|
* `['<', value1, value2]` returns `true` if `value1` is strictly lower than `value2`, or `false` otherwise.
|
||||||
|
* `['<=', value1, value2]` returns `true` if `value1` is lower than or equals `value2`, or `false` otherwise.
|
||||||
|
* `['>', value1, value2]` returns `true` if `value1` is strictly greater than `value2`, or `false` otherwise.
|
||||||
|
* `['>=', value1, value2]` returns `true` if `value1` is greater than or equals `value2`, or `false` otherwise.
|
||||||
|
* `['==', value1, value2]` returns `true` if `value1` equals `value2`, or `false` otherwise.
|
||||||
|
* `['!=', value1, value2]` returns `true` if `value1` does not equal `value2`, or `false` otherwise.
|
||||||
|
* `['!', value1]` returns `false` if `value1` is `true` or greater than `0`, or `true` otherwise.
|
||||||
|
* `['between', value1, value2, value3]` returns `true` if `value1` is contained between `value2` and `value3`
|
||||||
|
(inclusively), or `false` otherwise.
|
||||||
|
|
||||||
|
* Conversion operators:
|
||||||
|
* `['array', value1, ...valueN]` creates a numerical array from `number` values; please note that the amount of
|
||||||
|
values can currently only be 2, 3 or 4.
|
||||||
|
* `['color', red, green, blue, alpha]` creates a `color` value from `number` values; the `alpha` parameter is
|
||||||
|
optional; if not specified, it will be set to 1.
|
||||||
|
Note: `red`, `green` and `blue` components must be values between 0 and 255; `alpha` between 0 and 1.
|
||||||
|
Values can either be literals or another operator, as they will be evaluated recursively.
|
||||||
|
Literal values can be of the following types:
|
||||||
|
* `boolean`
|
||||||
|
* `number`
|
||||||
|
* `string`
|
||||||
|
|
||||||
tags: "webgl, point, layer, feature"
|
tags: "webgl, point, layer, feature"
|
||||||
experimental: true
|
experimental: true
|
||||||
@@ -29,6 +77,7 @@ experimental: true
|
|||||||
<option value="triangles-latitude">Triangles, color related to latitude</option>
|
<option value="triangles-latitude">Triangles, color related to latitude</option>
|
||||||
<option value="circles">Circles, size related to population</option>
|
<option value="circles">Circles, size related to population</option>
|
||||||
<option value="circles-zoom">Circles, size related to zoom</option>
|
<option value="circles-zoom">Circles, size related to zoom</option>
|
||||||
|
<option value="rotating-bars">Rotating bars</option>
|
||||||
</select>
|
</select>
|
||||||
<textarea style="width: 100%; height: 20rem; font-family: monospace; font-size: small;" id="style-editor"></textarea>
|
<textarea style="width: 100%; height: 20rem; font-family: monospace; font-size: small;" id="style-editor"></textarea>
|
||||||
<small>
|
<small>
|
||||||
|
|||||||
@@ -95,6 +95,35 @@ const predefinedStyles = {
|
|||||||
offset: [0, 0],
|
offset: [0, 0],
|
||||||
opacity: 0.95
|
opacity: 0.95
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'rotating-bars': {
|
||||||
|
symbol: {
|
||||||
|
symbolType: 'square',
|
||||||
|
rotation: ['*', [
|
||||||
|
'time'
|
||||||
|
], 0.1],
|
||||||
|
size: ['array', 4, [
|
||||||
|
'interpolate',
|
||||||
|
['linear'],
|
||||||
|
['get', 'population'],
|
||||||
|
20000, 4,
|
||||||
|
300000, 28]
|
||||||
|
],
|
||||||
|
color: [
|
||||||
|
'interpolate',
|
||||||
|
['linear'],
|
||||||
|
['get', 'population'],
|
||||||
|
20000, '#ffdc00',
|
||||||
|
300000, '#ff5b19'
|
||||||
|
],
|
||||||
|
offset: ['array', 0, [
|
||||||
|
'interpolate',
|
||||||
|
['linear'],
|
||||||
|
['get', 'population'],
|
||||||
|
20000, 2,
|
||||||
|
300000, 14]
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -167,3 +196,10 @@ function onSelectChange() {
|
|||||||
}
|
}
|
||||||
onSelectChange();
|
onSelectChange();
|
||||||
select.addEventListener('change', onSelectChange);
|
select.addEventListener('change', onSelectChange);
|
||||||
|
|
||||||
|
// animate the map
|
||||||
|
function animate() {
|
||||||
|
map.render();
|
||||||
|
window.requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
animate();
|
||||||
|
|||||||
@@ -138,9 +138,13 @@ ExampleBuilder.prototype.apply = function(compiler) {
|
|||||||
.filter(chunk => chunk.names[0] !== this.common);
|
.filter(chunk => chunk.names[0] !== this.common);
|
||||||
|
|
||||||
const exampleData = [];
|
const exampleData = [];
|
||||||
|
const uniqueTags = new Set();
|
||||||
const promises = chunks.map(async chunk => {
|
const promises = chunks.map(async chunk => {
|
||||||
const [assets, data] = await this.render(compiler.context, chunk);
|
const [assets, data] = await this.render(compiler.context, chunk);
|
||||||
|
|
||||||
|
// collect tags for main page... TODO: implement index tag links
|
||||||
|
data.tags.forEach(tag => uniqueTags.add(tag));
|
||||||
|
|
||||||
exampleData.push({
|
exampleData.push({
|
||||||
link: data.filename,
|
link: data.filename,
|
||||||
example: data.filename,
|
example: data.filename,
|
||||||
@@ -158,7 +162,8 @@ ExampleBuilder.prototype.apply = function(compiler) {
|
|||||||
|
|
||||||
const info = {
|
const info = {
|
||||||
examples: exampleData,
|
examples: exampleData,
|
||||||
index: createWordIndex(exampleData)
|
index: createWordIndex(exampleData),
|
||||||
|
tags: Array.from(uniqueTags)
|
||||||
};
|
};
|
||||||
|
|
||||||
const indexSource = `var info = ${JSON.stringify(info)}`;
|
const indexSource = `var info = ${JSON.stringify(info)}`;
|
||||||
@@ -182,6 +187,13 @@ ExampleBuilder.prototype.render = async function(dir, chunk) {
|
|||||||
data.olVersion = pkg.version;
|
data.olVersion = pkg.version;
|
||||||
data.filename = htmlName;
|
data.filename = htmlName;
|
||||||
|
|
||||||
|
// process tags
|
||||||
|
if (data.tags) {
|
||||||
|
data.tags = data.tags.replace(/[\s"]+/g, '').split(',');
|
||||||
|
} else {
|
||||||
|
data.tags = [];
|
||||||
|
}
|
||||||
|
|
||||||
// add in script tag
|
// add in script tag
|
||||||
const jsName = `${name}.js`;
|
const jsName = `${name}.js`;
|
||||||
let jsSource = getJsSource(chunk, path.join('.', jsName));
|
let jsSource = getJsSource(chunk, path.join('.', jsName));
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ tags: "GetLegendGraphic, getLegendUrl, WMS"
|
|||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
Legend:
|
Legend:
|
||||||
<div><img id="legend" src=""/></div>
|
<div><img id="legend"/></div>
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ title: Constrained Zoom
|
|||||||
shortdesc: Example of a zoom constrained view.
|
shortdesc: Example of a zoom constrained view.
|
||||||
docs: >
|
docs: >
|
||||||
This map has a view that is constrained between zoom levels 9 and 13. This is done using the `minZoom` and `maxZoom` view options.
|
This map has a view that is constrained between zoom levels 9 and 13. This is done using the `minZoom` and `maxZoom` view options.
|
||||||
tags: "bing, zoom, minZoom, maxZoom"
|
tags: "maptiler, zoom, minZoom, maxZoom"
|
||||||
cloak:
|
cloak:
|
||||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import TileLayer from '../src/ol/layer/Tile.js';
|
import TileLayer from '../src/ol/layer/Tile.js';
|
||||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
import XYZ from '../src/ol/source/XYZ.js';
|
||||||
|
|
||||||
|
|
||||||
|
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||||
|
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 map = new Map({
|
const map = new Map({
|
||||||
target: 'map',
|
target: 'map',
|
||||||
layers: [
|
layers: [
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new BingMaps({
|
source: new XYZ({
|
||||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
attributions: attributions,
|
||||||
imagerySet: 'Aerial'
|
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
"url": "https://github.com/openlayers/openlayers/issues"
|
"url": "https://github.com/openlayers/openlayers/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@openlayers/pepjs": "^0.5.3",
|
"elm-pep": "^1.0.2",
|
||||||
"pbf": "3.2.1",
|
"pbf": "3.2.1",
|
||||||
"pixelworks": "1.1.0",
|
"pixelworks": "1.1.0",
|
||||||
"rbush": "^3.0.1"
|
"rbush": "^3.0.1"
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"chaikin-smooth": "^1.0.4",
|
"chaikin-smooth": "^1.0.4",
|
||||||
"clean-css-cli": "4.3.0",
|
"clean-css-cli": "4.3.0",
|
||||||
"copy-webpack-plugin": "^5.0.4",
|
"copy-webpack-plugin": "^5.0.4",
|
||||||
"coveralls": "3.0.7",
|
"coveralls": "3.0.9",
|
||||||
"eslint": "^6.0.0",
|
"eslint": "^6.0.0",
|
||||||
"eslint-config-openlayers": "^13.0.0",
|
"eslint-config-openlayers": "^13.0.0",
|
||||||
"expect.js": "0.3.1",
|
"expect.js": "0.3.1",
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
"fs-extra": "^8.0.0",
|
"fs-extra": "^8.0.0",
|
||||||
"glob": "^7.1.5",
|
"glob": "^7.1.5",
|
||||||
"globby": "^10.0.0",
|
"globby": "^10.0.0",
|
||||||
"handlebars": "4.4.5",
|
"handlebars": "4.5.3",
|
||||||
"html-to-image": "^0.1.0",
|
"html-to-image": "^0.1.0",
|
||||||
"istanbul": "0.4.5",
|
"istanbul": "0.4.5",
|
||||||
"istanbul-instrumenter-loader": "^3.0.1",
|
"istanbul-instrumenter-loader": "^3.0.1",
|
||||||
@@ -79,13 +79,13 @@
|
|||||||
"karma-sourcemap-loader": "^0.3.7",
|
"karma-sourcemap-loader": "^0.3.7",
|
||||||
"karma-webpack": "^4.0.0-rc.2",
|
"karma-webpack": "^4.0.0-rc.2",
|
||||||
"loglevelnext": "^3.0.1",
|
"loglevelnext": "^3.0.1",
|
||||||
"marked": "0.7.0",
|
"marked": "0.8.0",
|
||||||
"mocha": "6.2.2",
|
"mocha": "7.0.0",
|
||||||
"ol-mapbox-style": "^5.0.2",
|
"ol-mapbox-style": "^5.0.2",
|
||||||
"pixelmatch": "^5.1.0",
|
"pixelmatch": "^5.1.0",
|
||||||
"pngjs": "^3.4.0",
|
"pngjs": "^3.4.0",
|
||||||
"proj4": "2.5.0",
|
"proj4": "2.6.0",
|
||||||
"puppeteer": "~1.20.0",
|
"puppeteer": "~2.0.0",
|
||||||
"rollup": "^1.25.1",
|
"rollup": "^1.25.1",
|
||||||
"rollup-plugin-babel": "^4.3.3",
|
"rollup-plugin-babel": "^4.3.3",
|
||||||
"rollup-plugin-commonjs": "^10.0.0",
|
"rollup-plugin-commonjs": "^10.0.0",
|
||||||
@@ -93,16 +93,16 @@
|
|||||||
"rollup-plugin-terser": "^5.0.0",
|
"rollup-plugin-terser": "^5.0.0",
|
||||||
"serve-static": "^1.14.0",
|
"serve-static": "^1.14.0",
|
||||||
"shx": "^0.3.2",
|
"shx": "^0.3.2",
|
||||||
"sinon": "^7.3.2",
|
"sinon": "^8.0.0",
|
||||||
"terser-webpack-plugin": "^2.0.1",
|
"terser-webpack-plugin": "^2.0.1",
|
||||||
"typescript": "3.5.3",
|
"typescript": "3.5.3",
|
||||||
"url-polyfill": "^1.1.5",
|
"url-polyfill": "^1.1.5",
|
||||||
"walk": "^2.3.9",
|
"walk": "^2.3.9",
|
||||||
"webpack": "4.41.2",
|
"webpack": "4.41.5",
|
||||||
"webpack-cli": "^3.3.2",
|
"webpack-cli": "^3.3.2",
|
||||||
"webpack-dev-middleware": "^3.6.2",
|
"webpack-dev-middleware": "^3.6.2",
|
||||||
"webpack-dev-server": "^3.3.1",
|
"webpack-dev-server": "^3.3.1",
|
||||||
"yargs": "^14.2.0"
|
"yargs": "^15.0.2"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "openlayers",
|
"extends": "openlayers",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 139 KiB |
@@ -0,0 +1,31 @@
|
|||||||
|
import Map from '../../../src/ol/Map.js';
|
||||||
|
import View from '../../../src/ol/View.js';
|
||||||
|
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
|
||||||
|
import MVT from '../../../src/ol/format/MVT.js';
|
||||||
|
import {createXYZ} from '../../../src/ol/tilegrid.js';
|
||||||
|
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
|
||||||
|
import VectorTileRenderType from '../../../src/ol/layer/VectorTileRenderType.js';
|
||||||
|
|
||||||
|
new Map({
|
||||||
|
layers: [
|
||||||
|
new VectorTileLayer({
|
||||||
|
renderMode: VectorTileRenderType.VECTOR,
|
||||||
|
source: new VectorTileSource({
|
||||||
|
format: new MVT(),
|
||||||
|
tileGrid: createXYZ(),
|
||||||
|
url: '/data/tiles/mapbox-streets-v6/{z}/{x}/{y}.vector.pbf',
|
||||||
|
transition: 0
|
||||||
|
})
|
||||||
|
})
|
||||||
|
],
|
||||||
|
target: 'map',
|
||||||
|
view: new View({
|
||||||
|
center: [1825927.7316762917, 6143091.089223046],
|
||||||
|
zoom: 14
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
render({
|
||||||
|
message: 'Vector tile layer renders with vector render mode',
|
||||||
|
tolerance: 0.01
|
||||||
|
});
|
||||||
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 23 KiB |
@@ -58,20 +58,6 @@ class ImageTile extends Tile {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
disposeInternal() {
|
|
||||||
if (this.state == TileState.LOADING) {
|
|
||||||
this.unlistenImage_();
|
|
||||||
this.image_ = getBlankImage();
|
|
||||||
}
|
|
||||||
if (this.interimTile) {
|
|
||||||
this.interimTile.dispose();
|
|
||||||
}
|
|
||||||
super.disposeInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the HTML image element for this tile (may be a Canvas, Image, or Video).
|
* Get the HTML image element for this tile (may be a Canvas, Image, or Video).
|
||||||
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
* @module ol/MapBrowserEventHandler
|
* @module ol/MapBrowserEventHandler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import '@openlayers/pepjs';
|
import 'elm-pep';
|
||||||
import {DEVICE_PIXEL_RATIO} from './has.js';
|
import {DEVICE_PIXEL_RATIO, PASSIVE_EVENT_LISTENERS} from './has.js';
|
||||||
import MapBrowserEventType from './MapBrowserEventType.js';
|
import MapBrowserEventType from './MapBrowserEventType.js';
|
||||||
import MapBrowserPointerEvent from './MapBrowserPointerEvent.js';
|
import MapBrowserPointerEvent from './MapBrowserPointerEvent.js';
|
||||||
import {listen, unlistenByKey} from './events.js';
|
import {listen, unlistenByKey} from './events.js';
|
||||||
import EventTarget from './events/Target.js';
|
import EventTarget from './events/Target.js';
|
||||||
import PointerEventType from './pointer/EventType.js';
|
import PointerEventType from './pointer/EventType.js';
|
||||||
|
import EventType from './events/EventType.js';
|
||||||
|
|
||||||
class MapBrowserEventHandler extends EventTarget {
|
class MapBrowserEventHandler extends EventTarget {
|
||||||
|
|
||||||
@@ -84,6 +85,12 @@ class MapBrowserEventHandler extends EventTarget {
|
|||||||
PointerEventType.POINTERDOWN,
|
PointerEventType.POINTERDOWN,
|
||||||
this.handlePointerDown_, this);
|
this.handlePointerDown_, this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {PointerEvent}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.originalPointerMoveEvent_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {?import("./events.js").EventsKey}
|
* @type {?import("./events.js").EventsKey}
|
||||||
* @private
|
* @private
|
||||||
@@ -92,6 +99,13 @@ class MapBrowserEventHandler extends EventTarget {
|
|||||||
PointerEventType.POINTERMOVE,
|
PointerEventType.POINTERMOVE,
|
||||||
this.relayEvent_, this);
|
this.relayEvent_, this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.boundHandleTouchMove_ = this.handleTouchMove_.bind(this);
|
||||||
|
|
||||||
|
this.element_.addEventListener(EventType.TOUCHMOVE, this.boundHandleTouchMove_,
|
||||||
|
PASSIVE_EVENT_LISTENERS ? {passive: false} : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,11 +260,26 @@ class MapBrowserEventHandler extends EventTarget {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
relayEvent_(pointerEvent) {
|
relayEvent_(pointerEvent) {
|
||||||
|
this.originalPointerMoveEvent_ = pointerEvent;
|
||||||
const dragging = !!(this.down_ && this.isMoving_(pointerEvent));
|
const dragging = !!(this.down_ && this.isMoving_(pointerEvent));
|
||||||
this.dispatchEvent(new MapBrowserPointerEvent(
|
this.dispatchEvent(new MapBrowserPointerEvent(
|
||||||
pointerEvent.type, this.map_, pointerEvent, dragging));
|
pointerEvent.type, this.map_, pointerEvent, dragging));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flexible handling of a `touch-action: none` css equivalent: because calling
|
||||||
|
* `preventDefault()` on a `pointermove` event does not stop native page scrolling
|
||||||
|
* and zooming, we also listen for `touchmove` and call `preventDefault()` on it
|
||||||
|
* when an interaction (currently `DragPan` handles the event.
|
||||||
|
* @param {TouchEvent} event Event.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
handleTouchMove_(event) {
|
||||||
|
if (this.originalPointerMoveEvent_.defaultPrevented) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {PointerEvent} pointerEvent Pointer
|
* @param {PointerEvent} pointerEvent Pointer
|
||||||
* event.
|
* event.
|
||||||
@@ -271,6 +300,8 @@ class MapBrowserEventHandler extends EventTarget {
|
|||||||
unlistenByKey(this.relayedListenerKey_);
|
unlistenByKey(this.relayedListenerKey_);
|
||||||
this.relayedListenerKey_ = null;
|
this.relayedListenerKey_ = null;
|
||||||
}
|
}
|
||||||
|
this.element_.removeEventListener(EventType.TOUCHMOVE, this.boundHandleTouchMove_);
|
||||||
|
|
||||||
if (this.pointerdownListenerKey_) {
|
if (this.pointerdownListenerKey_) {
|
||||||
unlistenByKey(this.pointerdownListenerKey_);
|
unlistenByKey(this.pointerdownListenerKey_);
|
||||||
this.pointerdownListenerKey_ = null;
|
this.pointerdownListenerKey_ = null;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/PluggableMap
|
* @module ol/PluggableMap
|
||||||
*/
|
*/
|
||||||
import {getUid} from './util.js';
|
|
||||||
import Collection from './Collection.js';
|
import Collection from './Collection.js';
|
||||||
import CollectionEventType from './CollectionEventType.js';
|
import CollectionEventType from './CollectionEventType.js';
|
||||||
import MapBrowserEvent from './MapBrowserEvent.js';
|
import MapBrowserEvent from './MapBrowserEvent.js';
|
||||||
@@ -22,7 +21,7 @@ import {listen, unlistenByKey} from './events.js';
|
|||||||
import EventType from './events/EventType.js';
|
import EventType from './events/EventType.js';
|
||||||
import {clone, createOrUpdateEmpty, equals, getForViewAndSize, isEmpty} from './extent.js';
|
import {clone, createOrUpdateEmpty, equals, getForViewAndSize, isEmpty} from './extent.js';
|
||||||
import {TRUE} from './functions.js';
|
import {TRUE} from './functions.js';
|
||||||
import {DEVICE_PIXEL_RATIO, IMAGE_DECODE} from './has.js';
|
import {DEVICE_PIXEL_RATIO, IMAGE_DECODE, PASSIVE_EVENT_LISTENERS} from './has.js';
|
||||||
import LayerGroup from './layer/Group.js';
|
import LayerGroup from './layer/Group.js';
|
||||||
import {hasArea} from './size.js';
|
import {hasArea} from './size.js';
|
||||||
import {DROP} from './structs/PriorityQueue.js';
|
import {DROP} from './structs/PriorityQueue.js';
|
||||||
@@ -131,17 +130,6 @@ import {toUserCoordinate, fromUserCoordinate} from './proj.js';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {HTMLElement} element Element.
|
|
||||||
* @param {string} touchAction Value for `touch-action'.
|
|
||||||
*/
|
|
||||||
function setTouchAction(element, touchAction) {
|
|
||||||
element.style.msTouchAction = touchAction;
|
|
||||||
element.style.touchAction = touchAction;
|
|
||||||
element.setAttribute('touch-action', touchAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fires import("./MapBrowserEvent.js").MapBrowserEvent
|
* @fires import("./MapBrowserEvent.js").MapBrowserEvent
|
||||||
* @fires import("./MapEvent.js").MapEvent
|
* @fires import("./MapEvent.js").MapEvent
|
||||||
@@ -305,15 +293,10 @@ class PluggableMap extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
this.keyHandlerKeys_ = null;
|
this.keyHandlerKeys_ = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {?Array<import("./events.js").EventsKey>}
|
|
||||||
*/
|
|
||||||
this.focusHandlerKeys_ = null;
|
|
||||||
|
|
||||||
const handleBrowserEvent = this.handleBrowserEvent.bind(this);
|
const handleBrowserEvent = this.handleBrowserEvent.bind(this);
|
||||||
this.viewport_.addEventListener(EventType.CONTEXTMENU, handleBrowserEvent, false);
|
this.viewport_.addEventListener(EventType.CONTEXTMENU, handleBrowserEvent, false);
|
||||||
this.viewport_.addEventListener(EventType.WHEEL, handleBrowserEvent, false);
|
this.viewport_.addEventListener(EventType.WHEEL, handleBrowserEvent,
|
||||||
|
PASSIVE_EVENT_LISTENERS ? {passive: false} : false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Collection<import("./control/Control.js").default>}
|
* @type {Collection<import("./control/Control.js").default>}
|
||||||
@@ -949,12 +932,14 @@ class PluggableMap extends BaseObject {
|
|||||||
// coordinates so interactions cannot be used.
|
// coordinates so interactions cannot be used.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let target = mapBrowserEvent.originalEvent.target;
|
let target = /** @type {Node} */ (mapBrowserEvent.originalEvent.target);
|
||||||
while (target instanceof HTMLElement) {
|
if (!mapBrowserEvent.dragging) {
|
||||||
if (target.parentElement === this.overlayContainerStopEvent_) {
|
while (target && target !== this.viewport_) {
|
||||||
return;
|
if (target.parentElement === this.overlayContainerStopEvent_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
target = target.parentElement;
|
||||||
}
|
}
|
||||||
target = target.parentElement;
|
|
||||||
}
|
}
|
||||||
mapBrowserEvent.frameState = this.frameState_;
|
mapBrowserEvent.frameState = this.frameState_;
|
||||||
const interactionsArray = this.getInteractions().getArray();
|
const interactionsArray = this.getInteractions().getArray();
|
||||||
@@ -1043,12 +1028,6 @@ class PluggableMap extends BaseObject {
|
|||||||
targetElement = this.getTargetElement();
|
targetElement = this.getTargetElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.focusHandlerKeys_) {
|
|
||||||
for (let i = 0, ii = this.focusHandlerKeys_.length; i < ii; ++i) {
|
|
||||||
unlistenByKey(this.focusHandlerKeys_[i]);
|
|
||||||
}
|
|
||||||
this.focusHandlerKeys_ = null;
|
|
||||||
}
|
|
||||||
if (this.keyHandlerKeys_) {
|
if (this.keyHandlerKeys_) {
|
||||||
for (let i = 0, ii = this.keyHandlerKeys_.length; i < ii; ++i) {
|
for (let i = 0, ii = this.keyHandlerKeys_.length; i < ii; ++i) {
|
||||||
unlistenByKey(this.keyHandlerKeys_[i]);
|
unlistenByKey(this.keyHandlerKeys_[i]);
|
||||||
@@ -1077,15 +1056,6 @@ class PluggableMap extends BaseObject {
|
|||||||
if (!this.renderer_) {
|
if (!this.renderer_) {
|
||||||
this.renderer_ = this.createRenderer();
|
this.renderer_ = this.createRenderer();
|
||||||
}
|
}
|
||||||
let hasFocus = true;
|
|
||||||
if (targetElement.hasAttribute('tabindex')) {
|
|
||||||
hasFocus = document.activeElement === targetElement;
|
|
||||||
this.focusHandlerKeys_ = [
|
|
||||||
listen(targetElement, EventType.FOCUS, setTouchAction.bind(this, this.viewport_, 'none')),
|
|
||||||
listen(targetElement, EventType.BLUR, setTouchAction.bind(this, this.viewport_, 'auto'))
|
|
||||||
];
|
|
||||||
}
|
|
||||||
setTouchAction(this.viewport_, hasFocus ? 'none' : 'auto');
|
|
||||||
|
|
||||||
const keyboardEventTarget = !this.keyboardEventTarget_ ?
|
const keyboardEventTarget = !this.keyboardEventTarget_ ?
|
||||||
targetElement : this.keyboardEventTarget_;
|
targetElement : this.keyboardEventTarget_;
|
||||||
@@ -1133,7 +1103,8 @@ class PluggableMap extends BaseObject {
|
|||||||
}
|
}
|
||||||
const view = this.getView();
|
const view = this.getView();
|
||||||
if (view) {
|
if (view) {
|
||||||
this.viewport_.setAttribute('data-view', getUid(view));
|
this.updateViewportSize_();
|
||||||
|
|
||||||
this.viewPropertyListenerKey_ = listen(
|
this.viewPropertyListenerKey_ = listen(
|
||||||
view, ObjectEventType.PROPERTYCHANGE,
|
view, ObjectEventType.PROPERTYCHANGE,
|
||||||
this.handleViewPropertyChanged_, this);
|
this.handleViewPropertyChanged_, this);
|
||||||
@@ -1391,6 +1362,27 @@ class PluggableMap extends BaseObject {
|
|||||||
parseFloat(computedStyle['borderBottomWidth'])
|
parseFloat(computedStyle['borderBottomWidth'])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateViewportSize_();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recomputes the viewport size and save it on the view object (if any)
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
updateViewportSize_() {
|
||||||
|
const view = this.getView();
|
||||||
|
if (view) {
|
||||||
|
let size = undefined;
|
||||||
|
const computedStyle = getComputedStyle(this.viewport_);
|
||||||
|
if (computedStyle.width && computedStyle.height) {
|
||||||
|
size = [
|
||||||
|
parseInt(computedStyle.width, 10),
|
||||||
|
parseInt(computedStyle.height, 10)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
view.setViewportSize(size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,10 +145,9 @@ class Tile extends EventTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* Called by the tile cache when the tile is removed from the cache due to expiry
|
||||||
*/
|
*/
|
||||||
disposeInternal() {
|
release() {
|
||||||
this.setState(TileState.ABORT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,15 +6,6 @@ import {fromKey, getKey} from './tilecoord.js';
|
|||||||
|
|
||||||
class TileCache extends LRUCache {
|
class TileCache extends LRUCache {
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number=} opt_highWaterMark High water mark.
|
|
||||||
*/
|
|
||||||
constructor(opt_highWaterMark) {
|
|
||||||
|
|
||||||
super(opt_highWaterMark);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Object<string, import("./TileRange.js").default>} usedTiles Used tiles.
|
* @param {!Object<string, import("./TileRange.js").default>} usedTiles Used tiles.
|
||||||
*/
|
*/
|
||||||
@@ -24,8 +15,7 @@ class TileCache extends LRUCache {
|
|||||||
if (tile.getKey() in usedTiles) {
|
if (tile.getKey() in usedTiles) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// This lets the GC clean up the object
|
this.pop().release();
|
||||||
this.pop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +33,7 @@ class TileCache extends LRUCache {
|
|||||||
this.forEach(function(tile) {
|
this.forEach(function(tile) {
|
||||||
if (tile.tileCoord[0] !== z) {
|
if (tile.tileCoord[0] !== z) {
|
||||||
this.remove(getKey(tile.tileCoord));
|
this.remove(getKey(tile.tileCoord));
|
||||||
tile.dispose();
|
tile.release();
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,8 +84,7 @@ class TileQueue extends PriorityQueue {
|
|||||||
handleTileChange(event) {
|
handleTileChange(event) {
|
||||||
const tile = /** @type {import("./Tile.js").default} */ (event.target);
|
const tile = /** @type {import("./Tile.js").default} */ (event.target);
|
||||||
const state = tile.getState();
|
const state = tile.getState();
|
||||||
if (tile.hifi && state === TileState.LOADED || state === TileState.ERROR ||
|
if (tile.hifi && state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) {
|
||||||
state === TileState.EMPTY || state === TileState.ABORT) {
|
|
||||||
tile.removeEventListener(EventType.CHANGE, this.boundHandleTileChange_);
|
tile.removeEventListener(EventType.CHANGE, this.boundHandleTileChange_);
|
||||||
const tileKey = tile.getKey();
|
const tileKey = tile.getKey();
|
||||||
if (tileKey in this.tilesLoadingKeys_) {
|
if (tileKey in this.tilesLoadingKeys_) {
|
||||||
@@ -102,27 +101,19 @@ class TileQueue extends PriorityQueue {
|
|||||||
*/
|
*/
|
||||||
loadMoreTiles(maxTotalLoading, maxNewLoads) {
|
loadMoreTiles(maxTotalLoading, maxNewLoads) {
|
||||||
let newLoads = 0;
|
let newLoads = 0;
|
||||||
let abortedTiles = false;
|
|
||||||
let state, tile, tileKey;
|
let state, tile, tileKey;
|
||||||
while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads &&
|
while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads &&
|
||||||
this.getCount() > 0) {
|
this.getCount() > 0) {
|
||||||
tile = /** @type {import("./Tile.js").default} */ (this.dequeue()[0]);
|
tile = /** @type {import("./Tile.js").default} */ (this.dequeue()[0]);
|
||||||
tileKey = tile.getKey();
|
tileKey = tile.getKey();
|
||||||
state = tile.getState();
|
state = tile.getState();
|
||||||
if (state === TileState.ABORT) {
|
if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
|
||||||
abortedTiles = true;
|
|
||||||
} else if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
|
|
||||||
this.tilesLoadingKeys_[tileKey] = true;
|
this.tilesLoadingKeys_[tileKey] = true;
|
||||||
++this.tilesLoading_;
|
++this.tilesLoading_;
|
||||||
++newLoads;
|
++newLoads;
|
||||||
tile.load();
|
tile.load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newLoads === 0 && abortedTiles) {
|
|
||||||
// Do not stop the render loop when all wanted tiles were aborted due to
|
|
||||||
// a small, saturated tile cache.
|
|
||||||
this.tileChangeCallback_();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,5 @@ export default {
|
|||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
ERROR: 3,
|
ERROR: 3,
|
||||||
EMPTY: 4,
|
EMPTY: 4
|
||||||
ABORT: 5
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
import {getUid} from './util.js';
|
import {getUid} from './util.js';
|
||||||
import Tile from './Tile.js';
|
import Tile from './Tile.js';
|
||||||
import {createCanvasContext2D} from './dom.js';
|
import {createCanvasContext2D} from './dom.js';
|
||||||
import {unlistenByKey} from './events.js';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,6 +18,10 @@ import {unlistenByKey} from './events.js';
|
|||||||
* @property {number} renderedTileZ
|
* @property {number} renderedTileZ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Array<HTMLCanvasElement>}
|
||||||
|
*/
|
||||||
|
const canvasPool = [];
|
||||||
|
|
||||||
class VectorRenderTile extends Tile {
|
class VectorRenderTile extends Tile {
|
||||||
|
|
||||||
@@ -26,13 +29,10 @@ class VectorRenderTile extends Tile {
|
|||||||
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||||
* @param {import("./TileState.js").default} state State.
|
* @param {import("./TileState.js").default} state State.
|
||||||
* @param {import("./tilecoord.js").TileCoord} urlTileCoord Wrapped tile coordinate for source urls.
|
* @param {import("./tilecoord.js").TileCoord} urlTileCoord Wrapped tile coordinate for source urls.
|
||||||
* @param {import("./tilegrid/TileGrid.js").default} sourceTileGrid Tile grid of the source.
|
|
||||||
* @param {function(VectorRenderTile):Array<import("./VectorTile").default>} getSourceTiles Function
|
* @param {function(VectorRenderTile):Array<import("./VectorTile").default>} getSourceTiles Function
|
||||||
* to get an source tiles for this tile.
|
* to get source tiles for this tile.
|
||||||
* @param {function(VectorRenderTile):void} removeSourceTiles Function to remove this tile from its
|
|
||||||
* source tiles's consumer count.
|
|
||||||
*/
|
*/
|
||||||
constructor(tileCoord, state, urlTileCoord, sourceTileGrid, getSourceTiles, removeSourceTiles) {
|
constructor(tileCoord, state, urlTileCoord, getSourceTiles) {
|
||||||
|
|
||||||
super(tileCoord, state, {transition: 0});
|
super(tileCoord, state, {transition: 0});
|
||||||
|
|
||||||
@@ -61,9 +61,9 @@ class VectorRenderTile extends Tile {
|
|||||||
this.errorSourceTileKeys = {};
|
this.errorSourceTileKeys = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {ImageData}
|
* @type {Object<number, ImageData>}
|
||||||
*/
|
*/
|
||||||
this.hitDetectionImageData = null;
|
this.hitDetectionImageData = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -71,6 +71,11 @@ class VectorRenderTile extends Tile {
|
|||||||
*/
|
*/
|
||||||
this.replayState_ = {};
|
this.replayState_ = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Array<import("./VectorTile.js").default>}
|
||||||
|
*/
|
||||||
|
this.sourceTiles = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
@@ -79,23 +84,7 @@ class VectorRenderTile extends Tile {
|
|||||||
/**
|
/**
|
||||||
* @type {!function():Array<import("./VectorTile.js").default>}
|
* @type {!function():Array<import("./VectorTile.js").default>}
|
||||||
*/
|
*/
|
||||||
this.getSourceTiles = getSourceTiles.bind(this, this);
|
this.getSourceTiles = getSourceTiles.bind(undefined, this);
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {!function(import("./VectorRenderTile.js").default):void}
|
|
||||||
*/
|
|
||||||
this.removeSourceTiles_ = removeSourceTiles;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {import("./tilegrid/TileGrid.js").default}
|
|
||||||
*/
|
|
||||||
this.sourceTileGrid_ = sourceTileGrid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Array<import("./events.js").EventsKey>}
|
|
||||||
*/
|
|
||||||
this.sourceTileListenerKeys = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* z of the source tiles of the last getSourceTiles call.
|
* z of the source tiles of the last getSourceTiles call.
|
||||||
@@ -115,27 +104,6 @@ class VectorRenderTile extends Tile {
|
|||||||
this.wrappedTileCoord = urlTileCoord;
|
this.wrappedTileCoord = urlTileCoord;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
disposeInternal() {
|
|
||||||
this.sourceTileListenerKeys.forEach(unlistenByKey);
|
|
||||||
this.sourceTileListenerKeys.length = 0;
|
|
||||||
this.removeSourceTiles_(this);
|
|
||||||
for (const key in this.context_) {
|
|
||||||
const canvas = this.context_[key].canvas;
|
|
||||||
canvas.width = 0;
|
|
||||||
canvas.height = 0;
|
|
||||||
}
|
|
||||||
for (const key in this.executorGroups) {
|
|
||||||
const executorGroups = this.executorGroups[key];
|
|
||||||
for (let i = 0, ii = executorGroups.length; i < ii; ++i) {
|
|
||||||
executorGroups[i].disposeInternal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.disposeInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("./layer/Layer.js").default} layer Layer.
|
* @param {import("./layer/Layer.js").default} layer Layer.
|
||||||
* @return {CanvasRenderingContext2D} The rendering context.
|
* @return {CanvasRenderingContext2D} The rendering context.
|
||||||
@@ -143,7 +111,7 @@ class VectorRenderTile extends Tile {
|
|||||||
getContext(layer) {
|
getContext(layer) {
|
||||||
const key = getUid(layer);
|
const key = getUid(layer);
|
||||||
if (!(key in this.context_)) {
|
if (!(key in this.context_)) {
|
||||||
this.context_[key] = createCanvasContext2D();
|
this.context_[key] = createCanvasContext2D(1, 1, canvasPool);
|
||||||
}
|
}
|
||||||
return this.context_[key];
|
return this.context_[key];
|
||||||
}
|
}
|
||||||
@@ -192,6 +160,16 @@ class VectorRenderTile extends Tile {
|
|||||||
load() {
|
load() {
|
||||||
this.getSourceTiles();
|
this.getSourceTiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
release() {
|
||||||
|
for (const key in this.context_) {
|
||||||
|
canvasPool.push(this.context_[key].canvas);
|
||||||
|
}
|
||||||
|
super.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,6 @@ class VectorTile extends Tile {
|
|||||||
|
|
||||||
super(tileCoord, state, opt_options);
|
super(tileCoord, state, opt_options);
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
this.consumers = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extent of this tile; set by the source.
|
* Extent of this tile; set by the source.
|
||||||
* @type {import("./extent.js").Extent}
|
* @type {import("./extent.js").Extent}
|
||||||
@@ -105,7 +100,9 @@ class VectorTile extends Tile {
|
|||||||
if (this.state == TileState.IDLE) {
|
if (this.state == TileState.IDLE) {
|
||||||
this.setState(TileState.LOADING);
|
this.setState(TileState.LOADING);
|
||||||
this.tileLoadFunction_(this, this.url_);
|
this.tileLoadFunction_(this, this.url_);
|
||||||
this.loader_(this.extent, this.resolution, this.projection);
|
if (this.loader_) {
|
||||||
|
this.loader_(this.extent, this.resolution, this.projection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* @module ol/View
|
* @module ol/View
|
||||||
*/
|
*/
|
||||||
import {DEFAULT_TILE_SIZE} from './tilegrid/common.js';
|
import {DEFAULT_TILE_SIZE} from './tilegrid/common.js';
|
||||||
import {getUid} from './util.js';
|
|
||||||
import {VOID} from './functions.js';
|
import {VOID} from './functions.js';
|
||||||
import {createExtent, none as centerNone} from './centerconstraint.js';
|
import {createExtent, none as centerNone} from './centerconstraint.js';
|
||||||
import BaseObject from './Object.js';
|
import BaseObject from './Object.js';
|
||||||
@@ -294,6 +293,12 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
this.projection_ = createProjection(options.projection, 'EPSG:3857');
|
this.projection_ = createProjection(options.projection, 'EPSG:3857');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {import("./size.js").Size}
|
||||||
|
*/
|
||||||
|
this.viewportSize_ = [100, 100];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {import("./coordinate.js").Coordinate|undefined}
|
* @type {import("./coordinate.js").Coordinate|undefined}
|
||||||
@@ -312,6 +317,12 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
this.targetRotation_;
|
this.targetRotation_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {import("./coordinate.js").Coordinate|undefined}
|
||||||
|
*/
|
||||||
|
this.cancelAnchor_ = undefined;
|
||||||
|
|
||||||
if (options.center) {
|
if (options.center) {
|
||||||
options.center = fromUserCoordinate(options.center, this.projection_);
|
options.center = fromUserCoordinate(options.center, this.projection_);
|
||||||
}
|
}
|
||||||
@@ -584,13 +595,19 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
cancelAnimations() {
|
cancelAnimations() {
|
||||||
this.setHint(ViewHint.ANIMATING, -this.hints_[ViewHint.ANIMATING]);
|
this.setHint(ViewHint.ANIMATING, -this.hints_[ViewHint.ANIMATING]);
|
||||||
|
let anchor;
|
||||||
for (let i = 0, ii = this.animations_.length; i < ii; ++i) {
|
for (let i = 0, ii = this.animations_.length; i < ii; ++i) {
|
||||||
const series = this.animations_[i];
|
const series = this.animations_[i];
|
||||||
if (series[0].callback) {
|
if (series[0].callback) {
|
||||||
animationCallback(series[0].callback, false);
|
animationCallback(series[0].callback, false);
|
||||||
}
|
}
|
||||||
|
anchor = anchor ||
|
||||||
|
series.filter(function(animation) {
|
||||||
|
return !animation.complete;
|
||||||
|
})[0].anchor;
|
||||||
}
|
}
|
||||||
this.animations_.length = 0;
|
this.animations_.length = 0;
|
||||||
|
this.cancelAnchor_ = anchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -637,7 +654,7 @@ class View extends BaseObject {
|
|||||||
animation.targetResolution :
|
animation.targetResolution :
|
||||||
animation.sourceResolution + progress * (animation.targetResolution - animation.sourceResolution);
|
animation.sourceResolution + progress * (animation.targetResolution - animation.sourceResolution);
|
||||||
if (animation.anchor) {
|
if (animation.anchor) {
|
||||||
const size = this.getSizeFromViewport_(this.getRotation());
|
const size = this.getViewportSize_(this.getRotation());
|
||||||
const constrainedResolution = this.constraints_.resolution(resolution, 0, size, true);
|
const constrainedResolution = this.constraints_.resolution(resolution, 0, size, true);
|
||||||
this.targetCenter_ = this.calculateCenterZoom(constrainedResolution, animation.anchor);
|
this.targetCenter_ = this.calculateCenterZoom(constrainedResolution, animation.anchor);
|
||||||
}
|
}
|
||||||
@@ -710,26 +727,33 @@ class View extends BaseObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the current viewport size.
|
||||||
* @private
|
* @private
|
||||||
* @param {number=} opt_rotation Take into account the rotation of the viewport when giving the size
|
* @param {number=} opt_rotation Take into account the rotation of the viewport when giving the size
|
||||||
* @return {import("./size.js").Size} Viewport size or `[100, 100]` when no viewport is found.
|
* @return {import("./size.js").Size} Viewport size or `[100, 100]` when no viewport is found.
|
||||||
*/
|
*/
|
||||||
getSizeFromViewport_(opt_rotation) {
|
getViewportSize_(opt_rotation) {
|
||||||
const size = [100, 100];
|
const size = this.viewportSize_;
|
||||||
const selector = '.ol-viewport[data-view="' + getUid(this) + '"]';
|
|
||||||
const element = document.querySelector(selector);
|
|
||||||
if (element) {
|
|
||||||
const metrics = getComputedStyle(element);
|
|
||||||
size[0] = parseInt(metrics.width, 10);
|
|
||||||
size[1] = parseInt(metrics.height, 10);
|
|
||||||
}
|
|
||||||
if (opt_rotation) {
|
if (opt_rotation) {
|
||||||
const w = size[0];
|
const w = size[0];
|
||||||
const h = size[1];
|
const h = size[1];
|
||||||
size[0] = Math.abs(w * Math.cos(opt_rotation)) + Math.abs(h * Math.sin(opt_rotation));
|
return [
|
||||||
size[1] = Math.abs(w * Math.sin(opt_rotation)) + Math.abs(h * Math.cos(opt_rotation));
|
Math.abs(w * Math.cos(opt_rotation)) + Math.abs(h * Math.sin(opt_rotation)),
|
||||||
|
Math.abs(w * Math.sin(opt_rotation)) + Math.abs(h * Math.cos(opt_rotation))
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
return size;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the viewport size on the view. The viewport size is not read every time from the DOM
|
||||||
|
* to avoid performance hit and layout reflow.
|
||||||
|
* This should be done on map size change.
|
||||||
|
* @param {import("./size.js").Size=} opt_size Viewport size; if undefined, [100, 100] is assumed
|
||||||
|
*/
|
||||||
|
setViewportSize(opt_size) {
|
||||||
|
this.viewportSize_ = Array.isArray(opt_size) ? opt_size.slice() : [100, 100];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -780,8 +804,8 @@ class View extends BaseObject {
|
|||||||
* The size is the pixel dimensions of the box into which the calculated extent
|
* The size is the pixel dimensions of the box into which the calculated extent
|
||||||
* should fit. In most cases you want to get the extent of the entire map,
|
* should fit. In most cases you want to get the extent of the entire map,
|
||||||
* that is `map.getSize()`.
|
* that is `map.getSize()`.
|
||||||
* @param {import("./size.js").Size=} opt_size Box pixel size. If not provided, the size of the
|
* @param {import("./size.js").Size=} opt_size Box pixel size. If not provided, the size
|
||||||
* first map that uses this view will be used.
|
* of the map that uses this view will be used.
|
||||||
* @return {import("./extent.js").Extent} Extent.
|
* @return {import("./extent.js").Extent} Extent.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
@@ -796,7 +820,7 @@ class View extends BaseObject {
|
|||||||
* @return {import("./extent.js").Extent} Extent.
|
* @return {import("./extent.js").Extent} Extent.
|
||||||
*/
|
*/
|
||||||
calculateExtentInternal(opt_size) {
|
calculateExtentInternal(opt_size) {
|
||||||
const size = opt_size || this.getSizeFromViewport_();
|
const size = opt_size || this.getViewportSize_();
|
||||||
const center = /** @type {!import("./coordinate.js").Coordinate} */ (this.getCenterInternal());
|
const center = /** @type {!import("./coordinate.js").Coordinate} */ (this.getCenterInternal());
|
||||||
assert(center, 1); // The view center is not defined
|
assert(center, 1); // The view center is not defined
|
||||||
const resolution = /** @type {!number} */ (this.getResolution());
|
const resolution = /** @type {!number} */ (this.getResolution());
|
||||||
@@ -919,7 +943,7 @@ class View extends BaseObject {
|
|||||||
* the given size.
|
* the given size.
|
||||||
*/
|
*/
|
||||||
getResolutionForExtentInternal(extent, opt_size) {
|
getResolutionForExtentInternal(extent, opt_size) {
|
||||||
const size = opt_size || this.getSizeFromViewport_();
|
const size = opt_size || this.getViewportSize_();
|
||||||
const xResolution = getWidth(extent) / size[0];
|
const xResolution = getWidth(extent) / size[0];
|
||||||
const yResolution = getHeight(extent) / size[1];
|
const yResolution = getHeight(extent) / size[1];
|
||||||
return Math.max(xResolution, yResolution);
|
return Math.max(xResolution, yResolution);
|
||||||
@@ -933,7 +957,7 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
getResolutionForValueFunction(opt_power) {
|
getResolutionForValueFunction(opt_power) {
|
||||||
const power = opt_power || 2;
|
const power = opt_power || 2;
|
||||||
const maxResolution = this.maxResolution_;
|
const maxResolution = this.getConstrainedResolution(this.maxResolution_);
|
||||||
const minResolution = this.minResolution_;
|
const minResolution = this.minResolution_;
|
||||||
const max = Math.log(maxResolution / minResolution) / Math.log(power);
|
const max = Math.log(maxResolution / minResolution) / Math.log(power);
|
||||||
return (
|
return (
|
||||||
@@ -964,17 +988,17 @@ class View extends BaseObject {
|
|||||||
* @return {function(number): number} Value for resolution function.
|
* @return {function(number): number} Value for resolution function.
|
||||||
*/
|
*/
|
||||||
getValueForResolutionFunction(opt_power) {
|
getValueForResolutionFunction(opt_power) {
|
||||||
const power = opt_power || 2;
|
const logPower = Math.log(opt_power || 2);
|
||||||
const maxResolution = this.maxResolution_;
|
const maxResolution = this.getConstrainedResolution(this.maxResolution_);
|
||||||
const minResolution = this.minResolution_;
|
const minResolution = this.minResolution_;
|
||||||
const max = Math.log(maxResolution / minResolution) / Math.log(power);
|
const max = Math.log(maxResolution / minResolution) / logPower;
|
||||||
return (
|
return (
|
||||||
/**
|
/**
|
||||||
* @param {number} resolution Resolution.
|
* @param {number} resolution Resolution.
|
||||||
* @return {number} Value.
|
* @return {number} Value.
|
||||||
*/
|
*/
|
||||||
function(resolution) {
|
function(resolution) {
|
||||||
const value = (Math.log(maxResolution / resolution) / Math.log(power)) / max;
|
const value = (Math.log(maxResolution / resolution) / logPower) / max;
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1067,7 +1091,7 @@ class View extends BaseObject {
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
fit(geometryOrExtent, opt_options) {
|
fit(geometryOrExtent, opt_options) {
|
||||||
const options = assign({size: this.getSizeFromViewport_()}, opt_options || {});
|
const options = assign({size: this.getViewportSize_()}, opt_options || {});
|
||||||
|
|
||||||
/** @type {import("./geom/SimpleGeometry.js").default} */
|
/** @type {import("./geom/SimpleGeometry.js").default} */
|
||||||
let geometry;
|
let geometry;
|
||||||
@@ -1085,7 +1109,7 @@ class View extends BaseObject {
|
|||||||
} else {
|
} else {
|
||||||
const userProjection = getUserProjection();
|
const userProjection = getUserProjection();
|
||||||
if (userProjection) {
|
if (userProjection) {
|
||||||
geometry = /** @type {import("./geom/SimpleGeometry.js").default} */ (geometry.clone().transform(userProjection, this.getProjection()));
|
geometry = /** @type {import("./geom/SimpleGeometry.js").default} */ (geometryOrExtent.clone().transform(userProjection, this.getProjection()));
|
||||||
} else {
|
} else {
|
||||||
geometry = geometryOrExtent;
|
geometry = geometryOrExtent;
|
||||||
}
|
}
|
||||||
@@ -1102,7 +1126,7 @@ class View extends BaseObject {
|
|||||||
const options = opt_options || {};
|
const options = opt_options || {};
|
||||||
let size = options.size;
|
let size = options.size;
|
||||||
if (!size) {
|
if (!size) {
|
||||||
size = this.getSizeFromViewport_();
|
size = this.getViewportSize_();
|
||||||
}
|
}
|
||||||
const padding = options.padding !== undefined ? options.padding : [0, 0, 0, 0];
|
const padding = options.padding !== undefined ? options.padding : [0, 0, 0, 0];
|
||||||
const nearest = options.nearest !== undefined ? options.nearest : false;
|
const nearest = options.nearest !== undefined ? options.nearest : false;
|
||||||
@@ -1249,10 +1273,10 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
adjustResolutionInternal(ratio, opt_anchor) {
|
adjustResolutionInternal(ratio, opt_anchor) {
|
||||||
const isMoving = this.getAnimating() || this.getInteracting();
|
const isMoving = this.getAnimating() || this.getInteracting();
|
||||||
const size = this.getSizeFromViewport_(this.getRotation());
|
const size = this.getViewportSize_(this.getRotation());
|
||||||
const newResolution = this.constraints_.resolution(this.targetResolution_ * ratio, 0, size, isMoving);
|
const newResolution = this.constraints_.resolution(this.targetResolution_ * ratio, 0, size, isMoving);
|
||||||
|
|
||||||
if (opt_anchor !== undefined) {
|
if (opt_anchor) {
|
||||||
this.targetCenter_ = this.calculateCenterZoom(newResolution, opt_anchor);
|
this.targetCenter_ = this.calculateCenterZoom(newResolution, opt_anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1292,7 +1316,7 @@ class View extends BaseObject {
|
|||||||
adjustRotationInternal(delta, opt_anchor) {
|
adjustRotationInternal(delta, opt_anchor) {
|
||||||
const isMoving = this.getAnimating() || this.getInteracting();
|
const isMoving = this.getAnimating() || this.getInteracting();
|
||||||
const newRotation = this.constraints_.rotation(this.targetRotation_ + delta, isMoving);
|
const newRotation = this.constraints_.rotation(this.targetRotation_ + delta, isMoving);
|
||||||
if (opt_anchor !== undefined) {
|
if (opt_anchor) {
|
||||||
this.targetCenter_ = this.calculateCenterRotate(newRotation, opt_anchor);
|
this.targetCenter_ = this.calculateCenterRotate(newRotation, opt_anchor);
|
||||||
}
|
}
|
||||||
this.targetRotation_ += delta;
|
this.targetRotation_ += delta;
|
||||||
@@ -1373,7 +1397,7 @@ class View extends BaseObject {
|
|||||||
|
|
||||||
// compute rotation
|
// compute rotation
|
||||||
const newRotation = this.constraints_.rotation(this.targetRotation_, isMoving);
|
const newRotation = this.constraints_.rotation(this.targetRotation_, isMoving);
|
||||||
const size = this.getSizeFromViewport_(newRotation);
|
const size = this.getViewportSize_(newRotation);
|
||||||
const newResolution = this.constraints_.resolution(this.targetResolution_, 0, size, isMoving);
|
const newResolution = this.constraints_.resolution(this.targetResolution_, 0, size, isMoving);
|
||||||
const newCenter = this.constraints_.center(this.targetCenter_, newResolution, size, isMoving);
|
const newCenter = this.constraints_.center(this.targetCenter_, newResolution, size, isMoving);
|
||||||
|
|
||||||
@@ -1390,6 +1414,7 @@ class View extends BaseObject {
|
|||||||
if (this.getAnimating() && !opt_doNotCancelAnims) {
|
if (this.getAnimating() && !opt_doNotCancelAnims) {
|
||||||
this.cancelAnimations();
|
this.cancelAnimations();
|
||||||
}
|
}
|
||||||
|
this.cancelAnchor_ = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1406,11 +1431,11 @@ class View extends BaseObject {
|
|||||||
const direction = opt_resolutionDirection || 0;
|
const direction = opt_resolutionDirection || 0;
|
||||||
|
|
||||||
const newRotation = this.constraints_.rotation(this.targetRotation_);
|
const newRotation = this.constraints_.rotation(this.targetRotation_);
|
||||||
const size = this.getSizeFromViewport_(newRotation);
|
const size = this.getViewportSize_(newRotation);
|
||||||
const newResolution = this.constraints_.resolution(this.targetResolution_, direction, size);
|
const newResolution = this.constraints_.resolution(this.targetResolution_, direction, size);
|
||||||
const newCenter = this.constraints_.center(this.targetCenter_, newResolution, size);
|
const newCenter = this.constraints_.center(this.targetCenter_, newResolution, size);
|
||||||
|
|
||||||
if (duration === 0) {
|
if (duration === 0 && !this.cancelAnchor_) {
|
||||||
this.targetResolution_ = newResolution;
|
this.targetResolution_ = newResolution;
|
||||||
this.targetRotation_ = newRotation;
|
this.targetRotation_ = newRotation;
|
||||||
this.targetCenter_ = newCenter;
|
this.targetCenter_ = newCenter;
|
||||||
@@ -1418,6 +1443,9 @@ class View extends BaseObject {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const anchor = opt_anchor || (duration === 0 ? this.cancelAnchor_ : undefined);
|
||||||
|
this.cancelAnchor_ = undefined;
|
||||||
|
|
||||||
if (this.getResolution() !== newResolution ||
|
if (this.getResolution() !== newResolution ||
|
||||||
this.getRotation() !== newRotation ||
|
this.getRotation() !== newRotation ||
|
||||||
!this.getCenterInternal() ||
|
!this.getCenterInternal() ||
|
||||||
@@ -1433,7 +1461,7 @@ class View extends BaseObject {
|
|||||||
resolution: newResolution,
|
resolution: newResolution,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
easing: easeOut,
|
easing: easeOut,
|
||||||
anchor: opt_anchor
|
anchor: anchor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1484,7 +1512,7 @@ class View extends BaseObject {
|
|||||||
* @return {import("./coordinate.js").Coordinate|undefined} Valid center position.
|
* @return {import("./coordinate.js").Coordinate|undefined} Valid center position.
|
||||||
*/
|
*/
|
||||||
getConstrainedCenter(targetCenter, opt_targetResolution) {
|
getConstrainedCenter(targetCenter, opt_targetResolution) {
|
||||||
const size = this.getSizeFromViewport_(this.getRotation());
|
const size = this.getViewportSize_(this.getRotation());
|
||||||
return this.constraints_.center(targetCenter, opt_targetResolution || this.getResolution(), size);
|
return this.constraints_.center(targetCenter, opt_targetResolution || this.getResolution(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1513,7 +1541,7 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
getConstrainedResolution(targetResolution, opt_direction) {
|
getConstrainedResolution(targetResolution, opt_direction) {
|
||||||
const direction = opt_direction || 0;
|
const direction = opt_direction || 0;
|
||||||
const size = this.getSizeFromViewport_(this.getRotation());
|
const size = this.getViewportSize_(this.getRotation());
|
||||||
|
|
||||||
return this.constraints_.resolution(targetResolution, direction, size);
|
return this.constraints_.resolution(targetResolution, direction, size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/MousePosition
|
* @module ol/control/MousePosition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'elm-pep';
|
||||||
import {listen} from '../events.js';
|
import {listen} from '../events.js';
|
||||||
import EventType from '../pointer/EventType.js';
|
import EventType from '../pointer/EventType.js';
|
||||||
import {getChangeEventType} from '../Object.js';
|
import {getChangeEventType} from '../Object.js';
|
||||||
import Control from './Control.js';
|
import Control from './Control.js';
|
||||||
import {getTransformFromProjections, identityTransform, get as getProjection, getUserProjection} from '../proj.js';
|
import {getTransformFromProjections, identityTransform, get as getProjection, getUserProjection} from '../proj.js';
|
||||||
import '@openlayers/pepjs';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -304,6 +304,8 @@ class OverviewMap extends Control {
|
|||||||
*/
|
*/
|
||||||
bindView_(view) {
|
bindView_(view) {
|
||||||
view.addEventListener(getChangeEventType(ViewProperty.ROTATION), this.boundHandleRotationChanged_);
|
view.addEventListener(getChangeEventType(ViewProperty.ROTATION), this.boundHandleRotationChanged_);
|
||||||
|
// Sync once with the new view
|
||||||
|
this.handleRotationChanged_();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/control/ZoomSlider
|
* @module ol/control/ZoomSlider
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'elm-pep';
|
||||||
import Control from './Control.js';
|
import Control from './Control.js';
|
||||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||||
import {easeOut} from '../easing.js';
|
import {easeOut} from '../easing.js';
|
||||||
@@ -9,7 +11,6 @@ import {stopPropagation} from '../events/Event.js';
|
|||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import {clamp} from '../math.js';
|
import {clamp} from '../math.js';
|
||||||
import PointerEventType from '../pointer/EventType.js';
|
import PointerEventType from '../pointer/EventType.js';
|
||||||
import '@openlayers/pepjs';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,7 +136,6 @@ class ZoomSlider extends Control {
|
|||||||
thumbElement.setAttribute('type', 'button');
|
thumbElement.setAttribute('type', 'button');
|
||||||
thumbElement.className = className + '-thumb ' + CLASS_UNSELECTABLE;
|
thumbElement.className = className + '-thumb ' + CLASS_UNSELECTABLE;
|
||||||
const containerElement = this.element;
|
const containerElement = this.element;
|
||||||
containerElement.setAttribute('touch-action', 'none');
|
|
||||||
containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||||
containerElement.appendChild(thumbElement);
|
containerElement.appendChild(thumbElement);
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,12 @@
|
|||||||
* Create an html canvas element and returns its 2d context.
|
* Create an html canvas element and returns its 2d context.
|
||||||
* @param {number=} opt_width Canvas width.
|
* @param {number=} opt_width Canvas width.
|
||||||
* @param {number=} opt_height Canvas height.
|
* @param {number=} opt_height Canvas height.
|
||||||
|
* @param {Array<HTMLCanvasElement>=} opt_canvasPool Canvas pool to take existing canvas from.
|
||||||
* @return {CanvasRenderingContext2D} The context.
|
* @return {CanvasRenderingContext2D} The context.
|
||||||
*/
|
*/
|
||||||
export function createCanvasContext2D(opt_width, opt_height) {
|
export function createCanvasContext2D(opt_width, opt_height, opt_canvasPool) {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = opt_canvasPool && opt_canvasPool.length ?
|
||||||
|
opt_canvasPool.shift() : document.createElement('canvas');
|
||||||
if (opt_width) {
|
if (opt_width) {
|
||||||
canvas.width = opt_width;
|
canvas.width = opt_width;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,5 +34,6 @@ export default {
|
|||||||
KEYPRESS: 'keypress',
|
KEYPRESS: 'keypress',
|
||||||
LOAD: 'load',
|
LOAD: 'load',
|
||||||
RESIZE: 'resize',
|
RESIZE: 'resize',
|
||||||
|
TOUCHMOVE: 'touchmove',
|
||||||
WHEEL: 'wheel'
|
WHEEL: 'wheel'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -207,12 +207,9 @@ export const shiftKeyOnly = function(mapBrowserEvent) {
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
export const targetNotEditable = function(mapBrowserEvent) {
|
export const targetNotEditable = function(mapBrowserEvent) {
|
||||||
const target = mapBrowserEvent.target;
|
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
|
||||||
const tagName = /** @type {Element} */ (target).tagName;
|
const tagName = /** @type {Element} */ (originalEvent.target).tagName;
|
||||||
return (
|
return tagName !== 'INPUT' && tagName !== 'SELECT' && tagName !== 'TEXTAREA';
|
||||||
tagName !== 'INPUT' &&
|
|
||||||
tagName !== 'SELECT' &&
|
|
||||||
tagName !== 'TEXTAREA');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -386,6 +386,8 @@ function createStyleDefaults() {
|
|||||||
* @property {Array<Style>} [defaultStyle] Default style. The
|
* @property {Array<Style>} [defaultStyle] Default style. The
|
||||||
* default default style is the same as Google Earth.
|
* default default style is the same as Google Earth.
|
||||||
* @property {boolean} [writeStyles=true] Write styles into KML.
|
* @property {boolean} [writeStyles=true] Write styles into KML.
|
||||||
|
* @property {null|string} [crossOrigin='anonymous'] The `crossOrigin` attribute for loaded images. Note that you must provide a
|
||||||
|
* `crossOrigin` value if you want to access pixel data with the Canvas renderer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -458,6 +460,13 @@ class KML extends XMLFeature {
|
|||||||
this.showPointNames_ = options.showPointNames !== undefined ?
|
this.showPointNames_ = options.showPointNames !== undefined ?
|
||||||
options.showPointNames : true;
|
options.showPointNames : true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {null|string}
|
||||||
|
*/
|
||||||
|
this.crossOrigin_ = options.crossOrigin !== undefined ?
|
||||||
|
options.crossOrigin : 'anonymous';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -494,7 +503,7 @@ class KML extends XMLFeature {
|
|||||||
*/
|
*/
|
||||||
readPlacemark_(node, objectStack) {
|
readPlacemark_(node, objectStack) {
|
||||||
const object = pushParseAndPop({'geometry': null},
|
const object = pushParseAndPop({'geometry': null},
|
||||||
PLACEMARK_PARSERS, node, objectStack);
|
PLACEMARK_PARSERS, node, objectStack, this);
|
||||||
if (!object) {
|
if (!object) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -537,7 +546,7 @@ class KML extends XMLFeature {
|
|||||||
readSharedStyle_(node, objectStack) {
|
readSharedStyle_(node, objectStack) {
|
||||||
const id = node.getAttribute('id');
|
const id = node.getAttribute('id');
|
||||||
if (id !== null) {
|
if (id !== null) {
|
||||||
const style = readStyle(node, objectStack);
|
const style = readStyle.call(this, node, objectStack);
|
||||||
if (style) {
|
if (style) {
|
||||||
let styleUri;
|
let styleUri;
|
||||||
let baseURI = node.baseURI;
|
let baseURI = node.baseURI;
|
||||||
@@ -565,7 +574,7 @@ class KML extends XMLFeature {
|
|||||||
if (id === null) {
|
if (id === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const styleMapValue = readStyleMapValue(node, objectStack);
|
const styleMapValue = readStyleMapValue.call(this, node, objectStack);
|
||||||
if (!styleMapValue) {
|
if (!styleMapValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1112,13 +1121,14 @@ const STYLE_MAP_PARSERS = makeStructureNS(
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @this {KML}
|
||||||
* @param {Element} node Node.
|
* @param {Element} node Node.
|
||||||
* @param {Array<*>} objectStack Object stack.
|
* @param {Array<*>} objectStack Object stack.
|
||||||
* @return {Array<Style>|string|undefined} StyleMap.
|
* @return {Array<Style>|string|undefined} StyleMap.
|
||||||
*/
|
*/
|
||||||
function readStyleMapValue(node, objectStack) {
|
function readStyleMapValue(node, objectStack) {
|
||||||
return pushParseAndPop(undefined,
|
return pushParseAndPop(undefined,
|
||||||
STYLE_MAP_PARSERS, node, objectStack);
|
STYLE_MAP_PARSERS, node, objectStack, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1137,6 +1147,7 @@ const ICON_STYLE_PARSERS = makeStructureNS(
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @this {KML}
|
||||||
* @param {Element} node Node.
|
* @param {Element} node Node.
|
||||||
* @param {Array<*>} objectStack Object stack.
|
* @param {Array<*>} objectStack Object stack.
|
||||||
*/
|
*/
|
||||||
@@ -1223,7 +1234,7 @@ function iconStyleParser(node, objectStack) {
|
|||||||
anchorOrigin: anchorOrigin,
|
anchorOrigin: anchorOrigin,
|
||||||
anchorXUnits: anchorXUnits,
|
anchorXUnits: anchorXUnits,
|
||||||
anchorYUnits: anchorYUnits,
|
anchorYUnits: anchorYUnits,
|
||||||
crossOrigin: 'anonymous', // FIXME should this be configurable?
|
crossOrigin: this.crossOrigin_,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
offsetOrigin: IconOrigin.BOTTOM_LEFT,
|
offsetOrigin: IconOrigin.BOTTOM_LEFT,
|
||||||
rotation: rotation,
|
rotation: rotation,
|
||||||
@@ -1719,13 +1730,14 @@ const STYLE_PARSERS = makeStructureNS(
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @this {KML}
|
||||||
* @param {Element} node Node.
|
* @param {Element} node Node.
|
||||||
* @param {Array<*>} objectStack Object stack.
|
* @param {Array<*>} objectStack Object stack.
|
||||||
* @return {Array<Style>} Style.
|
* @return {Array<Style>} Style.
|
||||||
*/
|
*/
|
||||||
function readStyle(node, objectStack) {
|
function readStyle(node, objectStack) {
|
||||||
const styleObject = pushParseAndPop(
|
const styleObject = pushParseAndPop(
|
||||||
{}, STYLE_PARSERS, node, objectStack);
|
{}, STYLE_PARSERS, node, objectStack, this);
|
||||||
if (!styleObject) {
|
if (!styleObject) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1885,7 +1897,7 @@ const PAIR_PARSERS = makeStructureNS(
|
|||||||
*/
|
*/
|
||||||
function pairDataParser(node, objectStack) {
|
function pairDataParser(node, objectStack) {
|
||||||
const pairObject = pushParseAndPop(
|
const pairObject = pushParseAndPop(
|
||||||
{}, PAIR_PARSERS, node, objectStack);
|
{}, PAIR_PARSERS, node, objectStack, this);
|
||||||
if (!pairObject) {
|
if (!pairObject) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1907,11 +1919,12 @@ function pairDataParser(node, objectStack) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @this {KML}
|
||||||
* @param {Element} node Node.
|
* @param {Element} node Node.
|
||||||
* @param {Array<*>} objectStack Object stack.
|
* @param {Array<*>} objectStack Object stack.
|
||||||
*/
|
*/
|
||||||
function placemarkStyleMapParser(node, objectStack) {
|
function placemarkStyleMapParser(node, objectStack) {
|
||||||
const styleMapValue = readStyleMapValue(node, objectStack);
|
const styleMapValue = readStyleMapValue.call(this, node, objectStack);
|
||||||
if (!styleMapValue) {
|
if (!styleMapValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {abstract} from '../util.js';
|
|||||||
import {extend} from '../array.js';
|
import {extend} from '../array.js';
|
||||||
import FeatureFormat from '../format/Feature.js';
|
import FeatureFormat from '../format/Feature.js';
|
||||||
import FormatType from '../format/FormatType.js';
|
import FormatType from '../format/FormatType.js';
|
||||||
import {isDocument, parse} from '../xml.js';
|
import {isDocument, parse, getXMLSerializer} from '../xml.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
@@ -23,7 +23,7 @@ class XMLFeature extends FeatureFormat {
|
|||||||
* @type {XMLSerializer}
|
* @type {XMLSerializer}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.xmlSerializer_ = new XMLSerializer();
|
this.xmlSerializer_ = getXMLSerializer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/format/xsd
|
* @module ol/format/xsd
|
||||||
*/
|
*/
|
||||||
import {getAllTextContent, DOCUMENT} from '../xml.js';
|
import {getAllTextContent, getDocument} from '../xml.js';
|
||||||
import {padNumber} from '../string.js';
|
import {padNumber} from '../string.js';
|
||||||
|
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ export function writeBooleanTextNode(node, bool) {
|
|||||||
* @param {string} string String.
|
* @param {string} string String.
|
||||||
*/
|
*/
|
||||||
export function writeCDATASection(node, string) {
|
export function writeCDATASection(node, string) {
|
||||||
node.appendChild(DOCUMENT.createCDATASection(string));
|
node.appendChild(getDocument().createCDATASection(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ export function writeDateTimeTextNode(node, dateTime) {
|
|||||||
padNumber(date.getUTCHours(), 2) + ':' +
|
padNumber(date.getUTCHours(), 2) + ':' +
|
||||||
padNumber(date.getUTCMinutes(), 2) + ':' +
|
padNumber(date.getUTCMinutes(), 2) + ':' +
|
||||||
padNumber(date.getUTCSeconds(), 2) + 'Z';
|
padNumber(date.getUTCSeconds(), 2) + 'Z';
|
||||||
node.appendChild(DOCUMENT.createTextNode(string));
|
node.appendChild(getDocument().createTextNode(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ export function writeDateTimeTextNode(node, dateTime) {
|
|||||||
*/
|
*/
|
||||||
export function writeDecimalTextNode(node, decimal) {
|
export function writeDecimalTextNode(node, decimal) {
|
||||||
const string = decimal.toPrecision();
|
const string = decimal.toPrecision();
|
||||||
node.appendChild(DOCUMENT.createTextNode(string));
|
node.appendChild(getDocument().createTextNode(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ export function writeDecimalTextNode(node, decimal) {
|
|||||||
*/
|
*/
|
||||||
export function writeNonNegativeIntegerTextNode(node, nonNegativeInteger) {
|
export function writeNonNegativeIntegerTextNode(node, nonNegativeInteger) {
|
||||||
const string = nonNegativeInteger.toString();
|
const string = nonNegativeInteger.toString();
|
||||||
node.appendChild(DOCUMENT.createTextNode(string));
|
node.appendChild(getDocument().createTextNode(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -157,5 +157,5 @@ export function writeNonNegativeIntegerTextNode(node, nonNegativeInteger) {
|
|||||||
* @param {string} string String.
|
* @param {string} string String.
|
||||||
*/
|
*/
|
||||||
export function writeStringTextNode(node, string) {
|
export function writeStringTextNode(node, string) {
|
||||||
node.appendChild(DOCUMENT.createTextNode(string));
|
node.appendChild(getDocument().createTextNode(string));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,3 +44,23 @@ export const DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;
|
|||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
export const IMAGE_DECODE = typeof Image !== 'undefined' && Image.prototype.decode;
|
export const IMAGE_DECODE = typeof Image !== 'undefined' && Image.prototype.decode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
export const PASSIVE_EVENT_LISTENERS = (function() {
|
||||||
|
let passive = false;
|
||||||
|
try {
|
||||||
|
const options = Object.defineProperty({}, 'passive', {
|
||||||
|
get: function() {
|
||||||
|
passive = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('_', null, options);
|
||||||
|
window.removeEventListener('_', null, options);
|
||||||
|
} catch (error) {
|
||||||
|
// passive not supported
|
||||||
|
}
|
||||||
|
return passive;
|
||||||
|
})();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
// FIXME draw drag box
|
// FIXME draw drag box
|
||||||
import Event from '../events/Event.js';
|
import Event from '../events/Event.js';
|
||||||
import {always, mouseOnly, mouseActionButton} from '../events/condition.js';
|
import {mouseActionButton} from '../events/condition.js';
|
||||||
import {VOID} from '../functions.js';
|
import {VOID} from '../functions.js';
|
||||||
import PointerInteraction from './Pointer.js';
|
import PointerInteraction from './Pointer.js';
|
||||||
import RenderBox from '../render/Box.js';
|
import RenderBox from '../render/Box.js';
|
||||||
@@ -22,7 +22,7 @@ import RenderBox from '../render/Box.js';
|
|||||||
* @property {string} [className='ol-dragbox'] CSS class name for styling the box.
|
* @property {string} [className='ol-dragbox'] CSS class name for styling the box.
|
||||||
* @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
|
* @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
|
||||||
* to indicate whether that event should be handled.
|
* to indicate whether that event should be handled.
|
||||||
* Default is {@link ol/events/condition~always}.
|
* Default is {@link ol/events/condition~mouseActionButton}.
|
||||||
* @property {number} [minArea=64] The minimum area of the box in pixel, this value is used by the default
|
* @property {number} [minArea=64] The minimum area of the box in pixel, this value is used by the default
|
||||||
* `boxEndCondition` function.
|
* `boxEndCondition` function.
|
||||||
* @property {EndCondition} [boxEndCondition] A function that takes a {@link module:ol/MapBrowserEvent~MapBrowserEvent} and two
|
* @property {EndCondition} [boxEndCondition] A function that takes a {@link module:ol/MapBrowserEvent~MapBrowserEvent} and two
|
||||||
@@ -104,8 +104,6 @@ class DragBoxEvent extends Event {
|
|||||||
* (see {@link module:ol/interaction/DragZoom~DragZoom} and
|
* (see {@link module:ol/interaction/DragZoom~DragZoom} and
|
||||||
* {@link module:ol/interaction/DragRotateAndZoom}).
|
* {@link module:ol/interaction/DragRotateAndZoom}).
|
||||||
*
|
*
|
||||||
* This interaction is only supported for mouse devices.
|
|
||||||
*
|
|
||||||
* @fires DragBoxEvent
|
* @fires DragBoxEvent
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
@@ -148,7 +146,7 @@ class DragBox extends PointerInteraction {
|
|||||||
* @private
|
* @private
|
||||||
* @type {import("../events/condition.js").Condition}
|
* @type {import("../events/condition.js").Condition}
|
||||||
*/
|
*/
|
||||||
this.condition_ = options.condition ? options.condition : always;
|
this.condition_ = options.condition ? options.condition : mouseActionButton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -186,10 +184,6 @@ class DragBox extends PointerInteraction {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
handleDragEvent(mapBrowserEvent) {
|
handleDragEvent(mapBrowserEvent) {
|
||||||
if (!mouseOnly(mapBrowserEvent)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
|
this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
|
||||||
|
|
||||||
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXDRAG,
|
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXDRAG,
|
||||||
@@ -200,10 +194,6 @@ class DragBox extends PointerInteraction {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
handleUpEvent(mapBrowserEvent) {
|
handleUpEvent(mapBrowserEvent) {
|
||||||
if (!mouseOnly(mapBrowserEvent)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.box_.setMap(null);
|
this.box_.setMap(null);
|
||||||
|
|
||||||
if (this.boxEndCondition_(mapBrowserEvent, this.startPixel_, mapBrowserEvent.pixel)) {
|
if (this.boxEndCondition_(mapBrowserEvent, this.startPixel_, mapBrowserEvent.pixel)) {
|
||||||
@@ -218,12 +208,7 @@ class DragBox extends PointerInteraction {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
handleDownEvent(mapBrowserEvent) {
|
handleDownEvent(mapBrowserEvent) {
|
||||||
if (!mouseOnly(mapBrowserEvent)) {
|
if (this.condition_(mapBrowserEvent)) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mouseActionButton(mapBrowserEvent) &&
|
|
||||||
this.condition_(mapBrowserEvent)) {
|
|
||||||
this.startPixel_ = mapBrowserEvent.pixel;
|
this.startPixel_ = mapBrowserEvent.pixel;
|
||||||
this.box_.setMap(mapBrowserEvent.map);
|
this.box_.setMap(mapBrowserEvent.map);
|
||||||
this.box_.setPixels(this.startPixel_, this.startPixel_);
|
this.box_.setPixels(this.startPixel_, this.startPixel_);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
import {scale as scaleCoordinate, rotate as rotateCoordinate} from '../coordinate.js';
|
import {scale as scaleCoordinate, rotate as rotateCoordinate} from '../coordinate.js';
|
||||||
import {easeOut} from '../easing.js';
|
import {easeOut} from '../easing.js';
|
||||||
import {noModifierKeys, primaryAction} from '../events/condition.js';
|
import {noModifierKeys, primaryAction, focus} from '../events/condition.js';
|
||||||
import {FALSE} from '../functions.js';
|
import {FALSE} from '../functions.js';
|
||||||
import PointerInteraction, {centroid as centroidFromPointers} from './Pointer.js';
|
import PointerInteraction, {centroid as centroidFromPointers} from './Pointer.js';
|
||||||
|
|
||||||
@@ -69,6 +69,20 @@ class DragPan extends PointerInteraction {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param {import("../MapBrowserEvent").default} mapBrowserEvent Event.
|
||||||
|
* @return {boolean} Condition passes.
|
||||||
|
*/
|
||||||
|
conditionInternal_(mapBrowserEvent) {
|
||||||
|
let pass = true;
|
||||||
|
if (mapBrowserEvent.map.getTargetElement().hasAttribute('tabindex')) {
|
||||||
|
pass = focus(mapBrowserEvent);
|
||||||
|
}
|
||||||
|
return pass && this.condition_(mapBrowserEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
@@ -101,6 +115,7 @@ class DragPan extends PointerInteraction {
|
|||||||
}
|
}
|
||||||
this.lastCentroid = centroid;
|
this.lastCentroid = centroid;
|
||||||
this.lastPointersCount_ = targetPointers.length;
|
this.lastPointersCount_ = targetPointers.length;
|
||||||
|
mapBrowserEvent.originalEvent.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,7 +160,7 @@ class DragPan extends PointerInteraction {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
handleDownEvent(mapBrowserEvent) {
|
handleDownEvent(mapBrowserEvent) {
|
||||||
if (this.targetPointers.length > 0 && this.condition_(mapBrowserEvent)) {
|
if (this.targetPointers.length > 0 && this.conditionInternal_(mapBrowserEvent)) {
|
||||||
const map = mapBrowserEvent.map;
|
const map = mapBrowserEvent.map;
|
||||||
const view = map.getView();
|
const view = map.getView();
|
||||||
this.lastCentroid = null;
|
this.lastCentroid = null;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import InteractionProperty from './Property.js';
|
|||||||
import VectorLayer from '../layer/Vector.js';
|
import VectorLayer from '../layer/Vector.js';
|
||||||
import VectorSource from '../source/Vector.js';
|
import VectorSource from '../source/Vector.js';
|
||||||
import {createEditingStyle} from '../style/Style.js';
|
import {createEditingStyle} from '../style/Style.js';
|
||||||
|
import {fromUserCoordinate, getUserProjection} from '../proj.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,11 +105,12 @@ import {createEditingStyle} from '../style/Style.js';
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that takes an array of coordinates and an optional existing geometry as
|
* Function that takes an array of coordinates and an optional existing geometry
|
||||||
* arguments, and returns a geometry. The optional existing geometry is the
|
* and a projection as arguments, and returns a geometry. The optional existing
|
||||||
* geometry that is returned when the function is called without a second
|
* geometry is the geometry that is returned when the function is called without
|
||||||
* argument.
|
* a second argument.
|
||||||
* @typedef {function(!SketchCoordType, import("../geom/SimpleGeometry.js").default=):
|
* @typedef {function(!SketchCoordType, import("../geom/SimpleGeometry.js").default=,
|
||||||
|
* import("../proj/Projection.js").default):
|
||||||
* import("../geom/SimpleGeometry.js").default} GeometryFunction
|
* import("../geom/SimpleGeometry.js").default} GeometryFunction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -296,14 +298,20 @@ class Draw extends PointerInteraction {
|
|||||||
/**
|
/**
|
||||||
* @param {!LineCoordType} coordinates The coordinates.
|
* @param {!LineCoordType} coordinates The coordinates.
|
||||||
* @param {import("../geom/SimpleGeometry.js").default=} opt_geometry Optional geometry.
|
* @param {import("../geom/SimpleGeometry.js").default=} opt_geometry Optional geometry.
|
||||||
|
* @param {import("../proj/Projection.js").default} projection The view projection.
|
||||||
* @return {import("../geom/SimpleGeometry.js").default} A geometry.
|
* @return {import("../geom/SimpleGeometry.js").default} A geometry.
|
||||||
*/
|
*/
|
||||||
geometryFunction = function(coordinates, opt_geometry) {
|
geometryFunction = function(coordinates, opt_geometry, projection) {
|
||||||
const circle = opt_geometry ? /** @type {Circle} */ (opt_geometry) :
|
const circle = opt_geometry ? /** @type {Circle} */ (opt_geometry) :
|
||||||
new Circle([NaN, NaN]);
|
new Circle([NaN, NaN]);
|
||||||
|
const center = fromUserCoordinate(coordinates[0], projection);
|
||||||
const squaredLength = squaredCoordinateDistance(
|
const squaredLength = squaredCoordinateDistance(
|
||||||
coordinates[0], coordinates[1]);
|
center, fromUserCoordinate(coordinates[1], projection));
|
||||||
circle.setCenterAndRadius(coordinates[0], Math.sqrt(squaredLength));
|
circle.setCenterAndRadius(center, Math.sqrt(squaredLength));
|
||||||
|
const userProjection = getUserProjection();
|
||||||
|
if (userProjection) {
|
||||||
|
circle.transform(projection, userProjection);
|
||||||
|
}
|
||||||
return circle;
|
return circle;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@@ -319,9 +327,10 @@ class Draw extends PointerInteraction {
|
|||||||
/**
|
/**
|
||||||
* @param {!LineCoordType} coordinates The coordinates.
|
* @param {!LineCoordType} coordinates The coordinates.
|
||||||
* @param {import("../geom/SimpleGeometry.js").default=} opt_geometry Optional geometry.
|
* @param {import("../geom/SimpleGeometry.js").default=} opt_geometry Optional geometry.
|
||||||
|
* @param {import("../proj/Projection.js").default} projection The view projection.
|
||||||
* @return {import("../geom/SimpleGeometry.js").default} A geometry.
|
* @return {import("../geom/SimpleGeometry.js").default} A geometry.
|
||||||
*/
|
*/
|
||||||
geometryFunction = function(coordinates, opt_geometry) {
|
geometryFunction = function(coordinates, opt_geometry, projection) {
|
||||||
let geometry = opt_geometry;
|
let geometry = opt_geometry;
|
||||||
if (geometry) {
|
if (geometry) {
|
||||||
if (mode === Mode.POLYGON) {
|
if (mode === Mode.POLYGON) {
|
||||||
@@ -675,6 +684,7 @@ class Draw extends PointerInteraction {
|
|||||||
*/
|
*/
|
||||||
startDrawing_(event) {
|
startDrawing_(event) {
|
||||||
const start = event.coordinate;
|
const start = event.coordinate;
|
||||||
|
const projection = event.map.getView().getProjection();
|
||||||
this.finishCoordinate_ = start;
|
this.finishCoordinate_ = start;
|
||||||
if (this.mode_ === Mode.POINT) {
|
if (this.mode_ === Mode.POINT) {
|
||||||
this.sketchCoords_ = start.slice();
|
this.sketchCoords_ = start.slice();
|
||||||
@@ -688,7 +698,7 @@ class Draw extends PointerInteraction {
|
|||||||
this.sketchLine_ = new Feature(
|
this.sketchLine_ = new Feature(
|
||||||
new LineString(this.sketchLineCoords_));
|
new LineString(this.sketchLineCoords_));
|
||||||
}
|
}
|
||||||
const geometry = this.geometryFunction_(this.sketchCoords_);
|
const geometry = this.geometryFunction_(this.sketchCoords_, undefined, projection);
|
||||||
this.sketchFeature_ = new Feature();
|
this.sketchFeature_ = new Feature();
|
||||||
if (this.geometryName_) {
|
if (this.geometryName_) {
|
||||||
this.sketchFeature_.setGeometryName(this.geometryName_);
|
this.sketchFeature_.setGeometryName(this.geometryName_);
|
||||||
@@ -706,6 +716,7 @@ class Draw extends PointerInteraction {
|
|||||||
modifyDrawing_(event) {
|
modifyDrawing_(event) {
|
||||||
let coordinate = event.coordinate;
|
let coordinate = event.coordinate;
|
||||||
const geometry = this.sketchFeature_.getGeometry();
|
const geometry = this.sketchFeature_.getGeometry();
|
||||||
|
const projection = event.map.getView().getProjection();
|
||||||
let coordinates, last;
|
let coordinates, last;
|
||||||
if (this.mode_ === Mode.POINT) {
|
if (this.mode_ === Mode.POINT) {
|
||||||
last = this.sketchCoords_;
|
last = this.sketchCoords_;
|
||||||
@@ -722,7 +733,7 @@ class Draw extends PointerInteraction {
|
|||||||
}
|
}
|
||||||
last[0] = coordinate[0];
|
last[0] = coordinate[0];
|
||||||
last[1] = coordinate[1];
|
last[1] = coordinate[1];
|
||||||
this.geometryFunction_(/** @type {!LineCoordType} */ (this.sketchCoords_), geometry);
|
this.geometryFunction_(/** @type {!LineCoordType} */ (this.sketchCoords_), geometry, projection);
|
||||||
if (this.sketchPoint_) {
|
if (this.sketchPoint_) {
|
||||||
const sketchPointGeom = this.sketchPoint_.getGeometry();
|
const sketchPointGeom = this.sketchPoint_.getGeometry();
|
||||||
sketchPointGeom.setCoordinates(coordinate);
|
sketchPointGeom.setCoordinates(coordinate);
|
||||||
@@ -759,6 +770,7 @@ class Draw extends PointerInteraction {
|
|||||||
addToDrawing_(event) {
|
addToDrawing_(event) {
|
||||||
const coordinate = event.coordinate;
|
const coordinate = event.coordinate;
|
||||||
const geometry = this.sketchFeature_.getGeometry();
|
const geometry = this.sketchFeature_.getGeometry();
|
||||||
|
const projection = event.map.getView().getProjection();
|
||||||
let done;
|
let done;
|
||||||
let coordinates;
|
let coordinates;
|
||||||
if (this.mode_ === Mode.LINE_STRING) {
|
if (this.mode_ === Mode.LINE_STRING) {
|
||||||
@@ -772,7 +784,7 @@ class Draw extends PointerInteraction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
coordinates.push(coordinate.slice());
|
coordinates.push(coordinate.slice());
|
||||||
this.geometryFunction_(coordinates, geometry);
|
this.geometryFunction_(coordinates, geometry, projection);
|
||||||
} else if (this.mode_ === Mode.POLYGON) {
|
} else if (this.mode_ === Mode.POLYGON) {
|
||||||
coordinates = /** @type {PolyCoordType} */ (this.sketchCoords_)[0];
|
coordinates = /** @type {PolyCoordType} */ (this.sketchCoords_)[0];
|
||||||
if (coordinates.length >= this.maxPoints_) {
|
if (coordinates.length >= this.maxPoints_) {
|
||||||
@@ -786,7 +798,7 @@ class Draw extends PointerInteraction {
|
|||||||
if (done) {
|
if (done) {
|
||||||
this.finishCoordinate_ = coordinates[0];
|
this.finishCoordinate_ = coordinates[0];
|
||||||
}
|
}
|
||||||
this.geometryFunction_(this.sketchCoords_, geometry);
|
this.geometryFunction_(this.sketchCoords_, geometry, projection);
|
||||||
}
|
}
|
||||||
this.updateSketchFeatures_();
|
this.updateSketchFeatures_();
|
||||||
if (done) {
|
if (done) {
|
||||||
@@ -803,13 +815,14 @@ class Draw extends PointerInteraction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const geometry = this.sketchFeature_.getGeometry();
|
const geometry = this.sketchFeature_.getGeometry();
|
||||||
|
const projection = this.getMap().getView().getProjection();
|
||||||
let coordinates;
|
let coordinates;
|
||||||
/** @type {LineString} */
|
/** @type {LineString} */
|
||||||
let sketchLineGeom;
|
let sketchLineGeom;
|
||||||
if (this.mode_ === Mode.LINE_STRING) {
|
if (this.mode_ === Mode.LINE_STRING) {
|
||||||
coordinates = /** @type {LineCoordType} */ (this.sketchCoords_);
|
coordinates = /** @type {LineCoordType} */ (this.sketchCoords_);
|
||||||
coordinates.splice(-2, 1);
|
coordinates.splice(-2, 1);
|
||||||
this.geometryFunction_(coordinates, geometry);
|
this.geometryFunction_(coordinates, geometry, projection);
|
||||||
if (coordinates.length >= 2) {
|
if (coordinates.length >= 2) {
|
||||||
this.finishCoordinate_ = coordinates[coordinates.length - 2].slice();
|
this.finishCoordinate_ = coordinates[coordinates.length - 2].slice();
|
||||||
}
|
}
|
||||||
@@ -818,7 +831,7 @@ class Draw extends PointerInteraction {
|
|||||||
coordinates.splice(-2, 1);
|
coordinates.splice(-2, 1);
|
||||||
sketchLineGeom = this.sketchLine_.getGeometry();
|
sketchLineGeom = this.sketchLine_.getGeometry();
|
||||||
sketchLineGeom.setCoordinates(coordinates);
|
sketchLineGeom.setCoordinates(coordinates);
|
||||||
this.geometryFunction_(this.sketchCoords_, geometry);
|
this.geometryFunction_(this.sketchCoords_, geometry, projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coordinates.length === 0) {
|
if (coordinates.length === 0) {
|
||||||
@@ -841,14 +854,15 @@ class Draw extends PointerInteraction {
|
|||||||
}
|
}
|
||||||
let coordinates = this.sketchCoords_;
|
let coordinates = this.sketchCoords_;
|
||||||
const geometry = sketchFeature.getGeometry();
|
const geometry = sketchFeature.getGeometry();
|
||||||
|
const projection = this.getMap().getView().getProjection();
|
||||||
if (this.mode_ === Mode.LINE_STRING) {
|
if (this.mode_ === Mode.LINE_STRING) {
|
||||||
// remove the redundant last point
|
// remove the redundant last point
|
||||||
coordinates.pop();
|
coordinates.pop();
|
||||||
this.geometryFunction_(coordinates, geometry);
|
this.geometryFunction_(coordinates, geometry, projection);
|
||||||
} else if (this.mode_ === Mode.POLYGON) {
|
} else if (this.mode_ === Mode.POLYGON) {
|
||||||
// remove the redundant last point in ring
|
// remove the redundant last point in ring
|
||||||
/** @type {PolyCoordType} */ (coordinates)[0].pop();
|
/** @type {PolyCoordType} */ (coordinates)[0].pop();
|
||||||
this.geometryFunction_(coordinates, geometry);
|
this.geometryFunction_(coordinates, geometry, projection);
|
||||||
coordinates = geometry.getCoordinates();
|
coordinates = geometry.getCoordinates();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,12 +895,10 @@ class Draw extends PointerInteraction {
|
|||||||
abortDrawing_() {
|
abortDrawing_() {
|
||||||
this.finishCoordinate_ = null;
|
this.finishCoordinate_ = null;
|
||||||
const sketchFeature = this.sketchFeature_;
|
const sketchFeature = this.sketchFeature_;
|
||||||
if (sketchFeature) {
|
this.sketchFeature_ = null;
|
||||||
this.sketchFeature_ = null;
|
this.sketchPoint_ = null;
|
||||||
this.sketchPoint_ = null;
|
this.sketchLine_ = null;
|
||||||
this.sketchLine_ = null;
|
this.overlay_.getSource().clear(true);
|
||||||
this.overlay_.getSource().clear(true);
|
|
||||||
}
|
|
||||||
return sketchFeature;
|
return sketchFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -968,9 +980,9 @@ function getDefaultStyleFunction() {
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
export function createRegularPolygon(opt_sides, opt_angle) {
|
export function createRegularPolygon(opt_sides, opt_angle) {
|
||||||
return function(coordinates, opt_geometry) {
|
return function(coordinates, opt_geometry, projection) {
|
||||||
const center = /** @type {LineCoordType} */ (coordinates)[0];
|
const center = fromUserCoordinate(/** @type {LineCoordType} */ (coordinates)[0], projection);
|
||||||
const end = /** @type {LineCoordType} */ (coordinates)[1];
|
const end = fromUserCoordinate(/** @type {LineCoordType} */ (coordinates)[1], projection);
|
||||||
const radius = Math.sqrt(
|
const radius = Math.sqrt(
|
||||||
squaredCoordinateDistance(center, end));
|
squaredCoordinateDistance(center, end));
|
||||||
const geometry = opt_geometry ? /** @type {Polygon} */ (opt_geometry) :
|
const geometry = opt_geometry ? /** @type {Polygon} */ (opt_geometry) :
|
||||||
@@ -982,6 +994,10 @@ export function createRegularPolygon(opt_sides, opt_angle) {
|
|||||||
angle = Math.atan(y / x) - (x < 0 ? Math.PI : 0);
|
angle = Math.atan(y / x) - (x < 0 ? Math.PI : 0);
|
||||||
}
|
}
|
||||||
makeRegular(geometry, center, radius, angle);
|
makeRegular(geometry, center, radius, angle);
|
||||||
|
const userProjection = getUserProjection();
|
||||||
|
if (userProjection) {
|
||||||
|
geometry.transform(projection, userProjection);
|
||||||
|
}
|
||||||
return geometry;
|
return geometry;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -996,8 +1012,10 @@ export function createRegularPolygon(opt_sides, opt_angle) {
|
|||||||
*/
|
*/
|
||||||
export function createBox() {
|
export function createBox() {
|
||||||
return (
|
return (
|
||||||
function(coordinates, opt_geometry) {
|
function(coordinates, opt_geometry, projection) {
|
||||||
const extent = boundingExtent(/** @type {LineCoordType} */ (coordinates));
|
const extent = boundingExtent(/** @type {LineCoordType} */ (coordinates).map(function(coordinate) {
|
||||||
|
return fromUserCoordinate(coordinate, projection);
|
||||||
|
}));
|
||||||
const boxCoordinates = [[
|
const boxCoordinates = [[
|
||||||
getBottomLeft(extent),
|
getBottomLeft(extent),
|
||||||
getBottomRight(extent),
|
getBottomRight(extent),
|
||||||
@@ -1011,6 +1029,10 @@ export function createBox() {
|
|||||||
} else {
|
} else {
|
||||||
geometry = new Polygon(boxCoordinates);
|
geometry = new Polygon(boxCoordinates);
|
||||||
}
|
}
|
||||||
|
const userProjection = getUserProjection();
|
||||||
|
if (userProjection) {
|
||||||
|
geometry.transform(projection, userProjection);
|
||||||
|
}
|
||||||
return geometry;
|
return geometry;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -807,8 +807,8 @@ class Modify extends PointerInteraction {
|
|||||||
if (!this.condition_(evt)) {
|
if (!this.condition_(evt)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.handlePointerAtPixel_(evt.pixel, evt.map);
|
|
||||||
const pixelCoordinate = evt.coordinate;
|
const pixelCoordinate = evt.coordinate;
|
||||||
|
this.handlePointerAtPixel_(evt.pixel, evt.map, pixelCoordinate);
|
||||||
this.dragSegments_.length = 0;
|
this.dragSegments_.length = 0;
|
||||||
this.modified_ = false;
|
this.modified_ = false;
|
||||||
const vertexFeature = this.vertexFeature_;
|
const vertexFeature = this.vertexFeature_;
|
||||||
@@ -916,16 +916,17 @@ class Modify extends PointerInteraction {
|
|||||||
*/
|
*/
|
||||||
handlePointerMove_(evt) {
|
handlePointerMove_(evt) {
|
||||||
this.lastPixel_ = evt.pixel;
|
this.lastPixel_ = evt.pixel;
|
||||||
this.handlePointerAtPixel_(evt.pixel, evt.map);
|
this.handlePointerAtPixel_(evt.pixel, evt.map, evt.coordinate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../pixel.js").Pixel} pixel Pixel
|
* @param {import("../pixel.js").Pixel} pixel Pixel
|
||||||
* @param {import("../PluggableMap.js").default} map Map.
|
* @param {import("../PluggableMap.js").default} map Map.
|
||||||
|
* @param {import("../coordinate.js").Coordinate=} opt_coordinate The pixel Coordinate.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
handlePointerAtPixel_(pixel, map) {
|
handlePointerAtPixel_(pixel, map, opt_coordinate) {
|
||||||
const pixelCoordinate = map.getCoordinateFromPixel(pixel);
|
const pixelCoordinate = opt_coordinate || map.getCoordinateFromPixel(pixel);
|
||||||
const projection = map.getView().getProjection();
|
const projection = map.getView().getProjection();
|
||||||
const sortByDistance = function(a, b) {
|
const sortByDistance = function(a, b) {
|
||||||
return projectedDistanceToSegmentDataSquared(pixelCoordinate, a, projection) -
|
return projectedDistanceToSegmentDataSquared(pixelCoordinate, a, projection) -
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @module ol/interaction/MouseWheelZoom
|
* @module ol/interaction/MouseWheelZoom
|
||||||
*/
|
*/
|
||||||
import {always} from '../events/condition.js';
|
import {always, focus} from '../events/condition.js';
|
||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import {DEVICE_PIXEL_RATIO, FIREFOX} from '../has.js';
|
import {DEVICE_PIXEL_RATIO, FIREFOX} from '../has.js';
|
||||||
import Interaction, {zoomByDelta} from './Interaction.js';
|
import Interaction, {zoomByDelta} from './Interaction.js';
|
||||||
@@ -134,13 +134,27 @@ class MouseWheelZoom extends Interaction {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param {import("../MapBrowserEvent").default} mapBrowserEvent Event.
|
||||||
|
* @return {boolean} Condition passes.
|
||||||
|
*/
|
||||||
|
conditionInternal_(mapBrowserEvent) {
|
||||||
|
let pass = true;
|
||||||
|
if (mapBrowserEvent.map.getTargetElement().hasAttribute('tabindex')) {
|
||||||
|
pass = focus(mapBrowserEvent);
|
||||||
|
}
|
||||||
|
return pass && this.condition_(mapBrowserEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
endInteraction_() {
|
endInteraction_() {
|
||||||
this.trackpadTimeoutId_ = undefined;
|
this.trackpadTimeoutId_ = undefined;
|
||||||
const view = this.getMap().getView();
|
const view = this.getMap().getView();
|
||||||
view.endInteraction(undefined, Math.sign(this.lastDelta_), this.lastAnchor_);
|
view.endInteraction(undefined, this.lastDelta_ ? (this.lastDelta_ > 0 ? 1 : -1) : 0, this.lastAnchor_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,7 +163,7 @@ class MouseWheelZoom extends Interaction {
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
handleEvent(mapBrowserEvent) {
|
handleEvent(mapBrowserEvent) {
|
||||||
if (!this.condition_(mapBrowserEvent)) {
|
if (!this.conditionInternal_(mapBrowserEvent)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const type = mapBrowserEvent.type;
|
const type = mapBrowserEvent.type;
|
||||||
|
|||||||
@@ -95,6 +95,16 @@ class PointerInteraction extends Interaction {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current number of pointers involved in the interaction,
|
||||||
|
* e.g. `2` when two fingers are used.
|
||||||
|
* @return {number} The number of pointers.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
getPointerCount() {
|
||||||
|
return this.targetPointers.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle pointer down events.
|
* Handle pointer down events.
|
||||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||||
@@ -136,9 +146,6 @@ class PointerInteraction extends Interaction {
|
|||||||
} else {
|
} else {
|
||||||
if (mapBrowserEvent.type == MapBrowserEventType.POINTERDOWN) {
|
if (mapBrowserEvent.type == MapBrowserEventType.POINTERDOWN) {
|
||||||
const handled = this.handleDownEvent(mapBrowserEvent);
|
const handled = this.handleDownEvent(mapBrowserEvent);
|
||||||
if (handled) {
|
|
||||||
mapBrowserEvent.preventDefault();
|
|
||||||
}
|
|
||||||
this.handlingDownUpSequence = handled;
|
this.handlingDownUpSequence = handled;
|
||||||
stopEvent = this.stopDown(handled);
|
stopEvent = this.stopDown(handled);
|
||||||
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE) {
|
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE) {
|
||||||
|
|||||||
@@ -294,7 +294,9 @@ class Heatmap extends VectorLayer {
|
|||||||
gl_FragColor.rgb *= gl_FragColor.a;
|
gl_FragColor.rgb *= gl_FragColor.a;
|
||||||
}`,
|
}`,
|
||||||
uniforms: {
|
uniforms: {
|
||||||
u_gradientTexture: this.gradient_
|
u_gradientTexture: function() {
|
||||||
|
return this.gradient_;
|
||||||
|
}.bind(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ import {assign} from '../obj.js';
|
|||||||
* * `'hybrid'`: Polygon and line elements are rendered as images, so pixels are scaled during zoom
|
* * `'hybrid'`: Polygon and line elements are rendered as images, so pixels are scaled during zoom
|
||||||
* animations. Point symbols and texts are accurately rendered as vectors and can stay upright on
|
* animations. Point symbols and texts are accurately rendered as vectors and can stay upright on
|
||||||
* rotated views.
|
* rotated views.
|
||||||
*
|
* * `'vector'`: Everything is rendered as vectors. Use this mode for improved performance on vector
|
||||||
|
* tile layers with only a few rendered features (e.g. for highlighting a subset of features of
|
||||||
|
* another layer with the same source).
|
||||||
* @property {import("../source/VectorTile.js").default} [source] Source.
|
* @property {import("../source/VectorTile.js").default} [source] Source.
|
||||||
* @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage
|
* @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage
|
||||||
* this layer in its layers collection, and the layer will be rendered on top. This is useful for
|
* this layer in its layers collection, and the layer will be rendered on top. This is useful for
|
||||||
@@ -92,8 +94,9 @@ class VectorTileLayer extends BaseVectorLayer {
|
|||||||
const renderMode = options.renderMode || VectorTileRenderType.HYBRID;
|
const renderMode = options.renderMode || VectorTileRenderType.HYBRID;
|
||||||
assert(renderMode == undefined ||
|
assert(renderMode == undefined ||
|
||||||
renderMode == VectorTileRenderType.IMAGE ||
|
renderMode == VectorTileRenderType.IMAGE ||
|
||||||
renderMode == VectorTileRenderType.HYBRID,
|
renderMode == VectorTileRenderType.HYBRID ||
|
||||||
28); // `renderMode` must be `'image'` or `'hybrid'`
|
renderMode == VectorTileRenderType.VECTOR,
|
||||||
|
28); // `renderMode` must be `'image'`, `'hybrid'` or `'vector'`.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
|
|||||||
@@ -11,9 +11,14 @@
|
|||||||
* * `'hybrid'`: Polygon and line elements are rendered as images, so pixels
|
* * `'hybrid'`: Polygon and line elements are rendered as images, so pixels
|
||||||
* are scaled during zoom animations. Point symbols and texts are accurately
|
* are scaled during zoom animations. Point symbols and texts are accurately
|
||||||
* rendered as vectors and can stay upright on rotated views.
|
* rendered as vectors and can stay upright on rotated views.
|
||||||
|
* * `'vector'`: Everything is rendered as vectors. Use this mode for improved
|
||||||
|
* performance on vector tile layers with only a few rendered features (e.g.
|
||||||
|
* for highlighting a subset of features of another layer with the same
|
||||||
|
* source).
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
IMAGE: 'image',
|
IMAGE: 'image',
|
||||||
HYBRID: 'hybrid'
|
HYBRID: 'hybrid',
|
||||||
|
VECTOR: 'vector'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import Layer from './Layer.js';
|
|||||||
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
|
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
|
||||||
* be visible.
|
* be visible.
|
||||||
* @property {import("../source/Vector.js").default} [source] Source.
|
* @property {import("../source/Vector.js").default} [source] Source.
|
||||||
* @property {boolean} [disableHitDetection] Setting this to true will provide a slight performance boost, but will
|
* @property {boolean} [disableHitDetection=false] Setting this to true will provide a slight performance boost, but will
|
||||||
* prevent all hit detection on the layer.
|
* prevent all hit detection on the layer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,12 @@
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||||
}
|
}
|
||||||
|
.ol-overlaycontainer, .ol-overlaycontainer-stopevent {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.ol-overlaycontainer > *, .ol-overlaycontainer-stopevent > * {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
.ol-selectable {
|
.ol-selectable {
|
||||||
-webkit-touch-callout: default;
|
-webkit-touch-callout: default;
|
||||||
-webkit-user-select: text;
|
-webkit-user-select: text;
|
||||||
@@ -144,6 +150,9 @@
|
|||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
.ol-control button span {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
.ol-zoom-extent button {
|
.ol-zoom-extent button {
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,15 +216,12 @@ export const checkFont = (function() {
|
|||||||
* @return {boolean} Font with style and weight is available
|
* @return {boolean} Font with style and weight is available
|
||||||
*/
|
*/
|
||||||
function isAvailable(fontStyle, fontWeight, fontFamily) {
|
function isAvailable(fontStyle, fontWeight, fontFamily) {
|
||||||
const context = getMeasureContext();
|
|
||||||
let available = true;
|
let available = true;
|
||||||
for (let i = 0; i < len; ++i) {
|
for (let i = 0; i < len; ++i) {
|
||||||
const referenceFont = referenceFonts[i];
|
const referenceFont = referenceFonts[i];
|
||||||
context.font = fontStyle + ' ' + fontWeight + ' ' + size + referenceFont;
|
referenceWidth = measureTextWidth(fontStyle + ' ' + fontWeight + ' ' + size + referenceFont, text);
|
||||||
referenceWidth = context.measureText(text).width;
|
|
||||||
if (fontFamily != referenceFont) {
|
if (fontFamily != referenceFont) {
|
||||||
context.font = fontStyle + ' ' + fontWeight + ' ' + size + fontFamily + ',' + referenceFont;
|
const width = measureTextWidth(fontStyle + ' ' + fontWeight + ' ' + size + fontFamily + ',' + referenceFont, text);
|
||||||
const width = context.measureText(text).width;
|
|
||||||
// If width and referenceWidth are the same, then the fallback was used
|
// If width and referenceWidth are the same, then the fallback was used
|
||||||
// instead of the font we wanted, so the font is not available.
|
// instead of the font we wanted, so the font is not available.
|
||||||
available = available && width != referenceWidth;
|
available = available && width != referenceWidth;
|
||||||
@@ -284,17 +281,6 @@ export const checkFont = (function() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {CanvasRenderingContext2D} Measure context.
|
|
||||||
*/
|
|
||||||
function getMeasureContext() {
|
|
||||||
if (!measureContext) {
|
|
||||||
measureContext = createCanvasContext2D(1, 1);
|
|
||||||
}
|
|
||||||
return measureContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} font Font to use for measuring.
|
* @param {string} font Font to use for measuring.
|
||||||
* @return {import("../size.js").Size} Measurement.
|
* @return {import("../size.js").Size} Measurement.
|
||||||
@@ -333,7 +319,9 @@ export const measureTextHeight = (function() {
|
|||||||
* @return {number} Width.
|
* @return {number} Width.
|
||||||
*/
|
*/
|
||||||
export function measureTextWidth(font, text) {
|
export function measureTextWidth(font, text) {
|
||||||
const measureContext = getMeasureContext();
|
if (!measureContext) {
|
||||||
|
measureContext = createCanvasContext2D(1, 1);
|
||||||
|
}
|
||||||
if (font != measureFont) {
|
if (font != measureFont) {
|
||||||
measureContext.font = font;
|
measureContext.font = font;
|
||||||
measureFont = measureContext.font;
|
measureFont = measureContext.font;
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ import {
|
|||||||
} from '../../transform.js';
|
} from '../../transform.js';
|
||||||
import {createCanvasContext2D} from '../../dom.js';
|
import {createCanvasContext2D} from '../../dom.js';
|
||||||
import {labelCache, defaultTextAlign, measureTextHeight, measureAndCacheTextWidth, measureTextWidths} from '../canvas.js';
|
import {labelCache, defaultTextAlign, measureTextHeight, measureAndCacheTextWidth, measureTextWidths} from '../canvas.js';
|
||||||
import Disposable from '../../Disposable.js';
|
import RBush from 'rbush/rbush.js';
|
||||||
import RBush from 'rbush';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +51,7 @@ const p3 = [];
|
|||||||
const p4 = [];
|
const p4 = [];
|
||||||
|
|
||||||
|
|
||||||
class Executor extends Disposable {
|
class Executor {
|
||||||
/**
|
/**
|
||||||
* @param {number} resolution Resolution.
|
* @param {number} resolution Resolution.
|
||||||
* @param {number} pixelRatio Pixel ratio.
|
* @param {number} pixelRatio Pixel ratio.
|
||||||
@@ -60,7 +59,6 @@ class Executor extends Disposable {
|
|||||||
* @param {SerializableInstructions} instructions The serializable instructions
|
* @param {SerializableInstructions} instructions The serializable instructions
|
||||||
*/
|
*/
|
||||||
constructor(resolution, pixelRatio, overlaps, instructions) {
|
constructor(resolution, pixelRatio, overlaps, instructions) {
|
||||||
super();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
@@ -156,15 +154,6 @@ class Executor extends Disposable {
|
|||||||
this.widths_ = {};
|
this.widths_ = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
disposeInternal() {
|
|
||||||
labelCache.release(this);
|
|
||||||
super.disposeInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} text Text.
|
* @param {string} text Text.
|
||||||
* @param {string} textKey Text style key.
|
* @param {string} textKey Text style key.
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {isEmpty} from '../../obj.js';
|
|||||||
import BuilderType from './BuilderType.js';
|
import BuilderType from './BuilderType.js';
|
||||||
import {create as createTransform, compose as composeTransform} from '../../transform.js';
|
import {create as createTransform, compose as composeTransform} from '../../transform.js';
|
||||||
import Executor from './Executor.js';
|
import Executor from './Executor.js';
|
||||||
import Disposable from '../../Disposable.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
@@ -26,7 +25,7 @@ const ORDER = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
class ExecutorGroup extends Disposable {
|
class ExecutorGroup {
|
||||||
/**
|
/**
|
||||||
* @param {import("../../extent.js").Extent} maxExtent Max extent for clipping. When a
|
* @param {import("../../extent.js").Extent} maxExtent Max extent for clipping. When a
|
||||||
* `maxExtent` was set on the Buillder for this executor group, the same `maxExtent`
|
* `maxExtent` was set on the Buillder for this executor group, the same `maxExtent`
|
||||||
@@ -40,7 +39,6 @@ class ExecutorGroup extends Disposable {
|
|||||||
* @param {number=} opt_renderBuffer Optional rendering buffer.
|
* @param {number=} opt_renderBuffer Optional rendering buffer.
|
||||||
*/
|
*/
|
||||||
constructor(maxExtent, resolution, pixelRatio, overlaps, allInstructions, opt_renderBuffer) {
|
constructor(maxExtent, resolution, pixelRatio, overlaps, allInstructions, opt_renderBuffer) {
|
||||||
super();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -128,24 +126,6 @@ class ExecutorGroup extends Disposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
disposeInternal() {
|
|
||||||
for (const z in this.executorsByZIndex_) {
|
|
||||||
const executors = this.executorsByZIndex_[z];
|
|
||||||
for (const key in executors) {
|
|
||||||
executors[key].disposeInternal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.hitDetectionContext_) {
|
|
||||||
const canvas = this.hitDetectionContext_.canvas;
|
|
||||||
canvas.width = 0;
|
|
||||||
canvas.height = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.disposeInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<BuilderType>} executors Executors.
|
* @param {Array<BuilderType>} executors Executors.
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import {getUid} from '../../util.js';
|
|
||||||
import LRUCache from '../../structs/LRUCache.js';
|
import LRUCache from '../../structs/LRUCache.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,59 +10,11 @@ import LRUCache from '../../structs/LRUCache.js';
|
|||||||
*/
|
*/
|
||||||
class LabelCache extends LRUCache {
|
class LabelCache extends LRUCache {
|
||||||
|
|
||||||
/**
|
expireCache() {
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
constructor(opt_highWaterMark) {
|
|
||||||
super(opt_highWaterMark);
|
|
||||||
this.consumers = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
this.consumers = {};
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @override
|
|
||||||
* @param {string} key Label key.
|
|
||||||
* @param {import("./Executor.js").default} consumer Label consumer.
|
|
||||||
* @return {HTMLCanvasElement} Label.
|
|
||||||
*/
|
|
||||||
get(key, consumer) {
|
|
||||||
const canvas = super.get(key);
|
|
||||||
const consumerId = getUid(consumer);
|
|
||||||
if (!(consumerId in this.consumers)) {
|
|
||||||
this.consumers[consumerId] = {};
|
|
||||||
}
|
|
||||||
this.consumers[consumerId][key] = true;
|
|
||||||
return canvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
prune() {
|
|
||||||
outer:
|
|
||||||
while (this.canExpireCache()) {
|
while (this.canExpireCache()) {
|
||||||
const key = this.peekLastKey();
|
this.pop();
|
||||||
for (const consumerId in this.consumers) {
|
|
||||||
if (key in this.consumers[consumerId]) {
|
|
||||||
break outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const canvas = this.pop();
|
|
||||||
canvas.width = 0;
|
|
||||||
canvas.height = 0;
|
|
||||||
for (const consumerId in this.consumers) {
|
|
||||||
delete this.consumers[consumerId][key];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {import("./Executor.js").default} consumer Label consumer.
|
|
||||||
*/
|
|
||||||
release(consumer) {
|
|
||||||
delete this.consumers[getUid(consumer)];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LabelCache;
|
export default LabelCache;
|
||||||
|
|||||||
@@ -131,8 +131,6 @@ class CanvasTextBuilder extends CanvasBuilder {
|
|||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
this.strokeKey_ = '';
|
this.strokeKey_ = '';
|
||||||
|
|
||||||
labelCache.prune();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,6 +138,7 @@ class CanvasTextBuilder extends CanvasBuilder {
|
|||||||
*/
|
*/
|
||||||
finish() {
|
finish() {
|
||||||
const instructions = super.finish();
|
const instructions = super.finish();
|
||||||
|
labelCache.expireCache();
|
||||||
instructions.textStates = this.textStates;
|
instructions.textStates = this.textStates;
|
||||||
instructions.fillStates = this.fillStates;
|
instructions.fillStates = this.fillStates;
|
||||||
instructions.strokeStates = this.strokeStates;
|
instructions.strokeStates = this.strokeStates;
|
||||||
@@ -461,7 +460,7 @@ class CanvasTextBuilder extends CanvasBuilder {
|
|||||||
strokeState.lineCap + strokeState.lineDashOffset + '|' + strokeState.lineWidth +
|
strokeState.lineCap + strokeState.lineDashOffset + '|' + strokeState.lineWidth +
|
||||||
strokeState.lineJoin + strokeState.miterLimit + '[' + strokeState.lineDash.join() + ']' :
|
strokeState.lineJoin + strokeState.miterLimit + '[' + strokeState.lineDash.join() + ']' :
|
||||||
'';
|
'';
|
||||||
this.textKey_ = textState.font + textState.scale + (textState.textAlign || '?');
|
this.textKey_ = textState.font + textState.scale + (textState.textAlign || '?') + (textState.textBaseline || '?');
|
||||||
this.fillKey_ = fillState ?
|
this.fillKey_ = fillState ?
|
||||||
(typeof fillState.fillStyle == 'string' ? fillState.fillStyle : ('|' + getUid(fillState.fillStyle))) :
|
(typeof fillState.fillStyle == 'string' ? fillState.fillStyle : ('|' + getUid(fillState.fillStyle))) :
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -33,15 +33,18 @@ export function createHitDetectionImageData(size, transforms, features, styleFun
|
|||||||
const renderer = new CanvasImmediateRenderer(context, 0.5, extent, null, rotation);
|
const renderer = new CanvasImmediateRenderer(context, 0.5, extent, null, rotation);
|
||||||
const featureCount = features.length;
|
const featureCount = features.length;
|
||||||
// Stretch hit detection index to use the whole available color range
|
// Stretch hit detection index to use the whole available color range
|
||||||
const indexFactor = Math.ceil((256 * 256 * 256) / featureCount);
|
const indexFactor = Math.ceil((256 * 256 * 256 - 1) / featureCount);
|
||||||
const featuresByZIndex = {};
|
const featuresByZIndex = {};
|
||||||
for (let i = 0; i < featureCount; ++i) {
|
for (let i = 1; i <= featureCount; ++i) {
|
||||||
const feature = features[i];
|
const feature = features[i - 1];
|
||||||
const featureStyleFunction = feature.getStyleFunction() || styleFunction;
|
const featureStyleFunction = feature.getStyleFunction() || styleFunction;
|
||||||
if (!styleFunction) {
|
if (!styleFunction) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let styles = featureStyleFunction(feature, resolution);
|
let styles = featureStyleFunction(feature, resolution);
|
||||||
|
if (!styles) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!Array.isArray(styles)) {
|
if (!Array.isArray(styles)) {
|
||||||
styles = [styles];
|
styles = [styles];
|
||||||
}
|
}
|
||||||
@@ -138,9 +141,9 @@ export function hitDetect(pixel, features, imageData) {
|
|||||||
const g = imageData.data[index + 1];
|
const g = imageData.data[index + 1];
|
||||||
const b = imageData.data[index + 2];
|
const b = imageData.data[index + 2];
|
||||||
const i = b + (256 * (g + (256 * r)));
|
const i = b + (256 * (g + (256 * r)));
|
||||||
const indexFactor = Math.ceil((256 * 256 * 256) / features.length);
|
const indexFactor = Math.ceil((256 * 256 * 256 - 1) / features.length);
|
||||||
if (i % indexFactor === 0) {
|
if (i && i % indexFactor === 0) {
|
||||||
resultFeatures.push(features[i / indexFactor]);
|
resultFeatures.push(features[i / indexFactor - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return resultFeatures;
|
return resultFeatures;
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
|
|
||||||
disposeInternal() {
|
disposeInternal() {
|
||||||
unlistenByKey(this.labelCacheKey_);
|
unlistenByKey(this.labelCacheKey_);
|
||||||
|
this.element_.parentNode.removeChild(this.element_);
|
||||||
super.disposeInternal();
|
super.disposeInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||