HTML: как объединить несколько таймеров - PullRequest
1 голос
/ 04 мая 2020

Я строю таймер на основе пользовательских данных. Ниже показано, как должен работать код: Вводимые пользователем данные: Время включения: 30 с

Время выключения: 10 с

Количество подходов: 4

Количество упражнений в наборе: 5

Отдых между наборами: 30 с

С указанными выше пользовательскими вводами таймер сделает это: Working Timer

Надеюсь, это имеет смысл должен делать. В настоящее время я пытаюсь реализовать отдых между подходами. Кто-нибудь знает, как я мог сделать это с тем, как мой код в настоящее время? Кроме того, totalTime уже включает количество времени, которое оставшееся время между наборами будет добавлено, если это поможет.

var numsets = document.getElementById("userInput1");
var numex = document.getElementById("userInput2");
var numwork = document.getElementById("userInput3");
var numrest = document.getElementById("userInput4");
var numrestafterset = document.getElementById("userInput5");

var sets;
var OGtimeon;
var OGtimeoff;
var totalTime;
var timeRemaining;
var hasBeenStarted = false;  // Boolean value to test what time to use

var isTimeON = true;
var timeon;
var timeoff;
var timeonRemaining;
var timeoffRemaining;
var setsRemaining;
var OGsets;
var Prepare;
var OGExPS;
var OGTOASets;
var ExercisePS;
var RestAfterS;
var Intervals
var j = 0;
var ExercisesRemaining;
var RestRemaining;

// function sleep(milliseconds) { //function I found online to create a sleep function
//     const date = Date.now();
//     let currentDate = null;
//     do {
//       currentDate = Date.now();
//     } while (currentDate - date < milliseconds);
//   }

// function updateRest() {
//     if (RestAfterS > 0) {
//         interval3 = setInterval(RestCount, 1000);
//     }
//     else {
//         startTime();
//     }

// function RestCount() {
//     while (RestAfterS != 0) {
//         RestAfterS--;
//     }
//     j = 0;
// }

function updatePrep() {
    if  (hasBeenStarted == false) {
        Prepare = 5;
        interval2 = setInterval(PrepCount, 1000);
    }
    else {
        startTime();
    }
}


function PrepCount() {
    let seconds = parseFloat(Prepare) % 60;

    if (Prepare == 0) {
        clearInterval(interval2);
        startTime();
    }
    else {
        PWR.innerHTML = "Get Ready!";
        textarea.innerHTML = Prepare;
        console.log(Prepare);
        Prepare--;
    }
}



function startTime() {

    // Set values in code
    OGsets = numsets.value;
    OGtimeon = numwork.value;
    OGtimeoff = numrest.value;
    OGTOASets = numrestafterset.value;
    OGExPS = numex.value;
    

    timeon = (hasBeenStarted)? timeonRemaining : OGtimeon;
    timeoff = (hasBeenStarted)? timeoffRemaining : OGtimeoff;
    sets = (hasBeenStarted)? setsRemaining : OGsets;
    ExercisePS = (hasBeenStarted)? ExercisesRemaining : OGExPS;
    RestAfterS = (hasBeenStarted)? RestRemaining : OGTOASets;

    // How much time on timer
    // Var = (expression)? true : false this is basically an if statement
    totalTime = (hasBeenStarted)? timeRemaining : ((parseFloat(OGtimeon)*parseFloat(sets)*parseFloat(ExercisePS))+(parseFloat(OGTOASets)*(parseFloat(sets)-1))+(parseFloat(OGtimeoff)*(parseFloat(sets)*(parseFloat(ExercisePS)-1))));
    Intervals = ((parseFloat(sets)*parseFloat(ExercisePS))+((parseFloat(sets)-1))+((parseFloat(sets)*(parseFloat(ExercisePS)-1))));
    hasBeenStarted = true;
    

    // Start timer
    interval = setInterval(updateCountdown, 1000);
}



