Расширение прототипов

Библиотека SVG.js предоставляет мощный и гибкий механизм для работы с векторной графикой в браузере, основываясь на объектной модели SVG. Одной из ключевых возможностей является расширение прототипов элементов, что позволяет создавать собственные методы для стандартных объектов SVG, таких как Rect, Circle, Line, Path и других.

Основы расширения прототипов

В SVG.js каждый графический элемент представлен объектом с прототипом, который содержит методы для управления атрибутами, трансформациями и событиями. Для добавления нового метода необходимо обратиться к прототипу конкретного типа элемента:

SVG.Rect.prototype.addShadow = function(offsetX, offsetY, blur, color) {
    this.style('filter', `drop-shadow(${offsetX}px ${offsetY}px ${blur}px ${color})`);
    return this; // возврат для цепочек методов
};

В этом примере создаётся метод addShadow для прямоугольников. Он добавляет эффект тени через CSS-свойство filter. Возврат this позволяет использовать метод в цепочках вызовов:

let rect = draw.rect(100, 50).fill('#f06').addShadow(5, 5, 10, 'rgba(0,0,0,0.5)');

Прототип Element как общий базовый

Все элементы SVG наследуются от базового прототипа SVG.Element. Расширяя его, можно создавать методы, доступные для всех типов элементов:

SVG.Element.prototype.fadeOut = function(duration = 1000) {
    this.animate(duration).opacity(0);
    return this;
};

Теперь fadeOut можно применять к любому объекту, будь то круг, прямоугольник или текст:

draw.circle(80).fill('#0f9').fadeOut(1500);
draw.text('Привет!').font({size: 24}).fadeOut();

Использование цепочек методов

SVG.js поддерживает метод цепочек, что делает код компактным и читаемым. При создании методов для прототипов важно всегда возвращать this, чтобы не ломать цепочку:

SVG.Circle.prototype.grow = function(factor) {
    let currentRadius = this.radius();
    this.radius(currentRadius * factor);
    return this;
};

draw.circle(50).fill('#09f').grow(1.5).move(100, 100);

Методы для групп элементов

Группы (SVG.Group) часто используют для объединения нескольких объектов. Прототип группы можно расширять аналогично:

SVG.G.prototype.rotateAll = function(angle) {
    this.each(function() {
        this.rotate(angle, this.cx(), this.cy());
    });
    return this;
};

let group = draw.group();
group.circle(40).fill('#f90').move(50, 50);
group.rect(60, 30).fill('#09f').move(20, 20);
group.rotateAll(45);

Метод each перебирает все дочерние элементы группы, применяя к ним заданную трансформацию.

Создание универсальных утилит

Для часто используемых операций удобно создавать методы, расширяющие базовый прототип:

SVG.Element.prototype.centerOn = function(x, y) {
    let bbox = this.bbox();
    this.move(x - bbox.width / 2, y - bbox.height / 2);
    return this;
};

draw.rect(120, 80).fill('#fa0').centerOn(200, 150);
draw.circle(60).fill('#0af').centerOn(200, 150);

Метод bbox() возвращает габариты элемента, что позволяет корректно центрировать объекты на холсте.

Расширение с учетом анимаций

SVG.js поддерживает анимированные методы. Расширяя прототип, можно создавать комбинированные эффекты:

SVG.Rect.prototype.pulse = function(duration = 500, scale = 1.2) {
    let originalWidth = this.width();
    let originalHeight = this.height();
    this.animate(duration, '<>').size(originalWidth * scale, originalHeight * scale)
        .animate(duration, '<>').size(originalWidth, originalHeight);
    return this;
};

draw.rect(80, 80).fill('#f0f').pulse();

Такой метод автоматически создает “пульсирующую” анимацию с возвратом к исходному размеру.

Практические рекомендации

  • Всегда возвращать this в новых методах для поддержки цепочек вызовов.
  • Использовать базовый прототип SVG.Element для методов, применимых ко всем объектам.
  • Применять методы групп (SVG.G) для работы с набором элементов.
  • Проверять совместимость методов с различными типами элементов, чтобы не возникало ошибок при использовании.
  • Использовать внутренние методы SVG.js (bbox(), animate(), move(), radius(), fill()) для получения и изменения состояния объектов.

Расширение прототипов делает SVG.js гибким инструментом для построения динамических интерфейсов, интерактивной графики и визуализации данных, позволяя создавать собственные высокоуровневые методы, которые упрощают и ускоряют работу с векторной графикой.