diff --git a/src/@types/AMap.d.ts b/src/@types/AMap.d.ts index 0e6aaab..8128451 100644 --- a/src/@types/AMap.d.ts +++ b/src/@types/AMap.d.ts @@ -69,6 +69,38 @@ declare global { toGeoJSON: () => GeoJSON.GeoJSON; } + + export type MapTypeLayerInfo = { + id: string; + enable: string; + name: string; + type: 'base' | 'overlay'; + // layer: AMap.Layer; + layer: any; // AMap.Layer 未暴露出来; + show: boolean + }; + + export type MapTypeOptions = { + defaultType?: number; + showTraffic?: boolean; + showRoad?: boolean; + }; + + export class MapType { + constructor(options?: MapTypeOptions); + + addLayer:(layerInfo: MapTypeLayerInfo) => void; + + removeLayer: (id: string) => void; + + addTo: (map: AMap.Map) => void; + + show: () => void; + + hide: () => void; + + remove: () => void; + } } namespace AMapUI { diff --git a/src/components/AMapMapType/AMapMapType.tsx b/src/components/AMapMapType/AMapMapType.tsx new file mode 100644 index 0000000..246b341 --- /dev/null +++ b/src/components/AMapMapType/AMapMapType.tsx @@ -0,0 +1,62 @@ +/* eslint-disable react/default-props-match-prop-types */ +import type { FC } from 'react'; +import { + useEffect, + useCallback, +} from 'react'; + +import useAMapPluginInstance from '../../hooks/useAMapPluginInstance'; +// import useAMap from '../../hooks/useAMap'; +import useAMapControlBinder from '../../hooks/useAMapControlBinder'; +import useAMapEventBinder from '../../hooks/useAMapEventBinder'; + +import type { AMapMapTypeProps } from './interface'; + +/** + * Origin API see: + * https://lbs.amap.com/api/jsapi-v2/documentation#hawkeye + */ + +const defaultProps = { + defaultType: 0, + showTraffic: false, + showRoad: false, + visible: true, + onShow: undefined, + onHide: undefined, +}; + +const AMapMapType: FC = ({ + defaultType, + showTraffic, + showRoad, + visible, + onHide, + onShow, +}) => { + const initInstance = useCallback((AMap) => new AMap!.MapType({ + defaultType, + showTraffic, + showRoad, + }), [defaultType, showRoad, showTraffic]); + const curInstance = useAMapPluginInstance('MapType', initInstance); + + useEffect(() => { + if (visible) { + curInstance?.show?.(); + } else { + curInstance?.hide?.(); + } + }, [curInstance, visible]); + + useAMapEventBinder(curInstance, 'show', onShow); + useAMapEventBinder(curInstance, 'hide', onHide); + + useAMapControlBinder(curInstance); + + return null; +}; + +AMapMapType.defaultProps = defaultProps; + +export default AMapMapType; diff --git a/src/components/AMapMapType/index.ts b/src/components/AMapMapType/index.ts new file mode 100644 index 0000000..51d0d9f --- /dev/null +++ b/src/components/AMapMapType/index.ts @@ -0,0 +1,3 @@ +export type { AMapMapTypeProps } from './interface'; + +export { default } from './AMapMapType'; diff --git a/src/components/AMapMapType/interface.d.ts b/src/components/AMapMapType/interface.d.ts new file mode 100644 index 0000000..d6be5aa --- /dev/null +++ b/src/components/AMapMapType/interface.d.ts @@ -0,0 +1,5 @@ +export type AMapMapTypeProps = AMap.MapTypeOptions & { + visible: boolean, + onHide: () => void, + onShow: () => void, +}; diff --git a/src/components/AMapMapType/stories/AMapMapType.stories.tsx b/src/components/AMapMapType/stories/AMapMapType.stories.tsx new file mode 100644 index 0000000..5d4b4be --- /dev/null +++ b/src/components/AMapMapType/stories/AMapMapType.stories.tsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { Story, Meta } from '@storybook/react'; +import { actions } from '@storybook/addon-actions'; + +import { AMapMapType, AMapMapTypeProps } from 'index'; +import { withAMapContainer } from '../../AMapMap/stories/AMapMap.stories'; + +const eventHandler = actions('onShow', 'onHide'); + +export default { + title: '组件(Components)/地图控件(Control)/AMapMapType', + component: AMapMapType, + decorators: [withAMapContainer], + args: { + defaultType: 0, + visible: true, + onShow: eventHandler.onShow, + onHide: eventHandler.onHide, + }, + argTypes: { + defaultType: { + description: '初始化默认图层类型。 默认底图: 0; 卫星图: 1。', + table: { + type: { summary: '0|1' }, + defaultValue: { summary: '0' }, + }, + control: { + type: 'select', + options: [0, 1], + }, + }, + showTraffic: { + description: '叠加实时交通图层', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: false }, + }, + control: 'boolean', + }, + showRoad: { + description: '叠加路网图层', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: false }, + }, + control: 'boolean', + }, + visible: { + description: '显示或隐藏', + control: 'boolean', + }, + onShow: { + description: '显示时触发此事件', + }, + onHide: { + description: '隐藏时触发此事件', + }, + }, +} as Meta; + +const Template: Story = (args) => ; + +export const CommonUse: typeof Template = Template.bind({}); +CommonUse.storyName = '一般使用'; +CommonUse.args = {}; + +export const DefaultType: typeof Template = Template.bind({}); +DefaultType.storyName = '默认卫星图'; +DefaultType.args = { defaultType: 1 }; + +export const DefaultShowTraffic: typeof Template = Template.bind({}); +DefaultShowTraffic.storyName = '默认开启路况'; +DefaultShowTraffic.args = { showTraffic: true }; + +export const DefaultShowRoad: typeof Template = Template.bind({}); +DefaultShowRoad.storyName = '默认叠加路网图层'; +DefaultShowRoad.args = { showTraffic: true }; diff --git a/src/hooks/useAMapPluginInstance.ts b/src/hooks/useAMapPluginInstance.ts new file mode 100644 index 0000000..7fcd3ce --- /dev/null +++ b/src/hooks/useAMapPluginInstance.ts @@ -0,0 +1,32 @@ +import { useEffect, useState } from 'react'; + +import useAMap from './useAMap'; + +type UseAMapFNReturnType = ReturnType; + +const useAMapPluginInstance = ( + pluginName: string, + initInstance: (AMap: UseAMapFNReturnType['__AMAP__'], amap: UseAMapFNReturnType['map']) => T, +) => { + const { __AMAP__: AMap, map } = useAMap(); + const [curInstance, setInstance] = useState(null); + + useEffect(() => { + if (!AMap || !map) return; + + const init = () => { + const instance = initInstance(AMap, map); + setInstance(instance); + }; + + if (AMap[pluginName]) { + init(); + } else { + AMap.plugin([`AMap.${pluginName}`], init); + } + }, [AMap, map, pluginName, initInstance]); + + return curInstance; +}; + +export default useAMapPluginInstance; diff --git a/src/index.ts b/src/index.ts index 70f126f..9cfc03d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ export { default as useAMapAPI } from './hooks/useAMapAPI'; export { default as useAMap } from './hooks/useAMap'; export { default as useAMapContainerBinder } from './hooks/useAMapContainerBinder'; export { default as useAMapEventBinder } from './hooks/useAMapEventBinder'; +export { default as useAMapPluginInstance } from './hooks/useAMapPluginInstance'; export * from './components/AMapAPIContainer'; export { @@ -12,6 +13,7 @@ export { default as AMapControlBar, AMapControlBarProps } from './components/AMa export { default as AMapHawkEye, AMapHawkEyeProps } from './components/AMapHawkEye'; export { default as AMapScale, AMapScaleProps } from './components/AMapScale'; export { default as AMapToolBar, AMapToolBarProps } from './components/AMapToolBar'; +export { default as AMapMapType, AMapMapTypeProps } from './components/AMapMapType'; export { default as AMapGeoJSON,