Snap.svg предоставляет мощные возможности для работы с векторной графикой, основанной на SVG, и одной из ключевых особенностей библиотеки является возможность расширять прототипы объектов для создания собственных методов и удобных абстракций.
Каждый элемент, создаваемый с помощью Snap.svg, будь то
circle, rect, path или
text, является объектом с прототипом Element.
Этот прототип содержит базовые методы для манипуляции элементами:
трансформации, анимации, работы с атрибутами и событиями. Например:
var s = Snap(400, 400);
var circle = s.circle(100, 100, 50);
circle.attr({
fill: "#f00",
stroke: "#000",
strokeWidth: 2
});
В данном примере circle наследует методы из прототипа
Element. Методы attr, transform,
animate, click и другие доступны всем
элементам SVG, создаваемым через Snap.
Element.prototypeДля расширения функциональности всех элементов можно добавлять методы
напрямую в прототип Element. Это позволяет создавать
собственные вспомогательные функции, которые будут доступны каждому
элементу. Пример:
Snap.Element.prototype.moveTo = function(x, y) {
this.attr({ cx: x, cy: y });
return this;
};
var circle = s.circle(50, 50, 20);
circle.moveTo(200, 150);
В этом примере добавлен метод moveTo, который
устанавливает новые координаты центра элемента. Метод возвращает
this, что позволяет строить цепочки вызовов.
Некоторые методы специфичны для определённых типов элементов.
Например, cx и cy актуальны для круга, а
x и y — для прямоугольника или текста. Можно
создавать универсальные методы с проверкой типа элемента:
Snap.Element.prototype.setPosition = function(x, y) {
if (this.type === "circle" || this.type === "ellipse") {
this.attr({ cx: x, cy: y });
} else if (this.type === "rect" || this.type === "text") {
this.attr({ x: x, y: y });
}
return this;
};
var rect = s.rect(10, 10, 50, 50);
rect.setPosition(100, 100);
var text = s.text(0, 0, "Hello");
text.setPosition(200, 200);
Такой подход позволяет создавать методы, которые работают с разными типами SVG-объектов без дублирования кода.
Snap.svg поддерживает цепочки вызовов через возвращение объекта
this. При расширении прототипов важно соблюдать этот
принцип для сохранения гибкости:
Snap.Element.prototype.resize = function(scale) {
this.transform(`s${scale},${scale}`);
return this;
};
circle.resize(1.5).attr({ fill: "#00f" }).animate({ r: 80 }, 1000);
Метод resize изменяет масштаб элемента, после чего можно
продолжить работу с элементом через стандартные методы Snap.svg.
Группы элементов (g) создаются через метод
group и также имеют прототип, поддерживающий расширение.
Методы, добавленные к Element.prototype, будут работать и с
отдельными элементами в группе, но для удобной работы с группами можно
создавать специализированные методы:
Snap.Element.prototype.setGroupOpacity = function(opacity) {
if (this.type === "g") {
this.selectAll("*").forEach(el => el.attr({ opacity: opacity }));
}
return this;
};
var group = s.group(
s.circle(50, 50, 30),
s.rect(40, 40, 20, 20)
);
group.setGroupOpacity(0.5);
Помимо добавления методов в прототип, часто используют вспомогательные функции для генерации сложных объектов с предустановленными свойствами и методами. Например, фабрика для создания кастомных фигур:
function createButton(x, y, width, height, label) {
var rect = s.rect(x, y, width, height, 5, 5).attr({ fill: "#ccc", stroke: "#333", strokeWidth: 2 });
var text = s.text(x + width/2, y + height/2, label).attr({ "text-anchor": "middle", "dominant-baseline": "middle", fill: "#000" });
var button = s.group(rect, text);
button.click(function() {
console.log(`Button ${label} clicked`);
});
return button;
}
var btn = createButton(50, 200, 120, 40, "Click Me");
Такой подход комбинирует расширение прототипа и композицию объектов для создания готовых интерактивных элементов интерфейса.
this: для поддержки цепочек
вызовов.Расширение прототипов в Snap.svg позволяет создавать высокоуровневые абстракции, упрощать повторяющиеся операции и строить мощные визуальные интерфейсы, полностью используя возможности SVG и JavaScript.