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.0 KB · 73 lines html
Raw Blame History
1<!--2  ============================================================3  SVGarden — https://www.svgarden.dev4  Author : Simon-Pierre Boucher5  Contact: contact@spboucher.ai6  File   : snippets/gauges/gauge-semicircle.html7  Desc   : Speedometer-style semicircle gauge with a springy needle8  ============================================================9-->10<!--svgarden11title: Semicircle speedometer12slug: gauge-semicircle13category: gauges14tags: [gauge, speedometer, needle, css-only]15difficulty: advanced16techniques: [calc-with-custom-properties, dasharray-zones, rotate, cubic-bezier-overshoot]17how_it_works: >18  The needle's resting angle is computed entirely in CSS: rotate(calc(var(--sg-value)19  * 1.8deg − 90deg)) maps 0–100 onto the −90°…+90° sweep of the dial. On load a20  keyframe animation swings it from −90° to that computed angle with an21  overshooting cubic-bezier, like a real spring-loaded needle. The colored zones22  are three copies of the same arc path wearing different stroke-dasharray23  windows — dash segments as a poor man's conic gradient.24customizable:25  - { var: "--sg-color", label: "Needle", type: color, default: "#7F77DD" }26  - { var: "--sg-size",  label: "Size",   type: range, min: 100, max: 280, default: 170, unit: px }27  - { var: "--sg-value", label: "Value",  type: range, min: 0, max: 100, default: 72 }28created: 2026-08-1029-->30<div class="sg-gauge-semicircle" style="--sg-color:#7F77DD; --sg-size:170px; --sg-value:72;">31  <svg viewBox="0 0 100 62" role="img" aria-label="Speedometer gauge">32    <title>Speedometer gauge</title>33    <path class="sg-gauge-semicircle-zone1" d="M10 55 A40 40 0 0 1 90 55" pathLength="100" />34    <path class="sg-gauge-semicircle-zone2" d="M10 55 A40 40 0 0 1 90 55" pathLength="100" />35    <path class="sg-gauge-semicircle-zone3" d="M10 55 A40 40 0 0 1 90 55" pathLength="100" />36    <line class="sg-gauge-semicircle-needle" x1="50" y1="55" x2="50" y2="21" />37    <circle class="sg-gauge-semicircle-hub" cx="50" cy="55" r="4.5" />38  </svg>39</div>40<style>41  .sg-gauge-semicircle {42    width: var(--sg-size);43  }44  .sg-gauge-semicircle svg {45    display: block;46    width: 100%;47  }48  .sg-gauge-semicircle path {49    fill: none;50    stroke-width: 7;51    stroke-linecap: round;52  }53  .sg-gauge-semicircle-zone1 { stroke: #2ba05a; stroke-dasharray: 60 100; }54  .sg-gauge-semicircle-zone2 { stroke: #efbb33; stroke-dasharray: 0 60 25 100; }55  .sg-gauge-semicircle-zone3 { stroke: #d4553f; stroke-dasharray: 0 85 15 100; }56  .sg-gauge-semicircle-needle {57    stroke: var(--sg-color);58    stroke-width: 3;59    stroke-linecap: round;60    transform-box: view-box;61    transform-origin: 50px 55px;62    transform: rotate(calc(var(--sg-value) * 1.8deg - 90deg));63    animation: sg-gauge-semicircle-swing 1.2s cubic-bezier(0.3, 1.4, 0.5, 1);64  }65  .sg-gauge-semicircle-hub {66    fill: var(--sg-color);67  }68  @keyframes sg-gauge-semicircle-swing {69    from { transform: rotate(-90deg); }70    to   { transform: rotate(calc(var(--sg-value) * 1.8deg - 90deg)); }71  }72</style>73