Разработка Canvas-анимаций для сайта: частицы, 3D, WebGL

Стандартные DOM-анимации тормозят при тысячах объектов, а размытые пиксели и проблемы с интеграцией в React или Vue портят впечатление от сайта. Мы разрабатываем Canvas-анимации под ключ — от частиц до WebGL-сцен с шейдерами, обеспечивая плавность и чёткость на любых устройствах. Наша команда берёт на себя весь цикл: от аудита производительности до внедрения и последующей поддержки.

Разработка и обслуживание любых видов сайтов:

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

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Разработка Canvas-анимаций для сайта: частицы, 3D, WebGL

Фронтенд-разработка: React, Vue, Next.js, NuxtСложный~3-5 дней
Часто задаваемые вопросы

Интерактивные фоны, частицы и 3D-сцены — тренд, но реализация через DOM или SVG упирается в производительность: 60 FPS держатся только до сотни объектов. Canvas же позволяет рендерить тысячи частиц без лагов — но только при правильной архитектуре. Например, клиент хотел фон из 3000 частиц на React — DOM уронил FPS до 5. Переписали на Canvas с пулом частиц — получили стабильные 60 FPS на мобильном.

Мы реализуем Canvas-анимации под ключ: от простых частиц до WebGL-сцен с шейдерами. Прозрачная стоимость разработки рассчитывается исходя из сложности. Оценим ваш проект за 1 день — свяжитесь с нами для консультации.

Какие проблемы решаем

Низкая производительность при большом количестве объектов

DOM-анимации тормозят уже на 100–200 элементах. Canvas перерисовывает всё за один проход, но требует ручного управления памятью и переиспользования объектов. Мы оптимизируем пулы частиц, избегаем gc и боремся с N+1 отрисовкой. Гарантируем, что после оптимизации анимация будет работать на 60 FPS на всех целевых устройствах.

Размытые пиксели на Retina-дисплеях

Стандартный canvas рисует в CSS-пикселях — на Retina изображение получается размытым. Мы умножаем размер на devicePixelRatio и масштабируем контекст.

Сложность интеграции с React/Vue

Простое использование canvas вызывает 'hydration mismatch' и потерю состояния. Мы обернули движок в хуки useCanvas с корректным управлением жизненным циклом.

Неконтролируемая память в анимациях

Без грамотного управления объектами память растёт, вызывая GC-фризы. Мы используем объектные пулы и избегаем аллокаций в render loop.

Какую производительность даёт Canvas

Canvas в 10–50 раз быстрее SVG на тысячах объектов благодаря отсутствию DOM-накладных расходов. Мы добиваемся стабильных 60 FPS за счёт:

  • requestAnimationFrame с автоматической паузой при неактивной вкладке
  • Ограничения delta-time (кап 100 ms)
  • Принудительного сброса gc через переиспользование объектов

Сравнение Canvas vs SVG vs DOM-анимации:

Характеристика Canvas SVG DOM-анимации
Максимум объектов 50 000+ 1 000 500
Интерактивность Своя система По событиям По событиям
Трансформации Кастомные CSS-свойства CSS-свойства
Retina-поддержка Через DPR Автоматически Автоматически

Оптимизация под Retina и мобильные устройства включена в стоимость.

Как мы это делаем: стек и примеры

Используем TypeScript, React 18, Three.js r150. Ключевые паттерны: Repository, BFF для частиц, render loop с разделением на update/draw. Код движка tree-shake-ready, что позволяет включать только нужные модули в финальный бандл.

Базовый Canvas-движок

// lib/canvas-engine.ts
export interface AnimationContext {
  canvas: HTMLCanvasElement
  ctx: CanvasRenderingContext2D
  width: number
  height: number
  dpr: number // device pixel ratio
  dt: number // delta time в секундах
}

export type RenderFn = (context: AnimationContext) => void

