使用【deck.gl】和react-map-gl来显示背景地图
最初
我们使用 react-map-gl 来展示背景地图,并放置了地图控制按钮。
由于与 deck.gl 结合使用时遇到了一些困难,我们来分享一下。
环境建立
创建一个React项目
因为deck.gl与React兼容性良好,所以选择使用React。
如果你使用 TypeScript,请参考 这里(由于类型检查容易出错,所以建议使用 JavaScript。顺便说一句,官方文档中没有写明类型,所以需要查看源代码…)
npx create-react-app sample
安装库文件
安装deck.gl。
npm install deck.gl --save
如果要安装 react-map-gl,请将 mapbox-gl 更改为 maplibre-gl,使用 MapLibre GL JS。
npm install --save react-map-gl mapbox-gl
实施
地图背景展示
我們會參考deck.gl官方文件中的MapboxOverlay進行實現。
要在react-map-gl v7的控制下使用deck.gl,必須使用MapboxOverlay。
import React from 'react';
import { LineLayer } from '@deck.gl/layers';
import { MapboxOverlay } from '@deck.gl/mapbox';
import Map, { useControl } from 'react-map-gl';
// Mapbox GL JS
import 'mapbox-gl/dist/mapbox-gl.css';
import './style.css';
const App = () => {
const DeckGLOverlay = (props) => {
const overlay = useControl(() => new MapboxOverlay(props));
overlay.setProps(props);
return null;
};
// Mapboxアクセストークン
const MAPBOX_ACCESS_TOKEN = 'your_access_token';
// 初期ビューポートの設定
const INITIAL_VIEW_STATE = {
latitude: 38.875584,
longitude: 139.7454316,
bearing: 0,
pitch: 0,
zoom: 5,
};
// LineLayerで使うデータ
const data = [{ sourcePosition: [139.7454316, 38.875584], targetPosition: [145.7454316, 40.875584] }];
// LineLayer
const layers = [new LineLayer({ id: 'line-layer', data })];
return (
<div className="App">
<Map
initialViewState={INITIAL_VIEW_STATE}
mapStyle="mapbox://styles/mapbox/dark-v9"
style={{ width: '100vw', height: '100vh' }}
mapboxAccessToken={MAPBOX_ACCESS_TOKEN}
>
<DeckGLOverlay layers={layers} />
</Map>
</div>
);
};
export default App;
由于官方文件是用TypeScript编写的,所以我用JavaScript重新编写了它。
官方文件中没有设置地图的样式,但如果不设置样式,地图将无法显示。
我已成功显示了背景地图和deck.gl的LineLayer!
用于控制的按钮布局
在 react-map-gl 中,有一些用于控制地图的部件可供选择。请查看 API 参考以获取详细信息。
这次我们将添加GeolocateControl控件,它可显示当前位置,FullscreenControl控件可切换到全屏模式,NavigationControl控件可放大或缩小地图,ScaleControl控件可显示比例尺。
实施非常简单。只需导入并添加组件即可。
import React from 'react';
import { LineLayer } from '@deck.gl/layers';
import { MapboxOverlay } from '@deck.gl/mapbox';
import Map, { useControl, NavigationControl, FullscreenControl, ScaleControl, GeolocateControl } from 'react-map-gl';
// Mapbox GL JS
import 'mapbox-gl/dist/mapbox-gl.css';
import './style.css';
const App = () => {
const DeckGLOverlay = (props) => {
const overlay = useControl(() => new MapboxOverlay(props));
overlay.setProps(props);
return null;
};
// Mapboxアクセストークン
const MAPBOX_ACCESS_TOKEN = 'your_access_token';
// 初期ビューポートの設定
const INITIAL_VIEW_STATE = {
latitude: 38.875584,
longitude: 139.7454316,
bearing: 0,
pitch: 0,
zoom: 5,
};
// LineLayerで使うデータ
const data = [{ sourcePosition: [139.7454316, 38.875584], targetPosition: [145.7454316, 40.875584] }];
// LineLayer
const layers = [new LineLayer({ id: 'line-layer', data })];
return (
<div className="App">
<Map
initialViewState={INITIAL_VIEW_STATE}
mapStyle="mapbox://styles/mapbox/dark-v9"
style={{ width: '100vw', height: '100vh' }}
mapboxAccessToken={MAPBOX_ACCESS_TOKEN}
>
<DeckGLOverlay layers={layers} />
<GeolocateControl />
<FullscreenControl />
<NavigationControl />
<ScaleControl />
</Map>
</div>
);
};
export default App;
我们可以安排控制按钮等的位置!能够轻松引入这些部件确实很方便。
闲聊:迷恋因素
参照deck.gl官方文档的“添加基础地图”部分时,我出现了问题。
实际上,这并不是一个推荐的方法…
import React from 'react';
import DeckGL from '@deck.gl/react';
import { LineLayer } from '@deck.gl/layers';
import { Map } from 'react-map-gl';
// Mapbox GL JS
import 'mapbox-gl/dist/mapbox-gl.css';
import './style.css';
const App = () => {
// Mapboxアクセストークン
const MAPBOX_ACCESS_TOKEN = 'your_access_token';
// 初期ビューポートの設定
const INITIAL_VIEW_STATE = {
latitude: 38.875584,
longitude: 139.7454316,
bearing: 0,
pitch: 0,
zoom: 5,
};
// LineLayerで使うデータ
const data = [{ sourcePosition: [139.7454316, 38.875584], targetPosition: [145.7454316, 40.875584] }];
// LineLayer
const layers = [new LineLayer({ id: 'line-layer', data })];
return (
<div className="App">
<DeckGL initialViewState={INITIAL_VIEW_STATE} controller={true} layers={layers}>
<Map mapboxAccessToken={MAPBOX_ACCESS_TOKEN} mapStyle="mapbox://styles/mapbox/dark-v9" />
</DeckGL>
</div>
);
};
export default App;
公式文档中没有 import ‘mapbox-gl/dist/mapbox-gl.css’; 这个代码,但是如果没有它,可能会导致属性等样式混乱,所以最好还是加上。
我可以这样通过deck.gl的图层和react-map-gl的背景地图来展示!
然而,这存在一个问题。
如果我放置react-map-gl提供的地图控制按钮,那就无法点击这些按钮。
import React from 'react';
import DeckGL from '@deck.gl/react';
import { LineLayer } from '@deck.gl/layers';
import { Map, useControl, NavigationControl, FullscreenControl, ScaleControl, GeolocateControl } from 'react-map-gl';
// Mapbox GL JS
import 'mapbox-gl/dist/mapbox-gl.css';
import './style.css';
const App = () => {
// Mapboxアクセストークン
const MAPBOX_ACCESS_TOKEN = 'your_access_token';
// 初期ビューポートの設定
const INITIAL_VIEW_STATE = {
latitude: 38.875584,
longitude: 139.7454316,
bearing: 0,
pitch: 0,
zoom: 5,
};
// LineLayerで使うデータ
const data = [{ sourcePosition: [139.7454316, 38.875584], targetPosition: [145.7454316, 40.875584] }];
// LineLayer
const layers = [new LineLayer({ id: 'line-layer', data })];
return (
<div className="App">
<DeckGL initialViewState={INITIAL_VIEW_STATE} controller={true} layers={layers}>
<Map mapboxAccessToken={MAPBOX_ACCESS_TOKEN} mapStyle="mapbox://styles/mapbox/dark-v9">
<GeolocateControl />
<FullscreenControl />
<NavigationControl />
<ScaleControl />
</Map>
</DeckGL>
</div>
);
};
export default App;
按下按钮没有任何反应。
在deck.gl的官方文档中,提到了与Mapbox一起使用的部分,包括了react-map-gl。
要在react-map-gl v7的控件中使用deck.gl,必须使用MapboxOverlay。
要在react-map-gl v7的控件中使用deck.gl,则需要使用MapboxOverlay。
由于 react-map-gl 的最新版本是 v7,所以适用。
这个问题我遇到了很多困难,希望 Get-Started 里面也能提到。
最后
在无法按下按钮的问题上,我遇到了相当大的困难,但在查阅官方文档后,找到了解决方案并成功解决了问题。这种陷阱问题很常见。如果遇到困难,让我们养成查看官方文档的习惯吧。