# 图片

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

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

- Requested language: `zh-CN`

- Content language: `zh-CN`

- Documentation version: `1.0.0-rc.0`

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

---

#### Package metadata

```json
{
  "preset": [
    {
      "client": "@univerjs/preset-sheets-drawing",
      "locale": "@univerjs/preset-sheets-drawing/locales/zh-CN",
      "style": "@univerjs/preset-sheets-drawing/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",
      "facade": "@univerjs/sheets-drawing-ui/facade",
      "locale": "@univerjs/sheets-drawing-ui/locale/zh-CN",
      "style": "@univerjs/sheets-drawing-ui/lib/index.css"
    }
  ],
  "server": false
}
```

图片功能允许用户在电子表格中插入和管理图片，以便更好地展示数据和信息。它支持多种图片格式和操作，帮助用户创建更丰富的文档。

目前支持插入的图片类型为：浮动图片、单元格图片

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

## 预设模式

### 安装

#### npm

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

#### pnpm

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

#### yarn

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

#### bun

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

### 使用

```typescript
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 ++]

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

如使用[协同编辑](https://docs.univer.ai/zh-CN/guides/sheets/features/collaboration.md)功能，请确保在 `UniverSheetsDrawingPreset` 中传入 `collaboration: true` 选项。

```typescript
UniverSheetsDrawingPreset({
  collaboration: true, // [!code ++]
})
```

### 预设与配置

```typescript
interface IUniverSheetsDrawingPresetConfig {
  /**
   * 是否使用了协同编辑功能。
   * @default false
   */
  collaboration?: boolean
  /**
   * 设置上传图片的最大允许大小，以字节为单位。
   * @default 5 * 1024 * 1024 (5MB)
   */
  allowImageSize?: number
}
```

## 插件模式

### 安装

#### npm

```bash
npm install @univerjs/docs-drawing @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui
```

#### pnpm

```bash
pnpm add @univerjs/docs-drawing @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui
```

#### yarn

```bash
yarn add @univerjs/docs-drawing @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui
```

#### bun

```bash
bun add @univerjs/docs-drawing @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui
```

### 使用

```typescript
import { LocaleType, mergeLocales, Univer } from '@univerjs/core'
import { UniverDocsDrawingPlugin } from '@univerjs/docs-drawing' // [!code ++]
import { IImageIoService, 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/drawing-ui/lib/index.css' // [!code ++]
import '@univerjs/sheets-drawing-ui/lib/index.css' // [!code ++]

import '@univerjs/sheets-drawing/facade' // [!code ++]
import '@univerjs/sheets-drawing-ui/facade' // [!code ++]

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

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

如使用[协同编辑](https://docs.univer.ai/zh-CN/guides/docs/features/collaboration.md)功能，需要添加 `override` 配置：

```typescript
univer.registerPlugin(UniverDrawingPlugin, {
  override: [[IImageIoService, null]], // [!code ++]
  // allowImageSize: 20 * 1024 * 1024, // 设置上传图片的最大允许大小为 20MB，非必需
})
```

### 插件与配置

```typescript
interface IUniverDrawingConfig {
  /**
   * 设置上传图片的最大允许大小，以字节为单位。
   * @default 5 * 1024 * 1024 (5MB)
   */
  allowImageSize?: number
}
```

## Facade API

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

### 引入

> [!INFO: 插件模式提示]
> 仅插件模式需要手动引入 Facade 包。预设模式已内置对应的 Facade 包，无需额外导入。

```typescript
import '@univerjs/sheets-drawing/facade'
import '@univerjs/sheets-drawing-ui/facade'
```

### 添加浮动 DOM

`FWorksheet.addFloatDomToPosition(layer)` 方法可以添加一个浮动的 DOM 元素到指定位置。

```tsx
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()

// 你应该在合适的时机注册组件（例如 Univer 加载完成时）
// 这是一个 React 组件。对于 Vue3 组件，第三个参数应该是 `{ framework: 'vue3' }`
univerAPI.registerComponent(
  'myFloatDom',
  ({ data }) => (
    <div style={{ width: '100%', height: '100%', background: '#fff', border: '1px solid #ccc', boxSizing: 'border-box' }}>
      popup content:
      {' '}
      {data?.label}
    </div>
  ),
)

// 添加浮动 DOM
// 如果 disposable 为 null，则浮动 DOM 添加失败
const disposable = fWorksheet.addFloatDomToPosition({
  componentKey: 'myFloatDom',
  initPosition: {
    startX: 100,
    endX: 300,
    startY: 100,
    endY: 200,
  },

  // 组件数据
  data: {
    label: 'hahah',
  },
})

// 2 秒后移除浮动 DOM
setTimeout(() => {
  disposable?.dispose()
}, 2000)
```

`FWorksheet.addFloatDomToRange(range, layer, domLayout)` 方法可以添加一个浮动的 DOM 元素到指定范围。

```tsx
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()

// 注册一个范围加载组件
function RangeLoading() {
  const divStyle = {
    width: '100%',
    height: '100%',
    backgroundColor: '#fff',
    border: '1px solid #ccc',
    boxSizing: 'border-box' as const,
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    textAlign: 'center' as const,
    transformOrigin: 'top left',
  }

  return (
    <div style={divStyle}>
      Loading...
    </div>
  )
}
univerAPI.registerComponent('RangeLoading', RangeLoading)

// 添加范围加载组件覆盖范围 A1:C3
const fRange = fWorksheet.getRange('A1:C3')
const disposable = fWorksheet.addFloatDomToRange(fRange, { componentKey: 'RangeLoading' }, {}, 'myRangeLoading')

// 2 秒后移除浮动 DOM
setTimeout(() => {
  disposable?.dispose()
}, 2000)

// 另外一个示例 -------------------
// 注册一个浮动按钮组件
function FloatButton() {
  const divStyle = {
    width: '100px',
    height: '30px',
    backgroundColor: '#fff',
    border: '1px solid #ccc',
    boxSizing: 'border-box' as const,
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    textAlign: 'center' as const,
    cursor: 'pointer',
  }

  const clickHandler = () => {
    console.warn('click')
  }

  return (
    <div style={divStyle} onClick={clickHandler}>
      FloatButton
    </div>
  )
}
univerAPI.registerComponent('FloatButton', FloatButton)

// 添加浮动按钮到范围 A5:C7，位置从 A5 单元格开始，宽度为 100px，高度为 30px，边距为范围宽度和高度的 100%
const fRange2 = fWorksheet.getRange('A5:C7')
const disposable2 = fWorksheet.addFloatDomToRange(
  fRange2,
  {
    componentKey: 'FloatButton',
  },
  {
    width: 100,
    height: 30,
    marginX: '100%', // 边距百分比到范围宽度，或像素
    marginY: '100%',
  },
  'myFloatButton',
)
```

`FWorksheet.addFloatDomToColumnHeader(column, layer, domPos)` 方法可以添加一个浮动的 DOM 元素到指定列头。

```tsx
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()

// 注册一个浮动按钮组件
function FloatButton() {
  const divStyle = {
    width: '100px',
    height: '30px',
    backgroundColor: '#fff',
    border: '1px solid #ccc',
    boxSizing: 'border-box' as const,
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    textAlign: 'center' as const,
    cursor: 'pointer',
  }

  const clickHandler = () => {
    console.warn('click')
  }

  return (
    <div style={divStyle} onClick={clickHandler}>
      FloatButton
    </div>
  )
}
univerAPI.registerComponent('FloatButton', FloatButton)

// 添加浮动按钮到列 D 头部，位置为右对齐，宽度为 100px，高度为 30px，边距为 0
const disposable = fWorksheet.addFloatDomToColumnHeader(
  3,
  {
    componentKey: 'FloatButton',
    allowTransform: false,
  },
  {
    width: 100,
    height: 30,
    marginX: 0,
    marginY: 0,
    horizonOffsetAlign: 'right',
  },
  'myFloatButton',
)

// 2 秒后移除浮动按钮
setTimeout(() => {
  disposable?.dispose()
}, 2000)
```

### 插入浮动图片

[`FWorksheet.newOverGridImage()`](https://docs.univer.ai/zh-CN/reference/facade/worksheet.md#newovergridimage) 创建一个浮动图片构建器，返回一个 `FOverGridImageBuilder` 实例，可以通过链式调用生成 `ISheetImage` 对象用于插入浮动图片。

以下是 [`FOverGridImageBuilder`](https://docs.univer.ai/zh-CN/reference/facade/chart.md) 上的一些成员方法：

| 方法              | 描述                                    |
| --------------- | ------------------------------------- |
| buildAsync      | 构建 `ISheetImage` 对象用于插入浮动图片           |
| setSource       | 设置 image 的来源                          |
| setColumn       | 设置 image 的水平方向位置                      |
| setRow          | 设置 image 的垂直方向位置                      |
| setColumnOffset | 设置 image 的水平方向偏移                      |
| setRowOffset    | 设置 image 的垂直方向偏移                      |
| setWidth        | 设置 image 的宽度                          |
| setHeight       | 设置 image 的高度                          |
| setAnchorType   | 设置 image 的锚点类型，是否随单元格位置和大小变化          |
| setCropTop      | 设置 image 的裁剪区域，定义顶部边缘，从而显示你想要的图像的特定部分 |
| setCropLeft     | 设置 image 的裁剪区域，定义左边缘，从而显示你想要的图像的特定部分  |
| setCropBottom   | 设置 image 的裁剪区域，定义底部边缘，从而显示你想要的图像的特定部分 |
| setCropRight    | 设置 image 的裁剪区域，定义右边缘，从而显示你想要的图像的特定部分  |
| setRotate       | 设置 image 的旋转角度                        |

```typescript
// 创建一个新的图片构建器并设置图片来源。
// 然后构建 `ISheetImage` 并插入到工作表中，位置从 F6 单元格开始，宽度为 500px，高度为 300px
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const image = await fWorksheet.newOverGridImage()
  .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
  .setColumn(5)
  .setRow(5)
  .setWidth(500)
  .setHeight(300)
  .buildAsync()
fWorksheet.insertImages([image])
```

亦可以通过 `FWorksheet.insertImage(url, column, row, offsetX, offsetY)` 方法插入图片。

```typescript
// 插入一个图片到工作表，位置为 F6，偏移为 10px
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()
const result = await fWorksheet.insertImage('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', 5, 5, 10, 10)
```

### 获取浮动图片

`FWorksheet.getImages()` 方法可以获取工作表中的所有浮动图片，返回一个 [`FOverGridImage[]`](https://docs.univer.ai/zh-CN/reference/facade/chart.md) 实例数组。

```typescript
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()
const images = fWorksheet.getImages()
images.forEach((image) => {
  image.getId()
})
```

亦可以通过 `FWorksheet.getImageById(id)` 方法获取指定 id 的浮动图片。

### 更新浮动图片

`FWorksheet.updateImages(sheetImages)` 方法可以更新浮动图片的位置和大小等属性。

```typescript
// 创建一个新的图片构建器并设置图片来源。
// 然后构建 `ISheetImage` 并插入到工作表中，位置从 F6 单元格开始，宽度为 500px，高度为 300px
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const image = await fWorksheet.newOverGridImage()
  .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
  .setColumn(5)
  .setRow(5)
  .setWidth(500)
  .setHeight(300)
  .buildAsync()
fWorksheet.insertImages([image])

// 4 秒后更新图片宽度为 100px，高度为 50px
setTimeout(async () => {
  const imageBuilder = fWorksheet.getImageById(image.drawingId).toBuilder()
  const newImage = await imageBuilder.setWidth(100).setHeight(50).buildAsync()
  fWorksheet.updateImages([newImage])
}, 4000)
```

### 删除浮动图片

`FWorksheet.deleteImages(sheetImages)` 方法可以删除浮动图片。

```typescript
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()
const image = fWorksheet.getImages()[0]

// 删除工作表中的第一个图片
fWorksheet.deleteImages([image])
```

### 插入单元格图片

`FRange.insertCellImageAsync(file)` 方法可以插入单元格图片。

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

// 在 A10 单元格插入一个图片
const fRange = fWorksheet.getRange('A10')
const result = await fRange.insertCellImageAsync('https://avatars.githubusercontent.com/u/61444807?s=48&v=4')
```
