Mapbox JS - 在父状态更新时以编程方式更新地图
Mapbox JS - Update map programatically when parent state updates
Gatsby 项目 - 尝试在更新具有所需路线的状态时突出显示 Mapbox 路线。
当前实施:
- 加载地图
- 使用 updateList 函数更新父列表状态
- 父级将更新的列表转发给其他组件以显示路由列表
- 其中一个列表项悬停
- activeItem 状态得到更新
- activeItem 使弹出窗口出现在当前地图上 >>>> 不起作用
由于 mapbox 地图似乎只能在 useEffect 挂钩中正确加载,我看不到任何其他方法可以根据父项的 activeItem 显示弹出窗口。如果有其他选择,请告诉我!
我尝试过的方法:
- 从 useEffect 挂钩中提取地图并在普通 const 中实例化它 -> “错误:无效类型:'container' 必须是字符串或 HTMLElement。”
- 使用 useState 挂钩为地图创建状态 -> 地图对于所有与地图相关的函数都是未定义的,例如map.on("加载", ....)
当前代码:
const EmbeddedMap = ({ updateList, activeItem }) => {
const mapContainerRef = useRef(null)
const [list, setList] = useState([])
useEffect(() => {
const map = new mapboxgl.Map({
container: mapContainerRef.current,
accessToken: process.env.GATSBY_MAPBOX_TOKEN,
style: "mapbox://styles/mapbox/...",
center: [-90.836, 51.134],
zoom: 6,
})
const popup = new mapboxgl.Popup()
const getUniqueFeatures = (array, comparatorProperty) =>
array.filter(
(v, i, a) =>
a.findIndex(
t =>
t.properties[comparatorProperty] ===
v.properties[comparatorProperty]
) === i
)
const updateMap = map => {
const features = map.queryRenderedFeatures({ layers: ["data"] })
if (features) {
const uniqueFeatures = getUniqueFeatures(features, "post_id")
setList(uniqueFeatures)
}
}
map.on("load", () => {
updateMap(map)
map.on("movestart", () => {
map.setFilter("data", ["has", "title"])
})
map.on("moveend", () => {
updateMap(map)
})
map.on("mousemove", "data", e => {
map.getCanvas().style.cursor = "pointer"
const feature = e.features[0]
setPopup(map, popup, feature)
})
map.on("mouseleave", "data", () => {
map.getCanvas().style.cursor = ""
})
map.on("click", "data", e => {
const feature = e.features[0]
map.flyTo({
center: feature.geometry.coordinates[0],
})
setPopup(map, popup, feature)
})
})
return () => map.remove()
}, [])
return (
<div>
<EmbeddedMapStyled ref={mapContainerRef} />
</div>
)
}
改变我对 ref 的方法解决了问题:
const map = useRef(null)
map.current = new mapboxgl.Map({
container: mapContainerRef.current,
accessToken: process.env.GATSBY_MAPBOX_TOKEN,
style: "mapbox://styles/data",
center: [-114.836, 51.134],
zoom: 6,
})
然后我可以轻松地重用地图,例如:
map.current.flyTo({
center: activeItem.startPoint,
})
Gatsby 项目 - 尝试在更新具有所需路线的状态时突出显示 Mapbox 路线。
当前实施:
- 加载地图
- 使用 updateList 函数更新父列表状态
- 父级将更新的列表转发给其他组件以显示路由列表
- 其中一个列表项悬停
- activeItem 状态得到更新
- activeItem 使弹出窗口出现在当前地图上 >>>> 不起作用
由于 mapbox 地图似乎只能在 useEffect 挂钩中正确加载,我看不到任何其他方法可以根据父项的 activeItem 显示弹出窗口。如果有其他选择,请告诉我!
我尝试过的方法:
- 从 useEffect 挂钩中提取地图并在普通 const 中实例化它 -> “错误:无效类型:'container' 必须是字符串或 HTMLElement。”
- 使用 useState 挂钩为地图创建状态 -> 地图对于所有与地图相关的函数都是未定义的,例如map.on("加载", ....)
当前代码:
const EmbeddedMap = ({ updateList, activeItem }) => {
const mapContainerRef = useRef(null)
const [list, setList] = useState([])
useEffect(() => {
const map = new mapboxgl.Map({
container: mapContainerRef.current,
accessToken: process.env.GATSBY_MAPBOX_TOKEN,
style: "mapbox://styles/mapbox/...",
center: [-90.836, 51.134],
zoom: 6,
})
const popup = new mapboxgl.Popup()
const getUniqueFeatures = (array, comparatorProperty) =>
array.filter(
(v, i, a) =>
a.findIndex(
t =>
t.properties[comparatorProperty] ===
v.properties[comparatorProperty]
) === i
)
const updateMap = map => {
const features = map.queryRenderedFeatures({ layers: ["data"] })
if (features) {
const uniqueFeatures = getUniqueFeatures(features, "post_id")
setList(uniqueFeatures)
}
}
map.on("load", () => {
updateMap(map)
map.on("movestart", () => {
map.setFilter("data", ["has", "title"])
})
map.on("moveend", () => {
updateMap(map)
})
map.on("mousemove", "data", e => {
map.getCanvas().style.cursor = "pointer"
const feature = e.features[0]
setPopup(map, popup, feature)
})
map.on("mouseleave", "data", () => {
map.getCanvas().style.cursor = ""
})
map.on("click", "data", e => {
const feature = e.features[0]
map.flyTo({
center: feature.geometry.coordinates[0],
})
setPopup(map, popup, feature)
})
})
return () => map.remove()
}, [])
return (
<div>
<EmbeddedMapStyled ref={mapContainerRef} />
</div>
)
}
改变我对 ref 的方法解决了问题:
const map = useRef(null)
map.current = new mapboxgl.Map({
container: mapContainerRef.current,
accessToken: process.env.GATSBY_MAPBOX_TOKEN,
style: "mapbox://styles/data",
center: [-114.836, 51.134],
zoom: 6,
})
然后我可以轻松地重用地图,例如:
map.current.flyTo({
center: activeItem.startPoint,
})