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