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

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


Функции как компоненты

Самый простой способ создать компонент — оформить его как функцию, которая принимает параметры и возвращает SVG-элемент.

const draw = SVG().addTo('body').size(500, 500);

function createButton(x, y, width, height, text) {
    const group = draw.group();
    const rect = group.rect(width, height).fill('#3498db').radius(5);
    const label = group.text(text).font({ size: 16, anchor: 'middle', leading: '1em' })
                    .move(x + width / 2, y + height / 2);
    group.move(x, y);
    return group;
}

const button1 = createButton(50, 50, 120, 40, 'Click Me');
const button2 = createButton(200, 50, 120, 40, 'Submit');

Ключевые моменты:

  • group() позволяет объединить несколько элементов в одну логическую единицу, которую можно перемещать, масштабировать и трансформировать как целое.
  • move(x, y) задаёт позицию всей группы.
  • Параметры функции делают компонент гибким для переиспользования.

Классы и наследование компонентов

Для более сложных компонентов удобно использовать классы. Это позволяет добавлять методы для изменения состояния, управления событиями и анимации.

class SvgButton {
    constructor(draw, x, y, width, height, text) {
        this.group = draw.group();
        this.rect = this.group.rect(width, height).fill('#2ecc71').radius(5);
        this.label = this.group.text(text).font({ size: 16, anchor: 'middle', leading: '1em' })
                       .move(width / 2, height / 2);
        this.group.move(x, y);
    }

    setText(newText) {
        this.label.text(newText);
    }

    setColor(color) {
        this.rect.fill(color);
    }

    onClick(callback) {
        this.group.click(callback);
    }
}

const draw = SVG().addTo('body').size(600, 400);
const btn = new SvgButton(draw, 50, 100, 150, 50, 'Press');
btn.onClick(() => btn.setColor('#e74c3c'));

Преимущества классов:

  • Лёгкая интеграция событий и анимаций.
  • Возможность добавлять наследование для расширения функционала.
  • Инкапсуляция логики компонента, минимизация глобальных переменных.

Использование шаблонов и конфигураций

Для проектов с большим количеством одинаковых компонентов удобно хранить настройки в объекте конфигурации и передавать его в компонент.

const buttonConfig = {
    width: 120,
    height: 50,
    fill: '#9b59b6',
    radius: 10,
    fontSize: 14,
    textColor: '#fff'
};

function createConfiguredButton(draw, x, y, text, config) {
    const group = draw.group();
    const rect = group.rect(config.width, config.height).fill(config.fill).radius(config.radius);
    const label = group.text(text).font({ size: config.fontSize, anchor: 'middle' })
                    .fill(config.textColor)
                    .move(config.width / 2, config.height / 2);
    group.move(x, y);
    return group;
}

const draw = SVG().addTo('body').size(500, 300);
createConfiguredButton(draw, 50, 50, 'Save', buttonConfig);
createConfiguredButton(draw, 200, 50, 'Cancel', buttonConfig);

Преимущества конфигураций:

  • Быстрое изменение внешнего вида всех компонентов.
  • Легко интегрировать темы и стили.
  • Поддержка масштабируемости и повторного использования.

Комбинирование и композиция компонентов

SVG.js позволяет создавать составные компоненты, где один компонент включает несколько других.

function createCard(draw, x, y, width, height, titleText, buttonText) {
    const card = draw.group();
    const background = card.rect(width, height).fill('#ecf0f1').radius(8);
    const title = card.text(titleText).font({ size: 18, anchor: 'start' }).move(10, 10);
    const button = createButton(10, height - 50, 100, 40, buttonText);
    card.add(button);
    card.move(x, y);
    return card;
}

const draw = SVG().addTo('body').size(600, 400);
createCard(draw, 50, 50, 250, 150, 'Card Title', 'Action');

Особенности композиции:

  • Компоненты можно комбинировать через group().add().
  • Внутренние компоненты сохраняют возможность управления своим состоянием.
  • Удобно создавать повторяющиеся блоки интерфейса, такие как панели, карточки или формы.

Интеграция с анимацией

Компоненты легко расширяются анимацией через методы SVG.js:

btn.group.hover(
    () => btn.setColor('#1abc9c'),
    () => btn.setColor('#2ecc71')
);

btn.group.animate(1000).move(300, 100).loop();
  • hover() позволяет задать динамическое изменение состояния при наведении.
  • animate() используется для плавного перемещения, изменения размеров, цвета и других свойств.
  • Комбинирование анимации с переиспользуемыми компонентами повышает интерактивность интерфейса.

Итоговые рекомендации по созданию компонентов

  • Всегда использовать группы (group) для логической инкапсуляции элементов.
  • Применять параметры или конфигурационные объекты для гибкости.
  • Использовать классы, если компонент требует внутреннего состояния или методов управления.
  • Комбинировать компоненты через композицию для создания сложных интерфейсов.
  • Интегрировать анимацию и события напрямую в компонент, чтобы сделать их полностью автономными.

Переиспользуемые компоненты в SVG.js повышают эффективность разработки, упрощают поддержку кода и делают интерфейс более структурированным и модульным.