Created
November 1, 2021 05:49
-
-
Save morlay/05ad3b49b5890d5a2e070f1214333df2 to your computer and use it in GitHub Desktop.
AMapBaseLayer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { must } from "@querycap/reactutils"; | |
import * as AMap from "AMap"; | |
import { Map } from "mapbox-gl"; | |
import React, { createContext, ReactNode, useContext, useEffect, useState } from "react"; | |
import { useMap, createCustomLayer } from "../mapbox"; | |
import { AMapSDKLoader, useAMapSDK } from "./AMapSDK"; | |
import { Styles } from "./Style"; | |
const createFovHack = (m: Map) => { | |
const currentFov = 0; | |
const transform = m.transform; | |
return (fov: number) => { | |
if (currentFov === fov) { | |
return; | |
} | |
transform._fov = fov; | |
transform._unmodified = false; | |
transform._calcMatrices(); | |
}; | |
}; | |
export interface IAMapSetting { | |
mapStyle: string; | |
onLoad: (amap: AMap.Map) => void; | |
} | |
const createCoverContainer = () => { | |
const $container = document.createElement("div"); | |
$container.style.position = "absolute"; | |
$container.style.width = "100%"; | |
$container.style.height = "100%"; | |
return $container; | |
}; | |
export const createAMapBaseLayer = createCustomLayer((opts: Partial<IAMapSetting>, a: typeof AMap) => (m) => { | |
const getMapZoom = () => m.getZoom() + 1; | |
const getMapCenter = () => { | |
return m.getCenter().toArray() as [number, number]; | |
}; | |
const setFov = createFovHack(m); | |
const $mc = m.getContainer(); | |
const $container = createCoverContainer(); | |
$mc.parentNode!.insertBefore($container, $mc); | |
const amap = new a.Map($container, { | |
...opts, | |
// mapStyle: "amap://styles/616174a8b4d390bb9ada76431e8e3836", | |
zoom: getMapZoom(), | |
crs: "EPSG3857", | |
center: new a.LngLat(...getMapCenter()), | |
pitch: m.getPitch() || 0, | |
rotation: 360 - m.getBearing() || 0, | |
viewMode: "3D", | |
pitchEnable: true, | |
rotateEnable: true, | |
expandZoomRange: true, | |
animateEnable: false, | |
doubleClickZoom: false, | |
dragEnable: false, | |
isHotspot: false, | |
jogEnable: false, | |
keyboardEnable: false, | |
resizeEnable: false, | |
scrollWheel: false, | |
touchZoom: false, | |
zoomEnable: false, | |
showBuildingBlock: false, | |
}); | |
amap.on("camerachange", ({ camera }: any) => { | |
setFov(camera.fov); | |
}); | |
opts.onLoad && opts.onLoad(amap); | |
return { | |
render: () => { | |
amap.setZoomAndCenter(getMapZoom(), getMapCenter()); | |
amap.setPitch(m.getPitch()); | |
amap.setRotation(360 - m.getBearing()); | |
}, | |
destroy: () => { | |
amap.destroy(); | |
$container.remove(); | |
}, | |
}; | |
}); | |
const AMapContext = createContext<{ amap: AMap.Map | undefined }>({ | |
amap: undefined, | |
}); | |
export const AMapContextProvider = AMapContext.Provider; | |
const useMapContext = () => useContext(AMapContext); | |
export const useAMap = () => useMapContext().amap; | |
export const mustAMap = must(() => { | |
const m = useAMap(); | |
return [m] as const; | |
}); | |
const AMapProvider = ({ children, ...settings }: Partial<IAMapSetting> & { children?: ReactNode }) => { | |
const [amap, setAMap] = useState<AMap.Map>(); | |
const AMapSDK = useAMapSDK(); | |
const m = useMap(); | |
useEffect(() => { | |
if (!m) { | |
return; | |
} | |
const baseLayer = createAMapBaseLayer( | |
"AMapSDK", | |
{ | |
...settings, | |
onLoad: (amap) => { | |
console.log(amap); | |
setAMap(amap); | |
}, | |
}, | |
AMapSDK, | |
); | |
m.addLayer(baseLayer as any); | |
return () => { | |
m.removeLayer(baseLayer.id); | |
}; | |
}, [m]); | |
return <AMapContextProvider value={{ amap: amap }}>{children}</AMapContextProvider>; | |
}; | |
export const AMapBaseLayer = ({ | |
sdkKey, | |
children, | |
...opts | |
}: Parameters<typeof AMapSDKLoader>[0] & Partial<IAMapSetting>) => { | |
return ( | |
<AMapSDKLoader sdkKey={sdkKey}> | |
<Styles /> | |
<AMapProvider {...opts}>{children}</AMapProvider> | |
</AMapSDKLoader> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment