Fabric.js Textbox에 Google Fonts를 적용하고, 텍스트의 특정 구간에만 굵게 또는 기울임 스타일을 적용하는 것은 두 가지 별개의 단계를 통해 이루어집니다. 먼저 웹 환경에 Google Fonts를 로드하여 Fabric.js가 해당 폰트를 인식하도록 하고, 그 다음 Textbox 객체의 setSelectionStyles 메서드를 사용하여 원하는 구간에 스타일을 적용합니다.

1. Google Fonts 로드 및 Textbox에 적용

Fabric.js는 브라우저에 로드된 폰트만 사용할 수 있습니다. 따라서 Google Fonts를 사용하려면 HTML 문서에 해당 폰트를 미리 로드해야 합니다. 가장 일반적인 방법은 HTML <head> 태그 내에 <link> 태그를 추가하거나, CSS 파일에서 @import 규칙을 사용하는 것입니다.

폰트 로드 예시 (HTML head 태그)

Google Fonts 웹사이트에서 원하는 폰트를 선택한 후 제공되는 <link> 태그를 HTML 문서의 <head> 섹션에 추가합니다. font-weightfont-style을 부분적으로 사용할 경우, 해당 스타일도 함께 로드해야 합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Fabric.js Google Fonts Example</title>
  <!-- Roboto 폰트 (일반, 굵게, 기울임) 로드 -->
  <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">
  <style>
    /* 폰트가 완전히 로드될 때까지 텍스트가 보이지 않는 현상 방지 (FOIT) */
    body { font-family: 'Roboto', sans-serif; }
  </style>
</head>
<body>
  <canvas id="canvas" width="800" height="600"></canvas>
  <script src="https://cdn.jsdelivr.net/npm/fabric@5.3.1/dist/fabric.min.js"></script>
  <script>
    // JavaScript 코드
  </script>
</body>
</html>

Textbox에 폰트 적용

폰트가 로드된 후에는 fabric.Textbox 객체를 생성할 때 fontFamily 속성을 설정하여 적용할 수 있습니다. 폰트 로딩은 비동기적으로 이루어지므로, 폰트가 완전히 로드된 후에 캔버스에 텍스트를 추가하거나 렌더링하는 것이 좋습니다. document.fonts.ready를 사용하여 폰트 로딩 완료를 기다릴 수 있습니다.

// 폰트가 로드되었는지 확인 후 Textbox 생성 및 추가
document.fonts.ready.then(() => {
  const canvas = new fabric.Canvas('canvas');

  const textbox = new fabric.Textbox('안녕하세요, Fabric.js와 Google Fonts를 사용한 멋진 텍스트입니다.', {
    left: 50,
    top: 50,
    width: 700,
    fontSize: 30,
    fill: '#333',
    fontFamily: 'Roboto' // 로드한 Google Font 이름 적용
  });

  canvas.add(textbox);
  canvas.renderAll();
});

2. Textbox 특정 구간에 굵게/기울임 스타일 적용

Fabric.js의 Textbox 객체는 setSelectionStyles 메서드를 통해 텍스트의 특정 구간에 다양한 스타일을 적용할 수 있습니다. 이 메서드는 시작 인덱스와 끝 인덱스를 받아 해당 범위의 텍스트에 스타일 객체를 적용합니다.

setSelectionStyles 메서드 사용법

  • styles: object: 적용할 스타일 속성들을 담은 객체. 예: { fontWeight: 'bold' }, { fontStyle: 'italic' }
  • startIndex?: number: 스타일을 적용할 시작 인덱스 (포함).
  • endIndex?: number: 스타일을 적용할 끝 인덱스 (미포함).
// 이미 생성된 textbox 객체에 스타일 적용
const canvas = new fabric.Canvas('canvas');
const textbox = new fabric.Textbox('안녕하세요, Fabric.js와 Google Fonts를 사용한 멋진 텍스트입니다.', {
  left: 50,
  top: 50,
  width: 700,
  fontSize: 30,
  fill: '#333',
  fontFamily: 'Roboto'
});
canvas.add(textbox);

// 'Google Fonts' 부분을 굵게 (bold) 적용
// '안녕하세요, Fabric.js와 '.length = 10
// 'Google Fonts'.length = 12
// 따라서 10번째 인덱스부터 22번째 인덱스(미포함)까지
textbox.setSelectionStyles({ fontWeight: 'bold' }, 10, 22); 

// '멋진 텍스트입니다' 부분을 기울임 (italic) 적용
// '안녕하세요, Fabric.js와 Google Fonts를 사용한 '.length = 29
// 따라서 29번째 인덱스부터 텍스트의 끝까지
textbox.setSelectionStyles({ fontStyle: 'italic' }, 29, textbox.text.length);

canvas.renderAll();

// 스타일이 적용된 후 Textbox의 크기나 줄바꿈이 변경될 수 있으므로, 
// 필요에 따라 initDimensions()를 호출하여 내부 계산을 갱신합니다.
textbox.initDimensions();
canvas.renderAll();

참고: fontWeight 속성은 'normal', 'bold' 또는 숫자로 된 문자열(예: '700')을 사용할 수 있습니다. fontStyle은 'normal', 'italic'을 사용합니다. 로드한 Google Font에 해당 font-weightfont-style 변형이 포함되어 있어야 올바르게 렌더링됩니다.

3. 주의사항 및 흔히 하는 실수

  • 폰트 로딩 시점: Fabric.js가 텍스트를 렌더링하기 전에 Google Fonts가 완전히 로드되어 있어야 합니다. 폰트 로딩은 비동기적이므로, document.fonts.ready를 사용하여 폰트 로딩 완료를 기다리거나, WebFontLoader 같은 라이브러리를 사용하는 것이 안정적입니다. 폰트가 로드되기 전에 텍스트를 렌더링하면 브라우저 기본 폰트로 표시되거나, 폰트 로드 후 레이아웃이 변경될 수 있습니다.
  • 폰트 이름 정확성: fontFamily 속성에 지정하는 이름은 Google Fonts에서 제공하는 정확한 폰트 이름과 일치해야 합니다. 대소문자나 공백에 유의하세요.
  • 스타일 변형 로드: 굵게(bold)나 기울임(italic) 스타일을 사용하려면 해당 폰트의 bolditalic 변형도 Google Fonts에서 함께 로드해야 합니다. 로드하지 않으면 브라우저가 기본적으로 폰트를 합성(faux bold/italic)하여 보여줄 수 있으나, 이는 의도한 것과 다를 수 있으며 품질이 떨어질 수 있습니다.
  • 성능: 너무 많은 Google Fonts를 로드하거나, 매우 큰 폰트 파일을 사용하면 페이지 로딩 성능에 영향을 줄 수 있습니다. 필요한 폰트와 스타일 변형만 최소한으로 로드하는 것이 좋습니다.
  • initDimensions() 호출: setSelectionStyles를 사용하여 텍스트 스타일을 변경하면 텍스트의 너비나 높이에 영향을 줄 수 있습니다. 특히 width가 고정된 Textbox의 경우 줄바꿈이 변경될 수 있으므로, 스타일 적용 후 textbox.initDimensions()를 호출하여 Textbox의 내부 크기 계산을 갱신하고 canvas.renderAll()로 다시 그려주는 것이 중요합니다.
  • 렌더링 이슈: 특정 환경이나 브라우저에서 폰트 로딩 및 렌더링에 미묘한 차이가 있을 수 있습니다. 항상 다양한 환경에서 테스트하여 원하는 대로 동작하는지 확인해야 합니다.