Add setStyle and getStyle to ol.Feature

As with vector layers and feature overlays, feature style can be set by calling
setStyle.  Calling getStyle returns what was passed to setStyle.  Internally, we call getStyleFunction.
This commit is contained in:
Tim Schaub
2014-02-12 16:49:53 -07:00
parent 477c369f6c
commit f4585331f2
5 changed files with 172 additions and 20 deletions

View File

@@ -18,19 +18,17 @@ var iconFeature = new ol.Feature({
rainfall: 500
});
var styleArray = [new ol.style.Style({
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'data/icon.png'
}))
})];
iconFeature.setStyleFunction(function(resolution) {
return styleArray;
});
iconFeature.setStyle(iconStyle);
var vectorSource = new ol.source.Vector({
features: [iconFeature]
});

View File

@@ -3,3 +3,5 @@
@exportProperty ol.Feature.prototype.setGeometryName
@exportProperty ol.Feature.prototype.getId
@exportProperty ol.Feature.prototype.setId
@exportProperty ol.Feature.prototype.getStyle
@exportProperty ol.Feature.prototype.setStyle

View File

@@ -34,6 +34,14 @@ ol.Feature = function(opt_geometryOrValues) {
*/
this.geometryName_ = 'geometry';
/**
* User provided style.
* @private
* @type {ol.style.Style|Array.<ol.style.Style>|
* ol.feature.FeatureStyleFunction}
*/
this.style_ = null;
/**
* @private
* @type {ol.feature.FeatureStyleFunction|undefined}
@@ -98,6 +106,16 @@ ol.Feature.prototype.getGeometryName = function() {
};
/**
* @return {ol.style.Style|Array.<ol.style.Style>|
* ol.feature.FeatureStyleFunction} User provided style.
* @todo stability experimental
*/
ol.Feature.prototype.getStyle = function() {
return this.style_;
};
/**
* @return {ol.feature.FeatureStyleFunction|undefined} Style function.
* @todo stability experimental
@@ -146,12 +164,13 @@ goog.exportProperty(
/**
* @param {ol.feature.FeatureStyleFunction|undefined} styleFunction Style
* function.
* @param {ol.style.Style|Array.<ol.style.Style>|
* ol.feature.FeatureStyleFunction} style Feature style.
* @todo stability experimental
*/
ol.Feature.prototype.setStyleFunction = function(styleFunction) {
this.styleFunction_ = styleFunction;
ol.Feature.prototype.setStyle = function(style) {
this.style_ = style;
this.styleFunction_ = ol.feature.createFeatureStyleFunction(style);
this.dispatchChangeEvent();
};
@@ -219,6 +238,42 @@ ol.feature.defaultStyleFunction = function(feature, resolution) {
};
/**
* Convert the provided object into a feature style function. Functions passed
* through unchanged. Arrays of ol.style.Style or single style objects wrapped
* in a new feature style function.
* @param {ol.feature.FeatureStyleFunction|Array.<ol.style.Style>|
* ol.style.Style} obj A feature style function, a single style, or an array
* of styles.
* @return {ol.feature.FeatureStyleFunction} A style function.
*/
ol.feature.createFeatureStyleFunction = function(obj) {
/**
* @type {ol.feature.FeatureStyleFunction}
*/
var styleFunction;
if (goog.isFunction(obj)) {
styleFunction = /** @type {ol.feature.FeatureStyleFunction} */ (obj);
} else {
/**
* @type {Array.<ol.style.Style>}
*/
var styles;
if (goog.isArray(obj)) {
styles = obj;
} else {
goog.asserts.assertInstanceof(obj, ol.style.Style);
styles = [obj];
}
styleFunction = function(resolution) {
return styles;
};
}
return styleFunction;
};
/**
* Convert the provided object into a style function. Functions passed through
* unchanged. Arrays of ol.style.Style or single style objects wrapped in a

View File

@@ -1448,7 +1448,7 @@ ol.format.KML.prototype.readPlacemark_ = function(node, objectStack) {
} else {
featureStyleFunction = ol.format.KML.makeFeatureStyleFunction_(style);
}
feature.setStyleFunction(featureStyleFunction);
feature.setStyle(featureStyleFunction);
return feature;
};

View File

@@ -209,7 +209,7 @@ describe('ol.Feature', function() {
describe('#getStyleFunction()', function() {
var styleFunction = function(feature, resolution) {
var styleFunction = function(resolution) {
return null;
};
@@ -218,9 +218,9 @@ describe('ol.Feature', function() {
expect(feature.getStyleFunction()).to.be(undefined);
});
it('returns the function passed to setStyleFunction', function() {
it('returns the function passed to setStyle', function() {
var feature = new ol.Feature();
feature.setStyleFunction(styleFunction);
feature.setStyle(styleFunction);
expect(feature.getStyleFunction()).to.be(styleFunction);
});
@@ -230,21 +230,40 @@ describe('ol.Feature', function() {
expect(feature.getStyleFunction()).to.be(undefined);
});
// TODO: also assert that 'styleFunction' passed to the constructor is
// not confused with the internal 'styleFunction_'.
// See https://github.com/openlayers/ol3/issues/1672
it('does not get confused with "styleFunction" option', function() {
var feature = new ol.Feature({
styleFunction: 'foo'
});
expect(feature.getStyleFunction()).to.be(undefined);
});
});
describe('#setStyleFunction()', function() {
describe('#setStyle()', function() {
var style = new ol.style.Style();
var styleFunction = function(feature, resolution) {
return null;
};
it('sets the style function', function() {
it('accepts a single style', function() {
var feature = new ol.Feature();
feature.setStyleFunction(styleFunction);
feature.setStyle(style);
var func = feature.getStyleFunction();
expect(func()).to.eql([style]);
});
it('accepts an array of styles', function() {
var feature = new ol.Feature();
feature.setStyle([style]);
var func = feature.getStyleFunction();
expect(func()).to.eql([style]);
});
it('accepts a style function', function() {
var feature = new ol.Feature();
feature.setStyle(styleFunction);
expect(feature.getStyleFunction()).to.be(styleFunction);
});
@@ -253,11 +272,60 @@ describe('ol.Feature', function() {
feature.on('change', function() {
done();
});
feature.setStyleFunction(styleFunction);
feature.setStyle(style);
});
});
describe('#getStyle()', function() {
var style = new ol.style.Style();
var styleFunction = function(resolution) {
return null;
};
it('returns what is passed to setStyle', function() {
var feature = new ol.Feature();
expect(feature.getStyle()).to.be(null);
feature.setStyle(style);
expect(feature.getStyle()).to.be(style);
feature.setStyle([style]);
expect(feature.getStyle()).to.eql([style]);
feature.setStyle(styleFunction);
expect(feature.getStyle()).to.be(styleFunction);
});
/**
* We should be able to make the assertion below, but the constructor
* calls setValues which calls setFoo when provided with 'foo'. This
* is different behavior than calling set('foo', 'bar').
* See https://github.com/openlayers/ol3/issues/1672
it('does not get confused with "style" option to constructor', function() {
var feature = new ol.Feature({
style: 'foo'
});
expect(feature.getStyle()).to.be(null);
});
*/
it('does not get confused with user set "style" property', function() {
var feature = new ol.Feature();
feature.set('style', 'foo');
expect(feature.getStyle()).to.be(null);
});
});
});
@@ -291,6 +359,35 @@ describe('ol.feature.createStyleFunction()', function() {
});
describe('ol.feature.createFeatureStyleFunction()', function() {
var style = new ol.style.Style();
it('creates a feature style function from a single style', function() {
var styleFunction = ol.feature.createFeatureStyleFunction(style);
expect(styleFunction()).to.eql([style]);
});
it('creates a feature style function from an array of styles', function() {
var styleFunction = ol.feature.createFeatureStyleFunction([style]);
expect(styleFunction()).to.eql([style]);
});
it('passes through a function', function() {
var original = function() {
return [style];
};
var styleFunction = ol.feature.createFeatureStyleFunction(original);
expect(styleFunction).to.be(original);
});
it('throws on (some) unexpected input', function() {
expect(function() {
ol.feature.createFeatureStyleFunction({bogus: 'input'});
}).to.throwException();
});
});
goog.require('goog.events');
goog.require('goog.object');