responsive gauge

by dgrebb

HTML

<h1>Fully responsive animated gauge</h1>

<div class="speed-gauge" data-speed-percentage="25">

  <svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">

    <defs>
        <linearGradient id="speed-range__gauge-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" stop-color="#5736cb"/>
          <stop offset="50%" stop-color="#aa2dc1"/>
          <stop offset="80%" stop-color="#d9003a"/>
        </linearGradient>
      </defs>
      <g>
        <path d="M16 84 A 47 47, 0, 1, 1, 84, 84" fill="none" stroke="#D3D3D3" stroke-dasharray="700 480" class="speed-range__gauge-gutter" vector-effect="non-scaling-stroke" />
        
        <path d="M16 84 A 47 47, 0, 1, 1, 84, 84" fill="none" stroke="url(#speed-range__gauge-gradient)" stroke-dasharray="0 500" class="speed-range__gauge-arc animate" vector-effect="non-scaling-stroke" />
      </g>

  </svg>

</div>

CSS

.speed-gauge {
  width: 100%;
  height: 400px;
  box-sizing: border-box;
  display: block;
}

.speed-gauge svg {
  width: 100%;
  display: block;
  border: 1px solid black;
  min-width: 100%;
  max-width: 100%;
  height: 100%;
}

.speed-range__gauge-gutter,
.speed-range__gauge-arc {
  stroke-width: 4;
}

.speed-range__gauge-arc {
  transition: .5s stroke-dasharray;
}

Babel + JSX

// set up selectors
const gutter = document.querySelector('.speed-range__gauge-gutter');
const gauge = document.querySelector('.speed-range__gauge-arc');
const gaugeContainer = document.querySelector('.speed-gauge');

// get the percentage to fill the gauge
const amount = Number(gaugeContainer.dataset.speedPercentage);

const calculateGauge = (amount) => {
	console.log('window adj');
  // get necessary style values
  const strokeStyles = window.getComputedStyle(gauge);
  const strokeWidth = Number( strokeStyles.getPropertyValue('stroke-width').replace('px', '') );
  const gaugeWidth = Number(gaugeContainer.offsetWidth - strokeWidth*2);
	const gutterLength = gaugeWidth * Math.PI;
  const gapLength = gutterLength * .25; // our gap is a 45 degree angle
  
  const gaugeAmount = Math.ceil( ( gutterLength - gapLength ) *  (amount  / 400 ) );
  //the below line is needed to calculate the percentage for internet explorer 11 and Edge
  //const gaugeAmount = Math.ceil( ( gutterLength - gapLength ) *  (amount  / 250 ) );
  
	gauge.style.strokeDasharray = `${gaugeAmount} ${gutterLength}`;
  gutter.style.strokeDasharray = gutterLength;
}

calculateGauge(amount);
window.addEventListener( 'resize', function(e) {
	calculateGauge(amount)
}, false );