Реализация Liquid/Blob эффектов на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

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

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

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация Liquid/Blob эффектов на сайте
Сложная
~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

Реализация Liquid/Blob эффектов на сайте

Blob и liquid эффекты — органические, «живые» формы: пятна с плавно меняющимися краями, жидкие переходы между состояниями, деформация геометрии по шуму. В вебе это реализуется через SVG (простые случаи), CSS-фильтры (трюк с blur+contrast), Canvas и WebGL (полный контроль).

SVG Blob с анимированным path

Базовый вариант: SVG-форма с анимацией контрольных точек через JS.

// Генерация blob-пути через cubicBezier контрольные точки
function createBlobPath(
  cx: number,
  cy: number,
  radius: number,
  points: number,
  variance: number,
  seed: number
): string {
  const angleStep = (Math.PI * 2) / points
  const coords: [number, number][] = []

  for (let i = 0; i < points; i++) {
    const angle = i * angleStep - Math.PI / 2
    const r = radius + (Math.random() * variance * 2 - variance)
    coords.push([
      cx + Math.cos(angle) * r,
      cy + Math.sin(angle) * r,
    ])
  }

  // Строим smooth path через catmull-rom -> bezier
  const d: string[] = []
  const n = coords.length

  for (let i = 0; i < n; i++) {
    const p0 = coords[(i - 1 + n) % n]
    const p1 = coords[i]
    const p2 = coords[(i + 1) % n]
    const p3 = coords[(i + 2) % n]

    const cp1x = p1[0] + (p2[0] - p0[0]) / 6
    const cp1y = p1[1] + (p2[1] - p0[1]) / 6
    const cp2x = p2[0] - (p3[0] - p1[0]) / 6
    const cp2y = p2[1] - (p3[1] - p1[1]) / 6

    if (i === 0) {
      d.push(`M ${p1[0]},${p1[1]}`)
    }
    d.push(`C ${cp1x},${cp1y} ${cp2x},${cp2y} ${p2[0]},${p2[1]}`)
  }

  d.push('Z')
  return d.join(' ')
}

// Анимация: морфинг между двумя blob-формами
class AnimatedBlob {
  private path: SVGPathElement
  private pathA: string
  private pathB: string
  private progress = 0
  private direction = 1
  private speed = 0.005

  constructor(path: SVGPathElement, cx: number, cy: number, radius: number) {
    this.path = path
    this.pathA = createBlobPath(cx, cy, radius, 8, radius * 0.25, 1)
    this.pathB = createBlobPath(cx, cy, radius, 8, radius * 0.25, 2)
    this.animate()
  }

  private animate() {
    this.progress += this.speed * this.direction
    if (this.progress >= 1 || this.progress <= 0) this.direction *= -1

    // GSAP morphSVG или нативный интерполятор
    this.path.setAttribute('d', this.interpolatePaths(
      this.pathA,
      this.pathB,
      this.progress
    ))

    requestAnimationFrame(() => this.animate())
  }
}

Проще использовать GSAP MorphSVGPlugin (Club GreenSock):

import gsap from 'gsap'
import MorphSVGPlugin from 'gsap/MorphSVGPlugin'

gsap.registerPlugin(MorphSVGPlugin)

// Морфинг между путями
gsap.to('#blob-path', {
  morphSVG: '#blob-path-b',
  duration: 3,
  ease: 'sine.inOut',
  repeat: -1,
  yoyo: true,
})

CSS Blob через filter: blur + contrast

Дешёвый, но эффективный трюк. Несколько кругов с blur, обёрнуты в контейнер с contrast(20). На границах blur перекрывающихся кругов возникает жидкое слипание.

<div class="blob-container">
  <div class="blob blob--1"></div>
  <div class="blob blob--2"></div>
  <div class="blob blob--3"></div>
  <div class="blob blob--cursor"></div>
</div>
.blob-container {
  position: fixed;
  inset: 0;
  filter: blur(40px) contrast(20);
  /* contrast() — ключ эффекта */
}

.blob {
  position: absolute;
  border-radius: 50%;
  background: #7000ff;
}

.blob--1 {
  width: 300px;
  height: 300px;
  top: 20%;
  left: 30%;
  animation: blob-float-1 8s ease-in-out infinite alternate;
}

.blob--2 {
  width: 200px;
  height: 200px;
  top: 50%;
  left: 60%;
  animation: blob-float-2 10s ease-in-out infinite alternate;
}

