# 이미지

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

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

- Requested language: `ko-KR`

- Content language: `ko-KR`

- Documentation version: `1.0.4`

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

---

#### Package metadata

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

이미지를 사용하면 스프레드시트의 내용을 풍부하게 하고 시각적 표현을 강화하며, 핵심 정보를 설명하거나 강조할 수 있습니다.

현재 플로팅 이미지와 셀 이미지를 지원합니다.

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

## 플러그인 모드

### 설치

#### 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 { IImageIoService, LocaleType, mergeLocales, Univer } from '@univerjs/core'
import { UniverDocsDrawingPlugin } from '@univerjs/docs-drawing' // [!code ++]
import { UniverDrawingPlugin } from '@univerjs/drawing' // [!code ++]
import { UniverDrawingUIPlugin } from '@univerjs/drawing-ui' // [!code ++]
import DrawingUIEnUS from '@univerjs/drawing-ui/locale/en-US' // [!code ++]
import { UniverSheetsDrawingPlugin } from '@univerjs/sheets-drawing' // [!code ++]
import { UniverSheetsDrawingUIPlugin } from '@univerjs/sheets-drawing-ui' // [!code ++]
import SheetsDrawingUIEnUS from '@univerjs/sheets-drawing-ui/locale/en-US' // [!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.EN_US,
  locales: {
    [LocaleType.EN_US]: mergeLocales(
      DrawingUIEnUS, // [!code ++]
      SheetsDrawingUIEnUS, // [!code ++]
    ),
  },
})

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

[공동 편집](https://docs.univer.ai/ko-KR/guides/docs/features/collaboration.md) 기능을 사용하는 경우 `override` 구성을 추가해야 합니다.

```typescript
univer.registerPlugin(UniverDrawingPlugin, {
  override: [[IImageIoService, null]], // [!code ++]
  // allowImageSize: 20 * 1024 * 1024, // set the maximum allowed size of uploaded images to 20MB, optional
})
```

### 플러그인 및 구성

```typescript
interface IUniverDrawingConfig {
  /**
   * The maximum allowed size of uploaded images in bytes.
   * @default 5 * 1024 * 1024 (5MB)
   */
  allowImageSize?: number
}
```

## 모바일 지원

먼저 [모바일 에디터](https://docs.univer.ai/ko-KR/guides/sheets/getting-started/installation.md#mobile-support)를 구성하세요. 이 페이지의 플러그인 모드 초기화 코드에서 아래 데스크톱 등록을 같은 패키지의 모바일 버전으로 바꾸고 **문서를 열기 전에** 완료하세요. 모델 플러그인, 스타일, 언어 파일과 Facade 가져오기는 유지하며 두 버전을 동시에 등록하지 마세요.

| 패키지                           | 데스크톱 등록                       | 모바일 등록                              |
| ----------------------------- | ----------------------------- | ----------------------------------- |
| `@univerjs/drawing-ui`        | `UniverDrawingUIPlugin`       | `UniverDrawingMobileUIPlugin`       |
| `@univerjs/sheets-drawing-ui` | `UniverSheetsDrawingUIPlugin` | `UniverSheetsDrawingMobileUIPlugin` |

## 프리셋 모드

### 설치

#### 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 UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US'
import { UniverSheetsDrawingPreset } from '@univerjs/preset-sheets-drawing' // [!code ++]
import UniverPresetSheetsDrawingEnUS from '@univerjs/preset-sheets-drawing/locales/en-US' // [!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.EN_US,
  locales: {
    [LocaleType.EN_US]: mergeLocales(
      UniverPresetSheetsCoreEnUS,
      UniverPresetSheetsDrawingEnUS, // [!code ++]
    ),
  },
  presets: [
    UniverSheetsCorePreset(),
    UniverSheetsDrawingPreset(), // [!code ++]
  ],
})
```

[공동 편집](https://docs.univer.ai/ko-KR/guides/sheets/features/collaboration.md) 기능을 사용하는 경우 `UniverSheetsDrawingPreset`에 `collaboration: true` 옵션을 전달해야 합니다.

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

### 프리셋 및 구성

```typescript
interface IUniverSheetsDrawingPresetConfig {
  /**
   * Whether use the collaboration feature.
   * @default false
   */
  collaboration?: boolean
  /**
   * The maximum allowed size of uploaded images in bytes.
   * @default 5 * 1024 * 1024 (5MB)
   */
  allowImageSize?: number
}
```

## Facade API

전체 Facade API 타입 정의는 [FacadeAPI](https://docs.univer.ai/ko-KR/reference/facade.md)에서 확인할 수 있습니다.

### 가져오기

> [!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()

// You should register components at an appropriate time (e.g., when Univer is loaded)
// This is a React component. For Vue3 components, the third parameter should be `{ 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>
  ),
)