function updateCountdown() {
    IntervalsLeft.innerHTML = Intervals;
    setsLeft.innerHTML = sets;

    var minutes= Math.floor (parseFloat(totalTime) / 60);
    var seconds = parseFloat(totalTime) % 60;
    if (seconds < 10) {
        textareaRemaining.innerHTML = minutes + ":0" + seconds;
    } else {
        textareaRemaining.innerHTML = minutes + ":" + seconds;
    }

    // Update TimeON / Time OFF
    if(isTimeON){          
        PWR.innerHTML = "Work!";    
        textarea.innerHTML = timeon;
        timeon--;
        if(timeon == 0){
            isTimeON = false;
            timeon = OGtimeon;
            Intervals--;
            IntervalsLeft.innerHTML = Intervals;
        }
        
    }
    //BELOW IS THE AREA I AM STUCK ON

    else{
        
       textarea.innerHTML = timeoff;
       timeoff--;
       PWR.innerHTML = "Rest!";
       if(timeoff == 0){
            isTimeON = true;
            timeoff = OGtimeoff;
            j++;
            Intervals--;
            IntervalsLeft.innerHTML = Intervals;
            if (j == OGExPS) {
                sets--;
                //updateRest();
                j = 0;
            }
             
        }
    }
        if( totalTime == 0 ){
            clearTimeout(interval);
            hasBeenStarted = false;
            console.log(sets);
            sets--;
            setsLeft.innerHTML = sets;
            PWR.innerHTML = "OMG YOU'RE DONE";
        }
        totalTime--;    
    }


    

    function updateRest() {
        if (RestAfterS > 0) {
            interval3 = setInterval(RestCount, 5000);
        }
        else {
            startTime();
        }
    }
    
    function RestCount() {
        while (RestAfterS != 0) {
            RestAfterS--;
            PWR.innerHTML = "Set Rest!";
            textarea.innerHTML = RestAfterS;
        }
        j = 0;
        clearInterval(interval3);
    }




function stop(){
    timeRemaining = totalTime;
    timeonRemaining = timeon;
    timeoffRemaining = timeoff;
    RestRemaining = RestAfterS;
    ExercisesRemaining = OGExPS;
    setsRemaining = sets;
    clearTimeout(interval);
    // document.getElementById("Counter").innerHTML = j;
    

}
p {
    display: inline-flex;
    align-items: center;
}
label {
    float: left;
    display: block;
}
#userInput1 {
    display: flex;
    margin-bottom: 10px;
}

#userInput2 {
    display: flex;
    margin-bottom: 10px;
}

#userInput3 {
    display: flex;
    margin-bottom: 10px;
}

#userInput4 {
    display: flex;
    margin-bottom: 10px;
}

#userInput5 {
    display: flex;
    margin-bottom: 10px;
}

#Prepare {
    display: flex;
    margin-bottom: 10px;
}

#sets {
    display: flex;
    margin-bottom: 10px;
}

#timeon {
    display: flex;
    margin-bottom: 10px;
}

#timeoff {
    display: flex;
    margin-bottom: 10px;
}

#TotalTime {
    display: flex;
    margin-bottom: 10px;
}

#Counter {
    display: flex;
    margin-bottom: 10px;
}


