1. 简介
文档写得还可以,实现原理到性能优化都包含了,就是感觉目录不是很循序渐进。
2. 使用
此时的我使用的deck
版本是8.9.33
。
基础使用官网也有讲,结合示例代码就能实现。不再赘述基础概念。
ts
// 这里为了又ts类型提示,引入的模块后面加了一个typed
// 下一个版本会默认拥有ts类型提示不需要加typed
import DeckGL from "@deck.gl/react/typed";
import { GeoJsonLayer } from "@deck.gl/layers/typed";
import { useState } from "react";
import { Layer, LayerExtension } from "@deck.gl/core/typed";
export default function App() {
// 新建图层组
const layers = [
// 新建GeoJson图层
new GeoJsonLayer({
id: "geojson",
// 加载数据
// 数据可以是字面量,或者一个网络地址,或者一个promise
// 上面提到的类型都必须满足,返回一个有length属性的数据类型
data: "/mapData.json",
opacity: 0.8,
stroked: false,
filled: true,
extruded: true,
wireframe: true,
getElevation: (f) => 2500,
getLineColor: [255, 0, 0],
pickable: true,
}),
];
return (
<DeckGL
layers={layers}
// 设置初始view状态,主要是中心点、缩放等级、倾斜角度等
initialViewState={{
latitude: 30.298245137499997,
longitude: 106.75365820549999,
zoom: 11,
maxZoom: 16,
pitch: 45,
bearing: 0,
}}
// 开始交互控制
controller={true}
></DeckGL>
);
}
这里黑黢黢的是因为我没设置填充颜色,不过地图样子还是能看出来。
2.1. 动态设置viewState
可能你想在后面的逻辑中修改viewState
,这个时候就需要让state
受控。
ts
const APP = () => {
const [viewState, setViewState] = useState({
latitude: 30.298245137499997,
longitude: 106.75365820549999,
zoom: 11,
maxZoom: 16,
pitch: 45,
bearing: 0,
});
return <DeckGL
// 不能同时设置initialViewState和viewState
viewState={viewState}
// 记得在事件中更新
// 因为deck内部状态是单向的
onViewStateChange={(e) => setViewState(e.viewState)}
></DeckGL>
}
2.2. 中心点怎么来
deck
的中心点并不能自动计算出来,只能手动设置。这里提供几种思路。
使用
truf
计算出来(推荐)
推荐这个方法的原因是,一般来说地图数据不会经常变,所以中心点计算一次就行了。
ts
// 随便找个地方把中心点算一下
console.log(truf.center(mapData)); // [经度, 维度]
ts
// 设置viewstate的时候直接写死
initialViewState={{
latitude: 30.298245137499997,
longitude: 106.75365820549999,
zoom: 11,
maxZoom: 16,
pitch: 45,
bearing: 0,
}}
使用
fitBounds
这个方法只在WebMercatorViewport中有,这个其实就是默认的view
,墨卡托投影。
ts
const initialViewState = useMemo(() => {
// 这里计算逻辑仅供参考
// 没有考虑实际数据格式
const minLat = Math.min(...mapData.map((l) => l.latitude))
const maxLat = Math.max(...mapData.map((l) => l.latitude))
const minLng = Math.min(...mapData.map((l) => l.longitude))
const maxLng = Math.max(...mapData.map((l) => l.longitude))
const southWest = [minLng, minLat]
const northEast = [maxLng, maxLat]
return new WebMercatorViewport({ width: 1920, height: 400 }).fitBounds([southWest, northEast], {padding: 200})
}, [mapData])
// 计算出来的initialViewState就可以给`deck`组件了
可以看到这个方法其实很麻烦,还要考虑视口宽高。