Giter VIP home page Giter VIP logo

kepler.gl's Introduction

version build stars MIT License Fossa

kepler.gl | Website | Demo App | Docs

Kepler.gl

Kepler.gl Demo

Kepler.gl is a data-agnostic, high-performance web-based application for visual exploration of large-scale geolocation data sets. Built on top of MapLibre GL and deck.gl, kepler.gl can render millions of points representing thousands of trips and perform spatial aggregations on the fly.

Kepler.gl is also a React component that uses Redux to manage its state and data flow. It can be embedded into other React-Redux applications and is highly customizable. For information on how to embed kepler.gl in your app take a look at this step-by-step tutorial on vis.academy.

Links

Env

Use Node 18.18.2 or above, older node versions have not been supported/ tested. For best results, use nvm nvm install.

Install kepler.gl

Install node (> 18.18.2), yarn, and project dependencies

npm install --save kepler.gl
// or
yarn add kepler.gl

kepler.gl is built upon mapbox. You will need a Mapbox Access Token to use it.

If you don't use a module bundler, it's also fine. Kepler.gl npm package includes precompiled production UMD builds in the umd folder. You can add the script tag to your html file as it follows:

<script src="https://unpkg.com/kepler.gl/umd/keplergl.min.js" />

or if you would like, you can load a specific version

<script src="https://unpkg.com/[email protected]/umd/keplergl.min.js" />

Develop kepler.gl

Take a look at the development guide to develop kepler.gl locally.

Basic Usage

Here are the basic steps to import kepler.gl into your app. You also take a look at the examples folder. Each example in the folder can be installed and run locally.

1. Mount reducer

Kepler.gl uses Redux to manage its internal state, along with react-palm middleware to handle side effects.

You need to add taskMiddleware of react-palm to your store too. We are actively working on a solution where react-palm will not be required, however it is still a very lightweight side effects management tool that is easier to test than react-thunk.

import {createStore, combineReducers, applyMiddleware, compose} from 'redux';
import keplerGlReducer from '@kepler.gl/reducers';
import {enhanceReduxMiddleware} from '@kepler.gl/middleware';

const initialState = {};
const reducers = combineReducers({
  // <-- mount kepler.gl reducer in your app
  keplerGl: keplerGlReducer,

  // Your other reducers here
  app: appReducer
});

// using createStore
export default createStore(
  reducer,
  initialState,
  applyMiddleware(
    enhanceReduxMiddleware([
      /* Add other middlewares here */
    ])
  )
);

Or if use enhancer:

// using enhancers
const initialState = {};
const middlewares = enhanceReduxMiddleware([
  // Add other middlewares here
]);
const enhancers = [applyMiddleware(...middlewares)];

export default createStore(reducer, initialState, compose(...enhancers));

If you mount kepler.gl reducer in another address instead of keplerGl, or the kepler.gl reducer is not mounted at root of your state, you will need to specify the path to it when you mount the component with the getState prop.

Read more about Reducers.

2. Mount Component

import KeplerGl from '@kepler.gl/components';

const Map = props => (
  <KeplerGl id="foo" width={width} mapboxApiAccessToken={token} height={height} />
);

Props

id (String, required)
  • Default: map

The id of this KeplerGl instance. id is required if you have multiple KeplerGl instances in your app. It defines the prop name of the KeplerGl state that is stored in the KeplerGl reducer. For example, the state of the KeplerGl component with id foo is stored in state.keplerGl.foo.

In case you create multiple kepler.gl instances using the same id, the kepler.gl state defined by the entry will be overridden by the latest instance and reset to a blank state.

mapboxApiAccessToken (String, required*)
  • Default: undefined

By default, kepler.gl uses mapbox-gl.js to render its base maps. You can create a free account at mapbox and create a token at www.mapbox.com/account/access-tokens.

If you replaced kepler.gl default map styles with your own, and they are not Mapbox styles. mapboxApiAccessToken will not be required.

Read more about Custom Map Styles.

getState (Function, optional)
  • Default: state => state.keplerGl

The path to the root keplerGl state in your reducer.

width (Number, optional)
  • Default: 800

Width of the KeplerGl UI.

