Skip to content

Commit

Permalink
[chore] consolidate copied kepler layer creation code
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisgervang committed Jul 8, 2021
1 parent fac6533 commit fe1f522
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 147 deletions.
3 changes: 3 additions & 0 deletions examples/worldview/src/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ const App = ({}) => {
const keplerDeckLayers = useKeplerDeckLayers(KEPLER_MAP_ID);
const deckProps = useMemo(() => {
return {
// layers: [...keplerDeckLayers, ...sceneLayers]
layers: [...sceneLayers, ...keplerDeckLayers]
// layers: []
// layers: keplerDeckLayers
};
}, [keplerDeckLayers, sceneLayers]);
const mapStyle = useSelector(selectMapStyle);
Expand Down
97 changes: 6 additions & 91 deletions examples/worldview/src/features/kepler/hooks.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {useEffect, useCallback, useMemo} from 'react';
import {useEffect, useMemo} from 'react';
import {
registerEntry,
setFilter,
Expand All @@ -7,7 +7,6 @@ import {
// updateMap
} from 'kepler.gl/actions';
import {useDispatch, useSelector} from 'react-redux';
import {createSelector} from 'reselect';

import {AUTH_TOKENS} from '../../constants';
import {updateViewState} from '../map';
Expand All @@ -19,6 +18,8 @@ import {
} from './keplerSlice';
import {attachAnimation} from '../renderer/rendererSlice';
import {KeplerAnimation} from '@hubble.gl/core';
import {createKeplerLayers} from '@hubble.gl/react';
import {viewStateSelector} from '../map/mapSlice';

export const useKepler = ({mapId, fetchMap, filterKeyframes, layerKeyframes, tripKeyframe}) => {
const dispatch = useDispatch();
Expand Down Expand Up @@ -91,98 +92,12 @@ export const useKeplerMapState = mapId => {
}, [Boolean(map)]);
};

/**
* Kepler Layer Creation
* Forked from kepler.gl
* https://github.com/keplergl/kepler.gl/blob/master/src/components/map-container.js
*/

const layersSelector = state => state.visState.layers;
const layerDataSelector = state => state.visState.layerData;
const mapLayersSelector = state => state.visState.mapLayers;
// const layerOrderSelector = state => state.visState.layerOrder;
export const layersToRenderSelector = createSelector(
layersSelector,
layerDataSelector,
mapLayersSelector,
// {[id]: true \ false}
(layers, layerData, mapLayers) =>
layers.reduce(
(accu, layer, idx) => ({
...accu,
[layer.id]: layer.shouldRenderLayer(layerData[idx]) && _isVisibleMapLayer(layer, mapLayers) // eslint-disable-line
}),
{}
)
);
/* component private functions */
function _isVisibleMapLayer(layer, mapLayers) {
// if layer.id is not in mapLayers, don't render it
return !mapLayers || (mapLayers && mapLayers[layer.id]);
}
function _onLayerSetDomain(idx, colorDomain) {
// TODO: this isn't dispatched to the redux store yet.
// layerConfigChange(this.props.mapData.visState.layers[idx], {
// colorDomain
// });
}

export const useKeplerDeckLayers = mapId => {
const selectKeplerMap = useMemo(() => createSelectKeplerMap(mapId), [mapId]);
const map = useSelector(selectKeplerMap);

const renderLayer = useCallback(
(overlays, idx) => {
const {
visState: {
datasets,
layers,
layerData,
hoverInfo,
clicked,
interactionConfig,
animationConfig
},
mapState
} = map;

const layer = layers[idx];
const data = layerData[idx];
const {gpuFilter} = datasets[layer.config.dataId] || {};

const objectHovered = clicked || hoverInfo;
const layerCallbacks = {
onSetLayerDomain: val => _onLayerSetDomain(idx, val)
};

// Layer is Layer class
const layerOverlay = layer.renderLayer({
data,
gpuFilter,
idx,
interactionConfig,
layerCallbacks,
mapState,
animationConfig,
objectHovered
});
return overlays.concat(layerOverlay || []);
},
[map]
);

const viewState = useSelector(viewStateSelector);
return useMemo(() => {
if (!map) return [];
const layersToRender = layersToRenderSelector(map);
// returns an arr of DeckGL layer objects
const {layerOrder, layerData, layers} = map.visState;
if (layerData && layerData.length) {
return layerOrder
.slice()
.reverse()
.filter(idx => layers[idx].overlayType === 'deckgl' && layersToRender[layers[idx].id])
.reduce(renderLayer, []); // Slicing & reversing to create same layer order as Kepler
}
return [];
}, [map]);
return createKeplerLayers(map, viewState);
}, [map && map.mapState, map && map.visState, viewState]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import isEqual from 'lodash.isequal';

import {deckStyle} from './constants';
import {RenderingSpinner} from './rendering-spinner';
import {createKeplerLayers} from '../../kepler-layers';

export class ExportVideoPanelPreview extends Component {
constructor(props) {
Expand All @@ -42,8 +43,6 @@ export class ExportVideoPanelPreview extends Component {
memoDevicePixelRatio: window.devicePixelRatio // memoize
};

this._onLayerSetDomain = this._onLayerSetDomain.bind(this);
this._renderLayer = this._renderLayer.bind(this);
this._onMapLoad = this._onMapLoad.bind(this);
this._resizeVideo = this._resizeVideo.bind(this);
this._resizeVideo();
Expand Down Expand Up @@ -91,69 +90,19 @@ export class ExportVideoPanelPreview extends Component {
window.devicePixelRatio = devicePixelRatio;
}

_onLayerSetDomain(idx, colorDomain) {
// TODO: this isn't dispatched to the redux store yet.
// layerConfigChange(this.props.mapData.visState.layers[idx], {
// colorDomain
// });
}

_renderLayer(overlays, idx) {
const {
mapData: {visState, mapState},
viewState
} = this.props;

const {
datasets,
layers,
layerData,
hoverInfo,
clicked,
interactionConfig,
animationConfig
} = visState;

const layer = layers[idx];
const data = layerData[idx];
const {gpuFilter} = datasets[layer.config.dataId] || {};

const objectHovered = clicked || hoverInfo;
const layerCallbacks = {
onSetLayerDomain: val => this._onLayerSetDomain(idx, val)
};

// Layer is Layer class
const layerOverlay = layer.renderLayer({
data,
gpuFilter,
idx,
interactionConfig,
layerCallbacks,
mapState: {...mapState, ...viewState},
animationConfig,
objectHovered
});
return overlays.concat(layerOverlay || []);
}

_getContainer() {
const {exportVideoWidth, resolution} = this.props;
const aspectRatio = resolution[0] / resolution[1];
return {height: exportVideoWidth / aspectRatio, width: exportVideoWidth};
}

createLayers() {
const {deckProps, mapData, viewState} = this.props;
// returns an arr of DeckGL layer objects
if (this.props.deckProps && this.props.deckProps.layers) {
return this.props.deckProps.layers;
if (deckProps && deckProps.layers) {
return deckProps.layers;
}
const layerOrder = this.props.mapData.visState.layerOrder;

return layerOrder
.slice()
.reverse()
.reduce(this._renderLayer, []); // Slicing & reversing to create same layer order as Kepler
return createKeplerLayers(mapData, viewState);
}

_onMapLoad() {
Expand Down
1 change: 1 addition & 0 deletions modules/react/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ export {
QuickAnimation
} from './components';
export {useNextFrame, useDeckAdapter} from './hooks';
export {createKeplerLayers} from './kepler-layers';
80 changes: 80 additions & 0 deletions modules/react/src/kepler-layers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {createSelector} from 'reselect';

/**
* Kepler Layer Creation
* Forked from kepler.gl
* https://github.com/keplergl/kepler.gl/blob/master/src/components/map-container.js
*/
const layersSelector = state => state.visState.layers;
const layerDataSelector = state => state.visState.layerData;
const mapLayersSelector = state => state.visState.mapLayers;
// const layerOrderSelector = state => state.visState.layerOrder;
const layersToRenderSelector = createSelector(
layersSelector,
layerDataSelector,
mapLayersSelector,
// {[id]: true \ false}
(layers, layerData, mapLayers) =>
layers.reduce(
(accu, layer, idx) => ({
...accu,
[layer.id]: layer.shouldRenderLayer(layerData[idx]) && _isVisibleMapLayer(layer, mapLayers) // eslint-disable-line
}),
{}
)
);
/* component private functions */
function _isVisibleMapLayer(layer, mapLayers) {
// if layer.id is not in mapLayers, don't render it
return !mapLayers || (mapLayers && mapLayers[layer.id]);
}

function _onLayerSetDomain(idx, colorDomain) {
// TODO: this isn't dispatched to the redux store yet.
// layerConfigChange(this.props.mapData.visState.layers[idx], {
// colorDomain
// });
}

function renderLayer(overlays, idx, map, viewState) {
const {
visState: {datasets, layers, layerData, hoverInfo, clicked, interactionConfig, animationConfig},
mapState
} = map;

const layer = layers[idx];
const data = layerData[idx];
const {gpuFilter} = datasets[layer.config.dataId] || {};

const objectHovered = clicked || hoverInfo;
const layerCallbacks = {
onSetLayerDomain: val => _onLayerSetDomain(idx, val)
};

// Layer is Layer class
const layerOverlay = layer.renderLayer({
data,
gpuFilter,
idx,
interactionConfig,
layerCallbacks,
mapState: {...mapState, ...viewState},
animationConfig,
objectHovered
});
return overlays.concat(layerOverlay || []);
}

export function createKeplerLayers(map, viewState) {
const layersToRender = layersToRenderSelector(map);
// returns an arr of DeckGL layer objects
const {layerOrder, layerData, layers} = map.visState;
if (layerData && layerData.length) {
return layerOrder
.slice()
.reverse()
.filter(idx => layers[idx].overlayType === 'deckgl' && layersToRender[layers[idx].id])
.reduce((overlays, idx) => renderLayer(overlays, idx, map, viewState), []); // Slicing & reversing to create same layer order as Kepler
}
return [];
}

0 comments on commit fe1f522

Please sign in to comment.