Paper.js — это мощная библиотека для векторной графики и работы с канвасом в браузере на JavaScript. В контексте React её применение требует особого подхода, поскольку Paper.js управляет своим собственным сценическим графом, а React оперирует виртуальным DOM. Основная задача — обеспечить согласованное взаимодействие между жизненным циклом компонентов React и Paper.js.
Для корректной работы Paper.js необходимо создать
<canvas> элемент и привязать его к Paper.js с помощью
paper.setup(canvas). В React рекомендуется использовать
ref, чтобы получить доступ к DOM-элементу:
import React, { useRef, useEffect } from 'react';
import paper from 'paper';
function PaperCanvas() {
const canvasRef = useRef(null);
useEffect(() => {
paper.setup(canvasRef.current);
const circle = new paper.Path.Circle({
center: [80, 50],
radius: 30,
fillColor: 'red'
});
paper.view.draw();
return () => {
paper.project.remove(); // очистка проекта при размонтировании
};
}, []);
return <canvas ref={canvasRef} width={400} height={400} />;
}
Ключевые моменты:
useRef обеспечивает доступ к DOM-элементу канваса.paper.setup привязывает Paper.js к конкретному
канвасу.paper.project.remove() освобождает ресурсы и
предотвращает утечки памяти.Paper.js создаёт объекты в проекте, которые остаются в памяти до их явного удаления. В React это требует внимательного контроля:
Path, Shape, Raster.position,
fillColor).object.remove() или project.clear().Пример динамического обновления позиции круга с использованием
useState:
import React, { useRef, useEffect, useState } from 'react';
import paper from 'paper';
function AnimatedCircle() {
const canvasRef = useRef(null);
const [position, setPosition] = useState({ x: 50, y: 50 });
useEffect(() => {
paper.setup(canvasRef.current);
const circle = new paper.Path.Circle({
center: [position.x, position.y],
radius: 30,
fillColor: 'blue'
});
paper.view.onFr ame = () => {
circle.position.x += 1;
paper.view.draw();
};
return () => {
paper.project.remove();
};
}, []);
return <canvas ref={canvasRef} width={400} height={400} />;
}
Paper.js поддерживает свои события (onMouseDown,
onMouseDrag, onKeyDown). В React лучше
регистрировать их после paper.setup и удалять при
размонтировании:
useEffect(() => {
paper.setup(canvasRef.current);
const path = new paper.Path();
path.strokeColor = 'black';
paper.view.onMouseD own = (event) => {
path.add(event.point);
};
return () => {
paper.view.onMouseD own = null;
paper.project.remove();
};
}, []);
Совет: не использовать одновременно React-события
(onClick) и Paper.js события на одном канвасе, чтобы
избежать конфликтов.
requestAnimationFramePaper.js интегрирует анимации через view.onFrame. React
перерисовывает виртуальный DOM отдельно, поэтому важно избегать
состояния React для каждой анимационной итерации, чтобы не
вызывать лишние ререндеры:
paper.view.onFr ame = (event) => {
circle.rotate(3); // вращение круга
paper.view.draw();
};
useRef для хранения объектов Paper.js
предотвращает лишние пересоздания при каждом ререндере компонента.В больших проектах рекомендуется разделять:
<canvas> и Paper.js.Пример структуры:
// PaperObjects.js
export const createCircle = (center, color) => {
return new paper.Path.Circle({
center,
radius: 20,
fillColor: color
});
};
// CanvasComponent.jsx
import { createCircle } from './PaperObjects';
useEffect(() => {
paper.setup(canvasRef.current);
const circle = createCircle([100, 100], 'green');
paper.view.onFr ame = () => circle.rotate(2);
return () => paper.project.remove();
}, []);
Paper.js поддерживает слои (Layer). Для React важно:
insertAbove,
insertBelow.const layer1 = new paper.Layer();
const layer2 = new paper.Layer();
const circle = new paper.Path.Circle({ center: [50, 50], radius: 20 });
layer1.addChild(circle);
const square = new paper.Path.Rectangle({ point: [70, 70], size: [50, 50] });
layer2.addChild(square);
useEffect – для инициализации Paper.js и очистки.useRef – для хранения канваса и объектов.useState – только для данных, которые влияют на
React-компоненты вне канваса.useMemo – для вычислений объектов, которые не должны
пересоздаваться при каждом ререндере.view.onFrame), а
не через React setInterval или
requestAnimationFrame.useRef, чтобы
избежать лишних пересозданий при ререндере.Эта методология обеспечивает стабильную работу Paper.js внутри React, позволяет создавать интерактивные анимации, векторные фигуры и графические интерфейсы без конфликта с виртуальным DOM.