使用【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重新编写了它。
官方文件中没有设置地图的样式,但如果不设置样式,地图将无法显示。

image.png

我已成功显示了背景地图和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;
image.png

我们可以安排控制按钮等的位置!能够轻松引入这些部件确实很方便。

闲聊:迷恋因素

参照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’; 这个代码,但是如果没有它,可能会导致属性等样式混乱,所以最好还是加上。

image.png

我可以这样通过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;
image.png

按下按钮没有任何反应。

image.png
image.png

在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 里面也能提到。

最后

在无法按下按钮的问题上,我遇到了相当大的困难,但在查阅官方文档后,找到了解决方案并成功解决了问题。这种陷阱问题很常见。如果遇到困难,让我们养成查看官方文档的习惯吧。

广告
将在 10 秒后关闭
bannerAds