Преобразование unix метки в процентное соотношение
Не могу решить задачку.
Есть функция time() и переменная $time.
К примеру unix метка на данный момент вот такое число 1608157239 а в переменной $time это же число только +3600.
Получается что переменная $time == 1608160839.
Потом я меняю значение переменной отнимая текущую unix метку:
$time = $time - time();
На выходе получаю динамическое число которое каждую секунду меньше на единицу и через 3600 секунд достигнет значение 0.
Так же есть HTML разметка:
<div class="progress">
<div class="progress-bar" style="width: 50%">
<span class="sr-only">50% Complete</span>
</div>
</div>
Задача:
Как вы видите в html разметки есть атрибут style и ширина в нем статическая.
Как преобразовать полученную динамическую переменную в проценты и подставить в верстку?
То есть на момент создание переменной которая равна 3600 в верстке должно быть значение width: 0%, а когда переменная $time достигнет 0 width должно равняться 100%.
Прошу помощи в реализации!
Ответы (2 шт):
Если период всегда 3600 секунд, то я не вижу смысла передавать переменную. В данном случае я использую анимацию CSS для изменения ширины (и 36 секунд), думаю что это оптимально и плавно. Что касается значений процентов то устанавливаю их через интервал и соответвенно видны рывки, но это можно поправить поиграв со значением интревала и инкрементом счетчика. Кнопки добавил исключительно для демонстрации - достаточно вызова соответсвующих функций.
const MAX_TIME = 36;
const resetBtn = document.querySelector('#reset');
const runBtn = document.querySelector('#run');
const progress = document.querySelector('.progress');
const sr = document.querySelector('.sr-only');
let intervalId = null;
progress.onanimationend = onAnimationEnd;
resetBtn.addEventListener('click', onReset, false);
runBtn.addEventListener('click', onRun, false);
resetBtn.disabled = true;
function onAnimationEnd () {
progress.classList.add('filled');
progress.classList.remove('runned');
runBtn.disabled = false;
}
function finish(){
clearInterval(intervalId);
runBtn.disabled = false;
resetBtn.disabled = true;
intervalId = null;
}
function onReset () {
if (intervalId) {
finish();
}
progress.classList.remove('runned');
progress.classList.remove('filled');
progress.classList.add('reseted');
sr.textContent = `0%`
}
function onRun () {
if (intervalId) return;
runBtn.disabled = true;
resetBtn.disabled = false;
let val = 0;
intervalId = setInterval(() => {
val += 1;
if (val === MAX_TIME) finish()
sr.textContent = `${Math.ceil(val * 100 / MAX_TIME )}%`
} ,1000)
progress.classList.remove('filled');
progress.classList.add('runned');
}
.progress {
z-index: 100;
background: red;
width: 0%;
}
.reseted {
width: 0%;
}
.filled {
width: 100%;
}
.runned {
animation: 36s run linear;
}
@keyframes run {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="progress">
<div class="progress-bar">
<span class="sr-only">0%</span>
</div>
</div>
<button id="reset">Reset</button>
<button id="run">Run</button>
</body>
</html>
На сколько я понял вас, какая-то операция работает на стороне сервера, она длится один час и вам нужно на клиент отдавать прогресс выполнения операции.
Так же, мне кажется, что сервер у вас на php (исправьте если ошибаюсь).
Начнем с простой математики. Если 0 соответствует 0%, а 3600 - 100%, можно посчитать, что
percent = n / (max - min) * 100
Таким образом min - время начала операции, max - время окончания операции (время начала + 1 час), n - время, прошедшее со времени начала.
// Важно заметить, что в js таймстамп содержит милисекунды, то есть число в 1000 раз больше
// const beginTimestamp = <?php echo $date * 1000; ?>;
const beginTimestamp = Date.now();
// Если изменить это число - прогрессбар будет двигатся быстрее/медленнее
const duration = 3600 * 1000;
const endTimestamp = beginTimestamp + duration;
const getPercentProgress = () => {
const now = Date.now();
const percent = (now - beginTimestamp) / (endTimestamp - beginTimestamp) * 100;
return Math.min(100, Math.max(0, percent)); // чтоб прогресс был в пределах 0..100
};
const progressBar = document.querySelector(".progress-bar");
const textLabel = document.querySelector(".sr-only");
setInterval(() => {
const progress = getPercentProgress();
progressBar.style.width = progress + "%";
textLabel.innerText = progress.toFixed(2) + "% Complete"; // 2 знака после точки
}, 100);
.progress-bar {
display: block;
height: 24px;
background-color: #da411d;
}
<div class="progress">
<div class="progress-bar" style="width: 50%">
<span class="sr-only">0% Complete</span>
</div>
</div>