Project Icon

kepler.gl

开源大规模地理数据可视化平台

kepler.gl是一个开源的Web地理数据可视化平台,能够高效处理和展示大规模位置数据。该平台基于MapLibre GL和deck.gl开发,支持实时渲染数百万数据点和进行空间聚合分析。作为React组件,kepler.gl采用Redux管理状态,易于集成到现有React应用中。平台提供多样化的地图样式和界面主题定制功能,适用于地理数据探索和分析场景。其灵活的架构设计使开发者能够根据需求进行功能扩展。

版本 构建 星标 MIT许可证 Fossa

kepler.gl | 网站 | 演示应用 | 文档

Kepler.gl

Kepler.gl演示

[Kepler.gl][web]是一个与数据无关的、高性能的基于Web的应用程序,用于大规模地理位置数据集的可视化探索。它基于MapLibre GLdeck.gl构建,kepler.gl可以渲染数百万个点,代表数千次行程,并实时执行空间聚合。

Kepler.gl也是一个React组件,使用Redux来管理其状态和数据流。它可以嵌入到其他React-Redux应用程序中,并且高度可定制。关于如何在你的应用中嵌入kepler.gl,请查看vis.academy上的这个分步[教程][vis-academy]。

链接

  • [网站][web]
  • [演示应用][demo-app]
  • [示例][examples]
  • [入门][get-started]
  • [应用用户指南][user-guide]
  • [Jupyter Widget用户指南][user-guide-jupyter]
  • [教程][vis-academy]
  • [Stack Overflow][stack]
  • [贡献指南][contributing]
  • [API参考][api-reference]
  • [路线图][roadmap]

环境

使用Node 18.18.2或以上版本,不支持/未测试旧版本的node。 为获得最佳结果,使用nvm nvm install

安装kepler.gl

安装node(> 18.18.2)、yarn和项目依赖

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

kepler.gl基于[mapbox][mapbox]构建。你需要一个[Mapbox访问令牌][mapbox-token]才能使用它。

如果你不使用模块打包器,也没关系。Kepler.gl npm包在umd文件夹中包含预编译的生产UMD构建。 你可以按如下方式将脚本标签添加到你的html文件中:

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

或者如果你愿意,你可以加载特定版本

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

开发kepler.gl

查看[开发指南][developers]以在本地开发kepler.gl。

基本用法

以下是将kepler.gl导入到你的应用程序的基本步骤。你也可以查看examples文件夹。文件夹中的每个示例都可以安装和本地运行。

1. 挂载reducer

Kepler.gl使用Redux管理其内部状态,并使用[react-palm][react-palm]中间件处理副作用。

你还需要将react-palmtaskMiddleware添加到你的store中。我们正在积极开发一个不需要react-palm的解决方案,但它仍然是一个非常轻量级的副作用管理工具,比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({
  // <-- 在你的应用中挂载kepler.gl reducer
  keplerGl: keplerGlReducer,

  // 你的其他reducers在这里
  app: appReducer
});

// 使用createStore
export default createStore(
  reducer,
  initialState,
  applyMiddleware(
    enhanceReduxMiddleware([
      /* 在这里添加其他中间件 */
    ])
  )
);

或者如果使用enhancer:

// 使用enhancers
const initialState = {};
const middlewares = enhanceReduxMiddleware([
  // 在这里添加其他中间件
]);
const enhancers = [applyMiddleware(...middlewares)];

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

如果你将kepler.gl reducer挂载在keplerGl以外的地址,或者kepler.gl reducer没有挂载在你的状态的根部,你需要在使用getState属性挂载组件时指定它的路径。

阅读更多关于[Reducers][reducers]的信息。

2. 挂载组件

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

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

属性

id(字符串,必需)
  • 默认值:map

此KeplerGl实例的id。如果你的应用中有多个KeplerGl实例,则id是必需的。它定义了存储在KeplerGl reducer中的KeplerGl状态的属性名。例如,id为foo的KeplerGl组件的状态存储在state.keplerGl.foo中。

如果你使用相同的id创建多个kepler.gl实例,由该条目定义的kepler.gl状态将被最新实例覆盖并重置为空白状态。

mapboxApiAccessToken(字符串,必需*)
  • 默认值:undefined

默认情况下,kepler.gl使用mapbox-gl.js渲染其基础地图。你可以在[mapbox][mapbox]创建一个免费账户,并在[www.mapbox.com/account/access-tokens][mapbox-token]创建一个令牌。

