diff --git a/examples/vector-layer.js b/examples/vector-layer.js
index 2fd564439c..d830b2dc6a 100644
--- a/examples/vector-layer.js
+++ b/examples/vector-layer.js
@@ -18,11 +18,6 @@ var raster = new ol.layer.Tile({
source: new ol.source.MapQuestOpenAerial()
});
-// TODO: discuss scale dependent rules
-ol.expr.register('resolution', function() {
- return map.getView().getView2D().getResolution();
-});
-
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
parser: new ol.parser.GeoJSON(),
@@ -42,7 +37,7 @@ var vector = new ol.layer.Vector({
]
}),
new ol.style.Rule({
- filter: 'resolution() < 5000',
+ maxResolution: 5000,
symbolizers: [
new ol.style.Text({
color: '#000000',
diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc
index 81e8d620d3..534f84670d 100644
--- a/src/objectliterals.jsdoc
+++ b/src/objectliterals.jsdoc
@@ -700,6 +700,12 @@
/**
* @typedef {Object} ol.style.RuleOptions
* @property {ol.expr.Expression|string|undefined} filter Filter.
+ * @property {number|undefined} maxResolution Optional maximum resolution. If
+ * a value is provided, the rule will apply at resolutions less than
+ * this value.
+ * @property {number|undefined} minResolution Optional minimum resolution. If
+ * a value is provided, the rule will apply at resolutions greater than or
+ * equal to this value.
* @property {Array.
|undefined} symbolizers Symbolizers.
*/
diff --git a/src/ol/layer/vectorlayer.js b/src/ol/layer/vectorlayer.js
index 3cdd40814b..f88beaf076 100644
--- a/src/ol/layer/vectorlayer.js
+++ b/src/ol/layer/vectorlayer.js
@@ -425,12 +425,13 @@ ol.layer.Vector.prototype.getPolygonVertices = function() {
/**
* @param {Object.} features Features.
+ * @param {number} resolution Map resolution.
* @return {Array.} symbolizers for features. Each array in this array
* contains 3 items: an array of features, the symbolizer literal, and
* an array with optional additional data for each feature.
*/
ol.layer.Vector.prototype.groupFeaturesBySymbolizerLiteral =
- function(features) {
+ function(features, resolution) {
var uniqueLiterals = {},
featuresBySymbolizer = [],
style = this.style_,
@@ -447,7 +448,7 @@ ol.layer.Vector.prototype.groupFeaturesBySymbolizerLiteral =
if (goog.isNull(style)) {
style = ol.style.getDefault();
}
- literals = style.createLiterals(feature);
+ literals = style.createLiterals(feature, resolution);
}
numLiterals = literals.length;
for (j = 0; j < numLiterals; ++j) {
diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js
index f8aa6fd19f..28c7f1997f 100644
--- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js
+++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js
@@ -509,7 +509,8 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
renderByGeometryType:
for (type in featuresToRender) {
- groups = layer.groupFeaturesBySymbolizerLiteral(featuresToRender[type]);
+ groups = layer.groupFeaturesBySymbolizerLiteral(
+ featuresToRender[type], tileResolution);
numGroups = groups.length;
for (j = 0; j < numGroups; ++j) {
group = groups[j];
diff --git a/src/ol/style/rule.js b/src/ol/style/rule.js
index 97ecb5b84c..4d94c669eb 100644
--- a/src/ol/style/rule.js
+++ b/src/ol/style/rule.js
@@ -39,16 +39,35 @@ ol.style.Rule = function(options) {
this.symbolizers_ = goog.isDef(options.symbolizers) ?
options.symbolizers : [];
+ /**
+ * @type {number}
+ * @private
+ */
+ this.minResolution_ = goog.isDef(options.minResolution) ?
+ options.minResolution : 0;
+
+ /**
+ * @type {number}
+ * @private
+ */
+ this.maxResolution_ = goog.isDef(options.maxResolution) ?
+ options.maxResolution : Infinity;
+
};
/**
* @param {ol.Feature} feature Feature.
+ * @param {number} resolution Map resolution.
* @return {boolean} Does the rule apply to the feature?
*/
-ol.style.Rule.prototype.applies = function(feature) {
- return goog.isNull(this.filter_) ?
- true : !!ol.expr.evaluateFeature(this.filter_, feature);
+ol.style.Rule.prototype.applies = function(feature, resolution) {
+ var applies = resolution >= this.minResolution_ &&
+ resolution < this.maxResolution_;
+ if (applies && !goog.isNull(this.filter_)) {
+ applies = !!ol.expr.evaluateFeature(this.filter_, feature);
+ }
+ return applies;
};
diff --git a/src/ol/style/style.js b/src/ol/style/style.js
index ced0b0c826..f4b832b188 100644
--- a/src/ol/style/style.js
+++ b/src/ol/style/style.js
@@ -45,17 +45,18 @@ ol.style.Style = function(options) {
/**
* Create an array of symbolizer literals for a feature.
* @param {ol.Feature} feature Feature.
+ * @param {number} resolution Map resolution.
* @return {Array.} Symbolizer literals for the
* feature.
*/
-ol.style.Style.prototype.createLiterals = function(feature) {
+ol.style.Style.prototype.createLiterals = function(feature, resolution) {
var rules = this.rules_,
symbolizers = [],
applies = false,
rule;
for (var i = 0, ii = rules.length; i < ii; ++i) {
rule = rules[i];
- if (rule.applies(feature)) {
+ if (rule.applies(feature, resolution)) {
applies = true;
symbolizers.push.apply(symbolizers, rule.getSymbolizers());
}
diff --git a/test/spec/ol/layer/vectorlayer.test.js b/test/spec/ol/layer/vectorlayer.test.js
index 099452a8ce..d3c0ee3494 100644
--- a/test/spec/ol/layer/vectorlayer.test.js
+++ b/test/spec/ol/layer/vectorlayer.test.js
@@ -134,7 +134,7 @@ describe('ol.layer.Vector', function() {
})
];
- var groups = layer.groupFeaturesBySymbolizerLiteral(features);
+ var groups = layer.groupFeaturesBySymbolizerLiteral(features, 1);
expect(groups.length).to.be(2);
expect(groups[0][0].length).to.be(1);
expect(groups[0][1].color).to.be('#BADA55');
@@ -164,7 +164,7 @@ describe('ol.layer.Vector', function() {
anotherFeatureWithSymbolizers.setSymbolizers([anotherSymbolizer]);
features.push(featureWithSymbolizers, anotherFeatureWithSymbolizers);
- var groups = layer.groupFeaturesBySymbolizerLiteral(features);
+ var groups = layer.groupFeaturesBySymbolizerLiteral(features, 1);
expect(groups).to.have.length(3);
expect(groups[2][0].length).to.be(2);
expect(groups[2][1].width).to.be(3);
diff --git a/test/spec/ol/style/rule.test.js b/test/spec/ol/style/rule.test.js
index c2a2e2d821..ff5d815773 100644
--- a/test/spec/ol/style/rule.test.js
+++ b/test/spec/ol/style/rule.test.js
@@ -2,28 +2,152 @@ goog.provide('ol.test.style.Rule');
describe('ol.style.Rule', function() {
+ describe('constructor', function() {
+
+ it('accepts a filter option', function() {
+ var rule = new ol.style.Rule({
+ filter: 'foo == "bar"'
+ });
+ expect(rule).to.be.a(ol.style.Rule);
+ });
+
+ it('accepts a minResolution option', function() {
+ var rule = new ol.style.Rule({
+ minResolution: 10
+ });
+ expect(rule).to.be.a(ol.style.Rule);
+ });
+
+ it('accepts a maxResolution option', function() {
+ var rule = new ol.style.Rule({
+ maxResolution: 100
+ });
+ expect(rule).to.be.a(ol.style.Rule);
+ });
+
+ });
+
describe('#applies()', function() {
var feature = new ol.Feature(),
rule;
it('returns true for a rule without filter', function() {
rule = new ol.style.Rule({});
- expect(rule.applies(feature)).to.be(true);
+ expect(rule.applies(feature, 1)).to.be(true);
});
- it('returns false when the rule does not apply', function() {
+ it('returns false when the filter evaluates to false', function() {
rule = new ol.style.Rule({
filter: new ol.expr.Literal(false)
});
- expect(rule.applies(feature)).to.be(false);
+ expect(rule.applies(feature, 1)).to.be(false);
});
- it('returns true when the rule applies', function() {
+ it('returns true when the filter evaluates to true', function() {
rule = new ol.style.Rule({
filter: new ol.expr.Literal(true)
});
- expect(rule.applies(feature)).to.be(true);
+ expect(rule.applies(feature, 1)).to.be(true);
});
+
+ it('returns false when the resolution is less than min', function() {
+ rule = new ol.style.Rule({
+ minResolution: 10
+ });
+ expect(rule.applies(feature, 9)).to.be(false);
+ });
+
+ it('returns true when the resolution is greater than min', function() {
+ rule = new ol.style.Rule({
+ minResolution: 10
+ });
+ expect(rule.applies(feature, 11)).to.be(true);
+ });
+
+ it('returns true when the resolution is equal to min', function() {
+ rule = new ol.style.Rule({
+ minResolution: 10
+ });
+ expect(rule.applies(feature, 10)).to.be(true);
+ });
+
+ it('returns false if filter evaluates to false (with min res)', function() {
+ rule = new ol.style.Rule({
+ filter: new ol.expr.Literal(false),
+ minResolution: 10
+ });
+ expect(rule.applies(feature, 11)).to.be(false);
+ });
+
+ it('returns true if filter evaluates to true (with min res)', function() {
+ rule = new ol.style.Rule({
+ filter: new ol.expr.Literal(true),
+ minResolution: 10
+ });
+ expect(rule.applies(feature, 11)).to.be(true);
+ });
+
+ it('returns false when the resolution is greater than max', function() {
+ rule = new ol.style.Rule({
+ maxResolution: 100
+ });
+ expect(rule.applies(feature, 101)).to.be(false);
+ });
+
+ it('returns true when the resolution is less than max', function() {
+ rule = new ol.style.Rule({
+ maxResolution: 100
+ });
+ expect(rule.applies(feature, 99)).to.be(true);
+ });
+
+ it('returns false when the resolution is equal to max', function() {
+ rule = new ol.style.Rule({
+ maxResolution: 100
+ });
+ expect(rule.applies(feature, 100)).to.be(false);
+ });
+
+ it('returns false if filter evaluates to false (with max res)', function() {
+ rule = new ol.style.Rule({
+ filter: new ol.expr.Literal(false),
+ maxResolution: 100
+ });
+ expect(rule.applies(feature, 99)).to.be(false);
+ });
+
+ it('returns true if filter evaluates to true (with max res)', function() {
+ rule = new ol.style.Rule({
+ filter: new ol.expr.Literal(true),
+ maxResolution: 100
+ });
+ expect(rule.applies(feature, 99)).to.be(true);
+ });
+
+ it('returns true if resolution is between min and max', function() {
+ rule = new ol.style.Rule({
+ minResolution: 10,
+ maxResolution: 100
+ });
+ expect(rule.applies(feature, 55)).to.be(true);
+ });
+
+ it('returns false if resolution is greater than min and max', function() {
+ rule = new ol.style.Rule({
+ minResolution: 10,
+ maxResolution: 100
+ });
+ expect(rule.applies(feature, 1000)).to.be(false);
+ });
+
+ it('returns false if resolution is less than min and max', function() {
+ rule = new ol.style.Rule({
+ minResolution: 10,
+ maxResolution: 100
+ });
+ expect(rule.applies(feature, 5)).to.be(false);
+ });
+
});
});
diff --git a/test/spec/ol/style/style.test.js b/test/spec/ol/style/style.test.js
index c5eb640828..18fdb5e8c8 100644
--- a/test/spec/ol/style/style.test.js
+++ b/test/spec/ol/style/style.test.js
@@ -57,12 +57,12 @@ describe('ol.style.Style', function() {
});
feature.set('foo', 'bar');
- var literals = style.createLiterals(feature);
+ var literals = style.createLiterals(feature, 1);
expect(literals).to.have.length(1);
expect(literals[0].fillColor).to.be('#BADA55');
feature.set('foo', 'baz');
- expect(style.createLiterals(feature)).to.have.length(0);
+ expect(style.createLiterals(feature, 1)).to.have.length(0);
});
it('uses the "else" symbolizers when no rules are provided', function() {
@@ -78,7 +78,7 @@ describe('ol.style.Style', function() {
geometry: new ol.geom.LineString([[1, 2], [3, 4]])
});
- var literals = style.createLiterals(feature);
+ var literals = style.createLiterals(feature, 1);
expect(literals).to.have.length(1);
expect(literals[0].color).to.be('#ff0000');
});
@@ -107,7 +107,7 @@ describe('ol.style.Style', function() {
geometry: new ol.geom.LineString([[1, 2], [3, 4]])
});
- var literals = style.createLiterals(feature);
+ var literals = style.createLiterals(feature, 1);
expect(literals).to.have.length(1);
expect(literals[0].color).to.be('#00ff00');
@@ -115,7 +115,7 @@ describe('ol.style.Style', function() {
name: 'match',
geometry: new ol.geom.LineString([[1, 2], [3, 4]])
});
- literals = style.createLiterals(feature);
+ literals = style.createLiterals(feature, 1);
expect(literals).to.have.length(1);
expect(literals[0].color).to.be('#ff00ff');
});
@@ -133,7 +133,7 @@ describe('ol.style.Style', function() {
it('returns an empty array for features without geometry', function() {
var feature = new ol.Feature();
- expect(style.createLiterals(feature))
+ expect(style.createLiterals(feature, 1))
.to.have.length(0);
});
@@ -141,7 +141,7 @@ describe('ol.style.Style', function() {
var feature = new ol.Feature();
feature.setGeometry(new ol.geom.Point([0, 0]));
- var literals = style.createLiterals(feature);
+ var literals = style.createLiterals(feature, 1);
expect(literals).to.have.length(1);
var literal = literals[0];
@@ -158,7 +158,7 @@ describe('ol.style.Style', function() {
var feature = new ol.Feature();
feature.setGeometry(new ol.geom.LineString([[0, 0], [1, 1]]));
- var literals = style.createLiterals(feature);
+ var literals = style.createLiterals(feature, 1);
expect(literals).to.have.length(1);
var literal = literals[0];
@@ -172,7 +172,7 @@ describe('ol.style.Style', function() {
var feature = new ol.Feature();
feature.setGeometry(new ol.geom.Polygon([[[0, 0], [1, 1], [0, 0]]]));
- var literals = style.createLiterals(feature);
+ var literals = style.createLiterals(feature, 1);
expect(literals).to.have.length(1);
var literal = literals[0];