@iweather-js/iweather-react 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/build.ts +26 -0
- package/package.json +3 -3
- package/src/content/GisConfigProvider.tsx +20 -0
- package/src/content/GisLayerProvider.tsx +29 -0
- package/src/content/GisStoreProvider.tsx +17 -0
- package/src/content/MultiMapStatusStoreProvider.tsx +11 -0
- package/src/content/context.ts +4 -0
- package/src/hooks/useCityInfo.ts +23 -0
- package/src/hooks/useConfigStore.ts +13 -0
- package/src/hooks/useEnabledLayers.ts +22 -0
- package/src/hooks/useGisStore.ts +11 -0
- package/src/hooks/useMultiMapStatusStore.ts +11 -0
- package/src/hooks/useProduct.ts +13 -0
- package/src/hooks/useStores.ts +12 -0
- package/src/index.ts +18 -0
- package/src/plugins/GisClickPlugin.tsx +41 -0
- package/src/plugins/GisRefPlugin.tsx +17 -0
- package/src/plugins/GisStateChangePlugin.tsx +85 -0
- package/src/plugins/GisStateSyncPlugin.tsx +82 -0
- package/src/views/map.css +36 -0
- package/src/views/map.tsx +58 -0
- package/tsconfig.json +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# iweather-react
|
|
2
2
|
|
|
3
|
+
## 0.0.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- test
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @iweather-js/iweather-lib@0.0.6
|
|
10
|
+
- @iweather-js/iweather-gl@0.0.7
|
|
11
|
+
|
|
12
|
+
## 0.0.6
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- test
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @iweather-js/iweather-lib@0.0.5
|
|
19
|
+
- @iweather-js/iweather-gl@0.0.6
|
|
20
|
+
|
|
3
21
|
## 0.0.5
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/build.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export async function build() {
|
|
2
|
+
const pkg = require('./package.json');
|
|
3
|
+
const packageName = pkg.name;
|
|
4
|
+
|
|
5
|
+
const result = await Bun.build({
|
|
6
|
+
entrypoints: ['./src/index.ts'],
|
|
7
|
+
outdir: './dist',
|
|
8
|
+
target: 'browser',
|
|
9
|
+
format: 'esm',
|
|
10
|
+
minify: true,
|
|
11
|
+
sourcemap: 'external',
|
|
12
|
+
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
if (!result.success) {
|
|
16
|
+
console.error(`❌ Build failed : ${packageName}`);
|
|
17
|
+
for (const message of result.logs) {
|
|
18
|
+
console.error(message);
|
|
19
|
+
}
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
console.log(`✅ Build success : ${packageName}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
build();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iweather-js/iweather-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "工具函数包",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"./css": "./dist/index.css"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@iweather-js/iweather-gl": "
|
|
17
|
-
"@iweather-js/iweather-lib": "
|
|
16
|
+
"@iweather-js/iweather-gl": "^0.0.7",
|
|
17
|
+
"@iweather-js/iweather-lib": "^0.0.6",
|
|
18
18
|
"@types/react": "^19.2.7",
|
|
19
19
|
"react": "^19.0.0",
|
|
20
20
|
"react-dom": "^19.0.0"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { createConfigStore, IConfigStore, IReadOnlyConfigStoreValue } from '@iweather-js/iweather-gl';
|
|
3
|
+
|
|
4
|
+
export const ConfigContext = React.createContext<IConfigStore | null>(null);
|
|
5
|
+
|
|
6
|
+
export function GisConfigProvider<LayerT = object, ProductTypeT = string, ModelTypeT = string, DataReqT = object>(
|
|
7
|
+
props: React.PropsWithChildren<{
|
|
8
|
+
initConfigState: IReadOnlyConfigStoreValue<LayerT, ProductTypeT, ModelTypeT, DataReqT>;
|
|
9
|
+
}>,
|
|
10
|
+
) {
|
|
11
|
+
const store = useMemo(() => {
|
|
12
|
+
const configStore = createConfigStore<LayerT, ProductTypeT, ModelTypeT, DataReqT>(props.initConfigState);
|
|
13
|
+
|
|
14
|
+
configStore.getState().initCtx();
|
|
15
|
+
|
|
16
|
+
return configStore;
|
|
17
|
+
}, []);
|
|
18
|
+
|
|
19
|
+
return <ConfigContext.Provider value={store as any}>{props.children}</ConfigContext.Provider>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { LayerMgrHub, TimeMgrHub } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { useStore } from 'zustand';
|
|
4
|
+
import { useStores } from '../hooks/useStores';
|
|
5
|
+
|
|
6
|
+
export function GisLayerProvider(props: React.PropsWithChildren) {
|
|
7
|
+
const stores = useStores();
|
|
8
|
+
|
|
9
|
+
const mapIsLoaded = useStore(stores.gisStore, state => state.mapIsLoaded);
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
let layerMgrHub: LayerMgrHub | undefined = undefined;
|
|
13
|
+
let timeMgrHub: TimeMgrHub | undefined = undefined;
|
|
14
|
+
|
|
15
|
+
if (mapIsLoaded) {
|
|
16
|
+
layerMgrHub = new LayerMgrHub();
|
|
17
|
+
timeMgrHub = new TimeMgrHub(layerMgrHub);
|
|
18
|
+
layerMgrHub.mount(stores);
|
|
19
|
+
timeMgrHub.mount(stores);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return () => {
|
|
23
|
+
layerMgrHub?.onUnmount();
|
|
24
|
+
timeMgrHub?.onUnmount();
|
|
25
|
+
};
|
|
26
|
+
}, [mapIsLoaded]);
|
|
27
|
+
|
|
28
|
+
return <>{props.children}</>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { createGisStore, IGisStore, IGisValue } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { useConfigStore } from '../hooks/useConfigStore';
|
|
4
|
+
|
|
5
|
+
export const GisStoreContent = React.createContext<IGisStore | null>(null);
|
|
6
|
+
|
|
7
|
+
export function GisStoreProvider<LayerT = object, ProductTypeT = string>(
|
|
8
|
+
props: React.PropsWithChildren<{ initGisState?: Partial<IGisValue<LayerT, ProductTypeT>> }>,
|
|
9
|
+
) {
|
|
10
|
+
const configStore = useConfigStore<LayerT, ProductTypeT>();
|
|
11
|
+
|
|
12
|
+
const gisStore = useMemo(() => {
|
|
13
|
+
return createGisStore(configStore, props.initGisState);
|
|
14
|
+
}, []);
|
|
15
|
+
|
|
16
|
+
return <GisStoreContent.Provider value={gisStore as any}>{props.children}</GisStoreContent.Provider>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { createMultiMapStatusStore } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { MultiMapStatusStoreContext } from './context';
|
|
4
|
+
|
|
5
|
+
export function MultiMapStatusStoreProvider(props: React.PropsWithChildren) {
|
|
6
|
+
const statusStore = useMemo(() => {
|
|
7
|
+
return createMultiMapStatusStore();
|
|
8
|
+
}, []);
|
|
9
|
+
|
|
10
|
+
return <MultiMapStatusStoreContext.Provider value={statusStore}>{props.children}</MultiMapStatusStoreContext.Provider>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { toAdcodeInfoVo } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { useStore } from 'zustand';
|
|
4
|
+
import { useConfigStore } from './useConfigStore';
|
|
5
|
+
import { useGisStore } from './useGisStore';
|
|
6
|
+
|
|
7
|
+
export function useCityInfo() {
|
|
8
|
+
const gisStore = useGisStore();
|
|
9
|
+
|
|
10
|
+
const configStore = useConfigStore();
|
|
11
|
+
|
|
12
|
+
const adcodeInfo = useStore(gisStore, state => state.adcodeInfo);
|
|
13
|
+
|
|
14
|
+
const { cityConfig } = configStore.getState();
|
|
15
|
+
|
|
16
|
+
const adcodeInfoVo = useMemo(() => {
|
|
17
|
+
return toAdcodeInfoVo(adcodeInfo);
|
|
18
|
+
}, [adcodeInfo]);
|
|
19
|
+
|
|
20
|
+
const cityInfo = cityConfig?.findCityInfo(adcodeInfoVo);
|
|
21
|
+
|
|
22
|
+
return { cityInfo, adcodeInfoVo };
|
|
23
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { IConfigStore } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { ConfigContext } from '../content/GisConfigProvider';
|
|
4
|
+
|
|
5
|
+
export function useConfigStore<LayerT = object, ProductTypeT = string, ModelTypeT = string, DataReqT = object>() {
|
|
6
|
+
const configStore = useContext(ConfigContext);
|
|
7
|
+
|
|
8
|
+
if (!configStore) {
|
|
9
|
+
throw new Error('GisConfigStore not found');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return configStore as unknown as IConfigStore<LayerT, ProductTypeT, ModelTypeT, DataReqT>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useStore } from 'zustand';
|
|
2
|
+
import { useShallow } from 'zustand/shallow';
|
|
3
|
+
import { useGisStore } from './useGisStore';
|
|
4
|
+
|
|
5
|
+
export function useEnabledLayers() {
|
|
6
|
+
const gisStore = useGisStore();
|
|
7
|
+
|
|
8
|
+
const enabledLayerOptopns = useStore(
|
|
9
|
+
gisStore,
|
|
10
|
+
useShallow(state => state.query.enabledLayerOptopns()),
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const enabledLayerMgrs = useStore(
|
|
14
|
+
gisStore,
|
|
15
|
+
useShallow(state => state.query.enabledLayerMgrs()),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
enabledLayerOptopns,
|
|
20
|
+
enabledLayerMgrs,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { IGisStore } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { GisStoreContent } from '../content/GisStoreProvider';
|
|
4
|
+
|
|
5
|
+
export function useGisStore<LayerT = object, ProductTypeT = string, ModelTypeT = string, DataReqT = object>() {
|
|
6
|
+
const gisStore = useContext(GisStoreContent);
|
|
7
|
+
|
|
8
|
+
if (!gisStore) throw new Error('gisStore is null');
|
|
9
|
+
|
|
10
|
+
return gisStore as unknown as IGisStore<LayerT, ProductTypeT, ModelTypeT, DataReqT>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { IMultiMapStatusStore } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { MultiMapStatusStoreContext } from '../content/context';
|
|
4
|
+
|
|
5
|
+
export function useMultiMapStatusStore() {
|
|
6
|
+
const multiMapStatusStore = useContext(MultiMapStatusStoreContext);
|
|
7
|
+
|
|
8
|
+
if (!multiMapStatusStore) throw new Error('multiMapStatusStore is null');
|
|
9
|
+
|
|
10
|
+
return multiMapStatusStore as IMultiMapStatusStore;
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useStore } from 'zustand';
|
|
2
|
+
import { useConfigStore } from './useConfigStore';
|
|
3
|
+
import { useGisStore } from './useGisStore';
|
|
4
|
+
|
|
5
|
+
export function useProduct<LayerT = object, ProductTypeT = string, ModelTypeT = string, DataReqT = object>() {
|
|
6
|
+
const configStore = useConfigStore<LayerT, ProductTypeT, ModelTypeT, DataReqT>();
|
|
7
|
+
|
|
8
|
+
const gisStore = useGisStore<LayerT, ProductTypeT, ModelTypeT, DataReqT>();
|
|
9
|
+
|
|
10
|
+
const productType = useStore(gisStore, state => state.productType);
|
|
11
|
+
|
|
12
|
+
return configStore.getState().productConfig.findProduct(productType!);
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useConfigStore } from './useConfigStore';
|
|
2
|
+
import { useGisStore } from './useGisStore';
|
|
3
|
+
|
|
4
|
+
export function useStores() {
|
|
5
|
+
const configStore = useConfigStore();
|
|
6
|
+
const gisStore = useGisStore();
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
configStore,
|
|
10
|
+
gisStore,
|
|
11
|
+
};
|
|
12
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from './content/GisStoreProvider';
|
|
2
|
+
export * from './content/GisConfigProvider';
|
|
3
|
+
export * from './content/GisLayerProvider';
|
|
4
|
+
export * from './content/MultiMapStatusStoreProvider';
|
|
5
|
+
|
|
6
|
+
export * from './plugins/GisRefPlugin';
|
|
7
|
+
export * from './plugins/GisStateChangePlugin';
|
|
8
|
+
export * from './plugins/GisClickPlugin';
|
|
9
|
+
export * from './plugins/GisStateSyncPlugin';
|
|
10
|
+
|
|
11
|
+
export * from './views/map';
|
|
12
|
+
|
|
13
|
+
export * from './hooks/useGisStore';
|
|
14
|
+
export * from './hooks/useStores';
|
|
15
|
+
export * from './hooks/useConfigStore';
|
|
16
|
+
export * from './hooks/useProduct';
|
|
17
|
+
export * from './hooks/useCityInfo';
|
|
18
|
+
export * from './hooks/useEnabledLayers';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { IMap } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { isEqual } from 'lodash-es';
|
|
4
|
+
import { LngLat } from 'maplibre-gl';
|
|
5
|
+
import { useGisStore } from '../hooks/useGisStore';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 点击事件
|
|
9
|
+
* @param props
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export function GisClickPlugin(props: { onClick?: (clickPoint: LngLat, map: IMap) => void }) {
|
|
13
|
+
const gisStore = useGisStore();
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const unsubscribeFuns: (() => void)[] = [];
|
|
17
|
+
|
|
18
|
+
if (props.onClick) {
|
|
19
|
+
unsubscribeFuns.push(
|
|
20
|
+
gisStore.subscribe(
|
|
21
|
+
state => {
|
|
22
|
+
return {
|
|
23
|
+
clickPoint: state.clickPoint,
|
|
24
|
+
map: state.map,
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
({ clickPoint, map }) => {
|
|
28
|
+
map && clickPoint && props.onClick?.(clickPoint, map);
|
|
29
|
+
},
|
|
30
|
+
{ equalityFn: isEqual, fireImmediately: true },
|
|
31
|
+
),
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return () => {
|
|
36
|
+
unsubscribeFuns.forEach(e => e?.());
|
|
37
|
+
};
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { useImperativeHandle } from 'react';
|
|
2
|
+
import { IGisFns } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { useStore } from 'zustand';
|
|
4
|
+
import { useGisStore } from '../hooks/useGisStore';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 地图ref插件
|
|
8
|
+
*/
|
|
9
|
+
export const GisRefPlugin = React.forwardRef<IGisFns['apply'], any>((props, ref) => {
|
|
10
|
+
const gisStore = useGisStore();
|
|
11
|
+
|
|
12
|
+
const apply = useStore(gisStore, state => state.apply);
|
|
13
|
+
|
|
14
|
+
useImperativeHandle(ref, () => apply, []);
|
|
15
|
+
|
|
16
|
+
return null;
|
|
17
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { IGisStore, IGisValue, IMapState, toGisValue } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { SubscribeMgr } from '@iweather-js/iweather-lib';
|
|
4
|
+
import { isEqual } from 'lodash-es';
|
|
5
|
+
import { useConfigStore } from '../hooks/useConfigStore';
|
|
6
|
+
import { useGisStore } from '../hooks/useGisStore';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 状态变更插件
|
|
10
|
+
* @param props
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
export function GisStateChangePlugin<LayerT = object, ProductTypeT = string, ModelTypeT = string, DataReqT = object>(props: {
|
|
14
|
+
onChange?: (gisValue: IGisValue<LayerT, ProductTypeT, ModelTypeT, DataReqT>) => void;
|
|
15
|
+
onMapStateChange?: (mapState: IMapState, gisStore: IGisStore<LayerT, ProductTypeT, ModelTypeT, DataReqT>) => void;
|
|
16
|
+
onScreenshot?: (screenshot: string) => void;
|
|
17
|
+
onMapIdle?: () => void;
|
|
18
|
+
}) {
|
|
19
|
+
const gisStore = useGisStore<LayerT, ProductTypeT, ModelTypeT, DataReqT>();
|
|
20
|
+
const configStore = useConfigStore<LayerT, ProductTypeT, ModelTypeT, DataReqT>();
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const subscribeMgr = SubscribeMgr.create();
|
|
24
|
+
|
|
25
|
+
if (props.onChange) {
|
|
26
|
+
subscribeMgr.add(
|
|
27
|
+
gisStore.subscribe(state => {
|
|
28
|
+
props.onChange?.(toGisValue<LayerT, ProductTypeT, ModelTypeT, DataReqT>({ configStore }, state));
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (props.onMapStateChange) {
|
|
34
|
+
subscribeMgr.add(
|
|
35
|
+
gisStore.subscribe(
|
|
36
|
+
state => {
|
|
37
|
+
const { bearing, pitch, bounds, center, zoom } = state;
|
|
38
|
+
return { bearing, pitch, bounds, center, zoom };
|
|
39
|
+
},
|
|
40
|
+
state => {
|
|
41
|
+
props.onMapStateChange?.(state, gisStore);
|
|
42
|
+
},
|
|
43
|
+
{ equalityFn: isEqual },
|
|
44
|
+
),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (props.onScreenshot) {
|
|
49
|
+
subscribeMgr.add(
|
|
50
|
+
gisStore.subscribe(
|
|
51
|
+
state => state.screenshot,
|
|
52
|
+
screenshot => {
|
|
53
|
+
screenshot && props.onScreenshot?.(screenshot);
|
|
54
|
+
},
|
|
55
|
+
{ equalityFn: isEqual },
|
|
56
|
+
),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (props.onMapIdle) {
|
|
61
|
+
const onIdleListener = () => {
|
|
62
|
+
props.onMapIdle?.();
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const unsubscribe = gisStore.subscribe(
|
|
66
|
+
state => state.map,
|
|
67
|
+
map => {
|
|
68
|
+
if (!map) return;
|
|
69
|
+
map?.on('idle', onIdleListener);
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
subscribeMgr.add(() => {
|
|
74
|
+
unsubscribe();
|
|
75
|
+
gisStore.getState().map?.off('idle', onIdleListener);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return () => {
|
|
80
|
+
subscribeMgr.dispose();
|
|
81
|
+
};
|
|
82
|
+
}, []);
|
|
83
|
+
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { getMapState, IGisStore, IGisValue, toGisValue } from '@iweather-js/iweather-gl';
|
|
3
|
+
import { debounce, isEqual } from 'lodash-es';
|
|
4
|
+
import { useStore } from 'zustand';
|
|
5
|
+
import { useConfigStore } from '../hooks/useConfigStore';
|
|
6
|
+
import { useGisStore } from '../hooks/useGisStore';
|
|
7
|
+
import { useMultiMapStatusStore } from '../hooks/useMultiMapStatusStore';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 地图状态同步插件
|
|
11
|
+
* 支持将一个gisStore的state变更同步到当前gisStore
|
|
12
|
+
*/
|
|
13
|
+
export const GisStateSyncPlugin = (props: {
|
|
14
|
+
gisStore: IGisStore;
|
|
15
|
+
transformState?: (state: IGisValue<any>) => IGisValue;
|
|
16
|
+
enableMapToStoreSync?: boolean;
|
|
17
|
+
}) => {
|
|
18
|
+
const configStore = useConfigStore();
|
|
19
|
+
const gisStore = useGisStore();
|
|
20
|
+
const multiMapStatusStore = useMultiMapStatusStore();
|
|
21
|
+
const mapIsLoaded = useStore(gisStore, state => state.mapIsLoaded);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const unsubscribeFun = props.gisStore.subscribe(
|
|
25
|
+
state => toGisValue({ configStore }, state),
|
|
26
|
+
state => {
|
|
27
|
+
if (multiMapStatusStore.getState().mapStateToStoreSyncing) return;
|
|
28
|
+
gisStore.getState().apply({ type: 'changeValue', value: props.transformState?.(state) || state });
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
fireImmediately: true,
|
|
32
|
+
equalityFn: isEqual,
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
return () => {
|
|
37
|
+
unsubscribeFun();
|
|
38
|
+
};
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!props.enableMapToStoreSync) return;
|
|
43
|
+
if (!mapIsLoaded) return;
|
|
44
|
+
|
|
45
|
+
// const listener = debounce(() => {
|
|
46
|
+
// const map = gisStore.getState().map;
|
|
47
|
+
// if (!map) return;
|
|
48
|
+
|
|
49
|
+
// multiMapStatusStore.getState().apply({ type: 'changeValue', value: { mapStateToStoreSyncing: true } });
|
|
50
|
+
|
|
51
|
+
// props.gisStore.getState().apply({ type: 'changeValue', value: getMapState(map) });
|
|
52
|
+
|
|
53
|
+
// multiMapStatusStore.getState().apply({ type: 'changeValue', value: { mapStateToStoreSyncing: false } });
|
|
54
|
+
// }, 100);
|
|
55
|
+
|
|
56
|
+
// gisStore.getState().map?.on('idle', listener);
|
|
57
|
+
|
|
58
|
+
const { map } = gisStore.getState();
|
|
59
|
+
if (!map) return;
|
|
60
|
+
|
|
61
|
+
// 状态变更事件
|
|
62
|
+
const onChangeListener = debounce(() => {
|
|
63
|
+
multiMapStatusStore.getState().apply({ type: 'changeValue', value: { mapStateToStoreSyncing: true } });
|
|
64
|
+
|
|
65
|
+
props.gisStore.getState().apply({ type: 'changeValue', value: getMapState(map) });
|
|
66
|
+
|
|
67
|
+
multiMapStatusStore.getState().apply({ type: 'changeValue', value: { mapStateToStoreSyncing: false } });
|
|
68
|
+
}, 500);
|
|
69
|
+
|
|
70
|
+
map.on('zoomend', onChangeListener);
|
|
71
|
+
map.on('moveend', onChangeListener);
|
|
72
|
+
map.on('pitchend', onChangeListener);
|
|
73
|
+
|
|
74
|
+
return () => {
|
|
75
|
+
map.off('zoomend', onChangeListener);
|
|
76
|
+
map.off('moveend', onChangeListener);
|
|
77
|
+
map.off('pitchend', onChangeListener);
|
|
78
|
+
};
|
|
79
|
+
}, [mapIsLoaded]);
|
|
80
|
+
|
|
81
|
+
return null;
|
|
82
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.maplibregl-ctrl {
|
|
2
|
+
display: none !important;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.mapboxgl-ctrl-attrib-inner {
|
|
6
|
+
display: none !important;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.mapboxgl-ctrl-bottom-left {
|
|
10
|
+
display: none !important;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.maplibregl-popup-content {
|
|
14
|
+
padding: 0px !important;
|
|
15
|
+
background: transparent !important;
|
|
16
|
+
box-shadow: none !important;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.maplibregl-popup-tip {
|
|
20
|
+
display: none !important;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.marker {
|
|
24
|
+
display: none;
|
|
25
|
+
border: none;
|
|
26
|
+
cursor: pointer;
|
|
27
|
+
padding: 0;
|
|
28
|
+
width: 50px;
|
|
29
|
+
height: 50px;
|
|
30
|
+
background-repeat: no-repeat;
|
|
31
|
+
background-size: contain;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.marker_visible {
|
|
35
|
+
display: block;
|
|
36
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
createMap,
|
|
4
|
+
initMapState,
|
|
5
|
+
mapAutoRotation,
|
|
6
|
+
mapScreenshotHandler,
|
|
7
|
+
mapSyncMoveHandler,
|
|
8
|
+
mapSyncTimeHandler,
|
|
9
|
+
syncMapStateToStoreHandler,
|
|
10
|
+
syncStoreStateToMapHandler,
|
|
11
|
+
} from '@iweather-js/iweather-gl';
|
|
12
|
+
import { useStores } from '../hooks/useStores';
|
|
13
|
+
import './map.css';
|
|
14
|
+
|
|
15
|
+
// import 'maplibre-gl/dist/maplibre-gl.css';
|
|
16
|
+
|
|
17
|
+
export function GisMap() {
|
|
18
|
+
const mapRef = useRef<HTMLDivElement>(null);
|
|
19
|
+
|
|
20
|
+
const stores = useStores();
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const mapContainer = mapRef.current;
|
|
24
|
+
|
|
25
|
+
if (!mapContainer) return;
|
|
26
|
+
|
|
27
|
+
const map = createMap(mapContainer, stores);
|
|
28
|
+
|
|
29
|
+
stores.gisStore.getState().apply({ type: 'changeValue', value: { map } });
|
|
30
|
+
|
|
31
|
+
map.keyboard.disable();
|
|
32
|
+
|
|
33
|
+
const unmountFuns: ((() => void) | undefined)[] = [];
|
|
34
|
+
|
|
35
|
+
map.once('style.load', () => {
|
|
36
|
+
initMapState(map, stores);
|
|
37
|
+
stores.gisStore.getState().apply({ type: 'changeValue', value: { mapIsLoaded: true } });
|
|
38
|
+
unmountFuns.push(mapSyncMoveHandler(stores));
|
|
39
|
+
unmountFuns.push(mapSyncTimeHandler(stores));
|
|
40
|
+
mapScreenshotHandler(stores);
|
|
41
|
+
syncStoreStateToMapHandler(stores);
|
|
42
|
+
syncMapStateToStoreHandler(stores);
|
|
43
|
+
mapAutoRotation(stores);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
map.on('click', e => {
|
|
47
|
+
stores.gisStore.getState().apply({ type: 'changeValue', value: { clickPoint: e.lngLat.wrap() } });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return () => {
|
|
51
|
+
unmountFuns.forEach(e => e?.());
|
|
52
|
+
map.remove();
|
|
53
|
+
stores.gisStore.getState().apply({ type: 'changeValue', value: { map: undefined, mapIsLoaded: false } });
|
|
54
|
+
};
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
return <div className='relative h-full w-full' ref={mapRef}></div>;
|
|
58
|
+
}
|