如果你用自己的地图样式替换了kepler.gl的默认地图样式,并且它们不是Mapbox样式,则不需要mapboxApiAccessToken

阅读更多关于[自定义地图样式][custom-map-styles]的信息。

getState(函数,可选)
  • 默认值:state => state.keplerGl

你的reducer中根keplerGl状态的路径。

width(数字,可选)
  • 默认值:800

KeplerGl UI的宽度。

height(数字,可选)
  • 默认值:800
appName(字符串,可选)
  • 默认值:Kepler.Gl

在侧面板头部显示的应用名称

version(字符串,可选)
  • 默认值:v1.0

在侧面板头部显示的版本

onSaveMap(函数,可选)
  • 默认值:undefined

在侧面板头部点击保存地图URL时调用的操作。

onViewStateChange(函数,可选)
  • 默认值:undefined
  • 参数:viewState - 包含经度、纬度、缩放等参数的更新后的视图状态对象

当地图视口更新时触发的操作。

getMapboxRef(mapbox, index) (函数,可选)
  • 默认值:undefined

KeplerGL添加或移除包含内部Mapbox地图的MapContainer组件时调用的函数。

mapbox参数在添加时是一个MapRef,在移除时是null

index参数对单个地图为0,对额外的地图为1(因为KeplerGL支持可选的分屏地图视图)。

actions (对象,可选)
  • 默认值:{}

用于替换默认kepler.gl action创建器的action创建器。仅在需要修改action payload时使用自定义action。

mint (布尔值,可选)
  • 默认值:true

组件挂载时是否加载全新的空白状态。当传入mint: true时,kepler.gl组件在重新挂载相同组件时总是加载新的状态,该组件内的状态在卸载时将被销毁。 传入mint: false时,kepler.gl将在组件卸载后仍保留其状态在store中,并在重新挂载时将其用作初始状态。这在模态框中挂载kepler.gl并在重新打开时保持相同地图时很有用。

阅读更多关于[组件][components]的信息。

theme (对象 | 字符串,可选)
  • 默认值:null

可选值为"dark""light""base" 你可以传入主题名称或用于自定义Kepler.gl样式的对象。Kepler.gl除默认的"dark"主题外还提供了"light"主题。当传入主题对象时,Kepler.gl将使用传入的值覆盖theme中的值。

阅读更多关于[自定义主题][custom-theme]的信息

mapboxApiUrl (字符串,可选)

  • 默认值:https://api.mapbox.com

如果你使用自己的mapbox瓦片服务器,可以传入你自己的瓦片服务器API URL。

mapStylesReplaceDefault (布尔值,可选)

  • 默认值:false

kepler.gl提供4种地图样式可供选择。如果你想提供自己的mapStyles,请传入true。详见下文。

mapStyles (数组,可选)

  • 默认值:[]

你可以提供额外的地图样式在地图样式选择面板中显示。默认情况下,额外的地图样式将添加到默认地图样式中。如果传入mapStylesReplaceDefault: true,它们将替换默认样式。kepler.gl将尝试根据你的样式的id命名约定对图层进行分组,并用它来允许切换基础地图图层的可见性。提供你自己的layerGroups来覆盖默认值以实现更准确的图层分组。

每个mapStyles应具有以下属性:

  • id (字符串,必需) 唯一字符串,不应为以下保留值之一:dark light muted muted_night
  • label (字符串,必需) 在地图样式选择面板中显示的名称
  • url (字符串,必需) mapbox样式url或指向按照Mapbox GL样式规范编写的地图样式json对象的url
  • icon (字符串,可选) 样式的图标图片,可以是url或图片数据url
  • layerGroups (数组,可选)
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
      },
      {
        // 添加这个将保留3D建筑选项
        slug: '3d building',
        filter: () => false,
        defaultVisibility: false
      }
    ]
  }
];

阅读更多关于[自定义地图样式][custom-map-styles]的信息。

initialUiState (对象,可选)

  • 默认值:undefined

应用于uiState reducer的初始UI状态,值将与默认的INITIAL_UI_STATE进行浅合并

localeMessages (对象,可选)

  • 默认值:undefined 修改默认翻译或添加新翻译

阅读更多关于[本地化][localization]的信息。

3. 向keplerGl reducer分发自定义actions。

