diff --git a/src/components/Control/SwipeControl/demos/default.tsx b/src/components/Control/SwipeControl/demos/default.tsx new file mode 100644 index 00000000..d26563cd --- /dev/null +++ b/src/components/Control/SwipeControl/demos/default.tsx @@ -0,0 +1,35 @@ +import { LarkMap, RasterLayer, SwipeControl, useLayer } from '@antv/larkmap'; +import React from 'react'; + +const CustomComponent = () => { + const rightRasterLayer = useLayer('rightRasterLayer'); + return ( + + ); +}; + +export default () => { + return ( + + + + + + ); +}; diff --git a/src/components/Control/SwipeControl/index.md b/src/components/Control/SwipeControl/index.md new file mode 100644 index 00000000..e18a3f5b --- /dev/null +++ b/src/components/Control/SwipeControl/index.md @@ -0,0 +1,37 @@ +--- +toc: content +order: 2 +group: + title: 控件组件 + order: 2 +nav: + title: 组件 + path: /components +--- + +## 卷帘 - SwipeControl + +### 介绍 + +该控件用于分屏对比两个地图上叠加图层,图层可以添加到地图的左侧(顶部)或右侧(底部)。未添加到卷帘上的图层将显示在两侧。 + +### 代码演示 + + + +### API + +| 参数 | 说明 | 类型 | +| --- | --- | --- | +| orientation | 卷帘方向设置,默认 'vertical' | `vertical|horizontal` | +| ratio | 卷帘的位置,值域为 0 到 1, 默认正中间为 0.5 | `number` | +| layers | 卷帘左侧的图层 | `Array` | +| rightLayers | 卷帘左侧的图层 | `Array` | +| className | 自定义样式名 | `string` | +| style | 自定义样式 | `CSSProperties` | +| onAdd | 组件被添加时的回调 | `(this) => void` | +| onRemove | 组件被移除时的回调 | `(this) => void` | +| onShow | 组件显示时的回调 | `(this) => void` | +| onHide | 组件隐藏时的回调 | `(this) => void` | +| onMoving | 卷帘移动事件 | `(data: {size: number[], ratio: number[]}) => void` | + diff --git a/src/components/Control/SwipeControl/index.tsx b/src/components/Control/SwipeControl/index.tsx new file mode 100644 index 00000000..dc52d61f --- /dev/null +++ b/src/components/Control/SwipeControl/index.tsx @@ -0,0 +1,90 @@ +import type { IZoomControlOption } from '@antv/l7'; +import { Swipe as L7Swipe } from '@antv/l7'; +import { omitBy } from 'lodash-es'; +import React, { useEffect, useMemo, useState } from 'react'; +import { getStyleText } from '../../../utils'; +import { useLayerList, useScene } from '../../LarkMap/hooks'; +import { useL7ComponentEvent, useL7ComponentUpdate } from '../hooks'; +import type { SwipeControlProps } from './types'; + +export const SwipeControl: React.FC = ({ + onShow, + onHide, + onAdd, + onRemove, + onMoving, + className, + style, + rightLayers, + layers: layerItems, + ratio, + orientation, +}) => { + const scene = useScene(); + const [control, setControl] = useState(); + const styleText = useMemo(() => getStyleText(style), [style]); + const fullLayerList = useLayerList(); + + const layers = (defaultLayers) => { + return defaultLayers?.length + ? defaultLayers + .map((layerItem) => { + if (typeof layerItem === 'string') { + console.log(layerItem); + return fullLayerList.find((layer) => layer.id === layerItem); + } + if (!Object.prototype.hasOwnProperty.call(layerItem, 'isComposite')) { + //@ts-ignore + const { layer } = layerItem; + + if (typeof layer === 'string') { + const targetLayer = fullLayerList.find((item) => item.id === layer); + return targetLayer ? { ...layerItem, layer: targetLayer } : undefined; + } + return layerItem; + } + + return layerItem; + }) + .filter((layer) => !!layer) + .map((layerItem) => { + //@ts-ignore + return layerItem.subLayers ? layerItem.subLayers.getLayers().map((layer) => layer.layer) : layerItem.layer; + }) + .flat() + : fullLayerList; + }; + + const controlOptions: Partial = useMemo(() => { + return { + rightLayers: layers(rightLayers), + layers: layers(layerItems), + ratio, + orientation, + style: styleText, + }; + }, [className, styleText, rightLayers, layers, ratio, orientation]); + + useEffect(() => { + const swipe = new L7Swipe(omitBy(controlOptions, (value) => value === undefined)); + setControl(swipe); + scene.addControl(swipe); + return () => { + scene.removeControl(swipe); + setControl(undefined); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useL7ComponentUpdate(control, controlOptions); + + useL7ComponentEvent(control, { + add: onAdd, + remove: onRemove, + show: onShow, + hide: onHide, + moving: onMoving, + }); + + return <>; +}; diff --git a/src/components/Control/SwipeControl/types.ts b/src/components/Control/SwipeControl/types.ts new file mode 100644 index 00000000..0398c0bc --- /dev/null +++ b/src/components/Control/SwipeControl/types.ts @@ -0,0 +1,11 @@ +import type { ISwipeControlOption, Zoom as L7Zoom } from '@antv/l7'; +import type { CSSProperties } from 'react'; +import type { IControlCallback, Layer } from '../../../types'; + +export interface SwipeControlProps + extends Omit, 'style' | 'layers'>, + IControlCallback { + style?: CSSProperties; + onMoving?: (data: { size: number[]; ratio: number[] }) => void; + layers: (Layer | string)[]; +} diff --git a/src/components/Control/index.ts b/src/components/Control/index.ts index aca7533a..1c889645 100644 --- a/src/components/Control/index.ts +++ b/src/components/Control/index.ts @@ -29,3 +29,6 @@ export type { ZoomControlProps } from './ZoomControl/types'; export { LogoControl } from './LogoControl'; export type { LogoControlProps } from './LogoControl/types'; + +export { SwipeControl } from './SwipeControl'; +export type { SwipeControlProps } from './SwipeControl/types'; \ No newline at end of file