# 形状

- Human documentation: [https://docs.univer.ai/zh-CN/guides/sheets/features/shapes](https://docs.univer.ai/zh-CN/guides/sheets/features/shapes)

- Agent Markdown: [https://docs.univer.ai/zh-CN/guides/sheets/features/shapes.md](https://docs.univer.ai/zh-CN/guides/sheets/features/shapes.md)

- Requested language: `zh-CN`

- Content language: `zh-CN`

- Documentation version: `1.0.0-rc.0`

- Source: [sheets/features/shapes.zh-CN.mdx](https://github.com/dream-num/documentation/blob/dev/content/guides/sheets/features/shapes.zh-CN.mdx)

---

#### Package metadata

```json
{
  "preset": [
    {
      "client": "@univerjs/preset-sheets-advanced",
      "locale": "@univerjs/preset-sheets-advanced/locales/zh-CN",
      "style": "@univerjs/preset-sheets-advanced/lib/index.css"
    }
  ],
  "plugins": [
    {
      "client": "@univerjs/drawing"
    },
    {
      "client": "@univerjs/drawing-ui",
      "locale": "@univerjs/drawing-ui/locale/zh-CN",
      "style": "@univerjs/drawing-ui/lib/index.css"
    },
    {
      "client": "@univerjs/sheets-drawing"
    },
    {
      "client": "@univerjs/sheets-drawing-ui",
      "locale": "@univerjs/sheets-drawing-ui/locale/zh-CN",
      "style": "@univerjs/sheets-drawing-ui/lib/index.css"
    },
    {
      "client": "@univerjs-pro/sheets-shape"
    },
    {
      "client": "@univerjs-pro/sheets-shape-ui",
      "facade": "@univerjs-pro/sheets-shape/facade",
      "locale": "@univerjs-pro/sheets-shape-ui/locale/zh-CN",
      "style": "@univerjs-pro/sheets-shape-ui/lib/index.css"
    }
  ],
  "license": true,
  "server": false
}
```

在 Univer Sheets 中，形状（Shapes）可以用于绘制流程图、注释标记、提示框，以及在工作表上构建可视化说明。

> Interactive example: [Open the playground](/playground/sheets/shapes)

## 预设模式

形状功能包含在 `@univerjs/preset-sheets-advanced` 预设中。

### 安装

> [!NOTE]
> `@univerjs/preset-sheets-advanced` 的 `UniverSheetsAdvancedPreset` 在运行时依赖 `UniverSheetsDrawingPreset`，请先安装 `@univerjs/preset-sheets-drawing`。

#### npm

```bash
npm install @univerjs/preset-sheets-drawing @univerjs/preset-sheets-advanced
```

#### pnpm

```bash
pnpm add @univerjs/preset-sheets-drawing @univerjs/preset-sheets-advanced
```

#### yarn

```bash
yarn add @univerjs/preset-sheets-drawing @univerjs/preset-sheets-advanced
```

#### bun

```bash
bun add @univerjs/preset-sheets-drawing @univerjs/preset-sheets-advanced
```

### 使用

```typescript
import { UniverSheetsAdvancedPreset } from '@univerjs/preset-sheets-advanced' // [!code ++]
import UniverPresetSheetsAdvancedZhCN from '@univerjs/preset-sheets-advanced/locales/zh-CN' // [!code ++]
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'
import UniverPresetSheetsCoreZhCN from '@univerjs/preset-sheets-core/locales/zh-CN'
import { UniverSheetsDrawingPreset } from '@univerjs/preset-sheets-drawing' // [!code ++]
import UniverPresetSheetsDrawingZhCN from '@univerjs/preset-sheets-drawing/locales/zh-CN' // [!code ++]
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets'

import '@univerjs/preset-sheets-core/lib/index.css'
import '@univerjs/preset-sheets-drawing/lib/index.css' // [!code ++]
import '@univerjs/preset-sheets-advanced/lib/index.css' // [!code ++]

const { univerAPI } = createUniver({
  locale: LocaleType.ZH_CN,
  locales: {
    [LocaleType.ZH_CN]: mergeLocales(
      UniverPresetSheetsCoreZhCN,
      UniverPresetSheetsDrawingZhCN, // [!code ++]
      UniverPresetSheetsAdvancedZhCN, // [!code ++]
    ),
  },
  presets: [
    UniverSheetsCorePreset(),
    UniverSheetsDrawingPreset(), // [!code ++]
    UniverSheetsAdvancedPreset(), // [!code ++]
  ],
})
```

如果你持有 Univer 商业许可，请参考 [客户端许可证使用说明](https://docs.univer.ai/zh-CN/guides/license.md#in-preset-mode) 进行配置。

## 插件模式

### 安装

#### npm

```bash
npm install @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui @univerjs-pro/sheets-shape @univerjs-pro/sheets-shape-ui
```

#### pnpm

```bash
pnpm add @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui @univerjs-pro/sheets-shape @univerjs-pro/sheets-shape-ui
```

#### yarn

```bash
yarn add @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui @univerjs-pro/sheets-shape @univerjs-pro/sheets-shape-ui
```

#### bun

```bash
bun add @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui @univerjs-pro/sheets-shape @univerjs-pro/sheets-shape-ui
```

> [!WARN]
> 形状插件依赖绘图插件，注册形状插件前必须先注册 `UniverDrawingPlugin`、`UniverSheetsDrawingPlugin`、`UniverDrawingUIPlugin` 和 `UniverSheetsDrawingUIPlugin`。

### 使用

```typescript
import { UniverSheetsShapePlugin } from '@univerjs-pro/sheets-shape' // [!code ++]
import { UniverSheetsShapeUIPlugin } from '@univerjs-pro/sheets-shape-ui' // [!code ++]
import SheetsShapeUIZhCN from '@univerjs-pro/sheets-shape-ui/locale/zh-CN' // [!code ++]
import { LocaleType, mergeLocales, Univer } from '@univerjs/core'
import { UniverDrawingPlugin } from '@univerjs/drawing' // [!code ++]
import { UniverDrawingUIPlugin } from '@univerjs/drawing-ui' // [!code ++]
import DrawingUIZhCN from '@univerjs/drawing-ui/locale/zh-CN' // [!code ++]
import { UniverSheetsDrawingPlugin } from '@univerjs/sheets-drawing' // [!code ++]
import { UniverSheetsDrawingUIPlugin } from '@univerjs/sheets-drawing-ui' // [!code ++]
import SheetsDrawingUIZhCN from '@univerjs/sheets-drawing-ui/locale/zh-CN' // [!code ++]

import '@univerjs-pro/sheets-shape/facade' // [!code ++]

import '@univerjs/drawing-ui/lib/index.css' // [!code ++]
import '@univerjs/sheets-drawing-ui/lib/index.css' // [!code ++]
import '@univerjs-pro/sheets-shape-ui/lib/index.css' // [!code ++]

const univer = new Univer({
  locale: LocaleType.ZH_CN,
  locales: {
    [LocaleType.ZH_CN]: mergeLocales(
      DrawingUIZhCN, // [!code ++]
      SheetsDrawingUIZhCN, // [!code ++]
      SheetsShapeUIZhCN, // [!code ++]
    ),
  },
})

univer.registerPlugin(UniverDrawingPlugin) // [!code ++]
univer.registerPlugin(UniverDrawingUIPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsDrawingPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsDrawingUIPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsShapePlugin) // [!code ++]
univer.registerPlugin(UniverSheetsShapeUIPlugin) // [!code ++]
```

如果你持有 Univer 商业许可，请参考 [客户端许可证使用说明](https://docs.univer.ai/zh-CN/guides/license.md#in-plugin-mode) 进行配置。

## Facade API

完整 Facade API 类型定义，请查看 [FacadeAPI](https://docs.univer.ai/zh-CN/reference/facade/univer.md)。

### 引入

> [!INFO: 插件模式说明]
> 只有插件模式需要手动导入 Facade 包。预设模式已经内置对应 Facade，无需额外导入。

```typescript
import '@univerjs-pro/sheets-shape/facade'
```

### 插入基础形状

向 `FWorksheet.insertShape` 传入通用形状创建数据，它会返回一个可直接操作的 Facade 实例。

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

const rectShape = fWorksheet.insertShape({
  shapeType: univerAPI.Enum.ShapeTypeEnum.Rect,
  transform: { left: 120, top: 80, width: 240, height: 120 },
  shapeData: {
    fill: {
      fillType: univerAPI.Enum.ShapeFillEnum.SolidFill,
      color: '#e6f4ff',
    },
    stroke: {
      lineStrokeType: univerAPI.Enum.ShapeLineTypeEnum.SolidLine,
      color: '#1677ff',
      width: 2,
    },
  },
})

if (!rectShape) throw new Error('Shape could not be inserted.')
```

### 插入并连接连接线形状

通过 `FWorksheet.insertShape` 插入连接线，再通过返回的 `FConnectorShape` Facade 绑定两端。

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

const leftShape = fWorksheet.insertShape({
  shapeType: univerAPI.Enum.ShapeTypeEnum.RoundRect,
  transform: { left: 80, top: 80, width: 180, height: 100 },
})
const rightShape = fWorksheet.insertShape({
  shapeType: univerAPI.Enum.ShapeTypeEnum.Ellipse,
  transform: { left: 420, top: 200, width: 180, height: 100 },
})
const connectorShape = fWorksheet.insertShape({
  shapeType: univerAPI.Enum.ShapeTypeEnum.BentConnector3,
  transform: { left: 240, top: 130, width: 240, height: 120 },
})

if (!leftShape || !rightShape || !connectorShape) {
  throw new Error('Shapes could not be inserted.')
}

const startSite = leftShape.getConnectionSites()[0]
const rightSites = rightShape.getConnectionSites()
const endSite = rightSites[2] ?? rightSites[0]

if (!startSite || !endSite) throw new Error('Connection site not found.')

connectorShape
  .bindStart(leftShape.getId(), startSite.index)
  .bindEnd(rightShape.getId(), endSite.index)
  .setEndArrow(univerAPI.Enum.ShapeArrowTypeEnum.Arrow)
```

### 更新和删除形状

直接通过形状的 Facade 实例更新或删除形状。

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

const firstShape = fWorksheet.getShapes().find(shape => !shape.isConnectorShape())

if (firstShape) {
  firstShape
    .setStrokeColor('#ff4d4f')
    .setStrokeWidth(3)
    .setSolidFill('#fff1f0')

  // 如有需要，可在更新后删除该形状
  const removed = firstShape.remove()
  console.log(removed)
}
```
