SVG - Percent Ring

From NoskeWiki
Jump to navigation Jump to search
Percent ring using JavaScript and SVG

About

NOTE: This page is a daughter page of: SVG and JavaScript


Percentage or progress rings look pretty sexy, but it's a little tricky (not impossible) to do a ring in pure CSS.... so here's a nice solution using Scalable Vector Graphics (SVG) and JavaScript.


Percent Ring with SVG and JavaScript

<!doctype html>
<!--
  BIG ACKNOWLEDGMENT:
  This expands on the great example from:
  https://css-tricks.com/building-progress-ring-quickly/
!-->
<html>
<head>
<meta charset="UTF-8">
<title>Progress Ring Demo</title>
  
  <script>
  /**
   * Sets the value of a SVG percent ring.
   * @param {number} percent The percent value to set.
   */
  function setPercentRing(percent) {
    var svg = document.getElementById('id-percent-ring-1');
    console.log(svg);

    var circle = svg.querySelector('circle');
    var radius = circle.r.baseVal.value;
    var circumference = radius * 2 * Math.PI;
    circle.style.strokeDasharray = `${circumference} ${circumference}`;
    circle.style.strokeDashoffset = `${circumference}`;

    const offset = circumference - percent / 100 * circumference;
    circle.style.strokeDashoffset = -offset;  // Set to positive for clockwise.

    var text = svg.querySelector('text');
    text.textContent = String(percent) + '%';
  }
  </script>
  
  <style>
  .big-button {
    background-color: #4CAF50; /* Green */
    border: none;
    color: white;
    text-align: center;
    text-decoration: none;
    font-size: 16px;
  }
  .percent-ring {
  }
  .percent-ring-circle {
    transition: 0.35s stroke-dashoffset;
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
  }    
  .circle-percent-text {
    font-weight: bold;
    font-family: "Segoe UI", Arial, sans-serif;
  }    
  </style>
  
</head>

<body>

<button type="button" class="big-button" onclick="setPercentRing(Math.round(Math.random() * 100));">Randomize</button>

<svg
  id="id-percent-ring-1"
  class="percent-ring"
  width="100%"
  height="220">
  <circle
    class="percent-ring-circle"
    stroke="forestgreen"
    stroke-width="15"
    fill="transparent"
    r="90"    // Set radius slightly less than height/2.
    cx="50%"
    cy="50%">
  </circle>  
  <text
    x="50%"
    y="50%"
    dominant-baseline="middle"
    text-anchor="middle"
    font-size="60px"
    class="circle-percent-text"  // You can also set text properties in CSS (or a mix).
    fill="forestgreen">0%</text>
</svg>
  
  
<svg
  id="id-circle-1"
  width="200"
  height="100">
  
  // Add a circle in the middle:
  <circle
    stroke="rgba(255.0,0,0,0.3)"
    stroke-width="15"
    fill="transparent"
    r="40"    // We set radius slightly less than height/2.
    cx="50%" cy="50%">
  </circle>
  
  // Make a rectangle and move it to the middle and rotate it:
  <rect
    width="60" height="10"
    x="0" y="0"
    rx="3" ry="3"  // Rounded edges. 
    // Translate it to the middle of the circle
    // then rotate about the middle:
    transform="translate(70, 45) rotate(45, 30, 5)"
    style="fill:rgba(255,0,0,0.3); stroke-width:1; stroke:rgba(255,0,0,1.0)">
  </rect>
  
  // Let's center text in the middle:
  <text
    x="50%" y="50%"
    dominant-baseline="middle" text-anchor="middle"
    font-size="30px" fill="#333333"
    class="circle-percent-text"  // You can also use CSS (or a mix).
    >SVG Rocks!</text>
  
  // Now create a poly line with the M (move to) command.
  // Note that lower case is for relative (l = line),
  // and uppercase would be for an absolute position.
  <path id="lineAB" d="M 0 80 l 30 15 30 -15" stroke="red"
  stroke-width="5" fill="none" />
  
  // Now create a curved Bézier path:
  // M (start_x start_y) q (rel_curve_target_x rel_curve_target_y rel_end_x rel_end_y).
  <path d="M 140 80 q 15 20 30 0 q 15 -20 30 0" stroke="blue" stroke-width="5" fill="#0000ff33"/>
</svg>

</body>
</html>


Links