Создание нескольких экземпляров библиотеки Two.js позволяет работать
с несколькими независимыми канвасами на одной странице, каждый из
которых управляется отдельным объектом Two. Для этого важно
понимать структуру инициализации и взаимодействие экземпляров между
собой.
// Создание первого экземпляра
const two1 = new Two({
width: 400,
height: 400,
type: Two.Types.svg
}).appendTo(document.body);
// Создание второго экземпляра
const two2 = new Two({
width: 300,
height: 300,
type: Two.Types.canvas
}).appendTo(document.body);
Каждый экземпляр создаёт отдельный контекст рендеринга, что позволяет
использовать разные размеры, типы рендеринга (svg,
canvas, webgl) и сцены, не влияя на другие
экземпляры.
Каждый объект Two имеет собственный scene —
корневой контейнер, в котором размещаются все графические объекты.
// Создание фигур для первого экземпляра
const circle1 = two1.makeCircle(200, 200, 50);
circle1.fill = '#FF8000';
circle1.stroke = 'black';
circle1.linewidth = 2;
// Создание фигур для второго экземпляра
const rect2 = two2.makeRectangle(150, 150, 100, 50);
rect2.fill = '#0080FF';
rect2.stroke = 'black';
rect2.linewidth = 2;
Каждая фигура привязана к конкретному экземпляру Two,
поэтому изменения в circle1 не затрагивают
rect2.
Two.js использует встроенный метод update() для
анимации, а также play() для запуска рендер-цикла. Для
нескольких экземпляров анимацию можно организовать независимо:
two1.bind('update', function(frameCount) {
circle1.rotation += 0.02;
});
two2.bind('update', function(frameCount) {
rect2.rotation -= 0.03;
});
two1.play();
two2.play();
Каждый экземпляр обрабатывает свои события и обновления независимо, что позволяет строить сложные интерфейсы с несколькими анимационными канвасами одновременно.
Несмотря на независимость, экземпляры могут взаимодействовать через DOM или JavaScript-логику. Например, синхронизация движения объектов разных экземпляров:
two1.bind('update', function() {
rect2.translation.x = circle1.translation.x;
});
two1.play();
two2.play();
Здесь rect2 повторяет горизонтальное перемещение
circle1, хотя оба объекта принадлежат разным
экземплярам.
При работе с несколькими экземплярами важно выбирать подходящий тип рендеринга для каждого из них, чтобы избежать конфликтов и просадок FPS.
Для удобства работы рекомендуется хранить каждый экземпляр в отдельной переменной и инкапсулировать логику создания объектов и анимации в функции:
function createTwoInstance(width, height, type, container) {
const two = new Two({ width, height, type }).appendTo(container);
const circle = two.makeCircle(width / 2, height / 2, 50);
circle.fill = '#00FF00';
two.bind('update', () => circle.rotation += 0.01);
two.play();
return two;
}
const twoA = createTwoInstance(400, 400, Two.Types.svg, document.body);
const twoB = createTwoInstance(300, 300, Two.Types.canvas, document.body);
Такой подход позволяет легко масштабировать проект и добавлять новые сцены без изменения существующих экземпляров.
События мыши или клавиатуры могут обрабатываться отдельно для каждого экземпляра, если использовать соответствующие DOM-элементы.
twoA.renderer.domElement.addEventListener('click', () => {
console.log('Clicked on first canvas');
});
twoB.renderer.domElement.addEventListener('click', () => {
console.log('Clicked on second canvas');
});
Каждый экземпляр реагирует только на события, происходящие внутри его контейнера, что обеспечивает полную изоляцию интерфейсов.
scene и renderer.bind('update')
для каждого объекта работает автономно.canvas + SVG) позволяет
балансировать производительность и визуальное качество.Эти принципы обеспечивают стабильное управление несколькими экземплярами Two.js на одной веб-странице.