height (Number, optional)
  • Default: 800
appName (String, optional)
  • Default: Kepler.Gl

App name displayed in side panel header

version (String, optional)
  • Default: v1.0

version displayed in side panel header

onSaveMap (Function, optional)
  • Default: undefined

Action called when click Save Map Url in side panel header.

onViewStateChange (Function, optional)
  • Default: undefined
  • Parameter: viewState - An updated view state object containing parameters such as longitude, latitude, zoom etc

Action triggered when map viewport is updated.

getMapboxRef(mapbox, index) (Function, optional)
  • Default: undefined

Function called when KeplerGL adds or removes a MapContainer component having an inner Mapbox map.

The mapbox argument is an MapRef when added or null when removed.

The index argument is 0 for a single map or 1 for an additional map (since KeplerGL supports an optional split map view).

actions (Object, optional)
  • Default: {}

Actions creators to replace default kepler.gl action creator. Only use custom action when you want to modify action payload.

mint (Boolean, optional)
  • Default: true

Whether to load a fresh empty state when component is mounted. when parse mint: true kepler.gl component will always load a fresh state when re-mount the same component, state inside this component will be destroyed once its unmounted. By Parsing mint: false kepler.gl will keep the component state in the store even when it is unmounted, and use it as initial state when re-mounted again. This is useful when mounting kepler.gl in a modal, and keep the same map when re-open.

Read more about Components.

theme (Object | String, optional)
  • default: null

One of "dark", "light" or "base" You can pass theme name or object used to customize Kepler.gl style. Kepler.gl provide an 'light' theme besides the default 'dark' theme. When pass in a theme object Kepler.gl will use the value passed as input to override values from theme.

Read more about Custom Theme

mapboxApiUrl (String, optional)

  • Default: https://api.mapbox.com

If you are using your own mapbox tile server, you can pass in your own tile server api url.

mapStylesReplaceDefault (Boolean, optional)

  • Default: false

kepler.gl provide 4 map styles to choose from. Pass true if you want to supply your own mapStyles. See Below.

mapStyles (Array, optional)

  • Default: []

You can supply additional map styles to be displayed in map style selection panel. By default, additional map styles will be added to default map styles. If pass mapStylesReplaceDefault: true, they will replace the default ones. kepler.gl will attempt to group layers of your style based on its id naming convention and use it to allow toggle visibility of base map layers. Supply your own layerGroups to override default for more accurate layer grouping.

Each mapStyles should has the following properties:

  • id (String, required) unique string that should not be one of these reserved dark light muted. muted_night
  • label (String, required) name to be displayed in map style selection panel
  • url (String, required) mapbox style url or a url pointing to the map style json object written in Mapbox GL Style Spec.
  • icon (String, optional) image icon of the style, it can be a url, or an image data url
  • layerGroups (Array, optional)
const mapStyles = [
  {
    id: 'my_dark_map',
    label: 'Dark Streets 9',
    url: 'mapbox://styles/mapbox/dark-v9',
    icon: `${apiHost}/styles/v1/mapbox/dark-v9/static/-122.3391,37.7922,9.19,0,0/400x300?access_token=${accessToken}&logo=false&attribution=false`,
    layerGroups: [
      {
        slug: 'label',
        filter: ({id}) => id.match(/(?=(label|place-|poi-))/),
        defaultVisibility: true
      },
      {
        // adding this will keep the 3d building option
        slug: '3d building',
        filter: () => false,
        defaultVisibility: false
      }
    ]
  }
];

Read more about Custom Map Styles.

initialUiState (object, optional)

  • Default: undefined

Intial UI State applied to uiState reducer, value will be shallow merged with default INITIAL_UI_STATE

localeMessages (object, optional)

  • Default: undefined Modify default translation or add new translation

Read more about Localization.

3. Dispatch custom actions to keplerGl reducer.

One advantage of using the reducer over React component state to handle keplerGl state is the flexibility to customize its behavior. If you only have one KeplerGl instance in your app or never intend to dispatch actions to KeplerGl from outside the component itself, you don’t need to worry about forwarding dispatch and can move on to the next section. But life is full of customizations, and we want to make yours as enjoyable as possible.

