Создание плагинов

Snap.svg предоставляет мощный и гибкий API для работы с векторной графикой в браузере, включая возможность расширения функциональности через плагины. Плагины позволяют добавлять новые методы к объектам Snap или расширять глобальные возможности библиотеки.

Подключение и структура плагина

Плагин в Snap.svg реализуется как функция, принимающая объект Snap в качестве аргумента:

(function(Snap, Element, Paper, glob) {
    // Здесь определяется функциональность плагина
})(Snap, Snap.Element, Snap.Paper, this);
  • Snap – основной объект библиотеки.
  • Element – прототип всех SVG-элементов (circle, rect, path и др.).
  • Paper – прототип контейнера Paper, внутри которого размещаются элементы SVG.
  • glob – глобальная область видимости (обычно window), используется для объявления глобальных функций, если это необходимо.

Такой подход обеспечивает изоляцию пространства имён и предотвращает конфликты с другими скриптами.

Расширение методов элементов

Чтобы добавить новый метод к элементу SVG, используется объект Element:

Snap.plugin(function(Snap, Element, Paper, glob) {
    Element.prototype.changeColor = function(color) {
        this.attr({ fill: color });
        return this; // поддержка цепочек вызовов
    };
});

Применение нового метода:

var paper = Snap(400, 400);
var circle = paper.circle(100, 100, 50);
circle.changeColor("#f06");

Ключевой момент: метод добавляется к Element.prototype, что делает его доступным для всех SVG-элементов.

Расширение методов контейнера Paper

Подобным образом можно добавлять методы к объекту Paper для удобного управления группой элементов:

Snap.plugin(function(Snap, Element, Paper, glob) {
    Paper.prototype.createRectGrid = function(rows, cols, cellWidth, cellHeight) {
        var group = this.group();
        for (var i = 0; i < rows; i++) {
            for (var j = 0; j < cols; j++) {
                var rect = this.rect(j * cellWidth, i * cellHeight, cellWidth, cellHeight);
                group.add(rect);
            }
        }
        return group;
    };
});

Использование:

var paper = Snap(500, 500);
var grid = paper.createRectGrid(5, 5, 50, 50);
grid.selectAll("rect").forEach(function(r) { r.attr({ fill: "#ccc" }); });

Добавление глобальных функций и утилит

Если функциональность плагина не связана напрямую с элементами, её можно объявить в глобальной области видимости через объект glob:

Snap.plugin(function(Snap, Element, Paper, glob) {
    glob.randomColor = function() {
        return "#" + Math.floor(Math.random()*16777215).toString(16);
    };
});

Теперь можно использовать randomColor в любом месте кода:

var paper = Snap(300, 300);
var circle = paper.circle(150, 150, 75);
circle.attr({ fill: randomColor() });

Советы по разработке плагинов

  1. Возврат this – при расширении Element или Paper рекомендуется возвращать объект, чтобы сохранить возможность цепочек вызовов.
  2. Изоляция кода – оборачивать плагин в немедленно вызываемую функцию (IIFE), чтобы не загрязнять глобальную область видимости.
  3. Использование Snap.plugin – всегда регистрировать плагины через встроенный метод, а не напрямую к прототипу, чтобы Snap.svg мог корректно обрабатывать зависимости.
  4. Совместимость типов – проверять тип элемента перед применением метода, например: if (this.type === "circle") { ... }.
  5. Документирование методов – включать описание, аргументы и возвращаемое значение, особенно если плагин планируется использовать в больших проектах.

Пример комплексного плагина

Snap.plugin(function(Snap, Element, Paper, glob) {

    // Метод для плавного изменения цвета элемента
    Element.prototype.fadeToColor = function(color, duration) {
        var el = this;
        Snap.animate(0, 1, function(val) {
            var startColor = Snap.color(el.attr("fill"));
            var endColor = Snap.color(color);
            var r = startColor.r + val * (endColor.r - startColor.r);
            var g = startColor.g + val * (endColor.g - startColor.g);
            var b = startColor.b + val * (endColor.b - startColor.b);
            el.attr({ fill: Snap.rgb(r, g, b) });
        }, duration || 1000);
        return this;
    };

    // Глобальная утилита для генерации случайного SVG элемента
    glob.createRandomShape = function(paper) {
        var shapes = ["circle", "rect", "ellipse"];
        var shapeType = shapes[Math.floor(Math.random() * shapes.length)];
        var x = Math.random() * paper.node.clientWidth;
        var y = Math.random() * paper.node.clientHeight;
        var size = 20 + Math.random() * 80;
        switch(shapeType) {
            case "circle": return paper.circle(x, y, size);
            case "rect": return paper.rect(x, y, size, size);
            case "ellipse": return paper.ellipse(x, y, size, size / 2);
        }
    };

});

Применение:

var paper = Snap(600, 400);
var shape = createRandomShape(paper);
shape.fadeToColor("#ff0000", 2000);

Такой подход позволяет создавать сложные, переиспользуемые расширения Snap.svg, которые можно интегрировать в проекты любой сложности, сохраняя читаемость и модульность кода.