Skip to content

How to set time according to svg length?

I am learning javascript and react and here I am stuck in the challange that where I have to set time according to SVG image’s length (something like progress bar).

For an ease and basic example, I am calculating total time of 24 hours in 1440 minutes and I have given passed time let passedMins = 1220

Now I need to fill the green line in svg circle according to the time elapse. Like every minute green line should add up more

import React, {
  useState,
  useEffect
} from 'react';

function Clock(props) {

  useEffect(() => {
    const circle = document.querySelector('circle');
    const circleLength = Math.floor(circle.getTotalLength());
    const perMinArea = circleLength / 1440;
    let passedMins = 1220;
    const fillArea = passedMins * perMinArea;
    circle.style.strokeDasharray = circleLength - fillArea;
    // circle.style.strokeDashoffset = circleLength -fillArea;

  }, [props.time])

  return (
    <div className = "clock-space" >
      <div className = "clock" >{props.time}</div>
      <svg width = "130" height = "130" className = "circle" viewBox = "0 0 130 130" fill = "none" xmlns = "http://www.w3.org/2000/svg">
        <circle cx="65" cy="65" r="61.5" stroke="lightgreen" strokeWidth="7"/>
      </svg>
    </div >
  );
}

export default Clock;

It looks like this:

Image of circle

It shows 3 lines where I want only one. Any suggestion to fix it?

Answer

You need to also pass the length of the circle to the circle.style.strokeDasharray. To do this, you need to get the length for the “minutes left” in terms of the circle’s total length. Please see example below.

const circle = document.querySelector('circle');
const timeLeftLabel = document.getElementById('time-left');
const circleLength = Math.floor(circle.getTotalLength());
const maxMinutes = 1440;
let passedMins = 1220;
let minsLeft = maxMinutes - passedMins;

// get percentage of minutes left
let minsLeftPercentage = minsLeft / maxMinutes;

// x % of length where x  = minsLeftPercentage
let leftLength = minsLeftPercentage * circleLength;

//combine leftLength and circleLength into comma-separated string
circle.style.strokeDasharray = leftLength + ',' + circleLength;

//just simple implementation for the {props.time} 
timeLeftLabel.innerText = minsLeft + ' minutes left';
<div className="clock-space">
  <div className="clock" id="time-left"></div>
  <svg width="130" height="130" className="circle" viewBox="0 0 130 130" fill="none" xmlns="http://www.w3.org/2000/svg">
        <circle cx="65" cy="65" r="61.5" stroke="lightgreen" strokeWidth="7"/>
      </svg>
</div>