There are multiple ways to dispatch actions to a specific KeplerGl instance.

  • In the root reducer, with reducer updaters.

Each action is mapped to a reducer updater in kepler.gl. You can import the reducer updater corresponding to a specific action, and call it with the previous state and action payload to get the updated state. e.g. updateVisDataUpdater is the updater for ActionTypes.UPDATE_VIS_DATA (take a look at each reducer reducers/vis-state.js for action to updater mapping). Here is an example how you can listen to an app action QUERY_SUCCESS and call updateVisDataUpdater to load data into Kepler.Gl.

import keplerGlReducer, {visStateUpdaters} from 'kepler.gl/reducers';

// Root Reducer
const reducers = combineReducers({
  keplerGl: keplerGlReducer,

  app: appReducer
});

const composedReducer = (state, action) => {
  switch (action.type) {
    case 'QUERY_SUCCESS':
      return {
        ...state,
        keplerGl: {
          ...state.keplerGl,

          // 'map' is the id of the keplerGl instance
          map: {
            ...state.keplerGl.map,
            visState: visStateUpdaters.updateVisDataUpdater(state.keplerGl.map.visState, {
              datasets: action.payload
            })
          }
        }
      };
  }
  return reducers(state, action);
};

export default composedReducer;

Read more about using updaters to modify kepler.gl state

  • Using redux connect

You can add a dispatch function to your component that dispatches actions to a specific keplerGl component, using connect.

// component
import KeplerGl from '@kepler.gl/components';

// action and forward dispatcher
import {toggleFullScreen, forwardTo} from '@kepler.gl/actions';
import {connect} from 'react-redux';

const MapContainer = props => (
  <div>
    <button onClick={() => props.keplerGlDispatch(toggleFullScreen())}/>
    <KeplerGl
      id="foo"
    />
  </div>
)

const mapStateToProps = state => state
const mapDispatchToProps = (dispatch, props) => ({
 dispatch,
 keplerGlDispatch: forwardTo(‘foo’, dispatch)
});

export default connect(
 mapStateToProps,
 mapDispatchToProps
)(MapContainer);
  • Wrap action payload

You can also simply wrap an action into a forward action with the wrapTo helper

// component
import KeplerGl from '@kepler.gl/components';

// action and forward dispatcher
import {toggleFullScreen, wrapTo} from '@kepler.gl/actions';

