This commit allows setting a z-index property on the layers and uses it in the canvas, WEBGL and DOM map renderers for ordering the layers before rendering. Default z-index is 0 for managed layers and 1000 for unmanaged ones. It allows always on bottom, always on top and more complex layer layouts.
538 lines
15 KiB
JavaScript
538 lines
15 KiB
JavaScript
goog.provide('ol.test.layer.LayerGroup');
|
|
|
|
describe('ol.layer.Group', function() {
|
|
|
|
describe('constructor (defaults)', function() {
|
|
|
|
var layerGroup;
|
|
|
|
beforeEach(function() {
|
|
layerGroup = new ol.layer.Group();
|
|
});
|
|
|
|
afterEach(function() {
|
|
goog.dispose(layerGroup);
|
|
});
|
|
|
|
it('creates an instance', function() {
|
|
expect(layerGroup).to.be.a(ol.layer.Group);
|
|
});
|
|
|
|
it('provides default brightness', function() {
|
|
expect(layerGroup.getBrightness()).to.be(0);
|
|
});
|
|
|
|
it('provides default contrast', function() {
|
|
expect(layerGroup.getContrast()).to.be(1);
|
|
});
|
|
|
|
it('provides default hue', function() {
|
|
expect(layerGroup.getHue()).to.be(0);
|
|
});
|
|
|
|
it('provides default opacity', function() {
|
|
expect(layerGroup.getOpacity()).to.be(1);
|
|
});
|
|
|
|
it('provides default saturation', function() {
|
|
expect(layerGroup.getSaturation()).to.be(1);
|
|
});
|
|
|
|
it('provides default visibility', function() {
|
|
expect(layerGroup.getVisible()).to.be(true);
|
|
});
|
|
|
|
it('provides default layerState', function() {
|
|
expect(layerGroup.getLayerState()).to.eql({
|
|
layer: layerGroup,
|
|
brightness: 0,
|
|
contrast: 1,
|
|
hue: 0,
|
|
opacity: 1,
|
|
saturation: 1,
|
|
visible: true,
|
|
managed: true,
|
|
sourceState: ol.source.State.READY,
|
|
extent: undefined,
|
|
zIndex: 0,
|
|
maxResolution: Infinity,
|
|
minResolution: 0
|
|
});
|
|
});
|
|
|
|
it('provides default empty layers collection', function() {
|
|
expect(layerGroup.getLayers()).to.be.a(ol.Collection);
|
|
expect(layerGroup.getLayers().getLength()).to.be(0);
|
|
});
|
|
|
|
});
|
|
|
|
describe('generic change event', function() {
|
|
|
|
var layer, group, listener;
|
|
beforeEach(function() {
|
|
layer = new ol.layer.Layer({
|
|
source: new ol.source.Source({
|
|
projection: 'EPSG:4326'
|
|
})
|
|
});
|
|
group = new ol.layer.Group({
|
|
layers: [layer]
|
|
});
|
|
listener = sinon.spy();
|
|
});
|
|
|
|
afterEach(function() {
|
|
goog.dispose(group);
|
|
goog.dispose(layer);
|
|
});
|
|
|
|
it('is dispatched by the group when layer opacity changes', function() {
|
|
group.on(goog.events.EventType.CHANGE, listener);
|
|
|
|
layer.setOpacity(0.5);
|
|
expect(listener.calledOnce).to.be(true);
|
|
});
|
|
|
|
it('is dispatched by the group when layer visibility changes', function() {
|
|
group.on(goog.events.EventType.CHANGE, listener);
|
|
|
|
layer.setVisible(false);
|
|
expect(listener.callCount).to.be(1);
|
|
|
|
layer.setVisible(true);
|
|
expect(listener.callCount).to.be(2);
|
|
});
|
|
|
|
});
|
|
|
|
describe('property change event', function() {
|
|
|
|
var layer, group, listener;
|
|
beforeEach(function() {
|
|
layer = new ol.layer.Layer({
|
|
source: new ol.source.Source({
|
|
projection: 'EPSG:4326'
|
|
})
|
|
});
|
|
group = new ol.layer.Group({
|
|
layers: [layer]
|
|
});
|
|
listener = sinon.spy();
|
|
});
|
|
|
|
afterEach(function() {
|
|
goog.dispose(group);
|
|
goog.dispose(layer);
|
|
});
|
|
|
|
it('is dispatched by the group when group opacity changes', function() {
|
|
group.on(ol.ObjectEventType.PROPERTYCHANGE, listener);
|
|
|
|
group.setOpacity(0.5);
|
|
expect(listener.calledOnce).to.be(true);
|
|
});
|
|
|
|
it('is dispatched by the group when group visibility changes', function() {
|
|
group.on(ol.ObjectEventType.PROPERTYCHANGE, listener);
|
|
|
|
group.setVisible(false);
|
|
expect(listener.callCount).to.be(1);
|
|
|
|
group.setVisible(true);
|
|
expect(listener.callCount).to.be(2);
|
|
});
|
|
|
|
});
|
|
|
|
describe('constructor (options)', function() {
|
|
|
|
it('accepts options', function() {
|
|
var layer = new ol.layer.Layer({
|
|
source: new ol.source.Source({
|
|
projection: 'EPSG:4326'
|
|
})
|
|
});
|
|
var layerGroup = new ol.layer.Group({
|
|
layers: [layer],
|
|
brightness: 0.5,
|
|
contrast: 10,
|
|
hue: 180,
|
|
opacity: 0.5,
|
|
saturation: 5,
|
|
visible: false,
|
|
zIndex: 10,
|
|
maxResolution: 500,
|
|
minResolution: 0.25
|
|
});
|
|
|
|
expect(layerGroup.getBrightness()).to.be(0.5);
|
|
expect(layerGroup.getContrast()).to.be(10);
|
|
expect(layerGroup.getHue()).to.be(180);
|
|
expect(layerGroup.getOpacity()).to.be(0.5);
|
|
expect(layerGroup.getSaturation()).to.be(5);
|
|
expect(layerGroup.getVisible()).to.be(false);
|
|
expect(layerGroup.getMaxResolution()).to.be(500);
|
|
expect(layerGroup.getMinResolution()).to.be(0.25);
|
|
expect(layerGroup.getLayerState()).to.eql({
|
|
layer: layerGroup,
|
|
brightness: 0.5,
|
|
contrast: 10,
|
|
hue: 180,
|
|
opacity: 0.5,
|
|
saturation: 5,
|
|
visible: false,
|
|
managed: true,
|
|
sourceState: ol.source.State.READY,
|
|
extent: undefined,
|
|
zIndex: 10,
|
|
maxResolution: 500,
|
|
minResolution: 0.25
|
|
});
|
|
expect(layerGroup.getLayers()).to.be.a(ol.Collection);
|
|
expect(layerGroup.getLayers().getLength()).to.be(1);
|
|
expect(layerGroup.getLayers().item(0)).to.be(layer);
|
|
|
|
goog.dispose(layer);
|
|
goog.dispose(layerGroup);
|
|
});
|
|
|
|
it('accepts an extent option', function() {
|
|
var layer = new ol.layer.Layer({
|
|
source: new ol.source.Source({
|
|
projection: 'EPSG:4326'
|
|
})
|
|
});
|
|
|
|
var groupExtent = [-10, -5, 10, 5];
|
|
var layerGroup = new ol.layer.Group({
|
|
layers: [layer],
|
|
brightness: 0.5,
|
|
contrast: 10,
|
|
hue: 180,
|
|
opacity: 0.5,
|
|
saturation: 5,
|
|
visible: false,
|
|
extent: groupExtent,
|
|
maxResolution: 500,
|
|
minResolution: 0.25
|
|
});
|
|
|
|
expect(layerGroup.getBrightness()).to.be(0.5);
|
|
expect(layerGroup.getContrast()).to.be(10);
|
|
expect(layerGroup.getHue()).to.be(180);
|
|
expect(layerGroup.getOpacity()).to.be(0.5);
|
|
expect(layerGroup.getSaturation()).to.be(5);
|
|
expect(layerGroup.getVisible()).to.be(false);
|
|
expect(layerGroup.getExtent()).to.eql(groupExtent);
|
|
expect(layerGroup.getMaxResolution()).to.be(500);
|
|
expect(layerGroup.getMinResolution()).to.be(0.25);
|
|
expect(layerGroup.getLayerState()).to.eql({
|
|
layer: layerGroup,
|
|
brightness: 0.5,
|
|
contrast: 10,
|
|
hue: 180,
|
|
opacity: 0.5,
|
|
saturation: 5,
|
|
visible: false,
|
|
managed: true,
|
|
sourceState: ol.source.State.READY,
|
|
extent: groupExtent,
|
|
zIndex: 0,
|
|
maxResolution: 500,
|
|
minResolution: 0.25
|
|
});
|
|
expect(layerGroup.getLayers()).to.be.a(ol.Collection);
|
|
expect(layerGroup.getLayers().getLength()).to.be(1);
|
|
expect(layerGroup.getLayers().item(0)).to.be(layer);
|
|
|
|
goog.dispose(layer);
|
|
goog.dispose(layerGroup);
|
|
});
|
|
});
|
|
|
|
describe('#getLayerState', function() {
|
|
|
|
var layerGroup;
|
|
|
|
beforeEach(function() {
|
|
layerGroup = new ol.layer.Group();
|
|
});
|
|
|
|
afterEach(function() {
|
|
goog.dispose(layerGroup);
|
|
});
|
|
|
|
it('returns a layerState from the properties values', function() {
|
|
layerGroup.setBrightness(-0.7);
|
|
layerGroup.setContrast(0.3);
|
|
layerGroup.setHue(-0.3);
|
|
layerGroup.setOpacity(0.3);
|
|
layerGroup.setSaturation(0.3);
|
|
layerGroup.setVisible(false);
|
|
layerGroup.setZIndex(10);
|
|
var groupExtent = [-100, 50, 100, 50];
|
|
layerGroup.setExtent(groupExtent);
|
|
layerGroup.setMaxResolution(500);
|
|
layerGroup.setMinResolution(0.25);
|
|
expect(layerGroup.getLayerState()).to.eql({
|
|
layer: layerGroup,
|
|
brightness: -0.7,
|
|
contrast: 0.3,
|
|
hue: -0.3,
|
|
opacity: 0.3,
|
|
saturation: 0.3,
|
|
visible: false,
|
|
managed: true,
|
|
sourceState: ol.source.State.READY,
|
|
extent: groupExtent,
|
|
zIndex: 10,
|
|
maxResolution: 500,
|
|
minResolution: 0.25
|
|
});
|
|
});
|
|
|
|
it('returns a layerState with clamped values', function() {
|
|
layerGroup.setBrightness(1.5);
|
|
layerGroup.setContrast(-0.7);
|
|
layerGroup.setHue(42);
|
|
layerGroup.setOpacity(-1.5);
|
|
layerGroup.setSaturation(-0.7);
|
|
layerGroup.setVisible(false);
|
|
expect(layerGroup.getLayerState()).to.eql({
|
|
layer: layerGroup,
|
|
brightness: 1,
|
|
contrast: 0,
|
|
hue: 42,
|
|
opacity: 0,
|
|
saturation: 0,
|
|
visible: false,
|
|
managed: true,
|
|
sourceState: ol.source.State.READY,
|
|
extent: undefined,
|
|
zIndex: 0,
|
|
maxResolution: Infinity,
|
|
minResolution: 0
|
|
});
|
|
|
|
layerGroup.setBrightness(-3);
|
|
layerGroup.setContrast(42);
|
|
layerGroup.setHue(-100);
|
|
layerGroup.setOpacity(3);
|
|
layerGroup.setSaturation(42);
|
|
layerGroup.setVisible(true);
|
|
expect(layerGroup.getLayerState()).to.eql({
|
|
layer: layerGroup,
|
|
brightness: -1,
|
|
contrast: 42,
|
|
hue: -100,
|
|
opacity: 1,
|
|
saturation: 42,
|
|
visible: true,
|
|
managed: true,
|
|
sourceState: ol.source.State.READY,
|
|
extent: undefined,
|
|
zIndex: 0,
|
|
maxResolution: Infinity,
|
|
minResolution: 0
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
describe('layers events', function() {
|
|
|
|
it('listen / unlisten for layers added to the collection', function() {
|
|
var layers = new ol.Collection();
|
|
var layerGroup = new ol.layer.Group({
|
|
layers: layers
|
|
});
|
|
expect(goog.object.getCount(layerGroup.listenerKeys_)).to.eql(0);
|
|
var layer = new ol.layer.Layer({});
|
|
layers.push(layer);
|
|
expect(goog.object.getCount(layerGroup.listenerKeys_)).to.eql(1);
|
|
|
|
var listeners = layerGroup.listenerKeys_[goog.getUid(layer)];
|
|
expect(listeners.length).to.eql(2);
|
|
expect(listeners[0]).to.be.a(goog.events.Listener);
|
|
expect(listeners[1]).to.be.a(goog.events.Listener);
|
|
|
|
// remove the layer from the group
|
|
layers.pop();
|
|
expect(goog.object.getCount(layerGroup.listenerKeys_)).to.eql(0);
|
|
expect(listeners[0].removed).to.eql(true);
|
|
expect(listeners[1].removed).to.eql(true);
|
|
});
|
|
|
|
});
|
|
|
|
describe('#setLayers', function() {
|
|
|
|
it('sets layers property', function() {
|
|
var layer = new ol.layer.Layer({
|
|
source: new ol.source.Source({
|
|
projection: 'EPSG:4326'
|
|
})
|
|
});
|
|
var layers = new ol.Collection([layer]);
|
|
var layerGroup = new ol.layer.Group();
|
|
|
|
layerGroup.setLayers(layers);
|
|
expect(layerGroup.getLayers()).to.be(layers);
|
|
|
|
goog.dispose(layerGroup);
|
|
goog.dispose(layer);
|
|
goog.dispose(layers);
|
|
});
|
|
|
|
});
|
|
|
|
|
|
describe('#getLayerStatesArray', function() {
|
|
|
|
it('returns an empty array if no layer', function() {
|
|
var layerGroup = new ol.layer.Group();
|
|
|
|
var layerStatesArray = layerGroup.getLayerStatesArray();
|
|
expect(layerStatesArray).to.be.a(Array);
|
|
expect(layerStatesArray.length).to.be(0);
|
|
|
|
goog.dispose(layerGroup);
|
|
});
|
|
|
|
var layer1 = new ol.layer.Layer({
|
|
source: new ol.source.Source({
|
|
projection: 'EPSG:4326'
|
|
})
|
|
});
|
|
var layer2 = new ol.layer.Layer({
|
|
source: new ol.source.Source({
|
|
projection: 'EPSG:4326'
|
|
}),
|
|
brightness: 0.5,
|
|
contrast: 10,
|
|
hue: 180,
|
|
opacity: 0.5,
|
|
saturation: 5,
|
|
visible: false,
|
|
maxResolution: 500,
|
|
minResolution: 0.25
|
|
});
|
|
var layer3 = new ol.layer.Layer({
|
|
source: new ol.source.Source({
|
|
projection: 'EPSG:4326'
|
|
}),
|
|
extent: [-5, -2, 5, 2]
|
|
});
|
|
|
|
it('does not transform layerStates by default', function() {
|
|
var layerGroup = new ol.layer.Group({
|
|
layers: [layer1, layer2]
|
|
});
|
|
|
|
var layerStatesArray = layerGroup.getLayerStatesArray();
|
|
expect(layerStatesArray).to.be.a(Array);
|
|
expect(layerStatesArray.length).to.be(2);
|
|
expect(layerStatesArray[0]).to.eql(layer1.getLayerState());
|
|
|
|
// layer state should match except for layer reference
|
|
var layerState = goog.object.clone(layerStatesArray[0]);
|
|
delete layerState.layer;
|
|
var groupState = goog.object.clone(layerGroup.getLayerState());
|
|
delete groupState.layer;
|
|
expect(layerState).to.eql(groupState);
|
|
|
|
expect(layerStatesArray[1]).to.eql(layer2.getLayerState());
|
|
|
|
goog.dispose(layerGroup);
|
|
});
|
|
|
|
it('uses the layer group extent if layer has no extent', function() {
|
|
var groupExtent = [-10, -5, 10, 5];
|
|
var layerGroup = new ol.layer.Group({
|
|
extent: groupExtent,
|
|
layers: [layer1]
|
|
});
|
|
var layerStatesArray = layerGroup.getLayerStatesArray();
|
|
expect(layerStatesArray[0].extent).to.eql(groupExtent);
|
|
goog.dispose(layerGroup);
|
|
});
|
|
|
|
it('uses the intersection of group and child extent', function() {
|
|
var groupExtent = [-10, -5, 10, 5];
|
|
var layerGroup = new ol.layer.Group({
|
|
extent: groupExtent,
|
|
layers: [layer3]
|
|
});
|
|
var layerStatesArray = layerGroup.getLayerStatesArray();
|
|
expect(layerStatesArray[0].extent).to.eql(
|
|
ol.extent.getIntersection(layer3.getExtent(), groupExtent));
|
|
goog.dispose(layerGroup);
|
|
});
|
|
|
|
it('transforms layerStates correctly', function() {
|
|
var layerGroup = new ol.layer.Group({
|
|
layers: [layer1, layer2],
|
|
brightness: 0.5,
|
|
contrast: 10,
|
|
hue: 180,
|
|
opacity: 0.5,
|
|
saturation: 5,
|
|
visible: false,
|
|
maxResolution: 150,
|
|
minResolution: 0.2
|
|
});
|
|
|
|
var layerStatesArray = layerGroup.getLayerStatesArray();
|
|
|
|
// compare layer state to group state
|
|
var groupState, layerState;
|
|
|
|
// layer state should match except for layer reference
|
|
layerState = goog.object.clone(layerStatesArray[0]);
|
|
delete layerState.layer;
|
|
groupState = goog.object.clone(layerGroup.getLayerState());
|
|
delete groupState.layer;
|
|
expect(layerState).to.eql(groupState);
|
|
|
|
// layer state should be transformed (and we ignore layer reference)
|
|
layerState = goog.object.clone(layerStatesArray[1]);
|
|
delete layerState.layer;
|
|
expect(layerState).to.eql({
|
|
brightness: 1,
|
|
contrast: 100,
|
|
hue: 360,
|
|
opacity: 0.25,
|
|
saturation: 25,
|
|
visible: false,
|
|
managed: true,
|
|
sourceState: ol.source.State.READY,
|
|
extent: undefined,
|
|
zIndex: 0,
|
|
maxResolution: 150,
|
|
minResolution: 0.25
|
|
});
|
|
|
|
goog.dispose(layerGroup);
|
|
});
|
|
|
|
goog.dispose(layer1);
|
|
goog.dispose(layer2);
|
|
goog.dispose(layer3);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
goog.require('goog.dispose');
|
|
goog.require('goog.events.EventType');
|
|
goog.require('goog.events.Listener');
|
|
goog.require('goog.object');
|
|
goog.require('ol.ObjectEventType');
|
|
goog.require('ol.extent');
|
|
goog.require('ol.layer.Layer');
|
|
goog.require('ol.layer.Group');
|
|
goog.require('ol.source.Source');
|
|
goog.require('ol.source.State');
|
|
goog.require('ol.Collection');
|