使用reducer而不是React组件状态来处理keplerGl状态的一个优势是可以灵活地自定义其行为。如果你的应用中只有一个KeplerGl实例,或者从不打算从组件外部向KeplerGl分发actions, 你无需担心转发dispatch,可以直接进入下一节。但生活充满定制,我们希望让你的体验尽可能愉快。

有多种方法可以向特定的KeplerGl实例分发actions。

  • 在根reducer中,使用reducer更新器。

kepler.gl中的每个action都映射到一个reducer更新器。你可以导入与特定action对应的reducer更新器,并使用前一个状态和action payload调用它来获取更新后的状态。 例如,updateVisDataUpdaterActionTypes.UPDATE_VIS_DATA的更新器(查看每个reducer reducers/vis-state.js以了解action到更新器的映射)。 这里有一个示例,说明如何监听应用action QUERY_SUCCESS并调用updateVisDataUpdater将数据加载到Kepler.Gl中。

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

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

  app: appReducer
});

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

          // 'map'是keplerGl实例的id
          map: {
            ...state.keplerGl.map,
            visState: visStateUpdaters.updateVisDataUpdater(state.keplerGl.map.visState, {
              datasets: action.payload
            })
          }
        }
      };
  }
  return reducers(state, action);
};

export default composedReducer;

阅读更多关于[使用更新器修改kepler.gl状态][using-updaters]的信息

  • 使用redux connect

你可以使用connect为组件添加一个dispatch函数,该函数向特定的keplerGl组件分发actions。

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

// action和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);
  • 包装action payload

你也可以简单地使用wrapTo辅助函数将action包装成一个forward action

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

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

// 创建一个函数将action payload包装到'foo'
const wrapToMap = wrapTo('foo');
const MapContainer = ({dispatch}) => (
  <div>
    <button onClick={() => dispatch(wrapToMap(toggleFullScreen())} />
    <KeplerGl
      id="foo"
    />
  </div>
);

阅读更多关于[转发分发actions][forward-actions]的信息

4. 自定义样式。

Kepler.gl使用Styled-Components实现CSS样式。通过使用该框架,Kepler.gl提供了以下方式来自定义其样式/主题:

  • 传递Theme prop
  • 使用Styled-Components的ThemeProvider

可自定义的属性列表在这里theme

自定义主题示例

传递Theme prop。

你可以通过向Kepler.gl React组件传递theme props来自定义Kepler.gl主题,如下所示:

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}
  />
);

如你所见,customTheme 对象定义了某些属性,这些属性将覆盖 Kepler.gl 的默认样式规则。

Styled-Components 主题提供者

为了使用 ThemeProvider 自定义 Kepler.gl 主题,你可以简单地用 ThemeProvider 包装 Kepler.gl,如下所示:

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. 渲染自定义 UI 组件

每个人都希望能灵活地渲染自定义的 kepler.gl 组件。Kepler.gl 有一个依赖注入系统,允许你注入组件到 KeplerGl 中替换现有的组件。你只需要为你想要替换的组件创建一个组件工厂,导入原始组件工厂,并在你的应用程序中挂载 KeplerGl 的根组件处调用 injectComponents。 看看 examples/demo-app/src/app.js,看它如何在 kepler.gl 中渲染自定义侧面板头部

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

// 定义自定义头部
const CustomHeader = () => <div>我的 kepler.gl 应用</div>;
const myCustomHeaderFactory = () => CustomHeader;

// 将自定义头部注入到 Kepler.gl 中,替换默认头部
const KeplerGl = injectComponents([[PanelHeaderFactory, myCustomHeaderFactory]]);

// 渲染 KeplerGl,它将渲染你的自定义头部而不是默认头部
const MapContainer = () => (
  <div>
    <KeplerGl id="foo" />
  </div>
);

使用 withState 辅助函数将 reducer 状态和动作作为额外的 props 添加到自定义组件中。

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

// 自定义动作包装到挂载的实例
const addTodo = text =>
  wrapTo('map', {
    type: 'ADD_TODO',
    text
  });

// 定义自定义头部
const CustomHeader = ({visState, addTodo}) => (
  <div onClick={() => addTodo('hello')}>{`已加载 ${
    Object.keys(visState.datasets).length
  } 个数据集`}</div>
);

