Compare commits

...

66 Commits

Author SHA1 Message Date
Andreas Hocevar
43637e2de8 Temporary release changes for v4.6.0-beta.1 2017-11-30 10:27:43 +01:00
Andreas Hocevar
0d1dead5c1 Add pixel ratio to label cache key 2017-11-30 10:24:14 +01:00
Andreas Hocevar
9c1561a496 Fix tests 2017-11-30 10:24:14 +01:00
Andreas Hocevar
84fd7477ed Improve vertical font placement in Firefox 2017-11-30 10:24:14 +01:00
Andreas Hocevar
23ccd0e56e Snap view center to pixel 2017-11-30 10:24:14 +01:00
Frédéric Junod
4990119f86 Merge pull request #7527 from openlayers/greenkeeper/eslint-4.12.1
Update eslint to the latest version 🚀
2017-11-30 08:27:18 +01:00
greenkeeper[bot]
741baa8d20 chore(package): update eslint to version 4.12.1 2017-11-30 06:05:47 +00:00
Andreas Hocevar
45d2f8debb Merge pull request #7521 from cs09g/patch-1
fix setMinZoom/setMaxZoom
2017-11-28 13:47:58 +01:00
cs09g
e745c63383 clamp when resolution is defined 2017-11-28 16:51:11 +09:00
Andreas Hocevar
5ed2f32621 Merge pull request #7519 from ahocevar/declutter-hit-detection
Reuse declutter tree for hit detection
2017-11-28 08:50:01 +01:00
Frédéric Junod
6e39926dd0 Merge pull request #7499 from openlayers/rm_attributions_FrameState
Remove attributions from olx.FrameState instances
2017-11-28 08:24:23 +01:00
cs09g
466d63ac41 fix setMinZoom/setMaxZoom
when view has resolutions property, setMinZoom/setMaxZoom doesn't work.
2017-11-28 16:20:26 +09:00
Andreas Hocevar
ac195c46b1 Reuse declutter tree for hit detection
Replaying for hit detection no longer declutters, but uses the declutter tree
from the previous rendered frame.
2017-11-28 01:36:47 +01:00
Andreas Hocevar
841e79b0e8 Merge pull request #7501 from ahocevar/vector-layer-image
Option to render vector layers as images
2017-11-27 18:11:10 +01:00
Andreas Hocevar
3c806f924e Address review comments 2017-11-27 17:54:16 +01:00
Andreas Hocevar
dde81d8585 Add renderMode option to ol.layer.Vector
This also deprecates ol.source.ImageVector.
2017-11-27 09:48:52 +01:00
Andreas Hocevar
29e3dd39e4 Merge pull request #7516 from ahocevar/overflow
Deprecate exceedLength and replace with overflow
2017-11-27 09:42:59 +01:00
Andreas Hocevar
674868a683 Deprecate exceedLength and replace with overflow 2017-11-27 09:25:41 +01:00
Andreas Hocevar
7ffed344d1 Merge pull request #7510 from ahocevar/states-no-fade
Do not fade the states layer
2017-11-27 08:47:40 +01:00
Andreas Hocevar
dce56ac73a Merge pull request #7513 from ahocevar/stroke-key
Make strokeKey safer
2017-11-27 08:47:09 +01:00
Andreas Hocevar
101b53e135 Merge pull request #7514 from ahocevar/less-aggressive-prune
Prune the label cache less aggressively
2017-11-27 08:46:42 +01:00
Andreas Hocevar
66d5d66129 Prune the label cache less aggressively 2017-11-26 23:30:58 +01:00
Andreas Hocevar
f426c1cd18 Make strokeKey safer 2017-11-26 12:50:14 +01:00
Andreas Hocevar
ceab6444b9 Merge pull request #7511 from openlayers/greenkeeper/rollup-0.52.0
Update rollup to the latest version 🚀
2017-11-26 10:47:41 +01:00
Marc Jansen
5085cd8d6a Merge pull request #7512 from openlayers/greenkeeper/eslint-4.12.0
Update eslint to the latest version 🚀
2017-11-26 10:25:07 +01:00
greenkeeper[bot]
4e0d52806c chore(package): update eslint to version 4.12.0 2017-11-26 05:41:40 +00:00
greenkeeper[bot]
ee8ccc33e0 fix(package): update rollup to version 0.52.0 2017-11-25 20:21:18 +00:00
Andreas Hocevar
5e43208d93 Do not fade the states layer 2017-11-25 10:08:43 +01:00
Frédéric Junod
7fbada28ac Merge pull request #7505 from fredj/rm_api_link
Remove ol.DeviceOrientation link from API index
2017-11-24 15:26:11 +01:00
Frederic Junod
2278715f85 Remove ol.DeviceOrientation link from API index
`ol.DeviceOrientation` is now deprecated
2017-11-24 12:39:05 +01:00
Frederic Junod
4f5613d2fa Remove attributions from olx.FrameState instances 2017-11-23 12:00:12 +01:00
Andreas Hocevar
c48685565d Merge pull request #7497 from nicholas-l/patch-1
Use getGeometry
2017-11-23 09:38:54 +01:00
Andreas Hocevar
0b3a92d89e Merge pull request #7495 from ahocevar/remove-layer-renderers-with-viewport
Remove layer renderers when viewport is removed
2017-11-23 08:58:18 +01:00
Frédéric Junod
53e675725b Merge pull request #7492 from fredj/type_cast_examples
Remove unneeded type cast from examples
2017-11-23 08:26:00 +01:00
Nicholas Latham
397c03a6b6 Use getGeometry
Use getGeometry for compatibility between RenderFeature and Feature
2017-11-23 15:13:47 +13:00
Andreas Hocevar
3e574529ad Remove layer renderers when viewport is removed 2017-11-22 23:56:28 +01:00
Frederic Junod
8aa591c04d Remove unneeded type cast from examples 2017-11-22 14:00:00 +01:00
Frédéric Junod
5d71dde8dd Merge pull request #7489 from fredj/draw_type_string
Allow string to be passed as ol.interaction.Draw type
2017-11-22 08:58:45 +01:00
Frederic Junod
c0d57ad005 Allow string to be passed as ol.interaction.Draw type 2017-11-21 09:55:54 +01:00
Frédéric Junod
ae6ba195f7 Merge pull request #7484 from openlayers/greenkeeper/closure-util-1.26.0
Update closure-util to the latest version 🚀
2017-11-17 15:01:06 +01:00
greenkeeper[bot]
f5c0ea3a28 fix(package): update closure-util to version 1.26.0 2017-11-17 12:32:57 +00:00
Frédéric Junod
f139b7001a Merge pull request #7445 from fredj/fs_css
Load css rules from full-screen.css in examples
2017-11-17 10:41:07 +01:00
Frédéric Junod
3e590f81ae Merge pull request #7481 from gberaudo/make_zoom_to_extent_extensible
Make zoom to extent control extensible
2017-11-17 09:10:50 +01:00
Andreas Hocevar
0bf7e95619 Merge pull request #7477 from ahocevar/text-style-keys
Make text states available for replay time
2017-11-16 19:59:45 +01:00
Andreas Hocevar
1aa54b52b0 Merge pull request #7482 from ahocevar/vectortile-unrotate
Reset rotation after rendering
2017-11-16 17:57:01 +01:00
Andreas Hocevar
006f8d49ec Reset rotation after rendering 2017-11-16 17:22:05 +01:00
Guillaume Beraudo
94e821f9bf Make zoom to extent control extensible 2017-11-16 15:54:13 +01:00
Andreas Hocevar
cbf24ebc4c Merge pull request #7480 from ahocevar/load-imagetile
Create a new image when loading tile after an error
2017-11-16 15:09:45 +01:00
Andreas Hocevar
f1aeb76ce8 Create a new image when loading after an error 2017-11-16 14:45:54 +01:00
Andreas Hocevar
000acfe854 Do not pass inexistent argument 2017-11-16 14:45:54 +01:00
Andreas Hocevar
8e9b69cb9b Merge pull request #7476 from ahocevar/reset-measurements
Reset text measurements when available fonts change
2017-11-16 13:43:04 +01:00
Andreas Hocevar
c35789ba73 Add and improve tests 2017-11-16 11:52:26 +01:00
Andreas Hocevar
ad8e4debbe Make text states available for replay time 2017-11-16 00:39:27 +01:00
Andreas Hocevar
febbba78dc Reset text measurements when available fonts change 2017-11-15 18:44:26 +01:00
Andreas Hocevar
4b0281bc8a Merge pull request #7454 from ahocevar/text-background-padding
Add text background rendering and text padding
2017-11-15 08:27:38 +01:00
Andreas Hocevar
c7f6c28d8e Merge pull request #7468 from chrismayer/chg-here-key
Add new API-key for HERE example
2017-11-14 12:34:17 +01:00
Christian Mayer
169e9583dd Add new HERE API-key to 'cloak' section
This adds the new API-key for the 'HERE Map Tile API' example to the
'cloak' section, so it is not visible in the example's code view.
2017-11-14 09:56:26 +01:00
Christian Mayer
b9540460ff Add new API-key for HERE example
Replace the existing API-key for the 'HERE Map Tile API' example
with a new one with a longer validity.
2017-11-14 09:09:17 +01:00
Frédéric Junod
697406cf59 Merge pull request #7465 from fredj/export_getAxisOrientation
Export ol.proj.Projection#getAxisOrientation function
2017-11-14 08:19:24 +01:00
Frederic Junod
c490fd4af8 Export ol.proj.Projection#getAxisOrientation function 2017-11-13 17:19:50 +01:00
Andreas Hocevar
53b85a9192 Add rendering tests 2017-11-13 13:58:11 +01:00
Andreas Hocevar
a77d01945f Merge pull request #7462 from ahocevar/scaleline-meters-per-unit
Respect metersPerUnit in ScaleLine control
2017-11-13 11:39:32 +01:00
Andreas Hocevar
9c45f9a8d6 Respect metersPerUnit in ScaleLine control 2017-11-13 11:09:54 +01:00
Andreas Hocevar
df90f1b78c Reuse more code 2017-11-12 22:49:32 +01:00
Andreas Hocevar
1afc686af9 Add text background rendering and text padding 2017-11-12 22:49:32 +01:00
Frederic Junod
2825436983 Add missing .map:-ms-fullscreen css rule in example 2017-11-10 10:21:08 +01:00
107 changed files with 1447 additions and 553 deletions

View File

@@ -1,5 +1,40 @@
## Upgrade notes
### Next release
#### Renamed `exceedLength` option of `ol.style.Text` to `overflow`
To update your applications, simply replace `exceedLength` with `overflow`.
#### Deprecation of `ol.source.ImageVector`
Rendering vector sources as image is now directly supported by `ol.layer.Vector` with the new `renderMode: 'image'` configuration option. Change code like this:
```js
new ol.layer.Image({
source: new ol.source.ImageVector({
style: myStyle,
source: new ol.source.Vector({
url: 'my/data.json',
format: new ol.format.GeoJSON()
})
})
});
```
to:
```js
new ol.layer.Vector({
renderMode: 'image',
style: myStyle,
source: new ol.source.Vector({
url: 'my/data.json',
format: new ol.format.GeoJSON()
})
});
```
### v4.5.0
#### Removed GeoJSON crs workaround for GeoServer

View File

@@ -35,7 +35,7 @@ Interactions for [vector features](ol.Feature.html)
<tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [ol.proj.transform()](ol.proj.html#.transform) and [ol.proj.transformExtent()](ol.proj.html#.transformExtent).</p>
[ol.proj](ol.proj.html)</td>
<td><p>Changes to all [ol.Objects](ol.Object.html) can be observed by calling the [object.on('propertychange')](ol.Object.html#on) method. Listeners receive an [ol.Object.Event](ol.Object.Event.html) with information on the changed property and old value.</p>
<td>[ol.DeviceOrientation](ol.DeviceOrientation.html)<br>
<td>
[ol.Geolocation](ol.Geolocation.html)<br>
[ol.Overlay](ol.Overlay.html)<br></td>
</tr></table>

View File

@@ -13,9 +13,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -22,9 +22,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: ol.proj.transform(

View File

@@ -51,9 +51,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: view
});

View File

@@ -59,9 +59,9 @@ ol.inherits(app.RotateNorthControl, ol.control.Control);
var map = new ol.Map({
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}).extend([
new app.RotateNorthControl()
]),

View File

@@ -92,8 +92,7 @@ app.Drag.prototype.handleDragEvent = function(evt) {
var deltaX = evt.coordinate[0] - this.coordinate_[0];
var deltaY = evt.coordinate[1] - this.coordinate_[1];
var geometry = /** @type {ol.geom.SimpleGeometry} */
(this.feature_.getGeometry());
var geometry = this.feature_.getGeometry();
geometry.translate(deltaX, deltaY);
this.coordinate_[0] = evt.coordinate[0];

View File

@@ -22,9 +22,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: view
});

View File