// Add a floating DOM
// If disposable is null, floating DOM addition failed
const disposable = fWorksheet.addFloatDomToPosition({
  componentKey: 'myFloatDom',
  initPosition: {
    startX: 100,
    endX: 300,
    startY: 100,
    endY: 200,
  },

  // Component data
  data: {
    label: 'hahah',
  },
})

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

`FWorksheet.addFloatDomToRange(range, layer, domLayout)` 메서드는 지정한 범위에 플로팅 DOM 요소를 추가합니다.

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

// Register a range loading component
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)

// Add the range loading component covering the range A1:C3
const fRange = fWorksheet.getRange('A1:C3')
const disposable = fWorksheet.addFloatDomToRange(fRange, { componentKey: 'RangeLoading' }, {}, 'myRangeLoading')

// Remove the floating DOM after 2 seconds
setTimeout(() => {
  disposable?.dispose()
}, 2000)

// another example-------------------
// Register a float button component
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)

// Add the float button to the range A5:C7, position is start from A5 cell, and width is 100px, height is 30px, margin is 100% of range width and height
const fRange2 = fWorksheet.getRange('A5:C7')
const disposable2 = fWorksheet.addFloatDomToRange(
  fRange2,
  {
    componentKey: 'FloatButton',
  },
  {
    width: 100,
    height: 30,
    marginX: '100%', // margin percent to range width, or pixel
    marginY: '100%',
  },
  'myFloatButton',
)
```

`FWorksheet.addFloatDomToColumnHeader(column, layer, domPos)` 메서드는 지정한 열 머리글에 플로팅 DOM 요소를 추가합니다.

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

// Register a float button component
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)

// Add the float button to the column D header, position is right align, width is 100px, height is 30px, margin is 0
const disposable = fWorksheet.addFloatDomToColumnHeader(
  3,
  {
    componentKey: 'FloatButton',
    allowTransform: false,
  },
  {
    width: 100,
    height: 30,
    marginX: 0,
    marginY: 0,
    horizonOffsetAlign: 'right',
  },
  'myFloatButton',
)

// Remove the float button after 2 seconds
setTimeout(() => {
  disposable?.dispose()
}, 2000)
```

### 플로팅 이미지 삽입

