Reputation: 2105
First of all, give thanks for reading my question and try to help me and apologize for my English.
I'm trying to create a method on Redux using React that change visibility of a layer.
My problem is that change visibility perfect but when all layers are no visibles and try to change them to visibles their before property is undefined, except last one that changes.
I'm going to explain me better with an example.
mapLayers is an array that contains 3 layers:
- [2] Layer3
- 1 Layer2
- [0] Layer1
CASE 1:
If I hide Layer1
his before property is undefined, and now I show Layer1
and now his before property is id of Layer2
.
MY PROBLEM:
- [2] Layer3
- 1 Layer2
- [0] Layer1
3 Layers are no visibles, so:
Layer2
to visible -> before = undefinedLayer3
to visible -> before = undefinedLayer1
to visible -> before = id of Layer2But when change Layer3
to visible (on step 2), before should be undefined and later, when chage visibility of Layer2
.. before of Layer3
should be Layer2
id.
Is important know that I'm using react-mapbox-gl, and I need before property to move and hido/show layers.
before: string Pass the id of a layer, it will display the current layer before the layer defined by the id.
https://github.com/alex3165/react-mapbox-gl/blob/master/docs/API.md
Here is my code:
static changeLayerVisibility(layer) {
let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
const ids = mapLayers.map(l => l.id);
const index = ids.indexOf(layer.id);
const newVisibility = (layer.layout.visibility === 'visible') ? 'none' : 'visible';
let nextVisibleLayer = mapLayers.find((layerObj, idx) => idx > index && layerObj.layout.visibility === 'visible');
let updateLayout = Object.assign({}, mapLayers[index], {
layout: Object.assign({}, mapLayers[index].layout, { visibility: newVisibility }),
paint: Object.assign({}, mapLayers[index].paint),
before: newVisibility === 'visible' && nextVisibleLayer ? nextVisibleLayer.id: undefined
});
mapLayers.splice(index, 1, updateLayout);
return (dispatch) => {
dispatch({
type: MapTypeConstants.SET_MAP_LAYERS,
payload: mapLayers
});
};
}
Upvotes: 0
Views: 98
Reputation: 2105
SOLUTION:
Thanks a lot for your help and ideas but I've solved it like this.
In Redux I've created a new method to update before property when layer has change his visibility and is undefined when should be the id of next layer.
And, Is not possible update that layer inside changeVisibility because, the layer that change the visibility should be drawn (rendered). If is not drawn, the application crash because property before has the id of next layer and next layer is not drawn yet.
REDUX:
static changeLayerVisibility(layer) {
let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
const ids = mapLayers.map(l => l.id);
const index = ids.indexOf(layer.id);
const layoutVisibility = (layer.layout.visibility === 'visible') ? 'none' : 'visible';
let nextVisibleLayer = mapLayers.find((layerObj, idx) => idx > index && layerObj.layout && layerObj.layout.visibility && layerObj.layout.visibility === 'visible');
let updateLayout = Object.assign({}, mapLayers[index], {
layout: Object.assign({}, mapLayers[index].layout, { visibility: layoutVisibility }),
paint: Object.assign({}, mapLayers[index].paint),
filter: (mapLayers[index].filter) ? Object.assign({}, mapLayers[index].filter) : {},
before: layoutVisibility === 'visible' && nextVisibleLayer ? nextVisibleLayer.id: undefined,
visible: (layoutVisibility === 'visible') ? true : false
});
if (this.updateLayout.type === 'raster') delete updateLayout.filter;
mapLayers.splice(index, 1, updateLayout);
return (dispatch) => {
dispatch({
type: MapTypeConstants.SET_MAP_LAYERS,
payload: mapLayers
});
};
}
static updateBefore(layer) {
let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
const ids = mapLayers.map(l => l.id);
const posInRedux = ids.indexOf(layer.id);
let updateBeforeLayout = Object.assign({}, layer, {
layout: Object.assign({}, layer.layout),
paint: Object.assign({}, layer.paint),
filter: (layer.filter) ? Object.assign({}, layer.filter) : {},
before: (mapLayers[posInRedux + 1]) ? String(mapLayers[posInRedux + 1].id) : undefined,
visible: layer.visible
});
if (this.updateBeforeLayout.type === 'raster') delete updateBeforeLayout.filter;
mapLayers.splice(posInRedux, 1, updateBeforeLayout);
return (dispatch) => {
dispatch({
type: MapTypeConstants.SET_MAP_LAYERS,
payload: mapLayers
});
};
}
FRONT-END:
changeVisibility(layer) {
this.props.changeLayerVisibility(layer);
let layerBeforeUndefined = this.props.mapGLlayers.find(l => l.visible === true && l.before === undefined);
if (layerBeforeUndefined) {
setTimeout( () => {
this.props.updateBefore(layerBeforeUndefined);
});
}
};
Now, I want reduce code in front because all logic it has to be one redux and it has to look like this:
changeVisibility(layer) {
let userMapboxLayers = this.props.map.getStyle().layers.filter(l => l.source && l.source.indexOf('sourceId_') !== -1);
this.props.changeLayerVisibility(userMapboxLayers, layer);
};
Upvotes: 0
Reputation: 2361
Actually,I think there is a better ways to set your properties.
First,use an Array to store visibility properties.Like the below, and the initial value should be false.
interface InVisiablityProps {
visible: Array<Boolean>
}
const initialState:InVisiablityProps = {
invisible: [false,false,false]
}
Every change the view to invisible.change the property to !(property)
Upvotes: 1