// create a function to wrapper action payload to 'foo'
const wrapToMap = wrapTo('foo');
const MapContainer = ({dispatch}) => (
  <div>
    <button onClick={() => dispatch(wrapToMap(toggleFullScreen())} />
    <KeplerGl
      id="foo"
    />
  </div>
);

Read more about forward dispatching actions

4. Customize style.

Kepler.gl implements css styling using Styled-Components. By using said framework Kepler.gl offers the ability to customize its style/theme using the following approaches:

  • Passing a Theme prop
  • Styled-Components ThemeProvider

The available properties to customize are listed here theme.

Custom theme example.

Passing a Theme prop.

You can customize Kepler.gl theme by passing a theme props to Kepler.gl react component as it follows:

const white = '#ffffff';
const customTheme = {
  sidePanelBg: white,
  titleTextColor: '#000000',
  sidePanelHeaderBg: '#f7f7F7',
  subtextColorActive: '#2473bd'
};

return (
  <KeplerGl
    mapboxApiAccessToken={MAPBOX_TOKEN}
    id="map"
    width={800}
    height={800}
    theme={customTheme}
  />
);

As you can see the customTheme object defines certain properties which will override Kepler.gl default style rules.

Styled-Components Theme Provider.

In order to customize Kepler.gl theme using ThemeProvider you can simply wrap Kepler.gl using ThemeProvider as it follows:

import {ThemeProvider} from 'styled-components';

const white = '#ffffff';
const customTheme = {
  sidePanelBg: white,
  titleTextColor: '#000000',
  sidePanelHeaderBg: '#f7f7F7',
  subtextColorActive: '#2473bd'
};

return (
  <ThemeProvider theme={customTheme}>
    <KeplerGl mapboxApiAccessToken={MAPBOX_TOKEN} id="map" width={800} height={800} />
  </ThemeProvider>
);

5. Render Custom UI components.

Everyone wants the flexibility to render custom kepler.gl components. Kepler.gl has a dependency injection system that allow you to inject components to KeplerGl replacing existing ones. All you need to do is to create a component factory for the one you want to replace, import the original component factory and call injectComponents at the root component of your app where KeplerGl is mounted. Take a look at examples/demo-app/src/app.js and see how it renders a custom side panel header in kepler.gl

import {injectComponents, PanelHeaderFactory} from '@kepler.gl/components';

// define custom header
const CustomHeader = () => <div>My kepler.gl app</div>;
const myCustomHeaderFactory = () => CustomHeader;

// Inject custom header into Kepler.gl, replacing default
const KeplerGl = injectComponents([[PanelHeaderFactory, myCustomHeaderFactory]]);

// render KeplerGl, it will render your custom header instead of the default
const MapContainer = () => (
  <div>
    <KeplerGl id="foo" />
  </div>
);

Using withState helper to add reducer state and actions to customized component as additional props.

import {withState, injectComponents, PanelHeaderFactory} from '@kepler.gl/components';
import {visStateLens} from '@kepler.gl/reducers';

// custom action wrap to mounted instance
const addTodo = text =>
  wrapTo('map', {
    type: 'ADD_TODO',
    text
  });

// define custom header
const CustomHeader = ({visState, addTodo}) => (
  <div onClick={() => addTodo('hello')}>{`${
    Object.keys(visState.datasets).length
  } dataset loaded`}</div>
);

// now CustomHeader will receive `visState` and `addTodo` as additional props.
const myCustomHeaderFactory = () =>
  withState(
    // keplerGl state lenses
    [visStateLens],
    // customMapStateToProps
    headerStateToProps,
    // actions
    {addTodo}
  )(CustomHeader);

Read more about replacing UI component

6. How to add data to map

To interact with a kepler.gl instance and add new data to it, you can dispatch the addDataToMap action from anywhere inside your app. It adds a dataset or multiple datasets to a kepler.gl instance and updates the full configuration (mapState, mapStyle, visState).

Parameters

  • data Object *required

    • datasets (Array<Object> | Object) *required datasets can be a dataset or an array of datasets Each dataset object needs to have info and data property.

      • datasets.info Object -info of a dataset
        • datasets.info.id string id of this dataset. If config is defined, id should matches the dataId in config.
        • datasets.info.label string A display name of this dataset
      • datasets.data Object *required The data object, in a tabular format with 2 properties fields and rows
        • datasets.data.fields Array<Object> *required Array of fields,
          • datasets.data.fields.name string *required Name of the field,
        • datasets.data.rows Array<Array> *required Array of rows, in a tabular format with fields and rows
    • options Object

      • options.centerMap boolean default: true if centerMap is set to true kepler.gl will place the map view within the data points boundaries
      • options.readOnly boolean default: false if readOnly is set to true the left setting panel will be hidden
      • options.keepExistingConfig boolean default: false whether to keep exiting map config, including layers, filters and splitMaps.
  • config Object this object will contain the full kepler.gl instance configuration {mapState, mapStyle, visState}

Kepler.gl provides an easy API KeplerGlSchema.getConfigToSave to generate a json blob of the current kepler instance configuration.

Examples

// app.js
import {addDataToMap} from '@kepler.gl/actions';

const sampleTripData = {
  fields: [
    {name: 'tpep_pickup_datetime', format: 'YYYY-M-D H:m:s', type: 'timestamp'},
    {name: 'pickup_longitude', format: '', type: 'real'},
    {name: 'pickup_latitude', format: '', type: 'real'}
  ],
  rows: [
    ['2015-01-15 19:05:39 +00:00', -73.99389648, 40.75011063],
    ['2015-01-15 19:05:39 +00:00', -73.97642517, 40.73981094],
    ['2015-01-15 19:05:40 +00:00', -73.96870422, 40.75424576]
  ]
};

const sampleConfig = {
  visState: {
    filters: [
      {
        id: 'me',
        dataId: 'test_trip_data',
        name: 'tpep_pickup_datetime',
        type: 'timeRange',
        view: 'enlarged'
      }
    ]
  }
};

this.props.dispatch(
  addDataToMap({
    datasets: {
      info: {
        label: 'Sample Taxi Trips in New York City',
        id: 'test_trip_data'
      },
      data: sampleTripData
    },
    option: {
      centerMap: true,
      readOnly: false
    },
    config: sampleConfig
  })
);

Read more about addDataToMap and Saving and loading maps with schema manager.

kepler.gl's People

Contributors

1chandu avatar akre54 avatar b2kdaman avatar benshope avatar birkskyum avatar chrisgervang avatar chrisirhc avatar danielruf avatar dariaterekhova-actionengine avatar dependabot[bot] avatar epeterson320 avatar heimendyd avatar heshan0131 avatar hodoje avatar ibgreen avatar igordykhta avatar jagerts avatar javidhsueh avatar jonsadka avatar jwasilgeo avatar lixun910 avatar macrigiuseppe avatar manassra avatar matheusmonte avatar morphoix avatar neokore avatar nicolasmartinrojo avatar norraell avatar sangarshanan avatar yanhann10 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kepler.gl's Issues

P1: Add an annotation layer

Even if we could pin multiple tooltips at a time to draw attention to specific objects it would make a massive difference.
Annotation layer as a GIS jargon for labelling options where you stick/pin a name, or other string/Int value of table data to got a proper and easy identification. Different of legend and tooltip popup it define clearly (depend of the case) what the data represents. Just something that takes lat, Lon, Text, offset type values. Like geom_text in ggplot2

image uploaded from ios 1

Shan:
My thinking is this can be an additional option for each layer as a ‘Add label’ toggle. point, line, arc and polygon should offer this option

Exporting Config does not include all MapStyles

Exporting the configuration only includes the currently selected map style and not all other map styles that have been added to the configuration. The expectation would be for the map styles to include all configured styles, and for the mapStyle to indicate which of the styles has been selected.

To reproduce the issue, open a default kepler.gl app. It should have the standard map styles added "Dark, Light, Muted Night, Muted Light". By default the Dark style is selected. Click on the "Save / Export" button and select "Export Config". Note that the map styles are empty in the config JSON.

"mapStyle": {
      "styleType": "dark",
      "topLayerGroups": {},
      "visibleLayerGroups": {
        "label": true,
        "road": true,
        "border": false,
        "building": true,
        "water": true,
        "land": true
      },
      "mapStyles": {}
    }

The expectation would be that all the map styles are in the config:

 "mapStyle": {
      "styleType": "dark",
      "topLayerGroups": {},
      "visibleLayerGroups": {
        "label": true,
        "road": true,
        "border": false,
        "building": true,
        "water": true,
        "land": true
      },
      "mapStyles": {
        "dark":  {
          "id": "dark",
          "label": "Dark",
          "icon": "...",
          "url": "..."
          "layerGroups": [],
       },
       "light": { ... },
       "mutednight": { ... },
       "mutedlight": { ... },         
      }
    }

Thus using this.getMapConfig() to preserve the map configuration when loading new data means having to regenerate the mapStyles. i.e.

// Created to show how to replace dataset with new data and keeping the same configuration
  replaceData = () => {
    // Use processCsvData helper to convert csv file into kepler.gl structure {fields, rows}
    const data = Processors.processCsvData(nycTripsSubset);
    // Create dataset structure
    const dataset = {
      data,
      info: {
        id: 'my_data'
        // this is used to match the dataId defined in nyc-config.json. For more details see API documentation.
        // It is paramount that this id mathces your configuration otherwise the configuration file will be ignored.
      }
    };

    // read the current configuration
    const config = this.getMapConfig();

    // addDataToMap action to inject dataset into kepler.gl instance
    this.props.dispatch(addDataToMap({datasets: dataset, config}));

means that the config won't have the complete set of mapstyles.

Possible Bug: Integer column appears as boolean

I've loaded some centroids that have valid coordinates in both geojson and csv (just to see if there was a difference). Map renders, but if I want to classify the data based upon an integer column Kepler recognizes the data, but incorrectly casts the data as a Boolean. Anyone else having the same issue?

CSV loading, but not displaying

Sorry for not having a more descriptive title, or a more specific description of the problem. I'll try to describe what I'm seeing as detailed as possible; and I'm attaching the test data below.

I have a CSV that is just not displaying on the map. It's a three-column file (title, WKT geometry, an "ItemType" string field). Some observations:

  • Upload seems to go fine. Colum types are properly recognized (string, geo, string), and everything looks ok in the grid view
  • After loading, the map stays empty
  • If I add a filter to show just rows of ItemType PLACE, the map renders as it should
  • If I add a filter to show just rows of ItemType OBJECT, the map goes back to blank
  • If I clip the CSV to just the first 500 rows (all of which are OBJECTs), and upload to a fresh map, everything works as it should.

Since the clipped dataset works, I'm guessing there might be something in the data that kepler.gl doesn't like. But I can't figure out what it is. Below, I'm attaching:

P1: Allow to edit individual colors

Request:
I would love the ability to edit the individual colors or have a custom color array type for use in “color based on”.

Reasoning:
Frequently the colors on a map represent an actual data value as opposed to just needing to visually differentiate between the values. For an overly simple example if an analysis is supposed to show locations that are being green lighted for another process, I should have the ability to set a specific green color for those points. And likewise set red, orange, yellow for points depending on their data value.

adding second timestamp filter break the enlarged state

step to reproduce:

  1. load any dataset with 2 timestamp column
  2. add a filter on one time
  3. add a filter on the other time

now 2 filters both mark themselves as enlarged internally. but only the first filter is used in the large panel.
if you click to show the second filter, it will hide the enlarged filter instead of switching to the second.

ability to add imagery tilelayers that aren't Mapbox

mapbox is great but it would be hugely beneficial if users had the option to load in WMS/WMTS imagery tilelayers as basemaps that are hosted/sold by other companies

or if you can't allow entire tilelayers to be added, consider adding single raster images, especially when users want to use kepler in disconnected environments where they woudn't have access to mapbox baselayers they could load a single raster image that is stored locally instead and still get the same effect

Unable to center the map when loading the new data

I was trying to load my trip data with custom visualization configuration to Kepler.gl
However, it seems the bounds of the map is not correct after called addDataToMap action.
Please see the code below:

Actual result:
screen shot 2018-06-19 at 4 16 34 pm
The map is centered to the default bound (San Francisco area).

Expected result:
screen shot 2018-06-19 at 4 29 23 pm
The actual trip is in Tucson, Arizona.

Allowing float argument for "Elevation scale"

First of all, thanks for this amazing work!

When enabling height, the elevation scale parameter is forced to be an integer apparently. But when visualizing small objects (like small individual houses, couple of meters wide), even the smallest value of 1 can be too high.

Can we allow floating point number here, pretty please?

P2: Enable data aggregation or transformation

Problem:
Currently, kepler.gl doesn’t do much with data aggregation or transformation. User has to massage the data in certain way that fits the layer paradigm. For example, I have to deserialize the points of each trip into a set of points with trip id to plot them by point layer.

Suggestions:

  • Enable to do nearest neighbor joins to create line or arc layers from two csv files of points. https://github.com/mourner/geokdbush can be helpful.
  • Join sequence of points (by timestamp/sequence id) into line

DateTime fields read as strings

Kepler.gl looks super cool and I'm excited to be able to use it. After adding my data, my fields only show up as integers and strings, even my DateTime field. I've tried going back into LibreCalc to set the format to date, time, and custom YYYY/MM/DD HH:MM:SS format, but it still just comes through as a string after upload the UTF-8 CSV file.
SyracuseSiteData_Qonly_UTF-8.zip

P0: Oddly drawn polygons

There are at least three oddly drawn polygons (US counties) in the image below: one in Alaska and two in the contiguous 48 states. This was produced with the kepler.gl website.

The was geojson file was originally an sf object stored in a .RData file (R language) - subsequently converted to geojson.

I attempted to replicate this problem with the geojson file in D3 v4 (seen here), but it did not produce the same oddly drawn polygons.

I have the geojson file, kepler config file, and D3 attempt contained within this gist.

GeoJSON LineStrings supported?

Hello,

I'm trying to visualize GeoJSON LineStrings of aircraft flight paths and nothing happens. I'm prompted to pick Lat0/Lng0 and Lat1/Lng0, but that makes it seem like it only supports "lines" with a start/finish location rather than multi-vertex linestrings. Is that correct? Are traditional line strings not supported at this time?

react-onclickoutside throws npm error

Seems kepler points directly too "react-onclickoutside": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.7.1.tgz" & this package is not found in npm registry currently. Throwing build errors due to this package saying {"error":"Not found"} when visiting the tarball link

TimeSlider precision

I would like to thanks the team first for this awesome projet :)

I have one week of data to display, and the frequency of data is per second.
I wanted to implement a TimeSlider widget to reduce the number of my data on screen, but it seems I can't reduce the slider's interval less than 24h...

Is there any hack to reduce the quantity of time in the time slider please (console hack, something like that...)?

Thanks!

403 Forbidden Error: Not able to render base map styles 'Light' or 'Muted Light' when Label Map Layer is selected

When running a local deployment of kepler.gl (also problem happened when doing a Vis Academy embed kepler.gl tutorial), the original Dark Base Map Style loads perfectly fine with my mapbox token, but when I try to switch the Base Map Style to 'Light' or 'Muted Light' the map doesn't render and I get loads of error.

The error doesn't appear when I try to load 'Muted Dark'.

Here is a screenshot of the map that loads when you select Light or Muted Light, it is not the correct basemap and if you zoom in much further even the simple country outline disappears and no labels or borders appear. I have also attached a screenshot of the console errors. I am able to load data no problem and am able to load custom styles no problem.
screenshot 8
screenshot 9

Yarn install fails - `react-onclickoutside-6.7.1` 404's from NPM

Problem

When running yarn install as of ~4PM PST on 5/25/18, the package for https://registry.npmjs.org/Pomax/-/react-onclickoutside-6.7.1.tgz fails to download from NPM with a 404 error. I've replicated this on a local machine and in Travis tests, and it looks to be specific to the NPM URL route.

Impact

  • Developers cannot install a local copy of kepler.gl
  • All tests for new PRs fail (#56)

cc/ @heshan0131

GeometryCollection GeoJSON not supported

Adding a GeometryCollection GeoJson layer throw this error:

deck.gl deck.gl error during initialization of <GeoJsonLayer:'vyik0jh'> Error: GeoJsonLayer: GeometryCollection not supported. 
Error: GeoJsonLayer: GeometryCollection not supported.

You can reproduce it with testCase.csv.zip

P2: Enable data aggregation or transformation

End up I need to massage the data in certain way that fits the layer paradigm. For example, I have to deserialize the points of each trip into a set of points with trip id to plot them by point layer.

Example: Join sequence of points (by timestamp/sequence id) into line

Demo App Fails Webpack Build

I'm currently unable to build the demo-app project in the /examples directory. Following the included readme, I ran npm install followed by npm start, but I'm receiving the following output. Any ideas? I'm not particularly well-versed in React, so am I missing something obvious?

> @ start /Users/username/Projects/demos/kepler-demo/node_modules/kepler.gl/examples/demo-app
> webpack-dev-server --progress --hot --open

 10% building modules 1/1 modules 0 active
Project is running at http://localhost:8080/
webpack output is served from /
 10% building modules 3/3 modules 0 activewebpack: wait until bundle finished: /
Hash: bfbb95190c60eccaeb52
Version: webpack 2.7.0
Time: 588ms
        Asset    Size  Chunks                    Chunk Names
    bundle.js  351 kB       0  [emitted]  [big]  app
bundle.js.map  413 kB       0  [emitted]         app
chunk    {0} bundle.js, bundle.js.map (app) 321 kB [entry] [rendered]
    [2] (webpack)/hot/emitter.js 77 bytes {0} [built]
    [3] (webpack)-dev-server/client?http://localhost:8080 7.93 kB {0} [built]
    [4] (webpack)/hot/dev-server.js 1.57 kB {0} [built]
    [5] ./src/main.js 369 bytes {0} [built] [failed] [1 error]
    [7] ./~/ansi-regex/index.js 135 bytes {0} [built]
    [8] ./~/events/events.js 8.33 kB {0} [built]
    [9] ./~/html-entities/index.js 231 bytes {0} [built]
   [12] ./~/loglevel/lib/loglevel.js 7.86 kB {0} [built]
   [18] ./~/strip-ansi/index.js 161 bytes {0} [built]
   [19] ./~/url/url.js 23.3 kB {0} [built]
   [21] (webpack)-dev-server/client/overlay.js 3.67 kB {0} [built]
   [22] (webpack)-dev-server/client/socket.js 1.08 kB {0} [built]
   [24] (webpack)/hot nonrecursive ^\.\/log$ 160 bytes {0} [built]
   [25] (webpack)/hot/log-apply-result.js 1.02 kB {0} [built]
   [26] multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/main.js 52 bytes {0} [built]
     + 12 hidden modules

ERROR in ./src/main.js
Module parse failed: /Users/username/Projects/demos/kepler-demo/node_modules/kepler.gl/examples/demo-app/src/main.js Unexpected token (36:2)
You may need an appropriate loader to handle this file type.
|
| const Root = () => (
|   <Provider store={store}>
|     <Router history={history}>
|       <Route path="/(:id)" component={App} />
 @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/main.js
webpack: Failed to compile.

Custom basemap background color

One of the custom mapbox styles questions we got was to be able to set a custom background color when using a basemap.

We'll need a mapbox style url to reproduce this issue.

Image Layer Possibility

I would like to project satellite images as a layer under geojson map data. Does anyone have any ideas or suggestions on how I could do this?

I have json files with GPS bounding boxes and associated satellite imagery (low quality jpg's and high quality tif's) that cover the spaces that I want to view.

My initial idea was to extend the GridLayer class, but so far I've had little luck. Any suggestsions would be highly appreciated

P0: Allow to import the exported map config

That would also open up the ability to reuse styles across projects or even on multiple datasets in the same project. You could possibly even allow for multiple datasets to be in a single layer with a single style (assuming their data structure is consistent)

  1. Save map config via save map choose config only, and downlaod the config json, and store somewhere that can be accessed via url

  2. Load kepler.gl/#/demo?mapConfig=http://xxxxx.xxxx.json. Load kepler.gl with a preset config (layers, filters, mapStyles etc).

3.1 The config might contain 1 dataset, in which case kepler.gl try to map layer, filter to it
3.2 The config contain 2 dataset...........

Rules to match config to data: dataset must contain field that layer column and layer color / size by are depends on. must contain fields that filters are depends on....

Currently
if you call receiveMapconfig without data preloaded, kepler will try to match layers / filters based on dataId, it is not finding those fieds, then it will saved the layer/filter to layersToBeMerged filtersToBeMerged. When you then call addDataToMap without config. kepler will use the to be merged the ones.

For Example:

  • If someone saved layer 1 -> dataset a; layer 2 -> dataset b
  • upload dataset a -> kepler create layer 1. layer 2 will not be match, it will be stored as layersToBeMerged in visState reducer

Increase upload limit

I am trying to upload 540 MB of data. Chrome won't support but it throws no error. Safari crashes and reloads the web page. Firefox too won't load the data.

what is the best way to go about making a sharable version of the map?

I've really enjoyed working with data in keplergl and have recommended it to others. One feedback question I've gotten back, and I've had difficulty with as well, is :

what is the best way to go about making a sharable version of the map?

It is very easy and intuitive to make things from client-side GUI, but they go away when you close the browser. There is export functionality, but not a lot of documentation on how to go about building a map with that exported data and configuration that you could share via github pages. There have been some great Medium posts on how users can load their own data into the application, perhaps something similar would be helpful if not here within a separate readme?

If someone wants to take this on, feel free to tag me for feedback / edits.

CSV Not Working

I'm trying to upload a very small CSV (2MB), and I followed the guidelines by having columns named x_lat, x_lng, and some others, but when I click to load the file, the interface has a spinning wheel indefinitely and never goes to the mapping screen. By the way, the project looks very interesting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.