export class CanvasEngine {
  private canvas: HTMLCanvasElement
  private ctx: CanvasRenderingContext2D
  private dpr: number
  private rafId: number | null = null
  private lastTime: number = 0
  private renderFn: RenderFn

  constructor(canvas: HTMLCanvasElement, renderFn: RenderFn) {
    this.canvas = canvas
    this.ctx = canvas.getContext('2d')!
    this.dpr = window.devicePixelRatio || 1
    this.renderFn = renderFn
    this.resize()
  }

  resize() {
    const { canvas, dpr } = this
    const rect = canvas.getBoundingClientRect()
    canvas.width = rect.width * dpr
    canvas.height = rect.height * dpr
    this.ctx.scale(dpr, dpr)
  }

  start() {
    this.lastTime = performance.now()
    this.tick(this.lastTime)
  }

  stop() {
    if (this.rafId !== null) {
      cancelAnimationFrame(this.rafId)
      this.rafId = null
    }
  }

  private tick = (timestamp: number) => {
    const dt = Math.min((timestamp - this.lastTime) / 1000, 0.1)
    this.lastTime = timestamp
    const rect = this.canvas.getBoundingClientRect()
    this.renderFn({
      canvas: this.canvas,
      ctx: this.ctx,
      width: rect.width,
      height: rect.height,
      dpr: this.dpr,
      dt,
    })
    this.rafId = requestAnimationFrame(this.tick)
  }
}

React-хук useCanvas

// hooks/useCanvas.ts
import { useEffect, useRef } from 'react'
import { CanvasEngine, RenderFn } from '../lib/canvas-engine'

export function useCanvas(renderFn: RenderFn) {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const engineRef = useRef<CanvasEngine | null>(null)

  useEffect(() => {
    const canvas = canvasRef.current
    if (!canvas) return

    const engine = new CanvasEngine(canvas, renderFn)
    engineRef.current = engine
    engine.start()

    const handleResize = () => engine.resize()
    window.addEventListener('resize', handleResize)

    return () => {
      engine.stop()
      window.removeEventListener('resize', handleResize)
    }
  }, [renderFn])

  return canvasRef
}

Система частиц с физикой

// lib/particle-system.ts
interface Particle {
  x: number
  y: number
  vx: number
  vy: number
  radius: number
  color: string
  life: number
  maxLife: number
}

export class ParticleSystem {
  private particles: Particle[] = []
  private readonly maxParticles: number

  constructor(maxParticles = 500) {
    this.maxParticles = maxParticles
  }

  emit(x: number, y: number, count = 5) {
    for (let i = 0; i < count; i++) {
      if (this.particles.length >= this.maxParticles) break
      const angle = Math.random() * Math.PI * 2
      const speed = 50 + Math.random() * 150
      this.particles.push({
        x,
        y,
        vx: Math.cos(angle) * speed,
        vy: Math.sin(angle) * speed - 100,
        radius: 2 + Math.random() * 4,
        color: `hsl(${200 + Math.random() * 60}, 80%, 60%)`,
        life: 1,
        maxLife: 0.8 + Math.random() * 0.8,
      })
    }
  }

  update(dt: number) {
    const gravity = 300
    this.particles = this.particles.filter(p => {
      p.x += p.vx * dt
      p.y += p.vy * dt
      p.vy += gravity * dt
      p.vx *= 0.99
      p.life -= dt / p.maxLife
      return p.life > 0
    })
  }

  draw(ctx: CanvasRenderingContext2D) {
    for (const p of this.particles) {
      ctx.save()
      ctx.globalAlpha = p.life * p.life
      ctx.fillStyle = p.color
      ctx.beginPath()
      ctx.arc(p.x, p.y, p.radius * p.life, 0, Math.PI * 2)
      ctx.fill()
      ctx.restore()
    }
  }
}

Пример компонента: ParticleCanvas — интерактивная система частиц с гравитацией, автоматической эмиссией и кликом мыши.

