이미지

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

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

플러그인 모드

설치

Shell
pnpm 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'import { UniverDrawingPlugin } from '@univerjs/drawing'import { UniverDrawingUIPlugin } from '@univerjs/drawing-ui'import DrawingUIEnUS from '@univerjs/drawing-ui/locale/en-US'import { UniverSheetsDrawingPlugin } from '@univerjs/sheets-drawing'import { UniverSheetsDrawingUIPlugin } from '@univerjs/sheets-drawing-ui'import SheetsDrawingUIEnUS from '@univerjs/sheets-drawing-ui/locale/en-US'import '@univerjs/drawing-ui/lib/index.css'import '@univerjs/sheets-drawing-ui/lib/index.css'import '@univerjs/sheets-drawing/facade'import '@univerjs/sheets-drawing-ui/facade'const univer = new Univer({  locale: LocaleType.EN_US,  locales: {    [LocaleType.EN_US]: mergeLocales(      DrawingUIEnUS,       SheetsDrawingUIEnUS,     ),  },})univer.registerPlugin(UniverDrawingPlugin)univer.registerPlugin(UniverDrawingUIPlugin)univer.registerPlugin(UniverSheetsDrawingPlugin)univer.registerPlugin(UniverSheetsDrawingUIPlugin)

공동 편집 기능을 사용하는 경우 override 구성을 추가해야 합니다.

TypeScript
univer.registerPlugin(UniverDrawingPlugin, {  override: [[IImageIoService, null]],   // 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}

모바일 지원

먼저 모바일 에디터를 구성하세요. 이 페이지의 플러그인 모드 초기화 코드에서 아래 데스크톱 등록을 같은 패키지의 모바일 버전으로 바꾸고 문서를 열기 전에 완료하세요. 모델 플러그인, 스타일, 언어 파일과 Facade 가져오기는 유지하며 두 버전을 동시에 등록하지 마세요.

패키지데스크톱 등록모바일 등록
@univerjs/drawing-uiUniverDrawingUIPluginUniverDrawingMobileUIPlugin
@univerjs/sheets-drawing-uiUniverSheetsDrawingUIPluginUniverSheetsDrawingMobileUIPlugin

프리셋 모드

설치

Shell
pnpm 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'import UniverPresetSheetsDrawingEnUS from '@univerjs/preset-sheets-drawing/locales/en-US'import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets'import '@univerjs/preset-sheets-core/lib/index.css'import '@univerjs/preset-sheets-drawing/lib/index.css'const { univerAPI } = createUniver({  locale: LocaleType.EN_US,  locales: {    [LocaleType.EN_US]: mergeLocales(      UniverPresetSheetsCoreEnUS,      UniverPresetSheetsDrawingEnUS,     ),  },  presets: [    UniverSheetsCorePreset(),    UniverSheetsDrawingPreset(),   ],})

공동 편집 기능을 사용하는 경우 UniverSheetsDrawingPreset에 collaboration: true 옵션을 전달해야 합니다.

TypeScript
UniverSheetsDrawingPreset({  collaboration: true, })

프리셋 및 구성

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에서 확인할 수 있습니다.

가져오기

플러그인 모드 참고

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 failedconst disposable = fWorksheet.addFloatDomToPosition({  componentKey: 'myFloatDom',  initPosition: {    startX: 100,    endX: 300,    startY: 100,    endY: 200,  },  // Component data  data: {    label: 'hahah',  },})// 2 秒后移除浮动 DOMsetTimeout(() => {  disposable?.dispose()}, 2000)

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

TSX
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()// Register a range loading componentfunction 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:C3const fRange = fWorksheet.getRange('A1:C3')const disposable = fWorksheet.addFloatDomToRange(fRange, { componentKey: 'RangeLoading' }, {}, 'myRangeLoading')// Remove the floating DOM after 2 secondssetTimeout(() => {  disposable?.dispose()}, 2000)// another example-------------------// Register a float button componentfunction 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 heightconst 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 componentfunction 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 0const 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 secondssetTimeout(() => {  disposable?.dispose()}, 2000)

플로팅 이미지 삽입

FWorksheet.newOverGridImage()는 플로팅 이미지 빌더를 만들고 FOverGridImageBuilder 인스턴스를 반환합니다. 체이닝 호출로 플로팅 이미지를 삽입할 ISheetImage 객체를 생성할 수 있습니다.

FOverGridImageBuilder의 주요 멤버 메서드는 다음과 같습니다.

메서드설명
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 300pxconst 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 10pxconst 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[] 인스턴스 배열로 반환합니다.

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 300pxconst 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 secondssetTimeout(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 sheetfWorksheet.deleteImages([image])

셀 이미지 삽입

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

TypeScript
const fWorkbook = univerAPI.getActiveWorkbook()const fWorksheet = fWorkbook.getActiveSheet()// Insert an image into the cell A10const 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가 필요합니다.

TypeScript
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()로 읽을 수 있습니다. 이미지 속성 패널에서도 투명도를 조절할 수 있습니다.

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

이 가이드는 어떠셨나요?

© 2026 DreamNum Co., Ltd.