SPB Git

spb/svgarden Public

SVGarden — searchable bank of 74 self-contained SVG+CSS animation snippets (svgarden.dev)

HTML 79.2% Astro 10.3% JavaScript 6% CSS 3.7% Shell 0.8%
3.3 KB · 86 lines html
Raw Blame History
1<!--2  ============================================================3  SVGarden — https://www.svgarden.dev4  Author : Simon-Pierre Boucher5  Contact: contact@spboucher.ai6  File   : snippets/filters/goo-menu.html7  Desc   : Gooey action menu — dots merge and separate like liquid8  ============================================================9-->10<!--svgarden11title: Goo menu12slug: goo-menu13category: filters14tags: [filter, goo, liquid, blob]15difficulty: advanced16techniques: [feGaussianBlur, "feColorMatrix (alpha threshold)", feBlend, filter-pipeline]17how_it_works: >18  The gooey look is a two-step filter pipeline. feGaussianBlur first smears every19  dot into a soft cloud, so where two dots come near, their alpha halos overlap20  and add up. feColorMatrix then multiplies alpha by 19 and subtracts 9, a hard21  threshold that crushes the blur back to a crisp edge — but the overlapping22  halos survive the cut, becoming the liquid bridge between shapes. A final23  feBlend redraws the original sharp circles on top so the dots stay clean while24  the goo happens between them.25customizable:26  - { var: "--sg-color",    label: "Color", type: color, default: "#7F77DD" }27  - { var: "--sg-size",     label: "Size",  type: range, min: 80, max: 240, default: 140, unit: px }28  - { var: "--sg-duration", label: "Cycle", type: range, min: 1.5, max: 6, step: 0.1, default: 2.8, unit: s }29created: 2026-08-1030-->31<div class="sg-goo-menu" style="--sg-color:#7F77DD; --sg-size:140px; --sg-duration:2.8s;">32  <svg viewBox="0 0 120 120" aria-hidden="true" focusable="false">33    <defs>34      <filter id="sg-goo-menu-goo" x="-30%" y="-30%" width="160%" height="160%">35        <feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />36        <feColorMatrix in="blur" mode="matrix"37          values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />38        <feBlend in="SourceGraphic" in2="goo" />39      </filter>40    </defs>41    <g filter="url(#sg-goo-menu-goo)">42      <circle class="sg-goo-menu-dot" cx="60" cy="60" r="15" />43      <circle class="sg-goo-menu-sat sg-goo-menu-sat1" cx="60" cy="60" r="11" />44      <circle class="sg-goo-menu-sat sg-goo-menu-sat2" cx="60" cy="60" r="11" />45      <circle class="sg-goo-menu-sat sg-goo-menu-sat3" cx="60" cy="60" r="11" />46    </g>47  </svg>48</div>49<style>50  .sg-goo-menu {51    width: var(--sg-size);52    height: var(--sg-size);53  }54  .sg-goo-menu svg {55    display: block;56    width: 100%;57    height: 100%;58  }59  .sg-goo-menu circle {60    fill: var(--sg-color);61  }62  .sg-goo-menu-sat {63    animation-duration: var(--sg-duration);64    animation-timing-function: ease-in-out;65    animation-iteration-count: infinite;66  }67  .sg-goo-menu-sat1 { animation-name: sg-goo-menu-up; }68  .sg-goo-menu-sat2 { animation-name: sg-goo-menu-right; }69  .sg-goo-menu-sat3 { animation-name: sg-goo-menu-left; }70  @keyframes sg-goo-menu-up {71    0%, 12%  { transform: translate(0, 0); }72    45%, 65% { transform: translate(0, -35px); }73    100%     { transform: translate(0, 0); }74  }75  @keyframes sg-goo-menu-right {76    0%, 12%  { transform: translate(0, 0); }77    45%, 65% { transform: translate(31px, 18px); }78    100%     { transform: translate(0, 0); }79  }80  @keyframes sg-goo-menu-left {81    0%, 12%  { transform: translate(0, 0); }82    45%, 65% { transform: translate(-31px, 18px); }83    100%     { transform: translate(0, 0); }84  }85</style>86