Реалізація SVG-анімацій (SMIL/CSS/JS) на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація SVG-анімацій (SMIL/CSS/JS) на сайті
Середня
~2-3 робочих дні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація SVG-анімацій (SMIL/CSS/JS) на сайті

SVG-анімації існують у трьох форматах, кожен зі своєю нішею. SMIL (Synchronized Multimedia Integration Language) — декларативні анімації всередині SVG-розмітки, працюють без JavaScript. CSS-анімації через @keyframes — для простих трансформацій. JavaScript через Web Animations API або GSAP — для інтерактивних та керованих сцен. Розглянемо всі три підходи з реальними прикладами.

SMIL: анімації всередину SVG

SMIL-анімації описуються прямо в SVG-коді через теги <animate>, <animateTransform>, <animateMotion>:

<!-- public/animations/logo.svg -->
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
  <!-- Анімація кольору заливки -->
  <circle cx="100" cy="100" r="50" fill="#3b82f6">
    <animate
      attributeName="fill"
      values="#3b82f6;#8b5cf6;#ec4899;#3b82f6"
      dur="3s"
      repeatCount="indefinite"
      calcMode="spline"
      keySplines="0.4 0 0.2 1; 0.4 0 0.2 1; 0.4 0 0.2 1"
    />
    <animate
      attributeName="r"
      values="50;45;50"
      dur="1.5s"
      repeatCount="indefinite"
    />
  </circle>

  <!-- Рух по шляху -->
  <circle r="8" fill="white">
    <animateMotion
      dur="4s"
      repeatCount="indefinite"
      rotate="auto"
    >
      <mpath href="#orbit-path" />
    </animateMotion>
  </circle>

  <path
    id="orbit-path"
    d="M 100,30 A 70,70 0 1,1 99.9,30"
    fill="none"
    stroke="rgba(255,255,255,0.2)"
    stroke-width="1"
  />

  <!-- Морфінг форми через атрибут d -->
  <path fill="#f59e0b">
    <animate
      attributeName="d"
      dur="2s"
      repeatCount="indefinite"
      values="
        M 100,20 L 180,80 L 150,160 L 50,160 L 20,80 Z;
        M 100,10 L 190,90 L 160,170 L 40,170 L 10,90 Z;
        M 100,20 L 180,80 L 150,160 L 50,160 L 20,80 Z
      "
    />
  </path>
</svg>

SMIL працює у всіх сучасних браузерах крім IE (уже не актуально). Немає підтримки в Safari iOS для деяких атрибутів — потрібно тестувати.

CSS-анімації SVG

CSS підходить для трансформацій, opacity, stroke-анімацій. Важливий момент: transform-origin в SVG працює не так, як у HTML — координати відносяться до SVG viewport:

/* styles/svg-animations.css */

/* Пульсуючий індикатор */
.pulse-ring {
  transform-origin: center;
  animation: pulse 2s ease-out infinite;
}

@keyframes pulse {
  0% { transform: scale(0.8); opacity: 1; }
  100% { transform: scale(2); opacity: 0; }
}

/* Відрисовка лінії (stroke dasharray/dashoffset) */
.draw-path {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: draw 2s ease-in-out forwards;
}

@keyframes draw {
  to { stroke-dashoffset: 0; }
}

/* Появлення з затримкою для груп елементів */
.stagger-item {
  opacity: 0;
  transform: translateY(20px);
  animation: fadeUp 0.5s ease-out forwards;
}

.stagger-item:nth-child(1) { animation-delay: 0.1s; }
.stagger-item:nth-child(2) { animation-delay: 0.2s; }
.stagger-item:nth-child(3) { animation-delay: 0.3s; }

@keyframes fadeUp {
  to { opacity: 1; transform: translateY(0); }
}
// components/AnimatedLogo.tsx
export function AnimatedLogo() {
  return (
    <svg viewBox="0 0 100 100" className="w-16 h-16">
      {/* Фонове кільце */}
      <circle
        cx="50" cy="50" r="40"
        fill="none"
        stroke="#e5e7eb"
        strokeWidth="4"
      />
      {/* Анімований прогрес */}
      <circle
        cx="50" cy="50" r="40"
        fill="none"
        stroke="#3b82f6"
        strokeWidth="4"
        strokeLinecap="round"
        className="draw-path"
        style={{ transformOrigin: '50px 50px', transform: 'rotate(-90deg)' }}
      />
    </svg>
  )
}

