Разбираемся с рисованием в SVG на примере анимированной гирлянды на чистом HTML и CSS

В преддверии Нового Года мне пришла идея сделать праздничный материал с реализацией гирлянды для сайта. Я выбрала не самый оптимальный и простой путь для реализации, моя цель была показать вам интересный опыт, немного развлечься вместе и разобраться с чем-то новым.

Основная идея

На картинке выше финальный результат с анимированной гирляндой вокруг логотипа. Цвета лампочек меняются по кругу от красного к зеленому по порядку: красный, желтый, синий, зеленый. Давайте посмотрим на реализацию.

Реализация лампочек

Основа самой гирлянды задается через SVG. Сам SVG я составляла вручную, без помощи редактора, специально чтобы в деталях разобрать и показать вам, как это работает. Для начала зададим обертку SVG шириной 1000 на 500:

<svg class="garland" height="500" width="1000">

</svg>

Также зададим нашему svg класс garland, в котором опишем необходимые для дальнейшей работы переменные CSS:

.garland {
  --red: #ff2c2c;
  --yellow: #ffeb00;
  --green: #00ff5d;
  --blue: #0095ff;
  --speed: 1.5s;
}

Итак, мы определили цвета: красный, желтый, зеленый и синий. И значение скорости, которое будет использовать в анимации.Теперь давайте сделаем цветные лампочки. Лампочки будут изображаться кружками, которые очень легко нарисовать в SVG через тег cicle, вот пример нашего первого шарика:

<circle cx="5" cy="5" r="5" class="red" />

Координаты cx и cy обозначаются центр окружности, а r – радиус. Таким образом, мы просто продолжаем добавлять новые круги, меняя координаты так, чтобы описать лампочками свисающую гирлянду:

    <circle cx="5" cy="5" r="5" class="red" />
    <circle cx="25" cy="25" r="5" class="blue" />
    <circle cx="35" cy="55" r="5" class="green" />
    <circle cx="65" cy="75" r="5" class="yellow" />
    <circle cx="105" cy="65" r="5" class="red" />
    ……

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

.red {
  fill: var(--red);
}

.yellow {
  fill: var(--yellow);
}

.blue {
  fill: var(--blue);
}

.green {
  fill: var(--green);
}

Через свойство fill мы задает соответствующий цвет шарику. Теперь давайте сделаем красиво и анимируем шарики так, чтобы цвет на них менялся по тому же порядку, какой у цветов шариков в гирлянде. Для этого опишем анимацию для каждого цвета шарика отдельно и пропишем ее в классе шарика. Приведу пример для красного шарика:

@keyframes blinkRed {
  0%{
    fill: var(--red);
  }
  25% {
    fill: var(--blue);
  }
  50% {
    fill: var(--green);
  }
  75% {
    fill: var(--yellow);
  }
}

.red {
  fill: var(--red);
  animation: var(--speed) alternate 0s infinite blinkRed;
}

Определяем анимацию через @keyframes, ¼ времени анимации шарик горит один из четырех цветов и так по порядку, пока не вернется к исходному. Прописываем эту анимацию через свойство animation в класс .red со скоростью, которую определили раньше и делаем анимацию infinite, чтобы наш шарик мигал бесконечно.На этом мы получили уже что-то похожее на гирлянду из мигающих шариков. Однако не хватает провода, на котором держаться лампочки, чтобы гирлянда была похожа на настоящую. Давайте решим это проблему.

Рисование провода гирлянды через кубическую кривую Безье

Чтобы нарисовать линию в SVG можно использовать тег path и описать кривую, которая будет олицетворять наш провод:

<path d="..." stroke="black" fill="transparent" />

Цвет линии делаем черным через stroke=”black” и задает прозрачную заливку, потому что нам нужен только контур. В атрибуте d будет задаваться сама наша линия. Дальше идет самое интересное.Для начала, чтобы поставить указатель в точку из которой начинается шнур, пишем “M 0 0” – это говорит о том, что теперь указать стоит в точке с координатами 0,0 в левом верхнем углу нашего SVG. Отсюда мы и начнем рисовать. Чтобы построить кривую, будет использовать кривую Безье, каждая отдельная кривая будет рисоваться от предыдущего шарика к следующему.В SVG есть несколько вариантов кривой, я взяла для реализации кубическую кривую Безье с двумя контрольными точками. Вы увидите в реализации, что первая контрольная точка всегда будет находится там же, где начало кривой, потому что мой вариант гирлянды висит довольно прямо и нет необходимости как-то сложно искривлять линию, однако в вашем случае вам может это понадобиться. Посмотрим как строится кривая Безье:

Итак кривая Безье задается через команду C и три точки:
x1, y1 – координаты первой контрольной точки
x2, y2 – координаты второй контрольной точки
x, y – координаты финальной точки кривой Безье
При это начальная точка идет через текущее положение указателя, если оно еще не задано или его нужно переместить, то это делается через команду M и указание соответствующих координат. В нашем случае кривая всегда будет заканчиваться в центре круга и следующая будет начинаться из этой же точки, поэтому указать уже будет находиться там, где нам нужно и его не обязательно отдельно перемещать. Итак, пример нескольких линий между первыми шариками:

d="M0 0 C 0 0, 3 3, 5 5,
             C 5 5, 10 20, 25 25, 
             C 25 25, 30 30, 35 55, 
             C 35 55, 35 75, 65 75, 
…..”

Сначала мы рисуем маленький хвостик провода от точки 0, 0 к середине первого шарика. Зачем у нас указатель уже находится в нужном положении для рисования следующей линии, нам нужно искривить линию вниз чтобы она как б свисала, для этого нам хватит одной контрольной точки, поэтому координаты x1 и y1 также оставляем в начальной точке. Конечная точка x,y всегда будет совпадать с серединой следующего шарика, поэтому ее всегда будет легко определить. Вторая контрольная точка будет задавать нужное нам искривление вниз, для этого выбираем точку ниже и правее начальной, но выше и левее конечной. Таким образом продолжаем от каждого шарика к следующему по кривой на каждую пару шариков, искривляя каждую на свой вкус, пока гирлянда не закончится. И не забываем в конце вернуть шнур от последнего шарика наверх. Конечный результат можно посмотреть ниже:

Если вы дошли до конца этой статьи, то надеюсь вам было интересно и вы узнали что-то новое из этого материала. Конечно на практике лучше использовать редактор для рисования SVG, а потом только анимировать его. Но, когда вы будете использовать готовый SVG в следующий раз, вы уже будете знать, как это делается под капотом. На этом у меня все, спасибо за внимание.

Добавить комментарий