Two.js предоставляет высокоуровневый API для работы с векторной графикой на HTML5 Canvas, SVG и WebGL. При работе с несколькими холстами часто возникает необходимость синхронизировать состояние объектов между ними, чтобы изменения на одном холсте автоматически отражались на других. Это может быть полезно при создании сложных визуализаций, панорам, мультиэкранных интерфейсов или редакторов графики.
Для начала создаются отдельные экземпляры Two для
каждого холста. Каждый экземпляр управляет своим DOM-элементом
(canvas или svg) и имеет независимый
рендеринг.
const elem1 = document.getElementById('canvas1');
const elem2 = document.getElementById('canvas2');
const two1 = new Two({ width: 500, height: 500 }).appendTo(elem1);
const two2 = new Two({ width: 500, height: 500 }).appendTo(elem2);
Каждый экземпляр имеет собственный метод update и цикл
анимации. Синхронизация потребует передачи состояния объектов из одного
экземпляра в другой.
Two.js использует объекты Shape, Group,
Path и т.д. для представления графических элементов. Чтобы
синхронизировать объекты, их свойства нужно копировать или
связывать.
Простейший способ — клонирование:
function cloneShape(shape) {
const clone = shape.constructor(shape.vertices ? shape.vertices.map(v => v.clone()) : []);
clone.fill = shape.fill;
clone.stroke = shape.stroke;
clone.linewidth = shape.linewidth;
clone.translation.copy(shape.translation);
clone.rotation = shape.rotation;
clone.scale = shape.scale;
return clone;
}
const circle1 = two1.makeCircle(100, 100, 50);
const circle2 = cloneShape(circle1);
two2.add(circle2);
two1.update();
two2.update();
Важно сохранять позицию, цвет, размер, трансформации, иначе визуальная копия будет отличаться.
Two.js не предоставляет встроенных средств синхронизации между холстами, но можно использовать кастомные события или подписки на изменения. Например, при изменении позиции объекта:
circle1.translation.bind(Two.Events.change, () => {
circle2.translation.copy(circle1.translation);
two2.update();
});
Можно создать функцию bindShapes для универсальной
привязки всех свойств:
function bindShapes(source, target, props = ['translation', 'rotation', 'scale']) {
props.forEach(prop => {
if (source[prop] && target[prop]) {
source[prop].bind(Two.Events.change, () => {
target[prop].copy(source[prop]);
target._renderer.flagReset = true;
});
}
});
}
Это позволяет поддерживать динамическую синхронизацию даже при анимации объектов.
Для сложных сцен часто используются группы (Group).
Синхронизация группы требует копирования всех дочерних объектов и
привязки их свойств:
const group1 = two1.makeGroup(circle1, two1.makeRectangle(200, 200, 100, 50));
const group2 = two2.makeGroup();
group1.children.forEach(child => {
const clone = cloneShape(child);
group2.add(clone);
bindShapes(child, clone);
});
two1.update();
two2.update();
Группы позволяют легко управлять несколькими объектами одновременно, сохраняя структуру сцены при синхронизации.
При использовании Two.js для анимаций
(two.bind('update', callback)) важно синхронизировать не
только статические свойства, но и вычисляемые параметры:
two1.bind('update', (frameCount, timeDelta) => {
circle1.rotation += 0.01;
circle2.rotation = circle1.rotation;
});
two1.play();
two2.play();
Для сложных анимаций рекомендуется централизовать вычисления на одном холсте, а остальные холсты лишь копируют результат.
copy и clone
для векторов и трансформаций вместо полной пересоздания
объектов.two.update() на каждом кадре для всех холстов, если
достаточно периодической синхронизации.Синхронизация холстов полезна при:
Эти методы создают живую связь между независимыми экземплярами Two.js, позволяя строить сложные визуальные системы с единым управлением.