首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用deck.gl缩放到圆弧的边界?

如何使用deck.gl缩放到圆弧的边界?
EN

Stack Overflow用户
提问于 2020-08-20 02:01:00
回答 1查看 1.4K关注 0票数 1

我已经使用deck.gl创建了一些圆弧。当您单击不同的点/多边形时,不同国家/地区之间会出现不同的圆弧。在执行此操作时,我希望地图缩放到这些弧线的边界。

为了清楚起见,这里有一个例子:当点击Glasgow时,我想要缩放到所示的弧线(尽可能紧密地):

似乎可以使用WebMercatorViewport调用fitBounds (请参阅:https://deck.gl/docs/api-reference/core/web-mercator-viewport#webmercatorviewport)

不过,我不清楚这是如何使用的。我试过找一些例子,但都找不到。我如何才能将其添加到我已有的内容中?

下面是圆弧的代码:

代码语言:javascript
运行
复制
    fetch('countries.json')
    .then(res => res.json())
    .then(data => {

      console.log('data',data)

      const inFlowColors = [
        [0, 55, 255]
      ];

      const outFlowColors = [
        [255, 200, 0]
      ];

      const countyLayer = new deck.GeoJsonLayer({
        id: 'geojson',
        data: data,
        stroked: true,
        filled: true,
        autoHighlight: true,
        lineWidthScale: 20,
        lineWidthMinPixels: 1,
        pointRadiusMinPixels: 10,
        opacity:.5,
        getFillColor: () => [0, 0, 0],
        getLineColor: () => [0,0,0],
        getLineWidth: 1,
        onClick: info => updateLayers(info.object),
        pickable: true
      });

      const deckgl = new deck.DeckGL({
        mapboxApiAccessToken: 'pk.eyJ1IjoidWJlcmRhdGEiLCJhIjoiY2pudzRtaWloMDAzcTN2bzN1aXdxZHB5bSJ9.2bkj3IiRC8wj3jLThvDGdA',
        mapStyle: 'mapbox://styles/mapbox/light-v9',
        initialViewState: {
          longitude: -19.903283,
          latitude: 36.371449,
          zoom: 1.5,
          maxZoom: 15,
          pitch: 0,
          bearing: 0
        },
        controller: true,
        layers: []
      });

      updateLayers(
        data.features.find(f => f.properties.name == 'United States' )
      );

      function updateLayers(selectedFeature) {
        const {exports, centroid, top_exports, export_value} = selectedFeature.properties;

        const arcs = Object.keys(exports).map(toId => {
          const f = data.features[toId];
          return {
            source: centroid,
            target: f.properties.centroid,
            value: exports[toId],
            top_exports: top_exports[toId],
            export_value: export_value[toId]
          };
        });

        arcs.forEach(a => {
          a.vol = a.value;
        });

        const arcLayer = new deck.ArcLayer({
          id: 'arc',
          data: arcs,
          getSourcePosition: d => d.source,
          getTargetPosition: d => d.target,
          getSourceColor: d => [0, 55, 255],
          getTargetColor: d => [255, 200, 0],
          getHeight: 0,
          getWidth: d => d.vol
        });

        deckgl.setProps({
          layers: [countyLayer, arcLayer]
        });

      }

    });

这是一个插入器:https://plnkr.co/edit/4L7HUYuQFM19m9rI

EN

回答 1

Stack Overflow用户

发布于 2020-08-25 19:08:37

我试着让它变得简单,从ReactJs的原始实现开始,然后尝试转换成普通的。

在ReactJS中,我会这样做。

react-map-gl导入LinearInterpolatorWebMercatorViewport

代码语言:javascript
运行
复制
import {LinearInterpolator, WebMercatorViewport} from 'react-map-gl';

然后,我为视口定义了一个useEffect:

代码语言:javascript
运行
复制
const [viewport, setViewport] = useState({
    latitude: 37.7577,
    longitude: -122.4376,
    zoom: 11,
    bearing: 0,
    pitch: 0
});

然后我将定义一个要显示的层:

代码语言:javascript
运行
复制
const layerGeoJson = new GeoJsonLayer({
    id: 'geojson',
    data: someData,
    ...
    pickable: true,
    onClick: onClickGeoJson,
    });

现在我们需要定义onClickGeoJson

代码语言:javascript
运行
复制
const onClickGeoJson = useCallback((event) => {
    const feature = event.features[0];
    const [minLng, minLat, maxLng, maxLat] = bbox(feature); // Turf.js
    const viewportWebMercator = new WebMercatorViewport(viewport);
    const {longitude, latitude, zoom} = viewport.fitBounds([[minLng, minLat], [maxLng, maxLat]], {
        padding: 20
    });
    viewportWebMercator = {
        ...viewport,
        longitude,
        latitude,
        zoom,
        transitionInterpolator: new LinearInterpolator({
            around: [event.offsetCenter.x, event.offsetCenter.y]
        }),
        transitionDuration: 1500,
    };
    setViewport(viewportWebMercator);
}, []);

第一个问题:用这种方法我们是在点或多边形上点击拟合,但你想要的是拟合圆弧。我认为解决这类问题的唯一方法是在多边形中添加一个关于圆弧边界的引用。您可以预先计算每个功能的边界并将其存储在geojson中(单击的元素),或者您可以仅在feature.properties中存储一个引用,以指向您有边界的另一个对象(您也可以动态计算它们)。

代码语言:javascript
运行
复制
const dataWithComputeBounds = { 
   'firstPoint': bounds_arc_computed,
   'secondPoint': bounds_arc_computed,
   ....
}

bounds_arc_computed需要是一个对象

代码语言:javascript
运行
复制
bounds_arc_computed = {
    minLng, minLat, maxLng, maxLat,
}

然后在onClick函数上只需引用

代码语言:javascript
运行
复制
   const { minLng, minLat, maxLng, maxLat} = dataWithComputedBounds[event.features[0].properties.reference];
   const viewportWebMercator = new WebMercatorViewport(viewport);
   ...

现在只需定义我们的主要元素:

代码语言:javascript
运行
复制
return (
    <DeckGL
        layers={[layerGeoJson]}
        initialViewState={INITIAL_VIEW_STATE}
        controller
    >
        <StaticMap
            reuseMaps
            mapStyle={mapStyle}
            preventStyleDiffing
            mapboxApiAccessToken={YOUR_TOKEN}
        />
    </DeckGL>
);

在这一点上,我们非常接近您已经链接的内容(https://codepen.io/vis-gl/pen/pKvrGP),但是您需要使用deckgl.setProps() onClick函数而不是setViewport来更改您的视区。

这对你来说有意义吗?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63492568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档