Интеграция с фреймворками

Two.js — это мощная библиотека для создания двумерной графики с поддержкой Canvas, SVG и WebGL. Она легко интегрируется в любые фронтенд-фреймворки, такие как React, Vue и Angular, благодаря своей модульной архитектуре и отсутствию жёстких зависимостей.

Инициализация Two.js в React

Для React предпочтительно использовать useRef и useEffect для управления жизненным циклом рендера. Основная идея — создать контейнер для канваса и привязать к нему экземпляр Two.js.

import React, { useRef, useEffect } from 'react';
import Two from 'two.js';

function TwoCanvas() {
  const containerRef = useRef(null);

  useEffect(() => {
    const params = { width: 800, height: 600, type: Two.Types.svg };
    const two = new Two(params).appendTo(containerRef.current);

    const circle = two.makeCircle(400, 300, 50);
    circle.fill = '#FF8000';
    circle.stroke = 'black';
    circle.linewidth = 3;

    two.update();

    return () => two.clear();
  }, []);

  return <div ref={containerRef}></div>;
}

export default TwoCanvas;

Ключевые моменты:

  • Использование useRef обеспечивает постоянную ссылку на DOM-элемент, к которому привязывается Two.js.
  • useEffect гарантирует создание и очистку графики при монтировании и размонтировании компонента.
  • Two.js автоматически обновляет сцену при вызове two.update(), что позволяет управлять анимациями и динамическим содержимым.

Интеграция в Vue 3

Во Vue 3 с Composition API Two.js подключается через ref и onMounted:

<template>
  <div ref="canvasContainer"></div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import Two from 'two.js';

const canvasContainer = ref(null);
let two;

onMounted(() => {
  two = new Two({ width: 600, height: 400, type: Two.Types.canvas }).appendTo(canvasContainer.value);

  const rect = two.makeRectangle(300, 200, 100, 100);
  rect.fill = '#3498db';
  rect.stroke = '#2980b9';
  rect.linewidth = 4;

  two.update();
});

onBeforeUnmount(() => {
  two.clear();
});
</script>

Особенности:

  • ref обеспечивает реактивную привязку к DOM-элементу.
  • onMounted гарантирует создание Two.js только после того, как элемент появился в DOM.
  • onBeforeUnmount позволяет корректно удалить объекты, предотвращая утечки памяти.

Использование Two.js в Angular

В Angular Two.js удобно интегрировать через ViewChild и lifecycle hooks:

import { Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core';
import Two from 'two.js';

@Component({
  selector: 'app-two-canvas',
  template: '<div #canvasContainer></div>',
})
export class TwoCanvasComponent implements OnInit, OnDestroy {
  @ViewChild('canvasContainer', { static: true }) container!: ElementRef;
  private two!: Two;

  ngOnInit() {
    this.two = new Two({ width: 500, height: 500, type: Two.Types.webgl }).appendTo(this.container.nativeElement);

    const triangle = this.two.makePolygon(250, 250, 80, 3);
    triangle.fill = '#2ecc71';
    triangle.stroke = '#27ae60';
    triangle.linewidth = 5;

    this.two.update();
  }

  ngOnDestroy() {
    this.two.clear();
  }
}

Angular требует явного управления жизненным циклом компонентов, поэтому ngOnInit и ngOnDestroy идеально подходят для инициализации и очистки сцены Two.js.

Анимации и реактивные данные

Two.js прекрасно работает с анимациями через свой встроенный метод bind:

two.bind('update', () => {
  circle.rotation += 0.02;
}).play();

Для реактивных фреймворков можно использовать связывание состояния с объектами Two.js. В React это делается через state и useEffect:

useEffect(() => {
  circle.fill = color;
  two.update();
}, [color]);

Во Vue аналогично применяется watch для реактивных переменных:

watch(fillColor, (newColor) => {
  rect.fill = newColor;
  two.update();
});

Оптимизация интеграции

  • Минимизировать вызовы two.update() — обновлять сцену только при изменениях объектов.
  • Очистка сцен при размонтировании компонентов предотвращает утечки памяти.
  • Использование WebGL для сложных сцен с большим количеством объектов обеспечивает плавность анимаций.

Поддержка событий

Two.js поддерживает базовые события для объектов через прослушивание DOM-событий:

circle._renderer.elem.addEventListener('click', () => {
  circle.fill = '#e74c3c';
  two.update();
});

В реактивных фреймворках события можно связывать с методами компонентов, сохраняя консистентность состояния приложения.

Структура проекта с Two.js

Для крупных проектов рекомендуется:

  • Разделять Two.js-логики по компонентам, чтобы каждый элемент сцены был отдельным модулем.
  • Хранить конфигурации сцен и объектов в отдельных файлах.
  • Использовать контроллеры анимаций, чтобы управлять несколькими сценами из одного центрального места.

Такой подход упрощает масштабирование и поддержку проекта, особенно в условиях сложных интерактивных интерфейсов.