@@ -1,9 +1,9 @@
---
layout: example.html
title: Drag-and-Drop Image Vector
shortdesc: Example of using the drag-and-drop interaction with a ol.source.ImageVector.
shortdesc: Example of using the drag-and-drop interaction with image vector rendering.
docs: >
Example of using the drag-and-drop interaction with a ol.source.ImageVector. Drag and drop GPX, GeoJSON, IGC, KML, or TopoJSON files on to the map. Each file is rendered to an image on the client.
Example of using the drag-and-drop interaction with an `ol.layer.Vector` with `renderMode: 'image'``. Drag and drop GPX, GeoJSON, IGC, KML, or TopoJSON files on to the map. Each file is rendered to an image on the client.
tags: "drag-and-drop-image-vector, gpx, geojson, igc, kml, topojson, vector, image"
cloak:
As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5: Your Bing Maps Key from http://www.bingmapsportal.com/ here

View File

@@ -7,10 +7,9 @@ goog.require('ol.format.KML');
goog.require('ol.format.TopoJSON');
goog.require('ol.interaction');
goog.require('ol.interaction.DragAndDrop');
goog.require('ol.layer.Image');
goog.require('ol.layer.Vector');
goog.require('ol.layer.Tile');
goog.require('ol.source.BingMaps');
goog.require('ol.source.ImageVector');
goog.require('ol.source.Vector');
goog.require('ol.style.Circle');
goog.require('ol.style.Fill');
@@ -115,11 +114,10 @@ dragAndDropInteraction.on('addfeatures', function(event) {
var vectorSource = new ol.source.Vector({
features: event.features
});
map.addLayer(new ol.layer.Image({
source: new ol.source.ImageVector({
source: vectorSource,
style: styleFunction
})
map.addLayer(new ol.layer.Vector({
renderMode: 'image',
source: vectorSource,
style: styleFunction
}));
map.getView().fit(vectorSource.getExtent());
});

View File

@@ -54,7 +54,7 @@ var typeSelect = document.getElementById('type');
function addInteractions() {
draw = new ol.interaction.Draw({
source: source,
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value)
type: typeSelect.value
});
map.addInteraction(draw);
snap = new ol.interaction.Snap({source: source});

View File

@@ -33,7 +33,7 @@ function addInteraction() {
if (value !== 'None') {
draw = new ol.interaction.Draw({
source: source,
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value)
type: typeSelect.value
});
map.addInteraction(draw);
}

View File

@@ -33,7 +33,7 @@ function addInteraction() {
if (value !== 'None') {
draw = new ol.interaction.Draw({
source: source,
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value),
type: typeSelect.value,
freehand: true
});
map.addInteraction(draw);

View File

@@ -67,7 +67,7 @@ function addInteraction() {
}
draw = new ol.interaction.Draw({
source: source,
type: /** @type {ol.geom.GeometryType} */ (value),
type: value,
geometryFunction: geometryFunction
});
map.addInteraction(draw);

View File

@@ -23,9 +23,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -30,9 +30,9 @@ var map = new ol.Map({
layers: [raster, vector],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -24,9 +24,9 @@ var map = new ol.Map({
})
],
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
target: 'map',
view: new ol.View({

View File

@@ -4,6 +4,9 @@
.map:-webkit-full-screen {
height: 100%;
}
.map:-ms-fullscreen {
height: 100%;
}
.map:fullscreen {
height: 100%;
}

View File

@@ -180,9 +180,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -23,9 +23,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: view
});
@@ -46,14 +46,14 @@ var positions = new ol.geom.LineString([],
/** @type {ol.geom.GeometryLayout} */ ('XYZM'));
// Geolocation Control
var geolocation = new ol.Geolocation(/** @type {olx.GeolocationOptions} */ ({
var geolocation = new ol.Geolocation({
projection: view.getProjection(),
trackingOptions: {
maximumAge: 10000,
enableHighAccuracy: true,
timeout: 600000
}
}));
});
var deltaMean = 500; // the geolocation sampling period mean in ms

View File

@@ -26,9 +26,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: view
});

View File

@@ -7,8 +7,8 @@ docs: >
<p>Be sure to respect the <a href="https://legal.here.com/en/terms/serviceterms/us/">HERE Service Terms</a> when using their tile API.</p>
tags: "here, here-maps, here-tile-api"
cloak:
a2qhegvZZFIuJDkkqjhQ: Your HERE Maps appId from https://developer.here.com/
lPJ3iaFLJDhD8fIAyU582A: Your HERE Maps appCode from https://developer.here.com/
kDm0Jq1K4Ak7Bwtn8uvk: Your HERE Maps appId from https://developer.here.com/
xnmvc4dKZrDfGlvQHXSvwQ: Your HERE Maps appCode from https://developer.here.com/
---
<div id="map" class="map"></div>
<select id="layer-select">

View File

@@ -3,8 +3,8 @@ goog.require('ol.View');
goog.require('ol.layer.Tile');
goog.require('ol.source.XYZ');
var appId = 'a2qhegvZZFIuJDkkqjhQ';
var appCode = 'lPJ3iaFLJDhD8fIAyU582A';
var appId = 'kDm0Jq1K4Ak7Bwtn8uvk';
var appCode = 'xnmvc4dKZrDfGlvQHXSvwQ';
var hereLayers = [
{
base: 'base',

View File

@@ -99,9 +99,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [703365.7089403362, 5714629.865071137],

View File

@@ -3,9 +3,7 @@ layout: example.html
title: Image Vector Layer
shortdesc: Example of an image vector layer.
docs: >
<p>This example uses a <code>ol.source.ImageVector</code> source. That source gets vector features from the
<code>ol.source.Vector</code> it's configured with, and draw these features to an HTML5 canvas element that
is then used as the image of an image layer.</p>
<p>This example uses <code>ol.layer.Vector</code> with `renderMode: 'image'`. This mode results in faster rendering during interaction and animations, at the cost of less accurate rendering.</p>
tags: "vector, image"
---
<div id="map" class="map"></div>

View File

@@ -1,38 +1,37 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.format.GeoJSON');
goog.require('ol.layer.Image');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.ImageVector');
goog.require('ol.source.OSM');
goog.require('ol.source.Vector');
goog.require('ol.style.Fill');
goog.require('ol.style.Stroke');
goog.require('ol.style.Style');
goog.require('ol.style.Text');
var style = new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.6)'
}),
stroke: new ol.style.Stroke({
color: '#319FD3',
width: 1
}),
text: new ol.style.Text()
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Image({
source: new ol.source.ImageVector({
source: new ol.source.Vector({
url: 'data/geojson/countries.geojson',
format: new ol.format.GeoJSON()
}),
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.6)'
}),
stroke: new ol.style.Stroke({
color: '#319FD3',
width: 1
})
})
})
new ol.layer.Vector({
renderMode: 'image',
source: new ol.source.Vector({
url: 'data/geojson/countries.geojson',
format: new ol.format.GeoJSON()
}),
style: function(feature) {
style.getText().setText(feature.get('name'));
return style;
}
})
],
target: 'map',

View File

@@ -22,9 +22,9 @@ if (!ol.has.WEBGL) {
renderer: /** @type {Array<ol.renderer.Type>} */ (['webgl', 'canvas']),
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -12,9 +12,9 @@ var map = new ol.Map({
layers: [osm],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -19,9 +19,9 @@ var map = new ol.Map({
layers: [osm, bing],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -62,5 +62,5 @@ var map = new ol.Map({
map.addInteraction(new ol.interaction.Draw({
source: source,
type: /** @type {ol.geom.GeometryType} */ ('LineString')
type: 'LineString'
}));

View File

@@ -35,9 +35,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
maxZoom: 18,

View File

@@ -179,7 +179,7 @@ function addInteraction() {
var type = (typeSelect.value == 'area' ? 'Polygon' : 'LineString');
draw = new ol.interaction.Draw({
source: source,
type: /** @type {ol.geom.GeometryType} */ (type),
type: type,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'

View File

@@ -27,9 +27,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [653600, 5723680],

View File

@@ -18,9 +18,9 @@ var mousePositionControl = new ol.control.MousePosition({
var map = new ol.Map({
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}).extend([mousePositionControl]),
layers: [
new ol.layer.Tile({

View File

@@ -15,9 +15,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -8,9 +8,9 @@ goog.require('ol.source.OSM');
var map = new ol.Map({
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}).extend([
new ol.control.ZoomToExtent({
extent: [

View File

@@ -30,9 +30,9 @@ var map = new ol.Map({
})
],
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
target: 'map',
view: new ol.View({

View File

@@ -18,13 +18,13 @@ var closer = document.getElementById('popup-closer');
/**
* Create an overlay to anchor the popup to the map.
*/
var overlay = new ol.Overlay(/** @type {olx.OverlayOptions} */ ({
var overlay = new ol.Overlay({
element: container,
autoPan: true,
autoPanAnimation: {
duration: 250
}
}));
});
/**

View File

@@ -13,9 +13,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [14200000, 4130000],

View File

@@ -10,9 +10,9 @@ var scaleLineControl = new ol.control.ScaleLine();
var map = new ol.Map({
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}).extend([
scaleLineControl
]),

View File

@@ -86,19 +86,19 @@ var Draw = {
},
Point: new ol.interaction.Draw({
source: vector.getSource(),
type: /** @type {ol.geom.GeometryType} */ ('Point')
type: 'Point'
}),
LineString: new ol.interaction.Draw({
source: vector.getSource(),
type: /** @type {ol.geom.GeometryType} */ ('LineString')
type: 'LineString'
}),
Polygon: new ol.interaction.Draw({
source: vector.getSource(),
type: /** @type {ol.geom.GeometryType} */ ('Polygon')
type: 'Polygon'
}),
Circle: new ol.interaction.Draw({
source: vector.getSource(),
type: /** @type {ol.geom.GeometryType} */ ('Circle')
type: 'Circle'
}),
getActive: function() {
return this.activeType ? this[this.activeType].getActive() : false;

View File

@@ -12,9 +12,9 @@ var map = new ol.Map({
})
],
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [0, 0],

View File

@@ -64,7 +64,7 @@ var raster = new ol.layer.Tile({
var draw = new ol.interaction.Draw({
source: vectorSource,
type: /** @type {ol.geom.GeometryType} */ ('Polygon')
type: 'Polygon'
});
var select = new ol.interaction.Select();

View File

@@ -5,7 +5,7 @@ shortdesc: Label decluttering with a custom renderer.
resources:
- https://cdn.polyfill.io/v2/polyfill.min.js?features=Set"
docs: >
Decluttering is used to avoid overlapping labels with `exceedLength: true` set on the text style. For MultiPolygon geometries, only the widest polygon is selected in a custom `geometry` function.
Decluttering is used to avoid overlapping labels with `overflow: true` set on the text style. For MultiPolygon geometries, only the widest polygon is selected in a custom `geometry` function.
tags: "vector, decluttering, labels"
---
<div id="map" class="map"></div>

View File

@@ -37,7 +37,7 @@ var labelStyle = new ol.style.Style({
},
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
exceedLength: true,
overflow: true,
fill: new ol.style.Fill({
color: '#000'
}),

View File

@@ -95,7 +95,7 @@ tags: "geojson, vector, openstreetmap, label"
</select>
<br />
<label>Exceed Len: </label>
<select disabled id="points-exceedlength">
<select disabled id="points-overflow">
<option value="true">True</option>
<option value="false" selected="selected">False</option>
</select>
@@ -204,7 +204,7 @@ tags: "geojson, vector, openstreetmap, label"
</select>
<br />
<label>Exceed Len: </label>
<select id="lines-exceedlength">
<select id="lines-overflow">
<option value="true">True</option>
<option value="false" selected="selected">False</option>
</select>
@@ -313,7 +313,7 @@ tags: "geojson, vector, openstreetmap, label"
</select>
<br />
<label>Exceed Len: </label>
<select id="polygons-exceedlength">
<select id="polygons-overflow">
<option value="true">True</option>
<option value="false" selected="selected">False</option>
</select>

View File

@@ -38,7 +38,7 @@ var myDom = {
weight: document.getElementById('lines-weight'),
placement: document.getElementById('lines-placement'),
maxangle: document.getElementById('lines-maxangle'),
exceedlength: document.getElementById('lines-exceedlength'),
overflow: document.getElementById('lines-overflow'),
size: document.getElementById('lines-size'),
offsetX: document.getElementById('lines-offset-x'),
offsetY: document.getElementById('lines-offset-y'),
@@ -56,7 +56,7 @@ var myDom = {
weight: document.getElementById('polygons-weight'),
placement: document.getElementById('polygons-placement'),
maxangle: document.getElementById('polygons-maxangle'),
exceedlength: document.getElementById('polygons-exceedlength'),
overflow: document.getElementById('polygons-overflow'),
size: document.getElementById('polygons-size'),
offsetX: document.getElementById('polygons-offset-x'),
offsetY: document.getElementById('polygons-offset-y'),
@@ -95,7 +95,7 @@ var createTextStyle = function(feature, resolution, dom) {
var weight = dom.weight.value;
var placement = dom.placement ? dom.placement.value : undefined;
var maxAngle = dom.maxangle ? parseFloat(dom.maxangle.value) : undefined;
var exceedLength = dom.exceedlength ? (dom.exceedlength.value == 'true') : undefined;
var overflow = dom.overflow ? (dom.overflow.value == 'true') : undefined;
var rotation = parseFloat(dom.rotation.value);
if (dom.font.value == '\'Open Sans\'' && !openSansAdded) {
var openSans = document.createElement('link');
@@ -120,7 +120,7 @@ var createTextStyle = function(feature, resolution, dom) {
offsetY: offsetY,
placement: placement,
maxAngle: maxAngle,
exceedLength: exceedLength,
overflow: overflow,
rotation: rotation
});
};

View File

@@ -127,9 +127,9 @@ map = new ol.Map({
layers: [raster, vector],
target: document.getElementById('map'),
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [739218, 5906096],

View File

@@ -41,7 +41,7 @@ var layers = [
'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale',
'FORMAT': 'image/jpeg'
},
serverType: /** @type {ol.source.WMSServerType} */ ('mapserver')
serverType: 'mapserver'
})
}),
new ol.layer.Image({
@@ -52,7 +52,7 @@ var layers = [
attributions: '© <a href="http://www.geo.admin.ch/internet/geoportal/' +
'en/home.html">National parks / geo.admin.ch</a>',
params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'},
serverType: /** @type {ol.source.WMSServerType} */ ('mapserver')
serverType: 'mapserver'
})
})
];

View File

@@ -14,7 +14,9 @@ var layers = [
source: new ol.source.TileWMS({
url: 'https://ahocevar.com/geoserver/wms',
params: {'LAYERS': 'topp:states', 'TILED': true},
serverType: 'geoserver'
serverType: 'geoserver',
// Countries have transparency, so do not fade tiles:
transition: 0
})
})
];

View File

@@ -23,11 +23,11 @@ var layers = [
}),
new ol.layer.Tile({
extent: extent,
source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
source: new ol.source.TileWMS({
attributions: ['Iowa State University'],
url: 'https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi',
params: {'LAYERS': 'nexrad-n0r-wmst'}
}))
})
})
];
var map = new ol.Map({

View File

@@ -11,9 +11,9 @@ goog.require('ol.tilegrid.WMTS');
var map = new ol.Map({
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
zoom: 5,

View File

@@ -49,9 +49,9 @@ var map = new ol.Map({
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
attributionOptions: {
collapsible: false
})
}
}),
view: new ol.View({
center: [-11158582, 4813697],

View File

@@ -275,7 +275,7 @@ olx.interaction.InteractionOptions;
* Method called by the map to notify the interaction that a browser event was
* dispatched to the map. If the function returns a falsy value,
* propagation of the event to other interactions in the map's interactions
* chain will be prevented (this includes functions with no explicit return). See
* chain will be prevented (this includes functions with no explicit return). See
* {@link https://developer.mozilla.org/en-US/docs/Glossary/Falsy}
* @type {function(ol.MapBrowserEvent):boolean}
* @api
@@ -3004,7 +3004,7 @@ olx.interaction.DragZoomOptions.prototype.out;
* features: (ol.Collection.<ol.Feature>|undefined),
* source: (ol.source.Vector|undefined),
* snapTolerance: (number|undefined),
* type: ol.geom.GeometryType,
* type: (ol.geom.GeometryType|string),
* maxPoints: (number|undefined),
* minPoints: (number|undefined),
* finishCondition: (ol.EventsConditionType|undefined),
@@ -3058,7 +3058,7 @@ olx.interaction.DrawOptions.prototype.snapTolerance;
/**
* Drawing type ('Point', 'LineString', 'Polygon', 'MultiPoint',
* 'MultiLineString', 'MultiPolygon' or 'Circle').
* @type {ol.geom.GeometryType}
* @type {ol.geom.GeometryType|string}
* @api
*/
olx.interaction.DrawOptions.prototype.type;
@@ -4262,6 +4262,7 @@ olx.layer.TileOptions.prototype.zIndex;
* maxResolution: (number|undefined),
* opacity: (number|undefined),
* renderBuffer: (number|undefined),
* renderMode: (ol.layer.VectorRenderType|string|undefined),
* source: (ol.source.Vector|undefined),
* map: (ol.PluggableMap|undefined),
* declutter: (boolean|undefined),
@@ -4274,6 +4275,20 @@ olx.layer.TileOptions.prototype.zIndex;
olx.layer.VectorOptions;
/**
* Render mode for vector layers:
* * `'image'`: Vector layers are rendered as images. Great performance, but
* point symbols and texts are always rotated with the view and pixels are
* scaled during zoom animations.
* * `'vector'`: Vector layers are rendered as vectors. Most accurate rendering
* even during animations, but slower performance.
* Default is `vector`.
* @type {ol.layer.VectorRenderType|string|undefined}
* @api
*/
olx.layer.VectorOptions.prototype.renderMode;
/**
* Render order. Function to be used when sorting features before rendering. By
* default features are drawn in the order that they are created. Use `null` to
@@ -4455,6 +4470,7 @@ olx.layer.VectorTileOptions.prototype.renderBuffer;
*/
olx.layer.VectorTileOptions.prototype.renderMode;
/**
* Render order. Function to be used when sorting features before rendering. By
* default features are drawn in the order that they are created.
@@ -4579,7 +4595,7 @@ olx.layer.VectorTileOptions.prototype.visible;
* @type {number|undefined}
* @api
*/
olx.layer.VectorOptions.prototype.zIndex;
olx.layer.VectorTileOptions.prototype.zIndex;
/**
@@ -7853,6 +7869,7 @@ olx.style.StrokeOptions.prototype.width;
* maxAngle: (number|undefined),
* offsetX: (number|undefined),
* offsetY: (number|undefined),
* overflow: (boolean|undefined),
* placement: (ol.style.TextPlacement|string|undefined),
* scale: (number|undefined),
* rotateWithView: (boolean|undefined),
@@ -7861,16 +7878,22 @@ olx.style.StrokeOptions.prototype.width;
* textAlign: (string|undefined),
* textBaseline: (string|undefined),
* fill: (ol.style.Fill|undefined),
* stroke: (ol.style.Stroke|undefined)}}
* stroke: (ol.style.Stroke|undefined),
* backgroundFill: (ol.style.Fill|undefined),
* backgroundStroke: (ol.style.Stroke|undefined),
* padding: (Array.<number>|undefined)}}
*/
olx.style.TextOptions;
/**
* **Deprecated**. Use the `overflow` option instead.
*
* For polygon labels or when `placement` is set to `'line'`, allow text to
* exceed the width of the polygon at the the label position or the length of
* exceed the width of the polygon at the label position or the length of
* the path that it follows. Default is `false`.
* @type {boolean|undefined}
* @deprecated
* @api
*/
olx.style.TextOptions.prototype.exceedLength;
@@ -7914,6 +7937,16 @@ olx.style.TextOptions.prototype.offsetX;
olx.style.TextOptions.prototype.offsetY;
/**
* For polygon labels or when `placement` is set to `'line'`, allow text to
* exceed the width of the polygon at the label position or the length of
* the path that it follows. Default is `false`.
* @type {boolean|undefined}
* @api
*/
olx.style.TextOptions.prototype.overflow;
/**
* Text placement.
* @type {ol.style.TextPlacement|undefined}
@@ -7990,6 +8023,34 @@ olx.style.TextOptions.prototype.fill;
olx.style.TextOptions.prototype.stroke;
/**
* Fill style for the text background when `placement` is `'point'`. Default is
* no fill.
* @type {ol.style.Fill|undefined}
* @api
*/
olx.style.TextOptions.prototype.backgroundFill;
/**
* Stroke style for the text background when `placement` is `'point'`. Default
* is no stroke.
* @type {ol.style.Stroke|undefined}
* @api
*/
olx.style.TextOptions.prototype.backgroundStroke;
/**
* Padding in pixels around the text for decluttering and background. The order
* of values in the array is `[top, right, bottom, left]`. Default is
* `[0, 0, 0, 0]`.
* @type {Array.<number>|undefined}
* @api
*/
olx.style.TextOptions.prototype.padding;
/**
* @typedef {{geometry: (undefined|string|ol.geom.Geometry|ol.StyleGeometryFunction),
* fill: (ol.style.Fill|undefined),

View File

@@ -1,6 +1,6 @@
{
"name": "openlayers",
"version": "4.5.0",
"version": "4.6.0-beta.1",
"description": "Build tools and sources for developing OpenLayers based mapping applications",
"keywords": [
"map",
@@ -39,14 +39,14 @@
],
"dependencies": {
"async": "2.6.0",
"closure-util": "1.25.0",
"closure-util": "1.26.0",
"fs-extra": "4.0.2",
"jsdoc": "3.5.5",
"nomnom": "1.8.1",
"pbf": "3.1.0",
"pixelworks": "1.1.0",
"rbush": "2.0.1",
"rollup": "^0.51.3",
"rollup": "^0.52.0",
"rollup-plugin-cleanup": "^2.0.0",
"rollup-plugin-commonjs": "^8.2.6",
"rollup-plugin-node-resolve": "^3.0.0",
@@ -57,7 +57,7 @@
"clean-css-cli": "4.1.10",
"coveralls": "3.0.0",
"debounce": "^1.1.0",
"eslint": "4.11.0",
"eslint": "4.12.1",
"eslint-config-openlayers": "7.0.0",
"eslint-plugin-openlayers-internal": "^3.1.0",
"expect.js": "0.3.1",

View File

@@ -174,6 +174,9 @@ ol.control.ScaleLine.prototype.updateElement_ = function() {
ol.proj.Units.METERS;
var pointResolution =
ol.proj.getPointResolution(projection, viewState.resolution, center, pointResolutionUnits);
if (units != ol.control.ScaleLineUnits.DEGREES) {
pointResolution *= projection.getMetersPerUnit();
}
var nominalCount = this.minWidth_ * pointResolution;
var suffix = '';

View File

@@ -22,9 +22,9 @@ ol.control.ZoomToExtent = function(opt_options) {
/**
* @type {ol.Extent}
* @private
* @protected
*/
this.extent_ = options.extent ? options.extent : null;
this.extent = options.extent ? options.extent : null;
var className = options.className !== undefined ? options.className :
'ol-zoom-extent';
@@ -62,16 +62,16 @@ ol.inherits(ol.control.ZoomToExtent, ol.control.Control);
*/
ol.control.ZoomToExtent.prototype.handleClick_ = function(event) {
event.preventDefault();
this.handleZoomToExtent_();
this.handleZoomToExtent();
};
/**
* @private
* @protected
*/
ol.control.ZoomToExtent.prototype.handleZoomToExtent_ = function() {
ol.control.ZoomToExtent.prototype.handleZoomToExtent = function() {
var map = this.getMap();
var view = map.getView();
var extent = !this.extent_ ? view.getProjection().getExtent() : this.extent_;
var extent = !this.extent ? view.getProjection().getExtent() : this.extent;
view.fit(extent);
};

View File

@@ -22,6 +22,12 @@ ol.ImageTile = function(tileCoord, state, src, crossOrigin, tileLoadFunction, op
ol.Tile.call(this, tileCoord, state, opt_options);
/**
* @private
* @type {?string}
*/
this.crossOrigin_ = crossOrigin;
/**
* Image URI
*
@@ -124,7 +130,14 @@ ol.ImageTile.prototype.handleImageLoad_ = function() {
* @api
*/
ol.ImageTile.prototype.load = function() {
if (this.state == ol.TileState.IDLE || this.state == ol.TileState.ERROR) {
if (this.state == ol.TileState.ERROR) {
this.state = ol.TileState.IDLE;
this.image_ = new Image();
if (this.crossOrigin_ !== null) {
this.image_.crossOrigin = this.crossOrigin_;
}
}
if (this.state == ol.TileState.IDLE) {
this.state = ol.TileState.LOADING;
this.changed();
this.imageListenerKeys_ = [

View File

@@ -88,7 +88,7 @@ ol.interaction.Draw = function(options) {
* @type {ol.geom.GeometryType}
* @private
*/
this.type_ = options.type;
this.type_ = /** @type {ol.geom.GeometryType} */ (options.type);
/**
* Drawing mode (derived from geometry type.

View File

@@ -6,6 +6,7 @@ goog.require('ol');
goog.require('ol.Object');
goog.require('ol.easing');
goog.require('ol.interaction.Property');
goog.require('ol.math');
/**
@@ -181,6 +182,14 @@ ol.interaction.Interaction.zoomByDelta = function(view, delta, opt_anchor, opt_d
var currentResolution = view.getResolution();
var resolution = view.constrainResolution(currentResolution, delta, 0);
if (resolution !== undefined) {
var resolutions = view.getResolutions();
resolution = ol.math.clamp(
resolution,
view.getMinResolution() || resolutions[resolutions.length - 1],
view.getMaxResolution() || resolutions[0]);
}
// If we have a constraint on center, we need to change the anchor so that the
// new center is within the extent. We first calculate the new center, apply
// the constraint to it, and then calculate back the anchor

View File

@@ -0,0 +1,16 @@
goog.provide('ol.layer.VectorRenderType');
/**
* @enum {string}
* Render mode for vector layers:
* * `'image'`: Vector layers are rendered as images. Great performance, but
* point symbols and texts are always rotated with the view and pixels are
* scaled during zoom animations.
* * `'vector'`: Vector layers are rendered as vectors. Most accurate rendering
* even during animations, but slower performance.
* @api
*/
ol.layer.VectorRenderType = {
IMAGE: 'image',
VECTOR: 'vector'
};

View File

@@ -3,6 +3,7 @@ goog.provide('ol.layer.Vector');
goog.require('ol');
goog.require('ol.LayerType');
goog.require('ol.layer.Layer');
goog.require('ol.layer.VectorRenderType');
goog.require('ol.obj');
goog.require('ol.style.Style');
@@ -75,6 +76,12 @@ ol.layer.Vector = function(opt_options) {
this.updateWhileInteracting_ = options.updateWhileInteracting !== undefined ?
options.updateWhileInteracting : false;
/**
* @private
* @type {ol.layer.VectorTileRenderType|string}
*/
this.renderMode_ = options.renderMode || ol.layer.VectorRenderType.VECTOR;
/**
* The layer type.
* @protected
@@ -197,6 +204,14 @@ ol.layer.Vector.prototype.setStyle = function(style) {
};
/**
* @return {ol.layer.VectorRenderType|string} The render mode.
*/
ol.layer.Vector.prototype.getRenderMode = function() {
return this.renderMode_;
};
/**
* @enum {string}
* @private

View File

@@ -24,6 +24,17 @@ goog.require('ol.obj');
ol.layer.VectorTile = function(opt_options) {
var options = opt_options ? opt_options : {};
var renderMode = options.renderMode || ol.layer.VectorTileRenderType.HYBRID;
ol.asserts.assert(renderMode == undefined ||
renderMode == ol.layer.VectorTileRenderType.IMAGE ||
renderMode == ol.layer.VectorTileRenderType.HYBRID ||
renderMode == ol.layer.VectorTileRenderType.VECTOR,
28); // `renderMode` must be `'image'`, `'hybrid'` or `'vector'`
if (options.declutter && renderMode == ol.layer.VectorTileRenderType.IMAGE) {
renderMode = ol.layer.VectorTileRenderType.HYBRID;
}
options.renderMode = renderMode;
var baseOptions = ol.obj.assign({}, options);
delete baseOptions.preload;
@@ -34,24 +45,6 @@ ol.layer.VectorTile = function(opt_options) {
this.setUseInterimTilesOnError(options.useInterimTilesOnError ?
options.useInterimTilesOnError : true);
var renderMode = options.renderMode;
ol.asserts.assert(renderMode == undefined ||
renderMode == ol.layer.VectorTileRenderType.IMAGE ||
renderMode == ol.layer.VectorTileRenderType.HYBRID ||
renderMode == ol.layer.VectorTileRenderType.VECTOR,
28); // `renderMode` must be `'image'`, `'hybrid'` or `'vector'`
if (options.declutter && renderMode == ol.layer.VectorTileRenderType.IMAGE) {
renderMode = ol.layer.VectorTileRenderType.HYBRID;
}
/**
* @private
* @type {ol.layer.VectorTileRenderType|string}
*/
this.renderMode_ = renderMode || ol.layer.VectorTileRenderType.HYBRID;
/**
* The layer type.
* @protected
@@ -74,14 +67,6 @@ ol.layer.VectorTile.prototype.getPreload = function() {
};
/**
* @return {ol.layer.VectorTileRenderType|string} The render mode.
*/
ol.layer.VectorTile.prototype.getRenderMode = function() {
return this.renderMode_;
};
/**
* Whether we use interim tiles on error.
* @return {boolean} Use interim tiles on error.

View File

@@ -428,7 +428,6 @@ ol.PluggableMap.prototype.addOverlayInternal_ = function(overlay) {
*/
ol.PluggableMap.prototype.disposeInternal = function() {
this.mapBrowserEventHandler_.dispose();
this.renderer_.dispose();
ol.events.unlisten(this.viewport_, ol.events.EventType.WHEEL,
this.handleBrowserEvent, this);
ol.events.unlisten(this.viewport_, ol.events.EventType.MOUSEWHEEL,
@@ -941,6 +940,7 @@ ol.PluggableMap.prototype.handleTargetChanged_ = function() {
}
if (!targetElement) {
this.renderer_.removeLayerRenderers();
ol.dom.removeNode(this.viewport_);
if (this.handleResize_ !== undefined) {
window.removeEventListener(ol.events.EventType.RESIZE,
@@ -1139,12 +1139,15 @@ ol.PluggableMap.prototype.renderFrame_ = function(time) {
layerStates[ol.getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
}
viewState = view.getState();
var center = viewState.center;
var pixelResolution = viewState.resolution / this.pixelRatio_;
center[0] = Math.round(center[0] / pixelResolution) * pixelResolution;
center[1] = Math.round(center[1] / pixelResolution) * pixelResolution;
frameState = /** @type {olx.FrameState} */ ({
animate: false,
attributions: {},
coordinateToPixelTransform: this.coordinateToPixelTransform_,
extent: extent,
focus: !this.focus_ ? viewState.center : this.focus_,
focus: !this.focus_ ? center : this.focus_,
index: this.frameIndex_++,
layerStates: layerStates,
layerStatesArray: layerStatesArray,

View File

@@ -197,6 +197,7 @@ ol.proj.Projection.prototype.getWorldExtent = function() {
* wnu - westing, northing, up - some planetary coordinate systems have
* "west positive" coordinate systems
* @return {string} Axis orientation.
* @api
*/
ol.proj.Projection.prototype.getAxisOrientation = function() {
return this.axisOrientation_;

View File

@@ -3,6 +3,7 @@ goog.provide('ol.render.canvas');
goog.require('ol.css');
goog.require('ol.dom');
goog.require('ol.obj');
goog.require('ol.structs.LRUCache');
goog.require('ol.transform');
@@ -77,6 +78,13 @@ ol.render.canvas.defaultTextAlign = 'center';
ol.render.canvas.defaultTextBaseline = 'middle';
/**
* @const
* @type {Array.<number>}
*/
ol.render.canvas.defaultPadding = [0, 0, 0, 0];
/**
* @const
* @type {number}
@@ -91,28 +99,39 @@ ol.render.canvas.labelCache = new ol.structs.LRUCache();
/**
* @type {!Object.<string, (number)>}
* @type {!Object.<string, number>}
*/
ol.render.canvas.checkedFonts_ = {};
/**
* @type {CanvasRenderingContext2D}
*/
ol.render.canvas.measureContext_ = null;
/**
* @type {!Object.<string, number>}
*/
ol.render.canvas.textHeights_ = {};
/**
* Clears the label cache when a font becomes available.
* @param {string} fontSpec CSS font spec.
*/
ol.render.canvas.checkFont = (function() {
var retries = 60;
var checked = ol.render.canvas.checkedFonts_;
var labelCache = ol.render.canvas.labelCache;
var font = '32px monospace';
var text = 'wmytzilWMYTZIL@#/&?$%10';
var context, interval, referenceWidth;
var interval, referenceWidth;
function isAvailable(fontFamily) {
if (!context) {
context = ol.dom.createCanvasContext2D(1, 1);
context.font = font;
referenceWidth = context.measureText(text).width;
}
var context = ol.render.canvas.getMeasureContext();
context.font = font;
referenceWidth = context.measureText(text).width;
var available = true;
if (fontFamily != 'monospace') {
context.font = '32px ' + fontFamily + ',monospace';
@@ -121,10 +140,6 @@ ol.render.canvas.checkFont = (function() {
// fallback was used instead of the font we wanted, so the font is not
// available.
available = width != referenceWidth;
// Setting the font back to a different one works around an issue in
// Safari where subsequent `context.font` assignments with the same font
// will not re-attempt to use a font that is currently loading.
context.font = font;
}
return available;
}
@@ -132,9 +147,12 @@ ol.render.canvas.checkFont = (function() {
function check() {
var done = true;
for (var font in checked) {
if (checked[font] < 60) {
if (checked[font] < retries) {
if (isAvailable(font)) {
checked[font] = 60;
checked[font] = retries;
ol.obj.clear(ol.render.canvas.textHeights_);
// Make sure that loaded fonts are picked up by Safari
ol.render.canvas.measureContext_ = null;
labelCache.clear();
} else {
++checked[font];
@@ -156,7 +174,7 @@ ol.render.canvas.checkFont = (function() {
for (var i = 0, ii = fontFamilies.length; i < ii; ++i) {
var fontFamily = fontFamilies[i];
if (!(fontFamily in checked)) {
checked[fontFamily] = 60;
checked[fontFamily] = retries;
if (!isAvailable(fontFamily)) {
checked[fontFamily] = 0;
if (interval === undefined) {
@@ -169,6 +187,59 @@ ol.render.canvas.checkFont = (function() {
})();
/**
* @return {CanvasRenderingContext2D} Measure context.
*/
ol.render.canvas.getMeasureContext = function() {
var context = ol.render.canvas.measureContext_;
if (!context) {
context = ol.render.canvas.measureContext_ = ol.dom.createCanvasContext2D(1, 1);
}
return context;
};
/**
* @param {string} font Font to use for measuring.
* @return {ol.Size} Measurement.
*/
ol.render.canvas.measureTextHeight = (function() {
var span;
var heights = ol.render.canvas.textHeights_;
return function(font) {
var height = heights[font];
if (height == undefined) {
if (!span) {
span = document.createElement('span');
span.textContent = 'M';
span.style.margin = span.style.padding = '0 !important';
span.style.position = 'absolute !important';
span.style.left = '-99999px !important';
}
span.style.font = font;
document.body.appendChild(span);
height = heights[font] = span.offsetHeight;
document.body.removeChild(span);
}
return height;
};
})();
/**
* @param {string} font Font.
* @param {string} text Text.
* @return {number} Width.
*/
ol.render.canvas.measureTextWidth = function(font, text) {
var measureContext = ol.render.canvas.getMeasureContext();
if (font != measureContext.font) {
measureContext.font = font;
}
return measureContext.measureText(text).width;
};
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {number} rotation Rotation.

View File

@@ -54,7 +54,7 @@ ol.render.canvas.LineStringReplay.prototype.drawLineString = function(lineString
if (strokeStyle === undefined || lineWidth === undefined) {
return;
}
this.updateStrokeStyle(state, true);
this.updateStrokeStyle(state, this.applyStroke);
this.beginGeometry(lineStringGeometry, feature);
this.hitDetectionInstructions.push([
ol.render.canvas.Instruction.SET_STROKE_STYLE,
@@ -81,7 +81,7 @@ ol.render.canvas.LineStringReplay.prototype.drawMultiLineString = function(multi
if (strokeStyle === undefined || lineWidth === undefined) {
return;
}
this.updateStrokeStyle(state, true);
this.updateStrokeStyle(state, this.applyStroke);
this.beginGeometry(multiLineStringGeometry, feature);
this.hitDetectionInstructions.push([
ol.render.canvas.Instruction.SET_STROKE_STYLE,
@@ -115,3 +115,17 @@ ol.render.canvas.LineStringReplay.prototype.finish = function() {
this.reverseHitDetectionInstructions();
this.state = null;
};
/**
* @inheritDoc.
*/
ol.render.canvas.LineStringReplay.prototype.applyStroke = function(state) {
if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
this.instructions.push([ol.render.canvas.Instruction.STROKE]);
state.lastStroke = this.coordinates.length;
}
state.lastStroke = 0;
ol.render.canvas.Replay.prototype.applyStroke.call(this, state);
this.instructions.push([ol.render.canvas.Instruction.BEGIN_PATH]);
};

View File

@@ -214,16 +214,10 @@ ol.render.canvas.PolygonReplay.prototype.finish = function() {
ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function(geometry) {
var state = this.state;
var fillStyle = state.fillStyle;
if (fillStyle !== undefined && (typeof fillStyle !== 'string' || state.currentFillStyle != fillStyle)) {
var fillInstruction = [ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle];
if (typeof fillStyle !== 'string') {
var fillExtent = geometry.getExtent();
fillInstruction.push([fillExtent[0], fillExtent[3]]);
}
this.instructions.push(fillInstruction);
state.currentFillStyle = state.fillStyle;
if (fillStyle !== undefined) {
this.updateFillStyle(state, this.applyFill, geometry);
}
if (state.strokeStyle !== undefined) {
this.updateStrokeStyle(state, false);
this.updateStrokeStyle(state, this.applyStroke);
}
};

View File

@@ -15,6 +15,7 @@ goog.require('ol.obj');
goog.require('ol.render.VectorContext');
goog.require('ol.render.canvas');
goog.require('ol.render.canvas.Instruction');
goog.require('ol.render.replay');
goog.require('ol.transform');
@@ -147,6 +148,12 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, pixelRatio,
*/
this.state = /** @type {ol.CanvasFillStrokeState} */ ({});
/**
* @private
* @type {number}
*/
this.viewRotation_ = 0;
/**
* @private
* @type {!ol.Transform}
@@ -162,6 +169,34 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, pixelRatio,
ol.inherits(ol.render.canvas.Replay, ol.render.VectorContext);
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {ol.Coordinate} p1 1st point of the background box.
* @param {ol.Coordinate} p2 2nd point of the background box.
* @param {ol.Coordinate} p3 3rd point of the background box.
* @param {ol.Coordinate} p4 4th point of the background box.
* @param {Array.<*>} fillInstruction Fill instruction.
* @param {Array.<*>} strokeInstruction Stroke instruction.
*/
ol.render.canvas.Replay.prototype.replayTextBackground_ = function(context, p1, p2, p3, p4,
fillInstruction, strokeInstruction) {
context.beginPath();
context.moveTo.apply(context, p1);
context.lineTo.apply(context, p2);
context.lineTo.apply(context, p3);
context.lineTo.apply(context, p4);
context.lineTo.apply(context, p1);
if (fillInstruction) {
this.fillOrigin_ = /** @type {Array.<number>} */ (fillInstruction[2]);
this.fill_(context);
}
if (strokeInstruction) {
this.setStrokeStyle_(context, /** @type {Array.<*>} */ (strokeInstruction));
context.stroke();
}
};
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {number} x X.
@@ -178,9 +213,14 @@ ol.inherits(ol.render.canvas.Replay, ol.render.VectorContext);
* @param {number} scale Scale.
* @param {boolean} snapToPixel Snap to pixel.
* @param {number} width Width.
* @param {Array.<number>} padding Padding.
* @param {Array.<*>} fillInstruction Fill instruction.
* @param {Array.<*>} strokeInstruction Stroke instruction.
*/
ol.render.canvas.Replay.prototype.replayImage_ = function(context, x, y, image, anchorX, anchorY,
declutterGroup, height, opacity, originX, originY, rotation, scale, snapToPixel, width) {
ol.render.canvas.Replay.prototype.replayImage_ = function(context, x, y, image,
anchorX, anchorY, declutterGroup, height, opacity, originX, originY,
rotation, scale, snapToPixel, width, padding, fillInstruction, strokeInstruction) {
var fillStroke = fillInstruction || strokeInstruction;
var localTransform = this.tmpLocalTransform_;
anchorX *= scale;
anchorY *= scale;
@@ -194,6 +234,25 @@ ol.render.canvas.Replay.prototype.replayImage_ = function(context, x, y, image,
var w = (width + originX > image.width) ? image.width - originX : width;
var h = (height + originY > image.height) ? image.height - originY : height;
var box = this.tmpExtent_;
var boxW = padding[3] + w * scale + padding[1];
var boxH = padding[0] + h * scale + padding[2];
var boxX = x - padding[3];
var boxY = y - padding[0];
/** @type {ol.Coordinate} */
var p1;
/** @type {ol.Coordinate} */
var p2;
/** @type {ol.Coordinate} */
var p3;
/** @type {ol.Coordinate} */
var p4;
if (fillStroke || rotation !== 0) {
p1 = [boxX, boxY];
p2 = [boxX + boxW, boxY];
p3 = [boxX + boxW, boxY + boxH];
p4 = [boxX, boxY + boxH];
}
var transform = null;
if (rotation !== 0) {
@@ -201,13 +260,14 @@ ol.render.canvas.Replay.prototype.replayImage_ = function(context, x, y, image,
var centerY = y + anchorY;
transform = ol.transform.compose(localTransform,
centerX, centerY, 1, 1, rotation, -centerX, -centerY);
ol.extent.createOrUpdateEmpty(box);
ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, [x, y]));
ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, [x + w, y]));
ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, [x + w, y + h]));
ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, [x, y + w]));
ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p1));
ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p2));
ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p3));
ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p4));
} else {
ol.extent.createOrUpdate(x, y, x + w * scale, y + h * scale, box);
ol.extent.createOrUpdate(boxX, boxY, boxX + boxW, boxY + boxH, box);
}
var canvas = context.canvas;
var intersects = box[0] <= canvas.width && box[2] >= 0 && box[1] <= canvas.height && box[3] >= 0;
@@ -216,10 +276,19 @@ ol.render.canvas.Replay.prototype.replayImage_ = function(context, x, y, image,
return;
}
ol.extent.extend(declutterGroup, box);
declutterGroup.push(intersects ?
var declutterArgs = intersects ?
[context, transform ? transform.slice(0) : null, opacity, image, originX, originY, w, h, x, y, scale] :
null);
null;
if (declutterArgs && fillStroke) {
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
}
declutterGroup.push(declutterArgs);
} else if (intersects) {
if (fillStroke) {
this.replayTextBackground_(context, p1, p2, p3, p4,
/** @type {Array.<*>} */ (fillInstruction),
/** @type {Array.<*>} */ (strokeInstruction));
}
ol.render.canvas.drawImage(context, transform, opacity, image, originX, originY, w, h, x, y, scale);
}
};
@@ -380,13 +449,12 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, feature) {
/**
* @private
* @param {CanvasRenderingContext2D} context Context.
* @param {number} rotation Rotation.
*/
ol.render.canvas.Replay.prototype.fill_ = function(context, rotation) {
ol.render.canvas.Replay.prototype.fill_ = function(context) {
if (this.fillOrigin_) {
var origin = ol.transform.apply(this.renderedTransform_, this.fillOrigin_.slice());
context.translate(origin[0], origin[1]);
context.rotate(rotation);
context.rotate(this.viewRotation_);
}
context.fill();
if (this.fillOrigin_) {
@@ -396,9 +464,28 @@ ol.render.canvas.Replay.prototype.fill_ = function(context, rotation) {
/**
* @param {ol.DeclutterGroup} declutterGroup Declutter group.
* @private
* @param {CanvasRenderingContext2D} context Context.
* @param {Array.<*>} instruction Instruction.
*/
ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup) {
ol.render.canvas.Replay.prototype.setStrokeStyle_ = function(context, instruction) {
context.strokeStyle = /** @type {ol.ColorLike} */ (instruction[1]);
context.lineWidth = /** @type {number} */ (instruction[2]);
context.lineCap = /** @type {string} */ (instruction[3]);
context.lineJoin = /** @type {string} */ (instruction[4]);
context.miterLimit = /** @type {number} */ (instruction[5]);
if (ol.has.CANVAS_LINE_DASH) {
context.lineDashOffset = /** @type {number} */ (instruction[7]);
context.setLineDash(/** @type {Array.<number>} */ (instruction[6]));
}
};
/**
* @param {ol.DeclutterGroup} declutterGroup Declutter group.
* @param {ol.Feature|ol.render.Feature} feature Feature.
*/
ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup, feature) {
if (declutterGroup && declutterGroup.length > 5) {
var groupCount = declutterGroup[4];
if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
@@ -407,14 +494,21 @@ ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup) {
minX: /** @type {number} */ (declutterGroup[0]),
minY: /** @type {number} */ (declutterGroup[1]),
maxX: /** @type {number} */ (declutterGroup[2]),
maxY: /** @type {number} */ (declutterGroup[3])
maxY: /** @type {number} */ (declutterGroup[3]),
value: feature
};
if (!this.declutterTree.collides(box)) {
this.declutterTree.insert(box);
var drawImage = ol.render.canvas.drawImage;
for (var j = 5, jj = declutterGroup.length; j < jj; ++j) {
if (declutterGroup[j]) {
drawImage.apply(undefined, /** @type {Array} */ (declutterGroup[j]));
var declutterData = /** @type {Array} */ (declutterGroup[j]);
if (declutterData) {
if (declutterData.length > 11) {
this.replayTextBackground_(declutterData[0],
declutterData[13], declutterData[14], declutterData[15], declutterData[16],
declutterData[11], declutterData[12]);
}
drawImage.apply(undefined, declutterData);
}
}
}
@@ -429,7 +523,6 @@ ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup) {
* @private
* @param {CanvasRenderingContext2D} context Context.
* @param {ol.Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
* @param {Array.<*>} instructions Instructions array.
@@ -441,7 +534,7 @@ ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup) {
* @template T
*/
ol.render.canvas.Replay.prototype.replay_ = function(
context, transform, viewRotation, skippedFeaturesHash,
context, transform, skippedFeaturesHash,
instructions, featureCallback, opt_hitExtent) {
/** @type {Array.<number>} */
var pixelCoordinates;
@@ -461,10 +554,13 @@ ol.render.canvas.Replay.prototype.replay_ = function(
var ii = instructions.length; // end of instructions
var d = 0; // data index
var dd; // end of per-instruction data
var anchorX, anchorY, prevX, prevY, roundX, roundY, declutterGroup;
var anchorX, anchorY, prevX, prevY, roundX, roundY, declutterGroup, image;
var pendingFill = 0;
var pendingStroke = 0;
var lastFillInstruction = null;
var lastStrokeInstruction = null;
var coordinateCache = this.coordinateCache_;
var viewRotation = this.viewRotation_;
var state = /** @type {olx.render.State} */ ({
context: context,
@@ -497,7 +593,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
break;
case ol.render.canvas.Instruction.BEGIN_PATH:
if (pendingFill > batchSize) {
this.fill_(context, viewRotation);
this.fill_(context);
pendingFill = 0;
}
if (pendingStroke > batchSize) {
@@ -552,12 +648,12 @@ ol.render.canvas.Replay.prototype.replay_ = function(
case ol.render.canvas.Instruction.DRAW_IMAGE:
d = /** @type {number} */ (instruction[1]);
dd = /** @type {number} */ (instruction[2]);
var image = /** @type {HTMLCanvasElement|HTMLVideoElement|Image} */
image = /** @type {HTMLCanvasElement|HTMLVideoElement|Image} */
(instruction[3]);
// Remaining arguments in DRAW_IMAGE are in alphabetical order
anchorX = /** @type {number} */ (instruction[4]);
anchorY = /** @type {number} */ (instruction[5]);
declutterGroup = /** @type {ol.DeclutterGroup} */ (instruction[6]);
declutterGroup = featureCallback ? null : /** @type {ol.DeclutterGroup} */ (instruction[6]);
var height = /** @type {number} */ (instruction[7]);
var opacity = /** @type {number} */ (instruction[8]);
var originX = /** @type {number} */ (instruction[9]);
@@ -568,70 +664,86 @@ ol.render.canvas.Replay.prototype.replay_ = function(
var snapToPixel = /** @type {boolean} */ (instruction[14]);
var width = /** @type {number} */ (instruction[15]);
var padding, backgroundFill, backgroundStroke;
if (instruction.length > 16) {
padding = /** @type {Array.<number>} */ (instruction[16]);
backgroundFill = /** @type {boolean} */ (instruction[17]);
backgroundStroke = /** @type {boolean} */ (instruction[18]);
} else {
padding = ol.render.canvas.defaultPadding;
backgroundFill = backgroundStroke = false;
}
if (rotateWithView) {
rotation += viewRotation;
}
for (; d < dd; d += 2) {
this.replayImage_(context,
pixelCoordinates[d], pixelCoordinates[d + 1], image, anchorX, anchorY,
declutterGroup, height, opacity, originX, originY, rotation, scale, snapToPixel, width);
declutterGroup, height, opacity, originX, originY, rotation, scale,
snapToPixel, width, padding,
backgroundFill ? /** @type {Array.<*>} */ (lastFillInstruction) : null,
backgroundStroke ? /** @type {Array.<*>} */ (lastStrokeInstruction) : null);
}
this.renderDeclutter_(declutterGroup);
this.renderDeclutter_(declutterGroup, feature);
++i;
break;
case ol.render.canvas.Instruction.DRAW_CHARS:
var begin = /** @type {number} */ (instruction[1]);
var end = /** @type {number} */ (instruction[2]);
var baseline = /** @type {number} */ (instruction[3]);
declutterGroup = /** @type {ol.DeclutterGroup} */ (instruction[4]);
var exceedLength = /** @type {number} */ (instruction[5]);
var fill = /** @type {boolean} */ (instruction[6]);
declutterGroup = featureCallback ? null : /** @type {ol.DeclutterGroup} */ (instruction[4]);
var overflow = /** @type {number} */ (instruction[5]);
var fillKey = /** @type {string} */ (instruction[6]);
var maxAngle = /** @type {number} */ (instruction[7]);
var measure = /** @type {function(string):number} */ (instruction[8]);
var offsetY = /** @type {number} */ (instruction[9]);
var stroke = /** @type {boolean} */ (instruction[10]);
var strokeKey = /** @type {string} */ (instruction[10]);
var strokeWidth = /** @type {number} */ (instruction[11]);
var text = /** @type {string} */ (instruction[12]);
var textAlign = /** @type {number} */ (instruction[13]);
var textKey = /** @type {string} */ (instruction[13]);
var textScale = /** @type {number} */ (instruction[14]);
var pathLength = ol.geom.flat.length.lineString(pixelCoordinates, begin, end, 2);
var textLength = measure(text);
if (exceedLength || textLength <= pathLength) {
var startM = (pathLength - textLength) * textAlign;
if (overflow || textLength <= pathLength) {
var textAlign = /** @type {ol.render.canvas.TextReplay} */ (this).textStates[textKey].textAlign;
var startM = (pathLength - textLength) * ol.render.replay.TEXT_ALIGN[textAlign];
var parts = ol.geom.flat.textpath.lineString(
pixelCoordinates, begin, end, 2, text, measure, startM, maxAngle);
if (parts) {
var c, cc, chars, label, part;
if (stroke) {
if (strokeKey) {
for (c = 0, cc = parts.length; c < cc; ++c) {
part = parts[c]; // x, y, anchorX, rotation, chunk
chars = /** @type {string} */ (part[4]);
label = /** @type {ol.render.canvas.TextReplay} */ (this).getImage(chars, false, true);
label = /** @type {ol.render.canvas.TextReplay} */ (this).getImage(chars, textKey, '', strokeKey);
anchorX = /** @type {number} */ (part[2]) + strokeWidth;
anchorY = baseline * label.height + (0.5 - baseline) * 2 * strokeWidth - offsetY;
this.replayImage_(context,
/** @type {number} */ (part[0]), /** @type {number} */ (part[1]), label,
anchorX, anchorY, declutterGroup, label.height, 1, 0, 0,
/** @type {number} */ (part[3]), textScale, false, label.width);
/** @type {number} */ (part[3]), textScale, false, label.width,
ol.render.canvas.defaultPadding, null, null);
}
}
if (fill) {
if (fillKey) {
for (c = 0, cc = parts.length; c < cc; ++c) {
part = parts[c]; // x, y, anchorX, rotation, chunk
chars = /** @type {string} */ (part[4]);
label = /** @type {ol.render.canvas.TextReplay} */ (this).getImage(chars, true, false);
label = /** @type {ol.render.canvas.TextReplay} */ (this).getImage(chars, textKey, fillKey, '');
anchorX = /** @type {number} */ (part[2]);
anchorY = baseline * label.height - offsetY;
this.replayImage_(context,
/** @type {number} */ (part[0]), /** @type {number} */ (part[1]), label,
anchorX, anchorY, declutterGroup, label.height, 1, 0, 0,
/** @type {number} */ (part[3]), textScale, false, label.width);
/** @type {number} */ (part[3]), textScale, false, label.width,
ol.render.canvas.defaultPadding, null, null);
}
}
}
}
this.renderDeclutter_(declutterGroup);
this.renderDeclutter_(declutterGroup, feature);
++i;
break;
case ol.render.canvas.Instruction.END_GEOMETRY:
@@ -648,7 +760,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
if (batchSize) {
pendingFill++;
} else {
this.fill_(context, viewRotation);
this.fill_(context);
}
++i;
break;
@@ -678,10 +790,11 @@ ol.render.canvas.Replay.prototype.replay_ = function(
++i;
break;
case ol.render.canvas.Instruction.SET_FILL_STYLE:
lastFillInstruction = instruction;
this.fillOrigin_ = instruction[2];
if (pendingFill) {
this.fill_(context, viewRotation);
this.fill_(context);
pendingFill = 0;
if (pendingStroke) {
context.stroke();
@@ -693,19 +806,12 @@ ol.render.canvas.Replay.prototype.replay_ = function(
++i;
break;
case ol.render.canvas.Instruction.SET_STROKE_STYLE:
lastStrokeInstruction = instruction;
if (pendingStroke) {
context.stroke();
pendingStroke = 0;
}
context.strokeStyle = /** @type {ol.ColorLike} */ (instruction[1]);
context.lineWidth = /** @type {number} */ (instruction[2]);
context.lineCap = /** @type {string} */ (instruction[3]);
context.lineJoin = /** @type {string} */ (instruction[4]);
context.miterLimit = /** @type {number} */ (instruction[5]);
if (ol.has.CANVAS_LINE_DASH) {
context.lineDashOffset = /** @type {number} */ (instruction[7]);
context.setLineDash(/** @type {Array.<number>} */ (instruction[6]));
}
this.setStrokeStyle_(context, /** @type {Array.<*>} */ (instruction));
++i;
break;
case ol.render.canvas.Instruction.STROKE:
@@ -722,7 +828,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
}
}
if (pendingFill) {
this.fill_(context, viewRotation);
this.fill_(context);
}
if (pendingStroke) {
context.stroke();
@@ -740,9 +846,9 @@ ol.render.canvas.Replay.prototype.replay_ = function(
*/
ol.render.canvas.Replay.prototype.replay = function(
context, transform, viewRotation, skippedFeaturesHash) {
var instructions = this.instructions;
this.replay_(context, transform, viewRotation,
skippedFeaturesHash, instructions, undefined, undefined);
this.viewRotation_ = viewRotation;
this.replay_(context, transform,
skippedFeaturesHash, this.instructions, undefined, undefined);
};
@@ -762,9 +868,9 @@ ol.render.canvas.Replay.prototype.replay = function(
ol.render.canvas.Replay.prototype.replayHitDetection = function(
context, transform, viewRotation, skippedFeaturesHash,
opt_featureCallback, opt_hitExtent) {
var instructions = this.hitDetectionInstructions;
return this.replay_(context, transform, viewRotation,
skippedFeaturesHash, instructions, opt_featureCallback, opt_hitExtent);
this.viewRotation_ = viewRotation;
return this.replay_(context, transform, skippedFeaturesHash,
this.hitDetectionInstructions, opt_featureCallback, opt_hitExtent);
};
@@ -849,9 +955,51 @@ ol.render.canvas.Replay.prototype.setFillStrokeStyle = function(fillStyle, strok
/**
* @param {ol.CanvasFillStrokeState} state State.
* @param {boolean} managePath Manage stoke() - beginPath() for linestrings.
* @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
*/
ol.render.canvas.Replay.prototype.updateStrokeStyle = function(state, managePath) {
ol.render.canvas.Replay.prototype.applyFill = function(state, geometry) {
var fillStyle = state.fillStyle;
var fillInstruction = [ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle];
if (typeof fillStyle !== 'string') {
var fillExtent = geometry.getExtent();
fillInstruction.push([fillExtent[0], fillExtent[3]]);
}
this.instructions.push(fillInstruction);
};
/**
* @param {ol.CanvasFillStrokeState} state State.
*/
ol.render.canvas.Replay.prototype.applyStroke = function(state) {
this.instructions.push([
ol.render.canvas.Instruction.SET_STROKE_STYLE,
state.strokeStyle, state.lineWidth * this.pixelRatio, state.lineCap,
state.lineJoin, state.miterLimit,
this.applyPixelRatio(state.lineDash), state.lineDashOffset * this.pixelRatio
]);
};
/**
* @param {ol.CanvasFillStrokeState} state State.
* @param {function(this:ol.render.canvas.Replay, ol.CanvasFillStrokeState, (ol.geom.Geometry|ol.render.Feature))} applyFill Apply fill.
* @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
*/
ol.render.canvas.Replay.prototype.updateFillStyle = function(state, applyFill, geometry) {
var fillStyle = state.fillStyle;
if (typeof fillStyle !== 'string' || state.currentFillStyle != fillStyle) {
applyFill.call(this, state, geometry);
state.currentFillStyle = fillStyle;
}
};
/**
* @param {ol.CanvasFillStrokeState} state State.
* @param {function(this:ol.render.canvas.Replay, ol.CanvasFillStrokeState)} applyStroke Apply stroke.
*/
ol.render.canvas.Replay.prototype.updateStrokeStyle = function(state, applyStroke) {
var strokeStyle = state.strokeStyle;
var lineCap = state.lineCap;
var lineDash = state.lineDash;
@@ -861,26 +1009,12 @@ ol.render.canvas.Replay.prototype.updateStrokeStyle = function(state, managePath
var miterLimit = state.miterLimit;
if (state.currentStrokeStyle != strokeStyle ||
state.currentLineCap != lineCap ||
!ol.array.equals(state.currentLineDash, lineDash) ||
(lineDash != state.currentLineDash && !ol.array.equals(state.currentLineDash, lineDash)) ||
state.currentLineDashOffset != lineDashOffset ||
state.currentLineJoin != lineJoin ||
state.currentLineWidth != lineWidth ||
state.currentMiterLimit != miterLimit) {
if (managePath) {
if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
this.instructions.push([ol.render.canvas.Instruction.STROKE]);
state.lastStroke = this.coordinates.length;
}
state.lastStroke = 0;
}
this.instructions.push([
ol.render.canvas.Instruction.SET_STROKE_STYLE,
strokeStyle, lineWidth * this.pixelRatio, lineCap, lineJoin, miterLimit,
this.applyPixelRatio(lineDash), lineDashOffset * this.pixelRatio
]);
if (managePath) {
this.instructions.push([ol.render.canvas.Instruction.BEGIN_PATH]);
}
applyStroke.call(this, state);
state.currentStrokeStyle = strokeStyle;
state.currentLineCap = lineCap;
state.currentLineDash = lineDash;

View File

@@ -185,32 +185,20 @@ ol.render.canvas.ReplayGroup.getCircleArray_ = function(radius) {
};
/**
* @param {!Object.<string, Array.<*>>} declutterReplays Declutter replays.
* @param {CanvasRenderingContext2D} context Context.
* @param {number} rotation Rotation.
*/
ol.render.canvas.ReplayGroup.replayDeclutter = function(declutterReplays, context, rotation) {
var zs = Object.keys(declutterReplays).map(Number).sort(ol.array.numberSafeCompareFunction);
var skippedFeatureUids = {};
for (var z = 0, zz = zs.length; z < zz; ++z) {
var replayData = declutterReplays[zs[z].toString()];
for (var i = 0, ii = replayData.length; i < ii;) {
var replay = replayData[i++];
var transform = replayData[i++];
replay.replay(context, transform, rotation, {});
}
}
};
ol.render.canvas.ReplayGroup.replayDeclutterHitDetection = function(
declutterReplays, context, rotation, featureCallback, hitExtent) {
var zs = Object.keys(declutterReplays).map(Number).sort(ol.array.numberSafeCompareFunction);
for (var z = 0, zz = zs.length; z < zz; ++z) {
var replayData = declutterReplays[zs[z].toString()];
for (var i = replayData.length - 1; i >= 0;) {
var transform = replayData[i--];
var replay = replayData[i--];
var result = replay.replayHitDetection(context, transform, rotation, {},
featureCallback, hitExtent);
if (result) {
return result;
}
replay.replay(context, transform, rotation, skippedFeatureUids);
}
}
};
@@ -326,6 +314,12 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
}
var mask = ol.render.canvas.ReplayGroup.getCircleArray_(hitTolerance);
var declutteredFeatures;
if (this.declutterTree_) {
declutteredFeatures = this.declutterTree_.all().map(function(entry) {
return entry.value;
});
}
/**
* @param {ol.Feature|ol.render.Feature} feature Feature.
@@ -337,7 +331,10 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
for (var j = 0; j < contextSize; j++) {
if (mask[i][j]) {
if (imageData[(j * contextSize + i) * 4 + 3] > 0) {
var result = callback(feature);
var result;
if (!declutteredFeatures || declutteredFeatures.indexOf(feature) !== -1) {
result = callback(feature);
}
if (result) {
return result;
} else {
@@ -350,13 +347,8 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
}
}
var result = this.replayHitDetection_(context, transform, rotation,
return this.replayHitDetection_(context, transform, rotation,
skippedFeaturesHash, hitDetectionCallback, hitExtent, declutterReplays);
if (!result && declutterReplays) {
result = ol.render.canvas.ReplayGroup.replayDeclutterHitDetection(
declutterReplays, context, rotation, hitDetectionCallback, hitExtent);
}
return result;
};

View File

@@ -78,18 +78,33 @@ ol.render.canvas.TextReplay = function(
*/
this.textFillState_ = null;
/**
* @type {Object.<string, ol.CanvasFillState>}
*/
this.fillStates = {};
/**
* @private
* @type {?ol.CanvasStrokeState}
*/
this.textStrokeState_ = null;
/**
* @type {Object.<string, ol.CanvasStrokeState>}
*/
this.strokeStates = {};
/**
* @private
* @type {ol.CanvasTextState}
*/
this.textState_ = /** @type {ol.CanvasTextState} */ ({});
/**
* @type {Object.<string, ol.CanvasTextState>}
*/
this.textStates = {};
/**
* @private
* @type {string}
@@ -110,61 +125,17 @@ ol.render.canvas.TextReplay = function(
/**
* @private
* @type {Object.<string, number>}
* @type {Object.<string, Object.<string, number>>}
*/
this.widths_ = {};
var labelCache = ol.render.canvas.labelCache;
labelCache.prune();
};
ol.inherits(ol.render.canvas.TextReplay, ol.render.canvas.Replay);
/**
* @param {string} font Font to use for measuring.
* @return {ol.Size} Measurement.
*/
ol.render.canvas.TextReplay.measureTextHeight = (function() {
var span;
var heights = {};
return function(font) {
var height = heights[font];
if (height == undefined) {
if (!span) {
span = document.createElement('span');
span.textContent = 'M';
span.style.margin = span.style.padding = '0 !important';
span.style.position = 'absolute !important';
span.style.left = '-99999px !important';
}
span.style.font = font;
document.body.appendChild(span);
height = heights[font] = span.offsetHeight;
document.body.removeChild(span);
}
return height;
};
})();
/**
* @param {string} font Font.
* @param {string} text Text.
* @return {number} Width.
*/
ol.render.canvas.TextReplay.measureTextWidth = (function() {
var measureContext;
var currentFont;
return function(font, text) {
if (!measureContext) {
measureContext = ol.dom.createCanvasContext2D(1, 1);
}
if (font != currentFont) {
currentFont = measureContext.font = font;
}
return measureContext.measureText(text).width;
};
})();
/**
* @param {string} font Font to use for measuring.
* @param {Array.<string>} lines Lines to measure.
@@ -177,7 +148,7 @@ ol.render.canvas.TextReplay.measureTextWidths = function(font, lines, widths) {
var width = 0;
var currentWidth, i;
for (i = 0; i < numLines; ++i) {
currentWidth = ol.render.canvas.TextReplay.measureTextWidth(font, lines[i]);
currentWidth = ol.render.canvas.measureTextWidth(font, lines[i]);
width = Math.max(width, currentWidth);
widths.push(currentWidth);
}
@@ -248,7 +219,7 @@ ol.render.canvas.TextReplay.prototype.drawText = function(geometry, feature) {
this.endGeometry(geometry, feature);
} else {
var label = this.getImage(this.text_, !!this.textFillState_, !!this.textStrokeState_);
var label = this.getImage(this.text_, this.textKey_, this.fillKey_, this.strokeKey_);
var width = label.width / this.pixelRatio;
switch (geometryType) {
case ol.geom.GeometryType.POINT:
@@ -268,7 +239,7 @@ ol.render.canvas.TextReplay.prototype.drawText = function(geometry, feature) {
break;
case ol.geom.GeometryType.POLYGON:
flatCoordinates = /** @type {ol.geom.Polygon} */ (geometry).getFlatInteriorPoint();
if (!textState.exceedLength && flatCoordinates[2] / this.resolution < width) {
if (!textState.overflow && flatCoordinates[2] / this.resolution < width) {
return;
}
stride = 3;
@@ -277,7 +248,7 @@ ol.render.canvas.TextReplay.prototype.drawText = function(geometry, feature) {
var interiorPoints = /** @type {ol.geom.MultiPolygon} */ (geometry).getFlatInteriorPoints();
flatCoordinates = [];
for (i = 0, ii = interiorPoints.length; i < ii; i += 3) {
if (textState.exceedLength || interiorPoints[i + 2] / this.resolution >= width) {
if (textState.overflow || interiorPoints[i + 2] / this.resolution >= width) {
flatCoordinates.push(interiorPoints[i], interiorPoints[i + 1]);
}
}
@@ -290,6 +261,11 @@ ol.render.canvas.TextReplay.prototype.drawText = function(geometry, feature) {
}
end = this.appendFlatCoordinates(flatCoordinates, 0, end, stride, false, false);
this.beginGeometry(geometry, feature);
if (textState.backgroundFill || textState.backgroundStroke) {
this.setFillStrokeStyle(textState.backgroundFill, textState.backgroundStroke);
this.updateFillStyle(this.state, this.applyFill, geometry);
this.updateStrokeStyle(this.state, this.applyStroke);
}
this.drawTextImage_(label, begin, end);
this.endGeometry(geometry, feature);
}
@@ -298,41 +274,42 @@ ol.render.canvas.TextReplay.prototype.drawText = function(geometry, feature) {
/**
* @param {string} text Text.
* @param {boolean} fill Fill.
* @param {boolean} stroke Stroke.
* @param {string} textKey Text style key.
* @param {string} fillKey Fill style key.
* @param {string} strokeKey Stroke style key.
* @return {HTMLCanvasElement} Image.
*/
ol.render.canvas.TextReplay.prototype.getImage = function(text, fill, stroke) {
ol.render.canvas.TextReplay.prototype.getImage = function(text, textKey, fillKey, strokeKey) {
var label;
var key = (stroke ? this.strokeKey_ : '') + this.textKey_ + text + (fill ? this.fillKey_ : '');
var key = strokeKey + textKey + text + fillKey + this.pixelRatio;
var labelCache = ol.render.canvas.labelCache;
if (!labelCache.containsKey(key)) {
var strokeState = this.textStrokeState_;
var fillState = this.textFillState_;
var textState = this.textState_;
var strokeState = strokeKey ? this.strokeStates[strokeKey] || this.textStrokeState_ : null;
var fillState = fillKey ? this.fillStates[fillKey] || this.textFillState_ : null;
var textState = this.textStates[textKey] || this.textState_;
var pixelRatio = this.pixelRatio;
var scale = textState.scale * pixelRatio;
var align = ol.render.replay.TEXT_ALIGN[textState.textAlign || ol.render.canvas.defaultTextAlign];
var strokeWidth = stroke && strokeState.lineWidth ? strokeState.lineWidth : 0;
var strokeWidth = strokeKey && strokeState.lineWidth ? strokeState.lineWidth : 0;
var lines = text.split('\n');
var numLines = lines.length;
var widths = [];
var width = ol.render.canvas.TextReplay.measureTextWidths(textState.font, lines, widths);
var lineHeight = ol.render.canvas.TextReplay.measureTextHeight(textState.font);
var lineHeight = ol.render.canvas.measureTextHeight(textState.font);
var height = lineHeight * numLines;
var renderWidth = (width + strokeWidth);
var context = ol.dom.createCanvasContext2D(
Math.ceil(renderWidth * scale),
Math.ceil((height + strokeWidth) * scale));
label = context.canvas;
labelCache.pruneAndSet(key, label);
labelCache.set(key, label);
if (scale != 1) {
context.scale(scale, scale);
}
context.font = textState.font;
if (stroke) {
if (strokeKey) {
context.strokeStyle = strokeState.strokeStyle;
context.lineWidth = strokeWidth * (ol.has.SAFARI ? scale : 1);
context.lineCap = strokeState.lineCap;
@@ -343,22 +320,22 @@ ol.render.canvas.TextReplay.prototype.getImage = function(text, fill, stroke) {
context.lineDashOffset = strokeState.lineDashOffset;
}
}
if (fill) {
if (fillKey) {
context.fillStyle = fillState.fillStyle;
}
context.textBaseline = 'top';
context.textBaseline = 'middle';
context.textAlign = 'center';
var leftRight = (0.5 - align);
var x = align * label.width / scale + leftRight * strokeWidth;
var i;
if (stroke) {
if (strokeKey) {
for (i = 0; i < numLines; ++i) {
context.strokeText(lines[i], x + leftRight * widths[i], 0.5 * strokeWidth + i * lineHeight);
context.strokeText(lines[i], x + leftRight * widths[i], 0.5 * (strokeWidth + lineHeight) + i * lineHeight);
}
}
if (fill) {
if (fillKey) {
for (i = 0; i < numLines; ++i) {
context.fillText(lines[i], x + leftRight * widths[i], 0.5 * strokeWidth + i * lineHeight);
context.fillText(lines[i], x + leftRight * widths[i], 0.5 * (strokeWidth + lineHeight) + i * lineHeight);
}
}
}
@@ -385,12 +362,18 @@ ol.render.canvas.TextReplay.prototype.drawTextImage_ = function(label, begin, en
this.instructions.push([ol.render.canvas.Instruction.DRAW_IMAGE, begin, end,
label, (anchorX - this.textOffsetX_) * pixelRatio, (anchorY - this.textOffsetY_) * pixelRatio,
this.declutterGroup_, label.height, 1, 0, 0, this.textRotateWithView_, this.textRotation_,
1, true, label.width
1, true, label.width,
textState.padding == ol.render.canvas.defaultPadding ?
ol.render.canvas.defaultPadding : textState.padding.map(function(p) {
return p * pixelRatio;
}),
!!textState.backgroundFill, !!textState.backgroundStroke
]);
this.hitDetectionInstructions.push([ol.render.canvas.Instruction.DRAW_IMAGE, begin, end,
label, (anchorX - this.textOffsetX_) * pixelRatio, (anchorY - this.textOffsetY_) * pixelRatio,
this.declutterGroup_, label.height, 1, 0, 0, this.textRotateWithView_, this.textRotation_,
1 / pixelRatio, true, label.width
1 / pixelRatio, true, label.width, textState.padding,
!!textState.backgroundFill, !!textState.backgroundStroke
]);
};
@@ -402,43 +385,76 @@ ol.render.canvas.TextReplay.prototype.drawTextImage_ = function(label, begin, en
* @param {ol.DeclutterGroup} declutterGroup Declutter group.
*/
ol.render.canvas.TextReplay.prototype.drawChars_ = function(begin, end, declutterGroup) {
var pixelRatio = this.pixelRatio;
var strokeState = this.textStrokeState_;
var fill = !!this.textFillState_;
var stroke = !!strokeState;
var textState = this.textState_;
var fillState = this.textFillState_;
var strokeKey = this.strokeKey_;
if (strokeState) {
if (!(strokeKey in this.strokeStates)) {
this.strokeStates[strokeKey] = /** @type {ol.CanvasStrokeState} */ ({
strokeStyle: strokeState.strokeStyle,
lineCap: strokeState.lineCap,
lineDashOffset: strokeState.lineDashOffset,
lineWidth: strokeState.lineWidth,
lineJoin: strokeState.lineJoin,
miterLimit: strokeState.miterLimit,
lineDash: strokeState.lineDash
});
}
}
var textKey = this.textKey_;
if (!(this.textKey_ in this.textStates)) {
this.textStates[this.textKey_] = /** @type {ol.CanvasTextState} */ ({
font: textState.font,
textAlign: textState.textAlign || ol.render.canvas.defaultTextAlign,
scale: textState.scale
});
}
var fillKey = this.fillKey_;
if (fillState) {
if (!(fillKey in this.fillStates)) {
this.fillStates[fillKey] = /** @type {ol.CanvasFillState} */ ({
fillStyle: fillState.fillStyle
});
}
}
var pixelRatio = this.pixelRatio;
var baseline = ol.render.replay.TEXT_ALIGN[textState.textBaseline];
var offsetY = this.textOffsetY_ * pixelRatio;
var textAlign = ol.render.replay.TEXT_ALIGN[textState.textAlign || ol.render.canvas.defaultTextAlign];
var text = this.text_;
var font = textState.font;
var textScale = textState.scale;
var strokeWidth = strokeState ? strokeState.lineWidth * textScale / 2 : 0;
var widths = this.widths_;
var widths = this.widths_[font];
if (!widths) {
this.widths_[font] = widths = {};
}
this.instructions.push([ol.render.canvas.Instruction.DRAW_CHARS,
begin, end, baseline, declutterGroup,
textState.exceedLength, fill, textState.maxAngle,
textState.overflow, fillKey, textState.maxAngle,
function(text) {
var width = widths[text];
if (!width) {
width = widths[text] = ol.render.canvas.TextReplay.measureTextWidth(font, text);
width = widths[text] = ol.render.canvas.measureTextWidth(font, text);
}
return width * textScale * pixelRatio;
},
offsetY, stroke, strokeWidth * pixelRatio, text, textAlign, 1
offsetY, strokeKey, strokeWidth * pixelRatio, text, textKey, 1
]);
this.hitDetectionInstructions.push([ol.render.canvas.Instruction.DRAW_CHARS,
begin, end, baseline, declutterGroup,
textState.exceedLength, fill, textState.maxAngle,
textState.overflow, fillKey, textState.maxAngle,
function(text) {
var width = widths[text];
if (!width) {
width = widths[text] = ol.render.canvas.TextReplay.measureTextWidth(font, text);
width = widths[text] = ol.render.canvas.measureTextWidth(font, text);
}
return width * textScale;
},
offsetY, stroke, strokeWidth, text, textAlign, 1 / pixelRatio
offsetY, strokeKey, strokeWidth, text, textKey, 1 / pixelRatio
]);
};
@@ -494,12 +510,15 @@ ol.render.canvas.TextReplay.prototype.setTextStyle = function(textStyle, declutt
var font = textStyle.getFont() || ol.render.canvas.defaultFont;
ol.render.canvas.checkFont(font);
var textScale = textStyle.getScale();
textState.exceedLength = textStyle.getExceedLength();
textState.overflow = textStyle.getOverflow();
textState.font = font;
textState.maxAngle = textStyle.getMaxAngle();
textState.placement = textStyle.getPlacement();
textState.textAlign = textStyle.getTextAlign();
textState.textBaseline = textStyle.getTextBaseline() || ol.render.canvas.defaultTextBaseline;
textState.backgroundFill = textStyle.getBackgroundFill();
textState.backgroundStroke = textStyle.getBackgroundStroke();
textState.padding = textStyle.getPadding() || ol.render.canvas.defaultPadding;
textState.scale = textScale === undefined ? 1 : textScale;
var textOffsetX = textStyle.getOffsetX();
@@ -517,7 +536,7 @@ ol.render.canvas.TextReplay.prototype.setTextStyle = function(textStyle, declutt
strokeState.lineCap + strokeState.lineDashOffset + '|' + strokeState.lineWidth +
strokeState.lineJoin + strokeState.miterLimit + '[' + strokeState.lineDash.join() + ']' :
'';
this.textKey_ = textState.font + (textState.textAlign || '?') + textState.scale;
this.textKey_ = textState.font + textState.scale + (textState.textAlign || '?');
this.fillKey_ = fillState ?
(typeof fillState.fillStyle == 'string' ? fillState.fillStyle : ('|' + ol.getUid(fillState.fillStyle))) :
'';

View File

@@ -1,9 +1,13 @@
goog.provide('ol.renderer.canvas.ImageLayer');
goog.require('ol');
goog.require('ol.ImageCanvas');
goog.require('ol.LayerType');
goog.require('ol.ViewHint');
goog.require('ol.extent');
goog.require('ol.layer.VectorRenderType');
goog.require('ol.obj');
goog.require('ol.plugins');
goog.require('ol.renderer.Type');
goog.require('ol.renderer.canvas.IntermediateCanvas');
goog.require('ol.transform');
@@ -31,6 +35,12 @@ ol.renderer.canvas.ImageLayer = function(imageLayer) {
*/
this.imageTransform_ = ol.transform.create();
/**
* @private
* @type {ol.renderer.canvas.VectorLayer}
*/
this.vectorRenderer_ = null;
};
ol.inherits(ol.renderer.canvas.ImageLayer, ol.renderer.canvas.IntermediateCanvas);
@@ -42,7 +52,9 @@ ol.inherits(ol.renderer.canvas.ImageLayer, ol.renderer.canvas.IntermediateCanvas
* @return {boolean} The renderer can render the layer.
*/
ol.renderer.canvas.ImageLayer['handles'] = function(type, layer) {
return type === ol.renderer.Type.CANVAS && layer.getType() === ol.LayerType.IMAGE;
return type === ol.renderer.Type.CANVAS && (layer.getType() === ol.LayerType.IMAGE ||
layer.getType() === ol.LayerType.VECTOR &&
/** @type {ol.layer.Vector} */ (layer).getRenderMode() === ol.layer.VectorRenderType.IMAGE);
};
@@ -53,7 +65,17 @@ ol.renderer.canvas.ImageLayer['handles'] = function(type, layer) {
* @return {ol.renderer.canvas.ImageLayer} The layer renderer.
*/
ol.renderer.canvas.ImageLayer['create'] = function(mapRenderer, layer) {
return new ol.renderer.canvas.ImageLayer(/** @type {ol.layer.Image} */ (layer));
var renderer = new ol.renderer.canvas.ImageLayer(/** @type {ol.layer.Image} */ (layer));
if (layer.getType() === ol.LayerType.VECTOR) {
var candidates = ol.plugins.getLayerRendererPlugins();
for (var i = 0, ii = candidates.length; i < ii; ++i) {
var candidate = /** @type {Object.<string, Function>} */ (candidates[i]);
if (candidate !== ol.renderer.canvas.ImageLayer && candidate['handles'](ol.renderer.Type.CANVAS, layer)) {
renderer.setVectorRenderer(candidate['create'](mapRenderer, layer));
}
}
}
return renderer;
};
@@ -105,12 +127,31 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame = function(frameState, laye
projection = sourceProjection;
}
}
image = imageSource.getImage(
renderedExtent, viewResolution, pixelRatio, projection);
if (image) {
var loaded = this.loadImage(image);
if (loaded) {
this.image_ = image;
if (this.vectorRenderer_) {
var context = this.vectorRenderer_.context;
var imageFrameState = /** @type {olx.FrameState} */ (ol.obj.assign({}, frameState, {
size: [
ol.extent.getWidth(renderedExtent) / viewResolution,
ol.extent.getHeight(renderedExtent) / viewResolution
],
viewState: /** @type {olx.ViewState} */ (ol.obj.assign({}, frameState.viewState, {
rotation: 0
}))
}));
if (this.vectorRenderer_.prepareFrame(imageFrameState, layerState)) {
context.canvas.width = imageFrameState.size[0] * pixelRatio;
context.canvas.height = imageFrameState.size[1] * pixelRatio;
this.vectorRenderer_.composeFrame(imageFrameState, layerState, context);
}
this.image_ = new ol.ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas);
} else {
image = imageSource.getImage(
renderedExtent, viewResolution, pixelRatio, projection);
if (image) {
var loaded = this.loadImage(image);
if (loaded) {
this.image_ = image;
}
}
}
}
@@ -140,3 +181,23 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame = function(frameState, laye
return !!this.image_;
};
/**
* @inheritDoc
*/
ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
if (this.vectorRenderer_) {
return this.vectorRenderer_.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, thisArg);
} else {
return ol.renderer.canvas.IntermediateCanvas.prototype.forEachFeatureAtCoordinate.call(this, coordinate, frameState, hitTolerance, callback, thisArg);
}
};
/**
* @param {ol.renderer.canvas.VectorLayer} renderer Vector renderer.
*/
ol.renderer.canvas.ImageLayer.prototype.setVectorRenderer = function(renderer) {
this.vectorRenderer_ = renderer;
};

View File

@@ -123,7 +123,7 @@ ol.renderer.canvas.IntermediateCanvas.prototype.forEachLayerAtCoordinate = funct
}
if (this.getLayer().getSource().forEachFeatureAtCoordinate !== ol.nullFunction) {
// for ImageVector sources use the original hit-detection logic,
// for ImageCanvas sources use the original hit-detection logic,
// so that for example also transparent polygons are detected
return ol.renderer.canvas.Layer.prototype.forEachLayerAtCoordinate.apply(this, arguments);
} else {

View File

@@ -70,10 +70,9 @@ ol.renderer.canvas.VectorLayer = function(vectorLayer) {
this.replayGroup_ = null;
/**
* @private
* @type {CanvasRenderingContext2D}
*/
this.context_ = ol.dom.createCanvasContext2D();
this.context = ol.dom.createCanvasContext2D();
ol.events.listen(ol.render.canvas.labelCache, ol.events.EventType.CLEAR, this.handleFontsChanged_, this);
@@ -139,7 +138,10 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
}
var replayGroup = this.replayGroup_;
if (replayGroup && !replayGroup.isEmpty()) {
var layer = this.getLayer();
if (this.declutterTree_) {
this.declutterTree_.clear();
}
var layer = /** @type {ol.layer.Vector} */ (this.getLayer());
var drawOffsetX = 0;
var drawOffsetY = 0;
var replayContext;
@@ -155,9 +157,9 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
drawWidth = drawHeight = drawSize;
}
// resize and clear
this.context_.canvas.width = drawWidth;
this.context_.canvas.height = drawHeight;
replayContext = this.context_;
this.context.canvas.width = drawWidth;
this.context.canvas.height = drawHeight;
replayContext = this.context;
} else {
replayContext = context;
}
@@ -230,9 +232,6 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
if (clipped) {
context.restore();
}
if (this.declutterTree_) {
this.declutterTree_.clear();
}
this.postCompose(context, frameState, layerState, transform);
};
@@ -250,7 +249,6 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(c
var layer = /** @type {ol.layer.Vector} */ (this.getLayer());
/** @type {Object.<string, boolean>} */
var features = {};
var declutterReplays = layer.getDeclutter() ? {} : null;
var result = this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
rotation, hitTolerance, {},
/**
@@ -263,10 +261,7 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(c
features[key] = true;
return callback.call(thisArg, feature, layer);
}
}, declutterReplays);
if (this.declutterTree_) {
this.declutterTree_.clear();
}
}, null);
return result;
}
};

View File

@@ -233,7 +233,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(
}
feature.getGeometry().transform(tileProjection, projection);
}
if (!bufferedExtent || ol.extent.intersects(bufferedExtent, feature.getExtent())) {
if (!bufferedExtent || ol.extent.intersects(bufferedExtent, feature.getGeometry().getExtent())) {
renderFeature.call(this, feature);
}
}
@@ -270,7 +270,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
var rotation = frameState.viewState.rotation;
hitTolerance = hitTolerance == undefined ? 0 : hitTolerance;
var layer = this.getLayer();
var declutterReplays = layer.getDeclutter() ? {} : null;
/** @type {Object.<string, boolean>} */
var features = {};
@@ -308,12 +307,9 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
features[key] = true;
return callback.call(thisArg, feature, layer);
}
}, declutterReplays);
}, null);
}
}
if (this.declutterTree_) {
this.declutterTree_.clear();
}
return found;
};
@@ -381,9 +377,15 @@ ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, fra
var pixelRatio = frameState.pixelRatio;
var rotation = frameState.viewState.rotation;
var size = frameState.size;
var offsetX = Math.round(pixelRatio * size[0] / 2);
var offsetY = Math.round(pixelRatio * size[1] / 2);
ol.render.canvas.rotateAtOffset(context, -rotation, offsetX, offsetY);
var offsetX, offsetY;
if (rotation) {
offsetX = Math.round(pixelRatio * size[0] / 2);
offsetY = Math.round(pixelRatio * size[1] / 2);
ol.render.canvas.rotateAtOffset(context, -rotation, offsetX, offsetY);
}
if (declutterReplays) {
this.declutterTree_.clear();
}
var tiles = this.renderedTiles;
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
var clips = [];
@@ -440,7 +442,10 @@ ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, fra
}
if (declutterReplays) {
ol.render.canvas.ReplayGroup.replayDeclutter(declutterReplays, context, rotation);
this.declutterTree_.clear();
}
if (rotation) {
ol.render.canvas.rotateAtOffset(context, rotation,
/** @type {number} */ (offsetX), /** @type {number} */ (offsetY));
}
ol.renderer.canvas.TileLayer.prototype.postCompose.apply(this, arguments);
};

View File

@@ -68,11 +68,11 @@ ol.renderer.Map.prototype.calculateMatrices2D = function(frameState) {
/**
* @inheritDoc
* Removes all layer renderers.
*/
ol.renderer.Map.prototype.disposeInternal = function() {
for (var id in this.layerRenderers_) {
this.layerRenderers_[id].dispose();
ol.renderer.Map.prototype.removeLayerRenderers = function() {
for (var key in this.layerRenderers_) {
this.removeLayerRendererByKey_(key).dispose();
}
};

View File

@@ -8,7 +8,6 @@ goog.require('ol.extent');
goog.require('ol.functions');
goog.require('ol.renderer.Type');
goog.require('ol.renderer.webgl.Layer');
goog.require('ol.source.ImageVector');
goog.require('ol.transform');
goog.require('ol.webgl');
goog.require('ol.webgl.Context');
@@ -248,8 +247,8 @@ ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, fra
return undefined;
}
if (this.getLayer().getSource() instanceof ol.source.ImageVector) {
// for ImageVector sources use the original hit-detection logic,
if (this.getLayer().getSource().forEachFeatureAtCoordinate !== ol.nullFunction) {
// for ImageCanvas sources use the original hit-detection logic,
// so that for example also transparent polygons are detected
var coordinate = ol.transform.apply(
frameState.pixelToCoordinateTransform, pixel.slice());

View File

@@ -14,7 +14,11 @@ goog.require('ol.transform');
/**
* @deprecated
* @classdesc
* **Deprecated**. Use an `ol.layer.Vector` with `renderMode: 'image'` and an
* `ol.source.Vector` instead.
*
* An image source whose images are canvas elements into which vector features
* read from a vector source (`ol.source.Vector`) are drawn. An
* `ol.source.ImageVector` object is to be used as the `source` of an image
@@ -148,12 +152,13 @@ ol.source.ImageVector.prototype.canvasFunctionInternal_ = function(extent, resol
this.canvasContext_.clearRect(0, 0, size[0], size[1]);
}
this.declutterTree_.clear();
var transform = this.getTransform_(ol.extent.getCenter(extent),
resolution, pixelRatio, size);
replayGroup.replay(this.canvasContext_, transform, 0, {});
this.replayGroup_ = replayGroup;
this.declutterTree_.clear();
return this.canvasContext_.canvas;
};
@@ -182,7 +187,6 @@ ol.source.ImageVector.prototype.forEachFeatureAtCoordinate = function(
return callback(feature);
}
}, null);
this.declutterTree_.clear();
return result;
}
};

View File

@@ -107,7 +107,6 @@ ol.source.Raster = function(options) {
*/
this.frameState_ = {
animate: false,
attributions: {},
coordinateToPixelTransform: ol.transform.create(),
extent: null,
focus: null,

View File

@@ -268,12 +268,10 @@ ol.structs.LRUCache.prototype.set = function(key, value) {
/**
* @param {string} key Key.
* @param {T} value Value.
* Prune the cache.
*/
ol.structs.LRUCache.prototype.pruneAndSet = function(key, value) {
ol.structs.LRUCache.prototype.prune = function() {
while (this.canExpireCache()) {
this.pop();
}
this.set(key, value);
};

View File

@@ -82,7 +82,7 @@ ol.style.Text = function(opt_options) {
* @private
* @type {boolean}
*/
this.exceedLength_ = options.exceedLength !== undefined ? options.exceedLength : false;
this.overflow_ = options.overflow !== undefined ? options.overflow : false;
/**
* @private
@@ -101,6 +101,24 @@ ol.style.Text = function(opt_options) {
* @type {number}
*/
this.offsetY_ = options.offsetY !== undefined ? options.offsetY : 0;
/**
* @private
* @type {ol.style.Fill}
*/
this.backgroundFill_ = options.backgroundFill ? options.backgroundFill : null;
/**
* @private
* @type {ol.style.Stroke}
*/
this.backgroundStroke_ = options.backgroundStroke ? options.backgroundStroke : null;
/**
* @private
* @type {Array.<number>}
*/
this.padding_ = options.padding === undefined ? null : options.padding;
};
@@ -124,7 +142,7 @@ ol.style.Text.prototype.clone = function() {
font: this.getFont(),
placement: this.getPlacement(),
maxAngle: this.getMaxAngle(),
exceedLength: this.getExceedLength(),
overflow: this.getOverflow(),
rotation: this.getRotation(),
rotateWithView: this.getRotateWithView(),
scale: this.getScale(),
@@ -140,12 +158,12 @@ ol.style.Text.prototype.clone = function() {
/**
* Get the `exceedLength` configuration.
* @return {boolean} Let text exceed the length of the path they follow.
* Get the `overflow` configuration.
* @return {boolean} Let text overflow the length of the path they follow.
* @api
*/
ol.style.Text.prototype.getExceedLength = function() {
return this.exceedLength_;
ol.style.Text.prototype.getOverflow = function() {
return this.overflow_;
};
@@ -280,13 +298,43 @@ ol.style.Text.prototype.getTextBaseline = function() {
/**
* Set the `exceedLength` property.
*
* @param {boolean} exceedLength Let text exceed the path that it follows.
* Get the background fill style for the text.
* @return {ol.style.Fill} Fill style.
* @api
*/
ol.style.Text.prototype.setExceedLength = function(exceedLength) {
this.exceedLength_ = exceedLength;
ol.style.Text.prototype.getBackgroundFill = function() {
return this.backgroundFill_;
};
/**
* Get the background stroke style for the text.
* @return {ol.style.Stroke} Stroke style.
* @api
*/
ol.style.Text.prototype.getBackgroundStroke = function() {
return this.backgroundStroke_;
};
/**
* Get the padding for the text.
* @return {Array.<number>} Padding.
* @api
*/
ol.style.Text.prototype.getPadding = function() {
return this.padding_;
};
/**
* Set the `overflow` property.
*
* @param {boolean} overflow Let text overflow the path that it follows.
* @api
*/
ol.style.Text.prototype.setOverflow = function(overflow) {
this.overflow_ = overflow;
};
@@ -420,3 +468,36 @@ ol.style.Text.prototype.setTextAlign = function(textAlign) {
ol.style.Text.prototype.setTextBaseline = function(textBaseline) {
this.textBaseline_ = textBaseline;
};
/**
* Set the background fill.
*
* @param {ol.style.Fill} fill Fill style.
* @api
*/
ol.style.Text.prototype.setBackgroundFill = function(fill) {
this.backgroundFill_ = fill;
};
/**
* Set the background stroke.
*
* @param {ol.style.Stroke} stroke Stroke style.
* @api
*/
ol.style.Text.prototype.setBackgroundStroke = function(stroke) {
this.backgroundStroke_ = stroke;
};
/**
* Set the padding (`[top, right, bottom, left]`).
*
* @param {!Array.<number>} padding Padding.
* @api
*/
ol.style.Text.prototype.setPadding = function(padding) {
this.padding_ = padding;
};

View File

@@ -180,6 +180,12 @@ ol.View.prototype.applyOptions_ = function(options) {
} else if (options.zoom !== undefined) {
properties[ol.ViewProperty.RESOLUTION] = this.constrainResolution(
this.maxResolution_, options.zoom - this.minZoom_);
if (this.resolutions_) { // in case map zoom is out of min/max zoom range
properties[ol.ViewProperty.RESOLUTION] = ol.math.clamp(
Number(this.getResolution() || properties[ol.ViewProperty.RESOLUTION]),
this.minResolution_, this.maxResolution_);
}
}
properties[ol.ViewProperty.ROTATION] =
options.rotation !== undefined ? options.rotation : 0;
@@ -815,7 +821,7 @@ ol.View.prototype.getZoomForResolution = function(resolution) {
var max, zoomFactor;
if (this.resolutions_) {
var nearest = ol.array.linearFindNearest(this.resolutions_, resolution, 1);
offset += nearest;
offset = nearest;
max = this.resolutions_[nearest];
if (nearest == this.resolutions_.length - 1) {
zoomFactor = 2;
@@ -1103,8 +1109,9 @@ ol.View.createResolutionConstraint_ = function(options) {
if (options.resolutions !== undefined) {
var resolutions = options.resolutions;
maxResolution = resolutions[0];
minResolution = resolutions[resolutions.length - 1];
maxResolution = resolutions[minZoom];
minResolution = resolutions[maxZoom] !== undefined ?
resolutions[maxZoom] : resolutions[resolutions.length - 1];
resolutionConstraint = ol.ResolutionConstraint.createSnapToResolutions(
resolutions);
} else {

View File

@@ -21,7 +21,7 @@ BUILDS=dist
#
# URL for canonical repo.
#
REMOTE=https://github.com/openlayers/openlayers.git
REMOTE=https://github.com/ahocevar/openlayers.git
#
# Display usage and exit.
@@ -98,7 +98,7 @@ main() {
npm install
build_js ${PROFILES}
build_css
npm publish
npm publish --tag beta
}
if test ${#} -ne 1; then

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -101,6 +101,33 @@ describe('ol.rendering.layer.Vector', function() {
});
});
it('renders opacity correctly with renderMode: \'image\'', function(done) {
createMap('canvas');
var smallLine = new ol.Feature(new ol.geom.LineString([
[center[0], center[1] - 1],
[center[0], center[1] + 1]
]));
smallLine.setStyle(new ol.style.Style({
zIndex: -99,
stroke: new ol.style.Stroke({width: 75, color: 'red'})
}));
source.addFeature(smallLine);
addPolygon(100);
addCircle(200);
addPolygon(250);
addCircle(500);
addPolygon(600);
addPolygon(720);
map.addLayer(new ol.layer.Vector({
renerMode: 'image',
source: source
}));
map.once('postrender', function() {
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas.png',
17, done);
});
});
it('renders transparent layers correctly with the canvas renderer', function(done) {
createMap('canvas');
var smallLine = new ol.Feature(new ol.geom.LineString([
@@ -140,6 +167,46 @@ describe('ol.rendering.layer.Vector', function() {
});
});
it('renders transparent layers correctly with renderMode: \'image\'', function(done) {
createMap('canvas');
var smallLine = new ol.Feature(new ol.geom.LineString([
[center[0], center[1] - 1],
[center[0], center[1] + 1]
]));
smallLine.setStyle([
new ol.style.Style({
stroke: new ol.style.Stroke({width: 75, color: 'red'})
}),
new ol.style.Style({
stroke: new ol.style.Stroke({width: 45, color: 'white'})
})
]);
source.addFeature(smallLine);
var smallLine2 = new ol.Feature(new ol.geom.LineString([
[center[0], center[1] - 1000],
[center[0], center[1] + 1000]
]));
smallLine2.setStyle([
new ol.style.Style({
stroke: new ol.style.Stroke({width: 35, color: 'blue'})
}),
new ol.style.Style({
stroke: new ol.style.Stroke({width: 15, color: 'green'})
})
]);
source.addFeature(smallLine2);
map.addLayer(new ol.layer.Vector({
renderMode: 'image',
source: source,
opacity: 0.5
}));
map.once('postrender', function() {
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-transparent.png',
7, done);
});
});
it('renders rotation correctly with the canvas renderer', function(done) {
createMap('canvas');
map.getView().setRotation(Math.PI + Math.PI / 4);
@@ -160,6 +227,27 @@ describe('ol.rendering.layer.Vector', function() {
});
});
it('renders rotation correctly with renderMode: \'image\'', function(done) {
createMap('canvas');
map.getView().setRotation(Math.PI + Math.PI / 4);
addPolygon(300);
addCircle(500);
map.addLayer(new ol.layer.Vector({
renderMode: 'image',
source: source,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 2,
color: 'black'
})
})
}));
map.once('postrender', function() {
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-rotated.png',
2.9, done);
});
});
it('renders fill/stroke batches correctly with the canvas renderer', function(done) {
createMap('canvas');
source = new ol.source.Vector({
@@ -510,6 +598,47 @@ describe('ol.rendering.layer.Vector', function() {
});
});
it('declutters text with renderMode: \'image\'', function(done) {
createMap('canvas');
var layer = new ol.layer.Vector({
renderMode: 'image',
source: source
});
map.addLayer(layer);
var centerFeature = new ol.Feature({
geometry: new ol.geom.Point(center),
text: 'center'
});
source.addFeature(centerFeature);
source.addFeature(new ol.Feature({
geometry: new ol.geom.Point([center[0] - 550, center[1]]),
text: 'west'
}));
source.addFeature(new ol.Feature({
geometry: new ol.geom.Point([center[0] + 550, center[1]]),
text: 'east'
}));
layer.setDeclutter(true);
layer.setStyle(function(feature) {
return new ol.style.Style({
text: new ol.style.Text({
text: feature.get('text'),
font: '12px sans-serif'
})
});
});
map.once('postrender', function() {
var hitDetected = map.getFeaturesAtPixel([42, 42]);
expect(hitDetected).to.have.length(1);
expect(hitDetected[0]).to.equal(centerFeature);
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter.png',
2.2, done);
});
});
it('declutters text and respects z-index', function(done) {
createMap('canvas');
var layer = new ol.layer.Vector({
@@ -589,6 +718,46 @@ describe('ol.rendering.layer.Vector', function() {
});
});
it('declutters images with renderMode: \'image\'', function(done) {
createMap('canvas');
var layer = new ol.layer.Vector({
renderMode: 'image',
source: source
});
map.addLayer(layer);
var centerFeature = new ol.Feature({
geometry: new ol.geom.Point(center)
});
source.addFeature(centerFeature);
source.addFeature(new ol.Feature({
geometry: new ol.geom.Point([center[0] - 550, center[1]])
}));
source.addFeature(new ol.Feature({
geometry: new ol.geom.Point([center[0] + 550, center[1]])
}));
layer.setDeclutter(true);
layer.setStyle(function(feature) {
return new ol.style.Style({
image: new ol.style.Circle({
radius: 15,
stroke: new ol.style.Stroke({
color: 'blue'
})
})
});
});
map.once('postrender', function() {
var hitDetected = map.getFeaturesAtPixel([40, 40]);
expect(hitDetected).to.have.length(1);
expect(hitDetected[0]).to.equal(centerFeature);
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter-image.png',
IMAGE_TOLERANCE, done);
});
});
it('declutters images and respects z-index', function(done) {
createMap('canvas');
var layer = new ol.layer.Vector({
@@ -715,6 +884,49 @@ describe('ol.rendering.layer.Vector', function() {
});
});
it('declutters text along lines and images with renderMode: \'image\'', function(done) {
createMap('canvas');
var layer = new ol.layer.Vector({
source: source
});
map.addLayer(layer);
var point = new ol.Feature(new ol.geom.Point(center));
point.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 8,
stroke: new ol.style.Stroke({
color: 'blue'
})
})
}));
var line = new ol.Feature(new ol.geom.LineString([
[center[0] - 650, center[1] - 200],
[center[0] + 650, center[1] - 200]
]));
line.setStyle(new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#CCC',
width: 12
}),
text: new ol.style.Text({
placement: 'line',
text: 'east-west',
font: '12px sans-serif'
})
}));
source.addFeature(point);
source.addFeature(line);
layer.setDeclutter(true);
map.once('postrender', function() {
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter-line.png',
IMAGE_TOLERANCE, done);
});
});
it('declutters text along lines and images with z-index', function(done) {
createMap('canvas');
var layer = new ol.layer.Vector({

View File

@@ -1,10 +1,12 @@
goog.require('ol.Feature');
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.format.MVT');
goog.require('ol.geom.Point');
goog.require('ol.layer.Vector');
goog.require('ol.layer.VectorTile');
goog.require('ol.obj');
goog.require('ol.source.Vector');
goog.require('ol.source.VectorTile');
goog.require('ol.style.Circle');
goog.require('ol.style.Fill');
@@ -92,6 +94,32 @@ describe('ol.rendering.layer.VectorTile', function() {
});
});
it('renders rotated view correctly with vector layer on top', function(done) {
createMap('canvas');
var vectorSource = new ol.source.Vector({
features: [
new ol.Feature(new ol.geom.Point([1825727.7316762917, 6143091.089223046]))
]
});
map.addLayer(new ol.layer.Vector({
zIndex: 1,
source: vectorSource,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
})
})
}));
map.getView().setRotation(Math.PI / 4);
waitForTiles(source, {}, function() {
expectResemble(map, 'rendering/ol/layer/expected/vectortile-vector-rotated.png',
14, done);
});
});
it('renders correctly with the canvas renderer (HiDPI)', function(done) {
createMap('canvas', 2);
waitForTiles(source, {}, function() {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Some files were not shown because too many files have changed in this diff Show More