Skip to content

Commit

Permalink
Merge pull request #918 from openlayers/add-source-before-or-after
Browse files Browse the repository at this point in the history
Match added layer to source of any adjacent layer
  • Loading branch information
ahocevar committed May 25, 2023
2 parents a3c64e6 + 55f19ee commit 6a98bf5
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 16 deletions.
41 changes: 28 additions & 13 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,34 +437,51 @@ export function getMapboxLayer(mapOrGroup, layerId) {
*/
export function addMapboxLayer(mapOrGroup, mapboxLayer, beforeLayerId) {
const mapboxLayers = mapOrGroup.get('mapbox-style').layers;
let index;
let spliceIndex;
let sourceIndex = -1;
if (beforeLayerId !== undefined) {
const beforeLayer = getMapboxLayer(mapOrGroup, beforeLayerId);
if (beforeLayer === undefined) {
throw new Error(`Layer with id "${beforeLayerId}" not found.`);
}
index = mapboxLayers.indexOf(beforeLayer);
spliceIndex = mapboxLayers.indexOf(beforeLayer);
} else {
index = mapboxLayers.length;
spliceIndex = mapboxLayers.length;
}
if (index === 0) {
throw new Error('Cannot add layer before first layer.');
let sourceOffset;
if (
spliceIndex > 0 &&
mapboxLayers[spliceIndex - 1].source === mapboxLayer.source
) {
sourceIndex = spliceIndex - 1;
sourceOffset = -1;
} else if (
spliceIndex < mapboxLayers.length &&
mapboxLayers[spliceIndex].source === mapboxLayer.source
) {
sourceIndex = spliceIndex;
sourceOffset = 0;
}
if (mapboxLayers[index - 1].source !== mapboxLayer.source) {
throw new Error('Added layer and layer before must use the same source.');
if (sourceIndex === -1) {
throw new Error(
'Added layer must have the same source as an adjacent layer.'
);
}
if (mapboxLayers.some((layer) => layer.id === mapboxLayer.id)) {
throw new Error(`Layer with id "${mapboxLayer.id}" already exists.`);
}
mapboxLayers.splice(index, 0, mapboxLayer);

const sourceLayerId = mapboxLayers[sourceIndex].id;
const args =
styleFunctionArgs[
getStyleFunctionKey(
mapOrGroup.get('mapbox-style'),
getLayer(mapOrGroup, mapboxLayers[index - 1].id)
getLayer(mapOrGroup, sourceLayerId)
)
];

mapboxLayers.splice(spliceIndex, 0, mapboxLayer);

if (args) {
const [
olLayer,
Expand All @@ -477,9 +494,7 @@ export function addMapboxLayer(mapOrGroup, mapboxLayer, beforeLayerId) {
getImage,
] = args;
if (Array.isArray(sourceOrLayers)) {
const layerIndex = beforeLayerId
? sourceOrLayers.indexOf(beforeLayerId)
: sourceOrLayers.length;
const layerIndex = sourceOrLayers.indexOf(sourceLayerId) + sourceOffset;
sourceOrLayers.splice(layerIndex, 0, mapboxLayer.id);
}
applyStylefunction(
Expand All @@ -493,7 +508,7 @@ export function addMapboxLayer(mapOrGroup, mapboxLayer, beforeLayerId) {
getImage
);
} else {
getLayer(mapOrGroup, mapboxLayers[index - 1].id).changed();
getLayer(mapOrGroup, mapboxLayers[sourceIndex].id).changed();
}
}

Expand Down
154 changes: 151 additions & 3 deletions test/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,15 @@ describe('util', function () {
map.setTarget(null);
});

it('adds a mapbox layer at the end of the layer stack', function () {
it('adds a mapbox layer before a specific layer', function () {
const layer = getLayer(map, 'landuse_park');
should.equal(layer.get('mapbox-layers').indexOf('landuse_park'), 1);
should.equal(
map
.get('mapbox-style')
.layers.findIndex((l) => l.id === 'landuse_park'),
2
);
const oldRevision = layer.getRevision();
addMapboxLayer(
map,
Expand All @@ -197,10 +204,151 @@ describe('util', function () {
},
'landuse_park'
);
should.notEqual(getMapboxLayer(map, 'inserted'), undefined);
should.notEqual(layer.get('mapbox-layers').indexOf('inserted'), -1);
should.deepEqual(getMapboxLayer(map, 'inserted'), {
id: 'inserted',
source: 'mapbox',
});
should.equal(layer.get('mapbox-layers').indexOf('landuse_park'), 2);
should.equal(
map
.get('mapbox-style')
.layers.findIndex((l) => l.id === 'landuse_park'),
3
);
should.equal(layer.get('mapbox-layers').indexOf('inserted'), 1);
should.equal(
map.get('mapbox-style').layers.findIndex((l) => l.id === 'inserted'),
2
);
should.equal(layer.getRevision(), oldRevision + 1);
});

it('adds a mapbox layer at the end of the layer stack', function () {
const layer = getLayer(map, 'country_label_1');
addMapboxLayer(map, {
id: 'inserted',
source: 'mapbox',
});
should.equal(
map.get('mapbox-style').layers.findIndex((l) => l.id === 'inserted'),
map.get('mapbox-style').layers.length - 1
);
should.equal(
layer.get('mapbox-layers').indexOf('inserted'),
layer.get('mapbox-layers').length - 1
);
});
});

describe('addMapboxLayer with multiple sources', function (done) {
let map;
beforeEach(function (done) {
const target = document.createElement('div');
map = new Map({
target: target,
});
apply(map, {
version: 8,
sources: {
source1: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {type: 'Point', coordinates: [0, 0]},
},
],
},
},
source2: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {type: 'Point', coordinates: [16, 48]},
},
],
},
},
},
layers: [
{
id: 'layer1',
source: 'source1',
type: 'circle',
},
{
id: 'layer2',
source: 'source2',
type: 'circle',
},
],
})
.then(() => done())
.catch((err) => done(err));
});
afterEach(function () {
map.setTarget(null);
});

it('adds a mapbox layer at the beginning of the layer stack', function () {
addMapboxLayer(
map,
{
id: 'inserted',
source: 'source1',
},
'layer1'
);
const layer = getLayer(map, 'inserted');
should.equal(
map.get('mapbox-style').layers.findIndex((l) => l.id === 'inserted'),
0
);
should.equal(layer.get('mapbox-layers').indexOf('inserted'), 0);
});

it('adds layers between sources - next layer', function () {
addMapboxLayer(
map,
{
id: 'inserted',
source: 'source1',
},
'layer2'
);
const layer = getLayer(map, 'inserted');
should.equal(map.getLayers().getArray().indexOf(layer), 0);
should.equal(
map.get('mapbox-style').layers.findIndex((l) => l.id === 'inserted'),
1
);
should.equal(layer.get('mapbox-layers').indexOf('inserted'), 1);
});

it('adds layers between sources - previous layer', function () {
addMapboxLayer(
map,
{
id: 'inserted',
source: 'source2',
},
'layer2'
);
const layer = getLayer(map, 'inserted');
should.equal(map.getLayers().getArray().indexOf(layer), 1);
should.equal(
map.get('mapbox-style').layers.findIndex((l) => l.id === 'inserted'),
1
);
should.equal(layer.get('mapbox-layers').indexOf('inserted'), 0);
});
});

describe('updateMapboxLayer', function () {
Expand Down

0 comments on commit 6a98bf5

Please sign in to comment.