Круговой таймер

by AJIEKCEU

HTML

<div class="apm-db-bonus-experience apm-db-bonus__experience"><h3 class="apm-db-bonus-experience__title">
                        Отыгрыш: 1750 RUB
                    </h3> <svg width="0" height="0" class="apm-db-bonus-experience__gradient">
                    <linearGradient id="linear-gradient" x1y2="50%" gradientUnits="userSpaceOnUse"><stop stop-color="hsl(28, 99%, 53%)"></stop> <stop offset="1" stop-color="hsl(28, 93%, 41%)"></stop></linearGradient></svg> <div id="bonus_experience_474067217" data-val="40" data-max-val="1750"><div class="apm-db-bonus-experience__circle"><svg xmlns="http://www.w3.org/2000/svg" width="80" height="80"><path fill="transparent" stroke="hsl(223, 16%, 22%)" stroke-width="11" d="M 39.99297327447252 5.500000715577855 A 34.5 34.5 0 1 1 39.95208019213653 5.500033279841929 Z" class="circles-maxValueStroke"></path><path fill="transparent" stroke="url(#linear-gradient)" stroke-width="11" d="M 39.99297327447252 5.500000715577855 A 34.5 34.5 0 0 1 44.90974788795331 5.851143859907431 " class="circles-valueStroke"></path></svg><div class="apm-db-bonus-experience__text">40</div></div></div></div>

SCSS

.kjoker-time {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 63px;
  height: 63px;
  &__label {
    position: relative;
    font-size: 18px;
    color: #fff;
    z-index: 50;
  }
  &__svg {
    --stroke-offset: 0;
    position: absolute;
    width: 63px;
    height: 63px;
  }
  
  &__bg {
    fill: #122A70;
  }
  
  &__stroke {
    stroke: url(#stroke-gradient_1);
    stroke-width: 5px;
    stroke-dasharray: 181 181;
    stroke-dashoffset: var(--stroke-offset);
    stroke-linecap: round;
    transition: 1s linear all;
  }
  
  &__border {
    stroke: url(#stroke-gradient_2);
    stroke-opacity: .2;
    stroke-width: 5px;
    stroke-linecap: round;
  }
  
  &__circle {
    fill: #fff;
    // 1.98 = 360deg / 181 (max-dashoffset)
    transform: rotate(calc(var(--stroke-offset) * (-1.98deg)));
    transform-origin: 50% 50%;
    transition: 1s linear all;
  }
}

JavaScript

// Credit: Mateusz Rybczonec

const FULL_DASH_ARRAY = 181;

const TIME_LIMIT = 10;
let timePassed = 0;
let timeLeft = TIME_LIMIT;
let timerInterval = null;


document.getElementsByClassName("kjoker-time__label")[0].innerHTML = `
  ${formatTime(timeLeft)}
`;

startTimer();

function onTimesUp() {
  clearInterval(timerInterval);
}

function startTimer() {
  timerInterval = setInterval(() => {
    timePassed = timePassed += 1;
    timeLeft = TIME_LIMIT - timePassed;
    document.getElementsByClassName("kjoker-time__label")[0].innerHTML = formatTime(timeLeft);
    setCircleDasharray();
    
    (timeLeft);

    if (timeLeft === 0) {
      onTimesUp();
    }
  }, 1000);
}

function formatTime(time) {
  const minutes = Math.floor(time / 60);
  let seconds = time % 60;
	
  if (seconds < 10) {
    seconds = `0${seconds}`;
  }

  return `${minutes}:${seconds}`;
}

function calculateTimeFraction() {
  const rawTimeFraction = (timeLeft - 1) / (TIME_LIMIT - 1);
  return FULL_DASH_ARRAY - FULL_DASH_ARRAY * (rawTimeFraction);
}

function setCircleDasharray() {
	let pos = (calculateTimeFraction()).toFixed(0);
  
  if(pos >= FULL_DASH_ARRAY){
  	pos = FULL_DASH_ARRAY;
  }

 document.getElementsByClassName("kjoker-time__stroke")[0].style.setProperty('--stroke-offset', -pos);
 document.getElementsByClassName("kjoker-time__circle")[0].style.setProperty('--stroke-offset', -pos);
}