Skip to content

Instantly share code, notes, and snippets.

@morlay
Created November 1, 2021 05:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save morlay/05ad3b49b5890d5a2e070f1214333df2 to your computer and use it in GitHub Desktop.
Save morlay/05ad3b49b5890d5a2e070f1214333df2 to your computer and use it in GitHub Desktop.
AMapBaseLayer
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