> Hello World !!!

     

@syaku

Fabric.js에서 수직 정렬과 크기 조절이 가능한 TextboxVertical 구현하기

728x90
반응형

Fabric.js에서 수직 정렬과 크기 조절이 가능한 TextboxVertical 구현하기

Implementing TextboxVertical with Vertical Alignment and Resizing in Fabric.js

Fabric.js를 사용하다 보면 텍스트박스의 수직 정렬과 크기 조절에 제한이 있다는 것을 발견하게 됩니다. 이러한 제한을 해결하기 위해 Textbox 클래스를 확장한 TextboxVertical 클래스를 소개합니다.

When using Fabric.js, you might notice limitations in textbox vertical alignment and resizing. To address these limitations, we introduce the TextboxVertical class that extends the Textbox class.

사용 목적 (Purpose)

  1. 텍스트박스 내 텍스트의 수직 정렬 (상단, 중앙, 하단)
    Text vertical alignment within textbox (top, middle, bottom)
  2. 텍스트박스의 높이와 너비를 자유롭게 조절
    Freely adjustable height and width of textbox
  3. 편집 모드에서도 정확한 커서 위치 유지
    Maintain accurate cursor position even in edit mode

주요 기능 (Key Features)

수직 정렬 지원 (Vertical Alignment Support)

  • verticalAlign 속성을 통해 텍스트의 수직 위치를 지정
    Specify vertical position of text through verticalAlign property
  • 'top', 'middle', 'bottom' 세 가지 옵션 제공
    Provides three options: 'top', 'middle', 'bottom'
  • 텍스트박스의 높이가 변경되어도 정렬 유지
    Maintains alignment even when textbox height changes

크기 조절 기능 (Resizing Capability)

  • 텍스트박스의 높이와 너비를 자유롭게 조절 가능
    Freely adjustable height and width of textbox
  • 스케일링 시 텍스트 왜곡 방지
    Prevents text distortion during scaling
  • 크기 조절 후에도 텍스트 정렬 유지
    Maintains text alignment after resizing

사용 방법 (Usage)

// TextboxVertical 인스턴스 생성
// Create TextboxVertical instance
const textbox = new TextboxVertical('Hello World', {
    left: 100,
    top: 100,
    width: 200,
    height: 150,
    verticalAlign: 'middle', // 'top', 'middle', 'bottom'
    textAlign: 'center'
});

// 캔버스에 추가
// Add to canvas
canvas.add(textbox);

장점 (Benefits)

  1. 유연한 레이아웃 (Flexible Layout)
    • 텍스트의 수직 위치를 자유롭게 조정 가능
      Freely adjustable vertical text position
    • 다양한 디자인 요구사항 충족
      Meets various design requirements
  2. 직관적인 사용성 (Intuitive Usability)
    • 기존 Textbox와 동일한 방식으로 사용
      Uses the same approach as the original Textbox
    • 추가된 verticalAlign 속성으로 쉽게 수직 정렬 제어
      Easy vertical alignment control with added verticalAlign property
  3. 안정적인 텍스트 편집 (Stable Text Editing)
    • 편집 모드에서도 정확한 커서 위치 제공
      Provides accurate cursor position in edit mode
    • 텍스트 입력 시 자연스러운 사용자 경험
      Natural user experience during text input

활용 사례 (Use Cases)

  • 배너 디자인 (Banner Design)
  • 카드 레이아웃 (Card Layouts)
  • 텍스트 중심 인포그래픽 (Text-focused Infographics)
  • 동적 콘텐츠가 필요한 웹 애플리케이션 (Web Applications Requiring Dynamic Content)
  • 텍스트 에디터 구현 (Text Editor Implementation)

이 커스텀 클래스를 통해 Fabric.js의 텍스트박스 기능을 한층 더 강화하고, 더 다양한 디자인과 레이아웃을 구현할 수 있습니다.

This custom class enhances Fabric.js textbox functionality and enables implementation of more diverse designs and layouts.

소스 코드


class TextboxVertical extends Textbox {
  constructor(text, options) {
    super(text, options);
    this.verticalAlign = options.verticalAlign || 'top'; // Default to 'top'
  }

  initDimensions() {
    if (!this.initialized) {
      return;
    }
    this.isEditing && this.initDelayedCursor();
    this._clearCache();
    // clear dynamicMinWidth as it will be different after we re-wrap line
    this.dynamicMinWidth = 0;
    // wrap lines
    this._styleMap = this._generateStyleMap(this._splitText());
    // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap
    if (this.dynamicMinWidth > this.width) {
      this._set('width', this.dynamicMinWidth);
    }
    if (this.textAlign.includes('justify')) {
      // once text is measured we need to make space fatter to make justified text.
      this.enlargeSpaces();
    }
    // clear cache and re-calculate height
    this.height = !this.height ? this.calcTextHeight() : this.height;
  }

  _render(ctx) {
    // 스케일 조정을 먼저 처리
    if (this.scaleY !== 1) {
      this.height = this.height * this.scaleY;
      this.scaleY = 1;
    }

    if (this.scaleX !== 1) {
      this.width = this.width * this.scaleX;
      this.scaleX = 1;
    }

    // 텍스트 높이 계산
    const totalTextHeight = this.calcTextHeight();
    let verticalOffset = 0;

    if (this.verticalAlign === 'middle') {
      verticalOffset = (this.height - totalTextHeight) / 2;
    } else if (this.verticalAlign === 'bottom') {
      verticalOffset = this.height - totalTextHeight;
    }

    // 편집 모드일 때는 오프셋을 조정
    if (this.isEditing) {
      this.top += verticalOffset;
      super._render(ctx);
      this.top -= verticalOffset;
    } else {
      // 편집 모드가 아닐 때는 기존 방식 유지
      ctx.translate(0, verticalOffset);
      super._render(ctx);
      ctx.translate(0, -verticalOffset);
    }
  }
}
728x90
반응형