input {
    height: 20px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-compatible" content="ie=edge" />
    <title>Document</title>
    <link rel="stylesheet" href="Countdown From Scratch.css" />
</head>
<script src="Countdown From Scratch.js" defer></script>
<body>
    <label>Number of Sets </label>    
    <input id="userInput1" type="numsets" value = "0"/>
    <label>Number of Exercises per Set </label>    
    <input id="userInput2" type="numex" value = "0"/>
    <label>Time to Work </label>
    <input id="userInput3" type="numwork" value = "0"/>
    <label>Time to Rest </label>
    <input id="userInput4" type="numrest" value = "0"/>
    <label>Time Inbetween Sets </label>
    <input id="userInput5" type="numrestafterset" value = "0"/>   

    <p id="Prepare"></p>
    <div id="sets"> </div>
    <div id="timeon"> </div>
    <div id="timeoff"> </div>
    <div id="TotalTime"> </div>
    <textarea id="textarea" placeholder="00:00"></textarea>
    <textarea id="PWR" placeholder="Hello!"></textarea>
    <textarea id="textareaRemaining" placeholder="00:00"></textarea>
    <textarea id="setsLeft" placeholder="00"></textarea>
    <textarea id="IntervalsLeft" placeholder="00"></textarea>

    
    <button onclick="updatePrep()">Start time</button>
    <button onclick="stop()">Stop time</button>


</body>
</html>

1 Ответ

2 голосов
/ 04 мая 2020

Я думаю, что у меня есть приблизительное представление о том, чего вы пытаетесь достичь sh здесь, но, пожалуйста, дайте мне знать, если я что-то неправильно истолковал.

Предположим, вы хотите выполнить последовательность эффектов с некоторыми продолжительность между ними. Чтобы сохранить небольшой пример, мы будем использовать console.log в качестве замены для любого эффекта, который вы хотите выполнить (например, установка innerHTML элемента DOM).

Как В первом примере мы ждем 1 секунду, отображаем «Hello», затем ждем 1,5 секунды и отображаем «There»:

setTimeout(() => {
  console.log('Hello');
  setTimeout(() => {
    console.log('There');
  }, 1500);
}, 1000);

Мы можем уточнить это, описав общие части как функцию:

function logAfter(message, delay, callback) {
  setTimeout(() => {
    console.log(message);
    if (callback) callback();
  }, delay);
}

Тогда наш пример можно записать в виде:

logAfter('Hello', 1000, () => {
  logAfter('There', 1500);
});

В качестве другого примера, который, возможно, более актуален для вашего проекта, вот как мы можем создать «l oop», который выполняет эффект несколько раз:

function logNAfter(message, times, delay, callback) {
  if (times === 0 && callback) {
    callback();
  }
  else {
    setTimeout(() => {
      console.log(message);
      logNAfter(message, times-1, delay, callback);
    }, delay);
  }
}

Мы могли бы использовать это для отображения «Привет!» 3 раза, каждый разделенный на полсекунды, а затем отобразить «До свидания!» один раз, 2 секунды спустя:

logNAfter('Hi There!', 3, 500, () => {
  logAfter('Goodbye!', 2000);
});

Теоретически вы можете создать произвольно длинную последовательность соответствующим образом распределенных эффектов таким образом. Однако я должен также упомянуть, что многие предпочли бы описать эти эффекты как Promise s вместо:

function logAfter(message, delay) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(message);
      resolve();
    }, delay);
  });
}

function logNAfter(message, times, delay) {
  if (times === 0) {
    return Promise.resolve();
  } else {
    return logAfter(message, delay)
      .then(() => logNAfter(message, times-1, delay));
  }
}

Первоначальными примерами стали:

logAfter('Hello', 1000)
  .then(() => logAfter('There', 1500));

logNAfter('Hi There!', 3, 500)
  .then(() => logAfter('Goodbye!', 2000));

Возможно, это лишь небольшое улучшение по сравнению с подходом в стиле обратного вызова, описанным выше, но гораздо понятнее, если вы сможете использовать async/await:

async function logAfter(message, delay) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(message);
      resolve();
    }, delay);
  });
}

async function logNAfter(message, times, delay) {
  for (let i = 0; i < times; ++i) {
    await logAfter(message, delay);
  }
}

async function demoSequence1() {
  await logAfter('Hello', 1000);
  await logAfter('There', 1500);
}

async function demoSequence2() {
  await logNAfter('Hi There!', 3, 500);
  await logAfter('Goodbye!', 2000);
}

Надеюсь, что это поможет!

...