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%
4.8 KB · 115 lines html
Raw Blame History
1<!--2  ============================================================3  SVGarden — https://www.svgarden.dev4  Author : Simon-Pierre Boucher5  Contact: contact@spboucher.ai6  File   : snippets/charts/chart-radar-pulse.html7  Desc   : Radar chart whose data area breathes and vertices ping8  ============================================================9-->10<!--svgarden11title: Radar pulse12slug: chart-radar-pulse13category: charts14tags: [chart, radar, pulse, polygon]15difficulty: intermediate16techniques: [transform-box, "polar → cartesian mapping", "animation-delay", scale]17how_it_works: >18  A radar chart is pure polar-to-cartesian mapping: each axis sits at 72°19  intervals (five axes), and a data point at strength v becomes the vertex20  (cx + v·R·cos θ, cy + v·R·sin θ) — every polygon here, rings included, was21  computed with that one formula. The rings are just the same pentagon at four22  radii, so the "grid" costs four polygons instead of trigonometry at runtime.23  The living feel comes from transform-box: fill-box on the data polygon, which24  makes a tiny scale oscillation breathe around the shape's own centroid rather25  than the SVG corner, while the vertex dots reuse one ping animation with26  staggered delays so attention sweeps around the chart.27customizable:28  - { var: "--sg-color",    label: "Area color", type: color, default: "#7F77DD" }29  - { var: "--sg-size",     label: "Size",       type: range, min: 110, max: 300, default: 170, unit: px }30  - { var: "--sg-duration", label: "Speed",      type: range, min: 1, max: 6, step: 0.5, default: 2.5, unit: s }31created: 2026-08-1032-->33<div class="sg-chart-radar-pulse" style="--sg-color:#7F77DD; --sg-size:170px; --sg-duration:2.5s;">34  <svg viewBox="0 0 140 140" role="img" aria-label="Radar chart of five skills: speed 90, power 65, defense 80, stamina 55, accuracy 70 out of 100">35    <title>Skill radar chart</title>36    <g class="sg-chart-radar-pulse-rings">37      <polygon points="70,18 119.5,53.9 100.6,112.1 39.4,112.1 20.5,53.9" />38      <polygon points="70,31 107.1,58 92.9,101.6 47.1,101.6 32.9,58" />39      <polygon points="70,44 94.7,62 85.3,91 54.7,91 45.3,62" />40      <polygon points="70,57 82.4,66 77.6,80.5 62.4,80.5 57.6,66" />41      <line x1="70" y1="70" x2="70" y2="18" />42      <line x1="70" y1="70" x2="119.5" y2="53.9" />43      <line x1="70" y1="70" x2="100.6" y2="112.1" />44      <line x1="70" y1="70" x2="39.4" y2="112.1" />45      <line x1="70" y1="70" x2="20.5" y2="53.9" />46    </g>47    <polygon class="sg-chart-radar-pulse-area" points="70,23.2 102.1,59.6 94.5,103.7 53.2,93.1 35.4,58.8" />48    <g class="sg-chart-radar-pulse-dots">49      <circle cx="70" cy="23.2" r="3" />50      <circle cx="102.1" cy="59.6" r="3" />51      <circle cx="94.5" cy="103.7" r="3" />52      <circle cx="53.2" cy="93.1" r="3" />53      <circle cx="35.4" cy="58.8" r="3" />54    </g>55    <g class="sg-chart-radar-pulse-labels">56      <text x="70" y="12">spd</text>57      <text x="128" y="52">pwr</text>58      <text x="105" y="122">def</text>59      <text x="35" y="122">sta</text>60      <text x="12" y="52">acc</text>61    </g>62  </svg>63</div>64<style>65  .sg-chart-radar-pulse {66    width: var(--sg-size);67  }68  .sg-chart-radar-pulse svg {69    display: block;70    width: 100%;71    font-family: inherit;72  }73  .sg-chart-radar-pulse-rings polygon,74  .sg-chart-radar-pulse-rings line {75    fill: none;76    stroke: rgba(128, 128, 128, 0.3);77    stroke-width: 1;78  }79  .sg-chart-radar-pulse-area {80    fill: var(--sg-color);81    fill-opacity: 0.35;82    stroke: var(--sg-color);83    stroke-width: 2;84    stroke-linejoin: round;85    transform-box: fill-box;86    transform-origin: center;87    animation: sg-chart-radar-pulse-breathe var(--sg-duration) ease-in-out infinite;88  }89  .sg-chart-radar-pulse-dots circle {90    fill: var(--sg-color);91    transform-box: fill-box;92    transform-origin: center;93    animation: sg-chart-radar-pulse-ping var(--sg-duration) ease-in-out infinite;94  }95  .sg-chart-radar-pulse-dots circle:nth-of-type(2) { animation-delay: calc(var(--sg-duration) * 0.2); }96  .sg-chart-radar-pulse-dots circle:nth-of-type(3) { animation-delay: calc(var(--sg-duration) * 0.4); }97  .sg-chart-radar-pulse-dots circle:nth-of-type(4) { animation-delay: calc(var(--sg-duration) * 0.6); }98  .sg-chart-radar-pulse-dots circle:nth-of-type(5) { animation-delay: calc(var(--sg-duration) * 0.8); }99  .sg-chart-radar-pulse-labels text {100    font-size: 9px;101    fill: currentColor;102    opacity: 0.65;103    text-anchor: middle;104  }105  @keyframes sg-chart-radar-pulse-breathe {106    0%, 100% { transform: scale(1); fill-opacity: 0.3; }107    50%      { transform: scale(1.045); fill-opacity: 0.5; }108  }109  @keyframes sg-chart-radar-pulse-ping {110    0%, 55%, 100% { transform: scale(1); opacity: 1; }111    70%           { transform: scale(1.9); opacity: 0.4; }112    85%           { transform: scale(1); opacity: 1; }113  }114</style>115