[`FWorksheet.newOverGridImage()`](https://docs.univer.ai/ko-KR/reference/facade/worksheet.md#newovergridimage)는 플로팅 이미지 빌더를 만들고 `FOverGridImageBuilder` 인스턴스를 반환합니다. 체이닝 호출로 플로팅 이미지를 삽입할 `ISheetImage` 객체를 생성할 수 있습니다.

[`FOverGridImageBuilder`](https://docs.univer.ai/ko-KR/reference/facade/over-grid-image-builder.md)의 주요 멤버 메서드는 다음과 같습니다.

| 메서드             | 설명                                           |
| --------------- | -------------------------------------------- |
| buildAsync      | 이미지를 빌드하고 `ISheetImage` 객체를 반환합니다.           |
| setSource       | 이미지 소스를 설정합니다.                               |
| setColumn       | 이미지의 가로 위치를 설정합니다.                           |
| setRow          | 이미지의 세로 위치를 설정합니다.                           |
| setColumnOffset | 이미지의 가로 오프셋을 설정합니다.                          |
| setRowOffset    | 이미지의 세로 오프셋을 설정합니다.                          |
| setWidth        | 이미지 너비를 설정합니다.                               |
| setHeight       | 이미지 높이를 설정합니다.                               |
| setAnchorType   | 셀에 따라 이미지의 위치와 크기가 변경되는지를 결정하는 앵커 유형을 설정합니다. |
| setCropTop      | 위쪽 경계를 지정해 이미지 자르기 영역을 설정하고 원하는 부분을 표시합니다.   |
| setCropLeft     | 왼쪽 경계를 지정해 이미지 자르기 영역을 설정하고 원하는 부분을 표시합니다.   |
| setCropBottom   | 아래쪽 경계를 지정해 이미지 자르기 영역을 설정하고 원하는 부분을 표시합니다.  |
| setCropRight    | 오른쪽 경계를 지정해 이미지 자르기 영역을 설정하고 원하는 부분을 표시합니다.  |
| setRotate       | 이미지의 회전 각도를 설정합니다.                           |

```typescript
// create a new image builder and set image source.
// then build `ISheetImage` and insert it into the sheet, position is start from F6 cell, width is 500px, height is 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
// Insert an image to the sheet, position is F6, offset is 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/ko-KR/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
// create a new image builder and set image source.
// then build `ISheetImage` and insert it into the sheet, position is start from F6 cell, width is 500px, height is 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])

// update the image width to 100px and height to 50px after 4 seconds
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]

// Delete the first image of the sheet
fWorksheet.deleteImages([image])
```

### 셀 이미지 삽입

`FRange.insertCellImageAsync(file)` 메서드는 셀 이미지를 삽입합니다.

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

// Insert an image into the cell A10
const fRange = fWorksheet.getRange('A10')
const result = await fRange.insertCellImageAsync('https://avatars.githubusercontent.com/u/61444807?s=48&v=4')
```

## 워크시트 배경 이미지

워크시트는 셀 뒤에 이미지 한 장을 반복해서 표시할 수 있습니다. 떠 있는 이미지 및 셀 이미지와 별도로 `IWorksheetData.backgroundImage`에 저장됩니다. Drawing 프리셋에 포함되며 플러그인 모드에는 `@univerjs/sheets-drawing`, Facade 및 렌더링·업로드용 Drawing UI가 필요합니다.

```ts
import '@univerjs/sheets-drawing/facade'

const sheet = univerAPI.getActiveWorkbook()?.getActiveSheet()
if (!sheet) throw new Error('No active worksheet')

sheet.setBackgroundImage('https://example.com/background.png')
console.log(sheet.getBackgroundImage())
sheet.deleteBackgroundImage()
```

`setBackgroundImage()`는 기본적으로 `ImageSourceType.URL`을 사용하여 배경을 교체하고 `deleteBackgroundImage()`는 배경을 제거합니다. 둘 다 실행 취소/다시 실행을 지원합니다. UI 업로드는 설정된 이미지 I/O 서비스를 사용합니다. 배경은 화면 표시용이며 인쇄에서 제외됩니다.

## 이미지 불투명도

부동 이미지 전체의 불투명도를 설정할 수 있습니다. `setOpacity()`는 `0`(투명)부터 `1`(불투명)까지의 유한한 숫자를 받으며 기본값은 `1`입니다. 잘못된 값은 `RangeError`를 발생시킵니다. 생성 전 `FOverGridImageBuilder` 또는 기존 `FOverGridImage`에서 설정하고, 두 객체의 `getOpacity()`로 읽을 수 있습니다. 이미지 속성 패널에서도 투명도를 조절할 수 있습니다.

```ts
const sheet = univerAPI.getActiveWorkbook()?.getActiveSheet()
const image = sheet?.getImages()[0]
if (image) {
  image.setOpacity(0.5)
  console.log(image.getOpacity())
}
```
