我已经使用deck.gl创建了一些圆弧。当您单击不同的点/多边形时,不同国家/地区之间会出现不同的圆弧。在执行此操作时,我希望地图缩放到这些弧线的边界。
为了清楚起见,这里有一个例子:当点击Glasgow时,我想要缩放到所示的弧线(尽可能紧密地):
似乎可以使用WebMercatorViewport调用fitBounds (请参阅:https://deck.gl/docs/api-reference/core/web-mercator-viewport#webmercatorviewport)
不过,我不清楚这是如何使用的。我试过找一些例子,但都找不到。我如何才能将其添加到我已有的内容中?
下面是圆弧的代码:
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]
});
}
});
发布于 2020-08-25 19:08:37
我试着让它变得简单,从ReactJs的原始实现开始,然后尝试转换成普通的。
在ReactJS中,我会这样做。
从react-map-gl
导入LinearInterpolator
和WebMercatorViewport
import {LinearInterpolator, WebMercatorViewport} from 'react-map-gl';
然后,我为视口定义了一个useEffect:
const [viewport, setViewport] = useState({
latitude: 37.7577,
longitude: -122.4376,
zoom: 11,
bearing: 0,
pitch: 0
});
然后我将定义一个要显示的层:
const layerGeoJson = new GeoJsonLayer({
id: 'geojson',
data: someData,
...
pickable: true,
onClick: onClickGeoJson,
});
现在我们需要定义onClickGeoJson
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中存储一个引用,以指向您有边界的另一个对象(您也可以动态计算它们)。
const dataWithComputeBounds = {
'firstPoint': bounds_arc_computed,
'secondPoint': bounds_arc_computed,
....
}
bounds_arc_computed
需要是一个对象
bounds_arc_computed = {
minLng, minLat, maxLng, maxLat,
}
然后在onClick函数上只需引用
const { minLng, minLat, maxLng, maxLat} = dataWithComputedBounds[event.features[0].properties.reference];
const viewportWebMercator = new WebMercatorViewport(viewport);
...
现在只需定义我们的主要元素:
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
来更改您的视区。
这对你来说有意义吗?
https://stackoverflow.com/questions/63492568
复制相似问题