Merge pull request #1032 from bbinet/minmax_resolution

Add support for layer min/maxResolution
This commit is contained in:
Bruno Binet
2013-09-19 09:11:16 -07:00
9 changed files with 254 additions and 21 deletions
+65
View File
@@ -0,0 +1,65 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Min/max resolution example</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./">OpenLayers 3 Examples</a>
<ul class="nav pull-right">
<li><iframe class="github-watch-button" src="http://ghbtns.com/github-btn.html?user=openlayers&repo=ol3&type=watch&count=true"
allowtransparency="true" frameborder="0" scrolling="0" height="20" width="90"></iframe></li>
<li><a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-hashtags="openlayers">&nbsp;</a></li>
<li><div class="g-plusone-wrapper"><div class="g-plusone" data-size="medium" data-annotation="none"></div></div></li>
</ul>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<div id="map" class="map"></div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<h4 id="title">Min/max resolution example</h4>
<p id="shortdesc">Show/hide layers depending on current view resolution.</p>
<div id="docs">
<p>
Zoom in twice: the MapBox layer should hide whereas the OSM layer should be shown.
</p>
<p>
If you continue to zoom in, you'll see the OSM layer also disappear.
</p>
<p>
The rendering of the layers are here controlled using minResolution and maxResolution options.
</p>
<p>See the <a href="min-max-resolution.js" target="_blank">min-max-resolution.js source</a> to see how this is done.</p>
</div>
<div id="tags">minResolution, maxResolution, resolution</div>
</div>
</div>
</div>
<script src="loader.js?id=min-max-resolution" type="text/javascript"></script>
<script src="../resources/social-links.js" type="text/javascript"></script>
</body>
</html>
+33
View File
@@ -0,0 +1,33 @@
goog.require('ol.Map');
goog.require('ol.View2D');
goog.require('ol.layer.Tile');
goog.require('ol.source.OSM');
goog.require('ol.source.TileJSON');
/**
* Create the map.
*/
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
minResolution: 200,
maxResolution: 2000
}),
new ol.layer.Tile({
source: new ol.source.TileJSON({
url: 'http://api.tiles.mapbox.com/v3/' +
'mapbox.natural-earth-hypso-bathy.jsonp',
crossOrigin: 'anonymous'
}),
minResolution: 2000,
maxResolution: 20000
})
],
target: 'map',
view: new ol.View2D({
center: [653600, 5723680],
zoom: 5
})
});
+20
View File
@@ -337,6 +337,10 @@
* @property {number|undefined} opacity Opacity. * @property {number|undefined} opacity Opacity.
* @property {number|undefined} saturation Saturation. * @property {number|undefined} saturation Saturation.
* @property {boolean|undefined} visible Visibility. * @property {boolean|undefined} visible Visibility.
* @property {number|undefined} minResolution The minimum resolution
* (inclusive) at which this layer will be visible.
* @property {number|undefined} maxResolution The maximum resolution
* (exclusive) below which this layer will be visible.
*/ */
/** /**
@@ -348,6 +352,10 @@
* @property {number|undefined} saturation Saturation. * @property {number|undefined} saturation Saturation.
* @property {ol.source.Source} source Source for this layer. * @property {ol.source.Source} source Source for this layer.
* @property {boolean|undefined} visible Visibility. Default is true (visible). * @property {boolean|undefined} visible Visibility. Default is true (visible).
* @property {number|undefined} minResolution The minimum resolution
* (inclusive) at which this layer will be visible.
* @property {number|undefined} maxResolution The maximum resolution
* (exclusive) below which this layer will be visible.
*/ */
/** /**
@@ -358,6 +366,10 @@
* @property {number|undefined} opacity Opacity. * @property {number|undefined} opacity Opacity.
* @property {number|undefined} saturation Saturation. * @property {number|undefined} saturation Saturation.
* @property {boolean|undefined} visible Visibility. * @property {boolean|undefined} visible Visibility.
* @property {number|undefined} minResolution The minimum resolution
* (inclusive) at which this layer will be visible.
* @property {number|undefined} maxResolution The maximum resolution
* (exclusive) below which this layer will be visible.
* @property {Array.<ol.layer.Base>|ol.Collection|undefined} layers Child layers. * @property {Array.<ol.layer.Base>|ol.Collection|undefined} layers Child layers.
*/ */
@@ -371,6 +383,10 @@
* @property {number|undefined} saturation Saturation. * @property {number|undefined} saturation Saturation.
* @property {ol.source.Source} source Source for this layer. * @property {ol.source.Source} source Source for this layer.
* @property {boolean|undefined} visible Visibility. Default is true (visible). * @property {boolean|undefined} visible Visibility. Default is true (visible).
* @property {number|undefined} minResolution The minimum resolution
* (inclusive) at which this layer will be visible.
* @property {number|undefined} maxResolution The maximum resolution
* (exclusive) below which this layer will be visible.
*/ */
/** /**
@@ -383,6 +399,10 @@
* @property {ol.source.Source} source Source for this layer. * @property {ol.source.Source} source Source for this layer.
* @property {ol.style.Style|undefined} style Style. * @property {ol.style.Style|undefined} style Style.
* @property {boolean|undefined} visible Visibility. Default is true (visible). * @property {boolean|undefined} visible Visibility. Default is true (visible).
* @property {number|undefined} minResolution The minimum resolution
* (inclusive) at which this layer will be visible.
* @property {number|undefined} maxResolution The maximum resolution
* (exclusive) below which this layer will be visible.
*/ */
/** /**
+69 -3
View File
@@ -18,7 +18,9 @@ ol.layer.LayerProperty = {
HUE: 'hue', HUE: 'hue',
OPACITY: 'opacity', OPACITY: 'opacity',
SATURATION: 'saturation', SATURATION: 'saturation',
VISIBLE: 'visible' VISIBLE: 'visible',
MAX_RESOLUTION: 'maxResolution',
MIN_RESOLUTION: 'minResolution'
}; };
@@ -29,7 +31,9 @@ ol.layer.LayerProperty = {
* opacity: number, * opacity: number,
* ready: boolean, * ready: boolean,
* saturation: number, * saturation: number,
* visible: boolean}} * visible: boolean,
* maxResolution: number,
* minResolution: number}}
*/ */
ol.layer.LayerState; ol.layer.LayerState;
@@ -58,6 +62,12 @@ ol.layer.Base = function(options) {
values.saturation = goog.isDef(values.saturation) ? values.saturation : 1; values.saturation = goog.isDef(values.saturation) ? values.saturation : 1;
/** @type {boolean} */ /** @type {boolean} */
values.visible = goog.isDef(values.visible) ? values.visible : true; values.visible = goog.isDef(values.visible) ? values.visible : true;
/** @type {number} */
values.maxResolution = goog.isDef(values.maxResolution) ?
values.maxResolution : Infinity;
/** @type {number} */
values.minResolution = goog.isDef(values.minResolution) ?
values.minResolution : 0;
this.setValues(values); this.setValues(values);
@@ -67,6 +77,8 @@ ol.layer.Base = function(options) {
ol.Object.getChangeEventType(ol.layer.LayerProperty.HUE), ol.Object.getChangeEventType(ol.layer.LayerProperty.HUE),
ol.Object.getChangeEventType(ol.layer.LayerProperty.OPACITY), ol.Object.getChangeEventType(ol.layer.LayerProperty.OPACITY),
ol.Object.getChangeEventType(ol.layer.LayerProperty.SATURATION), ol.Object.getChangeEventType(ol.layer.LayerProperty.SATURATION),
ol.Object.getChangeEventType(ol.layer.LayerProperty.MAX_RESOLUTION),
ol.Object.getChangeEventType(ol.layer.LayerProperty.MIN_RESOLUTION),
goog.events.EventType.LOAD goog.events.EventType.LOAD
], ],
this.handleLayerChange, false, this); this.handleLayerChange, false, this);
@@ -134,6 +146,8 @@ ol.layer.Base.prototype.getLayerState = function() {
var ready = this.isReady(); var ready = this.isReady();
var saturation = this.getSaturation(); var saturation = this.getSaturation();
var visible = this.getVisible(); var visible = this.getVisible();
var maxResolution = this.getMaxResolution();
var minResolution = this.getMinResolution();
return { return {
brightness: goog.isDef(brightness) ? goog.math.clamp(brightness, -1, 1) : 0, brightness: goog.isDef(brightness) ? goog.math.clamp(brightness, -1, 1) : 0,
contrast: goog.isDef(contrast) ? Math.max(contrast, 0) : 1, contrast: goog.isDef(contrast) ? Math.max(contrast, 0) : 1,
@@ -141,7 +155,9 @@ ol.layer.Base.prototype.getLayerState = function() {
opacity: goog.isDef(opacity) ? goog.math.clamp(opacity, 0, 1) : 1, opacity: goog.isDef(opacity) ? goog.math.clamp(opacity, 0, 1) : 1,
ready: ready, ready: ready,
saturation: goog.isDef(saturation) ? Math.max(saturation, 0) : 1, saturation: goog.isDef(saturation) ? Math.max(saturation, 0) : 1,
visible: goog.isDef(visible) ? !!visible : true visible: goog.isDef(visible) ? !!visible : true,
maxResolution: goog.isDef(maxResolution) ? maxResolution : Infinity,
minResolution: goog.isDef(minResolution) ? Math.max(minResolution, 0) : 0
}; };
}; };
@@ -167,6 +183,32 @@ ol.layer.Base.prototype.getLayersArray = goog.abstractMethod;
ol.layer.Base.prototype.getLayerStatesArray = goog.abstractMethod; ol.layer.Base.prototype.getLayerStatesArray = goog.abstractMethod;
/**
* @return {number} MaxResolution.
*/
ol.layer.Base.prototype.getMaxResolution = function() {
return /** @type {number} */ (
this.get(ol.layer.LayerProperty.MAX_RESOLUTION));
};
goog.exportProperty(
ol.layer.Base.prototype,
'getMaxResolution',
ol.layer.Base.prototype.getMaxResolution);
/**
* @return {number} MinResolution.
*/
ol.layer.Base.prototype.getMinResolution = function() {
return /** @type {number} */ (
this.get(ol.layer.LayerProperty.MIN_RESOLUTION));
};
goog.exportProperty(
ol.layer.Base.prototype,
'getMinResolution',
ol.layer.Base.prototype.getMinResolution);
/** /**
* @return {number} Opacity. * @return {number} Opacity.
*/ */
@@ -288,6 +330,30 @@ goog.exportProperty(
ol.layer.Base.prototype.setHue); ol.layer.Base.prototype.setHue);
/**
* @param {number} maxResolution MaxResolution.
*/
ol.layer.Base.prototype.setMaxResolution = function(maxResolution) {
this.set(ol.layer.LayerProperty.MAX_RESOLUTION, maxResolution);
};
goog.exportProperty(
ol.layer.Base.prototype,
'setMaxResolution',
ol.layer.Base.prototype.setMaxResolution);
/**
* @param {number} minResolution MinResolution.
*/
ol.layer.Base.prototype.setMinResolution = function(minResolution) {
this.set(ol.layer.LayerProperty.MIN_RESOLUTION, minResolution);
};
goog.exportProperty(
ol.layer.Base.prototype,
'setMinResolution',
ol.layer.Base.prototype.setMinResolution);
/** /**
* @param {number} opacity Opacity. * @param {number} opacity Opacity.
*/ */
+4
View File
@@ -206,6 +206,10 @@ ol.layer.Group.prototype.getLayerStatesArray = function(opt_obj) {
layerState.opacity *= ownLayerState.opacity; layerState.opacity *= ownLayerState.opacity;
layerState.saturation *= ownLayerState.saturation; layerState.saturation *= ownLayerState.saturation;
layerState.visible = layerState.visible && ownLayerState.visible; layerState.visible = layerState.visible && ownLayerState.visible;
layerState.maxResolution = Math.min(
layerState.maxResolution, ownLayerState.maxResolution);
layerState.minResolution = Math.max(
layerState.minResolution, ownLayerState.minResolution);
} }
return obj; return obj;
+4 -1
View File
@@ -114,13 +114,16 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
var layerStates = frameState.layerStates; var layerStates = frameState.layerStates;
var layersArray = frameState.layersArray; var layersArray = frameState.layersArray;
var viewResolution = frameState.view2DState.resolution;
var i, ii, image, layer, layerRenderer, layerState, transform; var i, ii, image, layer, layerRenderer, layerState, transform;
for (i = 0, ii = layersArray.length; i < ii; ++i) { for (i = 0, ii = layersArray.length; i < ii; ++i) {
layer = layersArray[i]; layer = layersArray[i];
layerRenderer = this.getLayerRenderer(layer); layerRenderer = this.getLayerRenderer(layer);
layerState = layerStates[goog.getUid(layer)]; layerState = layerStates[goog.getUid(layer)];
if (!layerState.visible || !layerState.ready) { if (!layerState.visible || !layerState.ready ||
viewResolution >= layerState.maxResolution ||
viewResolution < layerState.minResolution) {
continue; continue;
} }
layerRenderer.renderFrame(frameState, layerState); layerRenderer.renderFrame(frameState, layerState);
+7 -3
View File
@@ -551,12 +551,15 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
++this.textureCacheFrameMarkerCount_; ++this.textureCacheFrameMarkerCount_;
var layersArray = frameState.layersArray; var layersArray = frameState.layersArray;
var viewResolution = frameState.view2DState.resolution;
var i, ii, layer, layerRenderer, layerState; var i, ii, layer, layerRenderer, layerState;
for (i = 0, ii = layersArray.length; i < ii; ++i) { for (i = 0, ii = layersArray.length; i < ii; ++i) {
layer = layersArray[i]; layer = layersArray[i];
layerRenderer = this.getLayerRenderer(layer); layerRenderer = this.getLayerRenderer(layer);
layerState = frameState.layerStates[goog.getUid(layer)]; layerState = frameState.layerStates[goog.getUid(layer)];
if (layerState.visible && layerState.ready) { if (layerState.visible && layerState.ready &&
viewResolution < layerState.maxResolution &&
viewResolution >= layerState.minResolution) {
layerRenderer.renderFrame(frameState, layerState); layerRenderer.renderFrame(frameState, layerState);
} }
} }
@@ -580,10 +583,11 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
var currentProgram = null; var currentProgram = null;
var locations; var locations;
for (i = 0, ii = layersArray.length; i < ii; ++i) { for (i = 0, ii = layersArray.length; i < ii; ++i) {
layer = layersArray[i]; layer = layersArray[i];
layerState = frameState.layerStates[goog.getUid(layer)]; layerState = frameState.layerStates[goog.getUid(layer)];
if (!layerState.visible || !layerState.ready) { if (!layerState.visible || !layerState.ready ||
viewResolution >= layerState.maxResolution ||
viewResolution < layerState.minResolution) {
continue; continue;
} }
var useColor = var useColor =
+21 -5
View File
@@ -54,7 +54,9 @@ describe('ol.layer.Layer', function() {
opacity: 1, opacity: 1,
saturation: 1, saturation: 1,
visible: true, visible: true,
ready: true ready: true,
maxResolution: Infinity,
minResolution: 0
}); });
}); });
@@ -73,6 +75,8 @@ describe('ol.layer.Layer', function() {
opacity: 0.5, opacity: 0.5,
saturation: 5, saturation: 5,
visible: false, visible: false,
maxResolution: 500,
minResolution: 0.25,
foo: 42 foo: 42
}); });
@@ -82,6 +86,8 @@ describe('ol.layer.Layer', function() {
expect(layer.getOpacity()).to.be(0.5); expect(layer.getOpacity()).to.be(0.5);
expect(layer.getSaturation()).to.be(5); expect(layer.getSaturation()).to.be(5);
expect(layer.getVisible()).to.be(false); expect(layer.getVisible()).to.be(false);
expect(layer.getMaxResolution()).to.be(500);
expect(layer.getMinResolution()).to.be(0.25);
expect(layer.get('foo')).to.be(42); expect(layer.get('foo')).to.be(42);
expect(layer.getLayerState()).to.eql({ expect(layer.getLayerState()).to.eql({
brightness: 0.5, brightness: 0.5,
@@ -90,7 +96,9 @@ describe('ol.layer.Layer', function() {
opacity: 0.5, opacity: 0.5,
saturation: 5, saturation: 5,
visible: false, visible: false,
ready: true ready: true,
maxResolution: 500,
minResolution: 0.25
}); });
goog.dispose(layer); goog.dispose(layer);
@@ -121,6 +129,8 @@ describe('ol.layer.Layer', function() {
layer.setOpacity(0.3); layer.setOpacity(0.3);
layer.setSaturation(0.3); layer.setSaturation(0.3);
layer.setVisible(false); layer.setVisible(false);
layer.setMaxResolution(500);
layer.setMinResolution(0.25);
expect(layer.getLayerState()).to.eql({ expect(layer.getLayerState()).to.eql({
brightness: -0.7, brightness: -0.7,
contrast: 0.3, contrast: 0.3,
@@ -128,7 +138,9 @@ describe('ol.layer.Layer', function() {
opacity: 0.3, opacity: 0.3,
saturation: 0.3, saturation: 0.3,
visible: false, visible: false,
ready: true ready: true,
maxResolution: 500,
minResolution: 0.25
}); });
}); });
@@ -146,7 +158,9 @@ describe('ol.layer.Layer', function() {
opacity: 0, opacity: 0,
saturation: 0, saturation: 0,
visible: false, visible: false,
ready: true ready: true,
maxResolution: Infinity,
minResolution: 0
}); });
layer.setBrightness(-3); layer.setBrightness(-3);
@@ -162,7 +176,9 @@ describe('ol.layer.Layer', function() {
opacity: 1, opacity: 1,
saturation: 42, saturation: 42,
visible: true, visible: true,
ready: true ready: true,
maxResolution: Infinity,
minResolution: 0
}); });
}); });
+31 -9
View File
@@ -50,7 +50,9 @@ describe('ol.layer.Group', function() {
opacity: 1, opacity: 1,
saturation: 1, saturation: 1,
visible: true, visible: true,
ready: true ready: true,
maxResolution: Infinity,
minResolution: 0
}); });
}); });
@@ -76,7 +78,9 @@ describe('ol.layer.Group', function() {
hue: 180, hue: 180,
opacity: 0.5, opacity: 0.5,
saturation: 5, saturation: 5,
visible: false visible: false,
maxResolution: 500,
minResolution: 0.25
}); });
expect(layerGroup.getBrightness()).to.be(0.5); expect(layerGroup.getBrightness()).to.be(0.5);
@@ -85,6 +89,8 @@ describe('ol.layer.Group', function() {
expect(layerGroup.getOpacity()).to.be(0.5); expect(layerGroup.getOpacity()).to.be(0.5);
expect(layerGroup.getSaturation()).to.be(5); expect(layerGroup.getSaturation()).to.be(5);
expect(layerGroup.getVisible()).to.be(false); expect(layerGroup.getVisible()).to.be(false);
expect(layerGroup.getMaxResolution()).to.be(500);
expect(layerGroup.getMinResolution()).to.be(0.25);
expect(layerGroup.getLayerState()).to.eql({ expect(layerGroup.getLayerState()).to.eql({
brightness: 0.5, brightness: 0.5,
contrast: 10, contrast: 10,
@@ -92,7 +98,9 @@ describe('ol.layer.Group', function() {
opacity: 0.5, opacity: 0.5,
saturation: 5, saturation: 5,
visible: false, visible: false,
ready: true ready: true,
maxResolution: 500,
minResolution: 0.25
}); });
expect(layerGroup.getLayers()).to.be.a(ol.Collection); expect(layerGroup.getLayers()).to.be.a(ol.Collection);
expect(layerGroup.getLayers().getLength()).to.be(1); expect(layerGroup.getLayers().getLength()).to.be(1);
@@ -123,6 +131,8 @@ describe('ol.layer.Group', function() {
layerGroup.setOpacity(0.3); layerGroup.setOpacity(0.3);
layerGroup.setSaturation(0.3); layerGroup.setSaturation(0.3);
layerGroup.setVisible(false); layerGroup.setVisible(false);
layerGroup.setMaxResolution(500);
layerGroup.setMinResolution(0.25);
expect(layerGroup.getLayerState()).to.eql({ expect(layerGroup.getLayerState()).to.eql({
brightness: -0.7, brightness: -0.7,
contrast: 0.3, contrast: 0.3,
@@ -130,7 +140,9 @@ describe('ol.layer.Group', function() {
opacity: 0.3, opacity: 0.3,
saturation: 0.3, saturation: 0.3,
visible: false, visible: false,
ready: true ready: true,
maxResolution: 500,
minResolution: 0.25
}); });
}); });
@@ -148,7 +160,9 @@ describe('ol.layer.Group', function() {
opacity: 0, opacity: 0,
saturation: 0, saturation: 0,
visible: false, visible: false,
ready: true ready: true,
maxResolution: Infinity,
minResolution: 0
}); });
layerGroup.setBrightness(-3); layerGroup.setBrightness(-3);
@@ -164,7 +178,9 @@ describe('ol.layer.Group', function() {
opacity: 1, opacity: 1,
saturation: 42, saturation: 42,
visible: true, visible: true,
ready: true ready: true,
maxResolution: Infinity,
minResolution: 0
}); });
}); });
@@ -231,7 +247,9 @@ describe('ol.layer.Group', function() {
hue: 180, hue: 180,
opacity: 0.5, opacity: 0.5,
saturation: 5, saturation: 5,
visible: false visible: false,
maxResolution: 500,
minResolution: 0.25
}); });
it('does not transform layerStates by default', function() { it('does not transform layerStates by default', function() {
@@ -263,7 +281,9 @@ describe('ol.layer.Group', function() {
hue: 180, hue: 180,
opacity: 0.5, opacity: 0.5,
saturation: 5, saturation: 5,
visible: false visible: false,
maxResolution: 150,
minResolution: 0.2
}); });
obj = layerGroup.getLayerStatesArray(); obj = layerGroup.getLayerStatesArray();
@@ -277,7 +297,9 @@ describe('ol.layer.Group', function() {
opacity: 0.25, opacity: 0.25,
saturation: 25, saturation: 25,
visible: false, visible: false,
ready: true ready: true,
maxResolution: 150,
minResolution: 0.25
}); });
goog.dispose(layerGroup); goog.dispose(layerGroup);