Two.js — это библиотека для 2D-графики на JavaScript, предоставляющая удобный API для создания фигур, анимаций и взаимодействий. В React интеграция Two.js требует правильного управления жизненным циклом компонентов, чтобы избежать конфликтов с виртуальным DOM и обеспечить корректное обновление сцены.
Для начала создается экземпляр Two.js и связывается с DOM-элементом
через ref. Это позволяет React корректно управлять
контейнером рендеринга.
import React, { useRef, useEffect } from 'react';
import Two from 'two.js';
function TwoCanvas() {
const canvasRef = useRef(null);
useEffect(() => {
const params = { width: 800, height: 600 };
const two = new Two(params).appendTo(canvasRef.current);
return () => two.clear();
}, []);
return <div ref={canvasRef} />;
}
Ключевой момент: useRef используется
для хранения ссылки на контейнер, а useEffect управляет
созданием и очисткой сцены при монтировании и размонтировании
компонента.
Two.js предоставляет методы для построения основных геометрических объектов: прямоугольников, кругов, линий и полигонов. Для React важно, чтобы объекты создавались после инициализации сцены.
useEffect(() => {
const params = { width: 800, height: 600 };
const two = new Two(params).appendTo(canvasRef.current);
const circle = two.makeCircle(400, 300, 50);
circle.fill = '#FF8000';
circle.stroke = '#000000';
circle.linewidth = 5;
two.update();
return () => two.clear();
}, []);
Выделение: two.makeCircle автоматически
добавляет объект в сцену. Метод two.update() обязательно
вызывает перерисовку после внесения изменений.
Two.js поддерживает встроенный механизм анимаций через
two.bind('upd ate', callback). Для React важно корректно
отписываться от событий при размонтировании, чтобы избежать утечек
памяти.
useEffect(() => {
const two = new Two({ width: 800, height: 600 }).appendTo(canvasRef.current);
const rect = two.makeRectangle(400, 300, 100, 100);
rect.fill = '#0099FF';
let angle = 0;
two.bind('update', () => {
angle += 0.01;
rect.rotation = angle;
}).play();
return () => {
two.unbind('update');
two.clear();
};
}, []);
Ключевой момент:
two.bind('update', callback) позволяет реализовать
циклические анимации, а two.unbind('update') обеспечивает
корректную очистку при удалении компонента.
Для динамических изменений свойств фигур в зависимости от состояния
React можно использовать useState и эффекты:
import React, { useRef, useEffect, useState } from 'react';
import Two from 'two.js';
function ReactiveCircle() {
const canvasRef = useRef(null);
const [radius, setRadius] = useState(50);
useEffect(() => {
const two = new Two({ width: 800, height: 600 }).appendTo(canvasRef.current);
const circle = two.makeCircle(400, 300, radius);
circle.fill = '#FF0000';
two.update();
return () => two.clear();
}, []);
useEffect(() => {
if (!canvasRef.current) return;
const two = new Two({ width: 800, height: 600 }).appendTo(canvasRef.current);
two.clear();
const circle = two.makeCircle(400, 300, radius);
circle.fill = '#FF0000';
two.update();
}, [radius]);
return (
<div>
<div ref={canvasRef} />
<button onCl ick={() => setRadius(radius + 10)}>Увеличить радиус</button>
</div>
);
}
Выделение: каждое изменение состояния должно
обновлять фигуру через перерисовку сцены. В крупных проектах
рекомендуется сохранять объекты Two.js в ref, чтобы
минимизировать пересоздание сцены.
Two.js поддерживает базовые события, однако для полноценного взаимодействия в React чаще используют обработчики DOM, синхронизируя их с объектами Two.js:
useEffect(() => {
const two = new Two({ width: 800, height: 600 }).appendTo(canvasRef.current);
const circle = two.makeCircle(400, 300, 50);
circle.fill = '#00FF00';
two.update();
const handleMouseMove = (e) => {
const rect = canvasRef.current.getBoundingClientRect();
circle.translation.se t(e.clientX - rect.left, e.clientY - rect.top);
two.update();
};
canvasRef.current.addEventListener('mousemove', handleMouseMove);
return () => {
canvasRef.current.removeEventListener('mousemove', handleMouseMove);
two.clear();
};
}, []);
Ключевой момент: обработка событий напрямую на DOM обеспечивает совместимость с React и Two.js без конфликтов с виртуальным DOM.
useRef предотвращает лишние
пересоздания.Two экземпляра для всего
компонента сокращает накладные расходы.two.bind('update')
вместо постоянного вызова two.update().two.clear() или
two.remove(object) предотвращает утечки памяти при частом
обновлении компонентов.Two.js идеально интегрируется с современными React хуками:
useRef — хранение контейнера и объектов Two.js.useEffect — инициализация сцены, добавление и удаление
объектов, управление анимациями.useState — управление динамическими свойствами фигур и
перерисовкой сцены при изменениях.Такой подход обеспечивает полную реактивность интерфейса, высокую производительность и минимальные конфликты между Two.js и виртуальным DOM React.