keplergl / kepler.gl

Kepler.gl is a powerful open source geospatial analysis tool for large-scale data sets.
http://kepler.gl
MIT License
10.11k stars 1.71k forks source link

Add layer reducer #2569

Open AdrienHoule opened 2 months ago

AdrienHoule commented 2 months ago

Hi I need help i'm trying to make an action in my store that allow me to add deck.gl layers to the kepler map, so with the documentation I came with the following code that has no errors but does nothing.

my app.tsx :

import React, {useState} from 'react';
import KeplerGl from '@kepler.gl/components';
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
import {ScatterplotLayer} from '@deck.gl/layers';
import {useDispatch} from 'react-redux';
import {addLayer} from './store.ts';

const App = () => {
  const dispatch = useDispatch();

  const [showDeckLayer, setShowDeckLayer] = useState(true);

  const toggleDeckLayer = () => {
    setShowDeckLayer(!showDeckLayer);
    if (!showDeckLayer) {
      const layer = new ScatterplotLayer({
        id: 'deck-layer',
        data: [{position: [9.19, 42.0], size: 1000}],
        getRadius: (d: any) => d.size,
        getPosition: (d: any) => d.position,
        getColor: [255, 0, 0],
        pickable: true
      });
      dispatch(addLayer(layer));
    }
  };

  return (
    <div style={{position: 'absolute', width: '100%', height: '100%'}}>
      <button onClick={toggleDeckLayer}>Toggle Deck Layer</button>
      <AutoSizer>
        {({height, width}) => (
          <KeplerGl mapboxApiAccessToken="" id="map" width={width} height={height} />
        )}
      </AutoSizer>
    </div>
  );
};

export default App;

my store.ts :

// SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project

import {createStore, combineReducers, applyMiddleware, compose} from 'redux';
import keplerGlReducer, {enhanceReduxMiddleware, KeplerGlState} from '@kepler.gl/reducers';
import {createAction, handleActions} from 'redux-actions';

const mapStyles = {
  voyager: {
    id: 'voyager',
    label: 'Voyager',
    url: 'https://api.maptiler.com/maps/voyager/style.json?key=ySQ0fIYn7eSl3ppOeEJd',
    icon: 'https://api.maptiler.com/maps/voyager/256/0/0/0.png?key=ySQ0fIYn7eSl3ppOeEJd'
  },
  terrain: {
    id: 'terrain',
    label: 'Outdoor',
    url: 'https://api.maptiler.com/maps/outdoor/style.json?key=ySQ0fIYn7eSl3ppOeEJd',
    icon: 'https://openmaptiles.org/img/styles/terrain.jpg',
    layerGroups: [
      {
        slug: 'label',
        filter: ({id}) => id.match(/(?=(label|place-|poi-))/),
        defaultVisibility: true
      },
      {
        slug: 'road',
        filter: ({id}) => id.match(/(?=(road|railway|tunnel|street|bridge))(?!.*label)/),
        defaultVisibility: true
      },
      {
        slug: 'terrain',
        filter: ({id}) => id.match(/(?=(hillshade))/),
        defaultVisibility: true
      },
      {
        slug: 'building',
        filter: ({id}) => id.match(/building/),
        defaultVisibility: true
      }
    ]
  }
};
const customizedKeplerGlReducer = keplerGlReducer.initialState({
  mapStyle: {
    mapStyles,
    styleType: 'voyager'
  }
});

const initialState: KeplerGlState = {
  loaded: false,
  visState: {
    layers: []
  }
};

export const ADD_LAYER = 'ADD_LAYER';
export const addLayer = createAction(ADD_LAYER);

const layerReducer = handleActions(
  {
    [ADD_LAYER]: (state: KeplerGlState, action) => ({
      ...state,
      visState: {
        ...state.visState,
        layers: [...state.visState.layers, action.payload]
      }
    })
  },
  initialState
);

const reducers = combineReducers({
  keplerGl: customizedKeplerGlReducer,
  layers: layerReducer
});

const middlewares = enhanceReduxMiddleware([]);
const enhancers = [applyMiddleware(...middlewares)];

export default createStore(reducers, {}, compose(...enhancers));