Подробнее о шейдерах Для нестандартных эффектов (свечение, маски, волны) пишем кастомные шейдеры GLSL. Они выполняются на GPU, что экономит ресурсы CPU и повышает FPS. Шейдеры интегрируются через Three.js ShaderMaterial или нативный WebGL.

Почему Three.js — стандарт для 3D-анимаций на сайте?

Для сложных 3D-сцен на фоне сайта используем Three.js — он даёт готовые шейдеры, постпроцессинг и совместимость с WebGL 2.0. Мы пишем кастомные материалы и анимации, контролируя память через BufferGeometry.

// components/ThreeBackground.tsx
'use client'
import { useEffect, useRef } from 'react'
import * as THREE from 'three'

export function ThreeBackground() {
  const mountRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const mount = mountRef.current!
    const width = mount.clientWidth
    const height = mount.clientHeight

    const scene = new THREE.Scene()
    const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)
    camera.position.z = 50

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
    renderer.setSize(width, height)
    renderer.setPixelRatio(window.devicePixelRatio)
    mount.appendChild(renderer.domElement)

    const count = 3000
    const positions = new Float32Array(count * 3)
    for (let i = 0; i < count * 3; i++) {
      positions[i] = (Math.random() - 0.5) * 200
    }

    const geometry = new THREE.BufferGeometry()
    geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))

    const material = new THREE.PointsMaterial({
      size: 0.3,
      color: 0x3b82f6,
      transparent: true,
      opacity: 0.7,
    })

    const points = new THREE.Points(geometry, material)
    scene.add(points)

    let rafId: number
    const animate = () => {
      rafId = requestAnimationFrame(animate)
      points.rotation.x += 0.0003
      points.rotation.y += 0.0005
      renderer.render(scene, camera)
    }
    animate()

    const handleResize = () => {
      const w = mount.clientWidth
      const h = mount.clientHeight
      camera.aspect = w / h
      camera.updateProjectionMatrix()
      renderer.setSize(w, h)
    }
    window.addEventListener('resize', handleResize)

    return () => {
      cancelAnimationFrame(rafId)
      window.removeEventListener('resize', handleResize)
      renderer.dispose()
      mount.removeChild(renderer.domElement)
    }
  }, [])

  return <div ref={mountRef} className="absolute inset-0 -z-10" />
}

Как Canvas-анимации влияют на Core Web Vitals?

Правильно спроектированная Canvas-анимация не ухудшает LCP, CLS и INP. Мы используем requestAnimationFrame и Suspense для ленивой загрузки, чтобы не блокировать основной поток. В результате анимация стартует только после интерактива страницы, не замедляя первый рендер.

Процесс работы

  1. Аналитика — изучаем дизайн, требования к производительности, целевые устройства.
  2. Прототипирование — создаём MVP анимации с базовыми параметрами.
  3. Реализация — пишем движок с паттернами Repository, подключаем React-обвязку.
  4. Оптимизация — режем draw calls, добавляем LOD, проверяем Core Web Vitals.
  5. Деплой — настраиваем CI/CD, тесты на реальных устройствах.

Сроки ориентировочно

Тип анимации Сроки
Простые частицы / волны 1–2 дня
Интерактивная система (физика) 3–5 дней
3D-сцена с шейдерами 1–2 недели
Комплексный проект (анимация + бизнес-логика) 2–3 недели

Что входит в услугу

  • Исходный код (TS/React-компоненты, документация JSDoc)
  • Оптимизация под 60 FPS на целевых устройствах
  • Адаптация под мобильные и Retina
  • Интеграция с вашим приложением (Next.js, Nuxt, CRA)
  • Техническая поддержка 2 недели после сдачи

Сертифицированные специалисты Three.js и WebGL. Гарантия производительности 60 FPS. Закажите разработку Canvas-анимации в нашей командеи получите стабильные 60 FPS на любых устройствах.

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

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1543
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1374
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1142
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060