.blob--3 {
  width: 250px;
  height: 250px;
  top: 70%;
  left: 20%;
  animation: blob-float-3 12s ease-in-out infinite alternate;
}

@keyframes blob-float-1 {
  0%   { transform: translate(0, 0) scale(1); }
  50%  { transform: translate(80px, -60px) scale(1.1); }
  100% { transform: translate(-40px, 40px) scale(0.9); }
}

@keyframes blob-float-2 {
  0%   { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-100px, 80px) scale(1.2); }
}

@keyframes blob-float-3 {
  0%   { transform: translate(0, 0) scale(1); }
  100% { transform: translate(60px, -80px) scale(0.8); }
}

Blob-cursor — следует за мышью:

const blobCursor = document.querySelector('.blob--cursor')
let mouseX = 0, mouseY = 0
let currentX = 0, currentY = 0

document.addEventListener('mousemove', (e) => {
  mouseX = e.clientX
  mouseY = e.clientY
})

function animateCursor() {
  currentX += (mouseX - currentX) * 0.08
  currentY += (mouseY - currentY) * 0.08

  blobCursor.style.transform = `translate(${currentX - 75}px, ${currentY - 75}px)`
  requestAnimationFrame(animateCursor)
}

animateCursor()

WebGL Liquid через шейдер

Полный контроль над формой, цветом, поведением — через GLSL. Шейдер на основе sdf (signed distance function):

// Fragment shader — liquid metaballs
uniform float uTime;
uniform vec2 uMouse;
uniform vec2 uResolution;

// SDF для круга
float circle(vec2 p, vec2 center, float r) {
  return length(p - center) - r;
}

// Smooth union — "слипание" форм
float smoothUnion(float d1, float d2, float k) {
  float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
  return mix(d2, d1, h) - k * h * (1.0 - h);
}

void main() {
  vec2 uv = (gl_FragCoord.xy - uResolution * 0.5) / min(uResolution.x, uResolution.y);
  vec2 mouse = (uMouse - uResolution * 0.5) / min(uResolution.x, uResolution.y);

  // Три блоба с независимым движением
  vec2 p1 = vec2(sin(uTime * 0.7) * 0.3, cos(uTime * 0.5) * 0.2);
  vec2 p2 = vec2(cos(uTime * 0.4) * 0.25, sin(uTime * 0.8) * 0.25);
  vec2 p3 = mouse * 0.5;  // следует за мышью

  float d1 = circle(uv, p1, 0.18);
  float d2 = circle(uv, p2, 0.14);
  float d3 = circle(uv, p3, 0.12);

  float merged = smoothUnion(smoothUnion(d1, d2, 0.08), d3, 0.06);

  // Цвет: градиент внутри формы, rim-lighting по краям
  vec3 colorInner = vec3(0.4, 0.0, 1.0);
  vec3 colorRim = vec3(0.0, 0.8, 1.0);

  float fill = smoothstep(0.005, -0.005, merged);
  float rim = smoothstep(0.02, 0.0, merged) - smoothstep(0.0, -0.02, merged);

  vec3 color = mix(vec3(0.0), colorInner, fill);
  color += colorRim * rim * 0.8;

  gl_FragColor = vec4(color, fill + rim * 0.5);
}

React-компонент с CSS blob

import { useEffect, useRef } from 'react'

export function LiquidBackground() {
  const containerRef = useRef<HTMLDivElement>(null)
  const cursorBlobRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const cursor = cursorBlobRef.current
    if (!cursor) return

    let mx = 0, my = 0, cx = 0, cy = 0
    let rafId: number

    const onMove = (e: MouseEvent) => { mx = e.clientX; my = e.clientY }
    window.addEventListener('mousemove', onMove)

    const tick = () => {
      cx += (mx - cx) * 0.08
      cy += (my - cy) * 0.08
      cursor.style.transform = `translate(${cx - 75}px, ${cy - 75}px)`
      rafId = requestAnimationFrame(tick)
    }
    rafId = requestAnimationFrame(tick)

    return () => {
      window.removeEventListener('mousemove', onMove)
      cancelAnimationFrame(rafId)
    }
  }, [])

  return (
    <div ref={containerRef} className="blob-container">
      <div className="blob blob--1" />
      <div className="blob blob--2" />
      <div ref={cursorBlobRef} className="blob blob--cursor" />
    </div>
  )
}

Сроки

CSS blob с cursor-following — 1 день. SVG морфинг через GSAP — 2–3 дня. WebGL metaballs с кастомным шейдером и интерактивностью — 5–7 дней.