Клонирование элементов

Клонирование — это создание точной копии существующего SVG-элемента с сохранением его структуры, атрибутов и вложенных узлов. В библиотеке Snap.svg клонирование реализовано через метод clone(), который позволяет быстро дублировать элементы без ручного пересоздания.

Клонирование особенно полезно при работе с повторяющимися графическими объектами: иконками, узорами, анимациями и интерактивными элементами интерфейса.


Метод clone()

Базовый синтаксис:

var copy = element.clone();
  • element — исходный SVG-элемент (например, rect, circle, path)
  • copy — новый независимый объект

Клон полностью повторяет исходный элемент:

  • геометрию
  • атрибуты (fill, stroke, transform и др.)
  • вложенные элементы (если это группа)

Пример базового клонирования

var s = Snap(400, 400);

var rect = s.rect(50, 50, 100, 100).attr({
    fill: "blue"
});

var rectClone = rect.clone().attr({
    x: 200,
    fill: "red"
});

В этом примере:

  • создаётся прямоугольник
  • затем создаётся его копия
  • у копии изменяется положение и цвет

Исходный и клонированный элементы независимы друг от друга.


Независимость клонов

После клонирования элементы не связаны:

rect.attr({ fill: "green" });

Изменение исходного элемента не влияет на клон, и наоборот.

Это ключевое отличие от ссылочных структур — создаётся полноценная копия, а не ссылка.


Клонирование групп

Если элемент является группой (g), метод clone() копирует всю вложенную структуру:

var group = s.group(
    s.circle(50, 50, 20),
    s.rect(40, 40, 20, 20)
);

var groupClone = group.clone().attr({
    transform: "translate(100, 0)"
});

Клон содержит:

  • все дочерние элементы
  • их атрибуты
  • иерархию

Клонирование с трансформациями

Трансформации (transform) также копируются:

var circle = s.circle(100, 100, 30).attr({
    fill: "orange",
    transform: "rotate(45)"
});

var clone = circle.clone().attr({
    transform: "rotate(45) translate(100, 0)"
});

Важно учитывать:

  • трансформация копируется как есть
  • при добавлении новой трансформации она заменяет старую, если не объединять вручную

Клонирование и позиционирование

После клонирования часто требуется изменить координаты:

var base = s.rect(10, 10, 50, 50);

for (var i = 0; i < 5; i++) {
    base.clone().attr({
        x: 10 + i * 60
    });
}

Создаётся серия одинаковых элементов с разным положением.


Клонирование с использованием матриц

Для более сложных преобразований можно применять матрицы:

var matrix = new Snap.Matrix();
matrix.translate(150, 0);
matrix.rotate(30, 0, 0);

var clone = element.clone().transform(matrix);

Это позволяет:

  • комбинировать трансформации
  • точно управлять положением и поворотом

Клонирование и события

События (например, click) не копируются автоматически:

var rect = s.rect(0, 0, 100, 100);

rect.click(function() {
    console.log("original");
});

var clone = rect.clone();

clone.click(function() {
    console.log("clone");
});

Каждому клону необходимо назначать обработчики отдельно.


Клонирование и data

Метод data() используется для хранения пользовательских данных:

rect.data("id", 1);

var clone = rect.clone();

console.log(clone.data("id")); // undefined

Данные не копируются, так как не являются частью DOM-структуры SVG.


Глубокое клонирование и ограничения

Метод clone() выполняет глубокое копирование DOM-узлов, но не копирует:

  • JavaScript-ссылки
  • пользовательские свойства объекта
  • обработчики событий
  • данные через data()

Это важно учитывать при построении сложных интерфейсов.


Практика: генерация паттернов

Клонирование удобно для создания повторяющихся структур:

var dot = s.circle(10, 10, 5).attr({ fill: "#000" });

for (var y = 0; y < 5; y++) {
    for (var x = 0; x < 5; x++) {
        dot.clone().attr({
            cx: 10 + x * 20,
            cy: 10 + y * 20
        });
    }
}

Результат — сетка из точек.


Клонирование сложных объектов

При работе с SVG-иконками или иллюстрациями:

Snap.load("icon.svg", function(fragment) {
    var icon = fragment.select("g");

    var icon1 = icon.clone().attr({ transform: "translate(0, 0)" });
    var icon2 = icon.clone().attr({ transform: "translate(100, 0)" });

    s.append(icon1, icon2);
});

Позволяет:

  • загружать один SVG
  • использовать его многократно

Оптимизация через клонирование

Клонирование снижает:

  • количество кода
  • нагрузку на создание новых элементов
  • вероятность ошибок

Особенно эффективно при:

  • генерации интерфейсов
  • визуализации данных
  • создании анимаций

Частые ошибки

1. Ожидание копирования событий

clone.click(...) // требуется повторная привязка

2. Перезапись трансформации

clone.attr({ transform: "translate(100,0)" })

Старая трансформация теряется.

3. Игнорирование координат Клон появляется в том же месте, что и оригинал.


Комбинирование с анимацией

Клоны удобно использовать в анимациях:

var base = s.circle(50, 50, 20);

for (var i = 0; i < 3; i++) {
    base.clone().animate({
        cx: 100 + i * 50
    }, 1000);
}

Создаётся несколько анимированных копий одного элемента.


Клонирование как инструмент композиции

Клонирование позволяет:

  • строить сложные сцены из базовых элементов
  • создавать модульную графику
  • повторно использовать готовые компоненты

Подход особенно полезен при:

  • разработке UI-компонентов
  • создании визуальных эффектов
  • работе с динамическими данными