JavaScript: Web Animations API

Web Animations API — нативний JS без бібліотек, гарна продуктивність:

// utils/svg-animator.ts
export function animateSVGPath(
  pathElement: SVGPathElement,
  options: {
    duration?: number
    easing?: string
    delay?: number
  } = {}
): Animation {
  const length = pathElement.getTotalLength()

  pathElement.style.strokeDasharray = `${length}`
  pathElement.style.strokeDashoffset = `${length}`

  return pathElement.animate(
    [
      { strokeDashoffset: length },
      { strokeDashoffset: 0 },
    ],
    {
      duration: options.duration ?? 1500,
      easing: options.easing ?? 'ease-in-out',
      delay: options.delay ?? 0,
      fill: 'forwards',
    }
  )
}

export function animateSVGGroup(
  elements: SVGElement[],
  staggerMs = 100
): Animation[] {
  return elements.map((el, i) =>
    el.animate(
      [
        { opacity: 0, transform: 'translateY(20px)' },
        { opacity: 1, transform: 'translateY(0)' },
      ],
      {
        duration: 500,
        delay: i * staggerMs,
        easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
        fill: 'forwards',
      }
    )
  )
}

GSAP + SVG: просунутий рівень

GSAP надає максимальний контроль над SVG-анімаціями, особливо для складних часових ліній:

// components/AnimatedDiagram.tsx
import { useEffect, useRef } from 'react'
import { gsap } from 'gsap'
import { DrawSVGPlugin } from 'gsap/DrawSVGPlugin'

gsap.registerPlugin(DrawSVGPlugin)

export function AnimatedDiagram() {
  const svgRef = useRef<SVGSVGElement>(null)

  useEffect(() => {
    if (!svgRef.current) return

    const ctx = gsap.context(() => {
      const paths = svgRef.current!.querySelectorAll('.data-path')
      const nodes = svgRef.current!.querySelectorAll('.node')
      const labels = svgRef.current!.querySelectorAll('.label')

      const tl = gsap.timeline({ repeat: -1, repeatDelay: 2 })

      // Послідовна відрисовка шляхів
      tl.from(paths, {
        drawSVG: '0%',
        duration: 1.5,
        stagger: 0.3,
        ease: 'power2.inOut',
      })
      // Появлення вузлів
      .from(nodes, {
        scale: 0,
        opacity: 0,
        transformOrigin: 'center',
        stagger: 0.15,
        ease: 'back.out(2)',
        duration: 0.5,
      }, '-=0.5')
      // Появлення підписів
      .from(labels, {
        opacity: 0,
        y: 10,
        stagger: 0.1,
        duration: 0.4,
      }, '-=0.3')
    }, svgRef)

    return () => ctx.revert()
  }, [])

  return (
    <svg ref={svgRef} viewBox="0 0 400 300">
      <path className="data-path" d="M 50,150 C 150,50 250,50 350,150" stroke="#3b82f6" strokeWidth="2" fill="none" />
      <circle className="node" cx="50" cy="150" r="8" fill="#3b82f6" />
      <circle className="node" cx="200" cy="80" r="8" fill="#8b5cf6" />
      <circle className="node" cx="350" cy="150" r="8" fill="#3b82f6" />
      <text className="label" x="50" y="170" textAnchor="middle" fontSize="12">Початок</text>
      <text className="label" x="350" y="170" textAnchor="middle" fontSize="12">Кінець</text>
    </svg>
  )
}

Доступність SVG-анімацій

// Для декоративних анімацій
<svg aria-hidden="true" focusable="false">
  {/* ... */}
</svg>

// Для інформативних
<svg role="img" aria-label="Анімований прогрес завантаження 75%">
  <title>Завантаження файлу</title>
  <desc>Прогрес-бар показує 75% завершення завантаження</desc>
  {/* ... */}
</svg>

Поважайте prefers-reduced-motion:

@media (prefers-reduced-motion: reduce) {
  .draw-path,
  .pulse-ring,
  .stagger-item {
    animation: none;
  }
  .draw-path { stroke-dashoffset: 0; }
}

Типові терміни

Прості CSS stroke-анімації для іконок — 2–4 години. SMIL-анімації для логотипу/ілюстрації — 1 день. Складна JS-анімована діаграма/інфографіка з GSAP — 2–4 дні.