// 现在 CustomHeader 将接收 `visState` 和 `addTodo` 作为额外的 props
const myCustomHeaderFactory = () =>
  withState(
    // keplerGl 状态镜头
    [visStateLens],
    // 自定义 mapStateToProps
    headerStateToProps,
    // 动作
    {addTodo}
  )(CustomHeader);

阅读更多关于[替换 UI 组件][replace-ui-component]的内容

6. 如何向地图添加数据

要与 kepler.gl 实例交互并向其添加新数据,你可以在应用程序内的任何地方调度 addDataToMap 动作。它向 kepler.gl 实例添加一个或多个数据集,并更新完整的配置(mapState、mapStyle、visState)。

参数

  • data [Object][40] *必需

    • datasets ([Array][41]<[Object][40]> | [Object][40]) *必需 datasets 可以是一个数据集或数据集数组 每个数据集对象需要有 infodata 属性。

      • datasets.info [Object][40] -数据集的信息
        • datasets.info.id [string][42] 此数据集的 id。如果定义了 config,id 应该与 config 中的 dataId 匹配。
        • datasets.info.label [string][42] 此数据集的显示名称
      • datasets.data [Object][40] *必需 数据对象,以表格格式包含 2 个属性 fieldsrows
        • datasets.data.fields [Array][41]<[Object][40]> *必需 字段数组,
          • datasets.data.fields.name [string][42] *必需 字段名称,
        • datasets.data.rows [Array][41]<[Array][41]> *必需 行数组,以表格格式包含 fieldsrows
    • options [Object][40]

      • options.centerMap [boolean][43] 默认值: true 如果 centerMap 设置为 true,kepler.gl 将把地图视图放置在数据点边界内
      • options.readOnly [boolean][43] 默认值: false 如果 readOnly 设置为 true,左侧设置面板将被隐藏
      • options.keepExistingConfig [boolean][43] 默认值: false 是否保留现有的地图配置,包括图层、过滤器和分割地图。
  • config [Object][40] 此对象将包含完整的 kepler.gl 实例配置 {mapState, mapStyle, visState}

Kepler.gl 提供了一个简单的 API KeplerGlSchema.getConfigToSave 来生成当前 kepler 实例配置的 json blob。

示例

// 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: '纽约市示例出租车行程',
        id: 'test_trip_data'
      },
      data: sampleTripData
    },
    option: {
      centerMap: true,
      readOnly: false
    },
    config: sampleConfig
  })
);

阅读更多关于 addDataToMap 和[使用模式管理器保存和加载地图][saving-loading-w-schema]的内容。 [contributing]: contributing/README.md [demo-app]: http://kepler.gl/#/demo [github]: https://github.com/keplergl/kepler.gl [github-pr]: https://help.github.com/articles/creating-a-pull-request/ [mapbox]: https://www.mapbox.com [mapbox-token]: https://www.mapbox.com/help/define-access-token/ [developers]: contributing/DEVELOPERS.md [examples]: https://github.com/keplergl/kepler.gl/tree/master/examples [react-palm]: https://github.com/btford/react-palm [roadmap]: https://github.com/keplergl/kepler.gl/wiki/Kepler.gl-2019-Roadmap [stack]: https://stackoverflow.com/questions/tagged/kepler.gl [web]: http://www.kepler.gl/ [vis-academy]: http://vis.academy/#/kepler.gl/ [user-guide]: docs/user-guides/README.md [user-guide-jupyter]: docs/keplergl-jupyter/README.md [api-reference]: docs/api-reference/README.md [get-started]: ./docs/api-reference/get-started.md [reducers]: docs/api-reference/reducers/README.md [components]: docs/api-reference/components/README.md [custom-theme]: docs/api-reference/custom-theme/README.md [reducers]: docs/api-reference/reducers/README.md [actions-updaters]: docs/api-reference/actions/README.md [processors]: docs/api-reference/processors/README.md [schemas]: docs/api-reference/schemas/README.md [using-updaters]: ./docs/api-reference/advanced-usages/using-updaters.md [custom-map-styles]: ./docs/api-reference/advanced-usages/custom-map-styles.md [forward-actions]: ./docs/api-reference/advanced-usages/forward-actions.md [replace-ui-component]: ./docs/api-reference/advanced-usages/replace-ui-component.md [saving-loading-w-schema]: ./docs/api-reference/advanced-usages/saving-loading-w-schema.md [localization]: ./docs/api-reference/localization/README.md [40]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object [41]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array [42]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String [43]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean [44]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number [45]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号