У меня есть этот код с CSS-анимацией:
@keyframes progress-bar {
0% {
width: 0;
}
50% {
width: 100%;
}
100% {
width: 0;
}
}
.box {
position: relative;
height: 3px;
margin-top: 20px;
background: transparent;
}
.line {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 100%;
background: red;
-webkit-animation: progress-bar 6s ease-in infinite alternate forwards;
animation: progress-bar 6s ease-in infinite alternate forwards;
}<div class = "box">
<div class = "line"></div>
</div>Это пример ссылки на коды и ящик: ссылка
Это позволяет мне бесконечно заполнять div.line за три секунды, а затем снова скрывать ее ширину за три секунды.
Я хочу реализовать в Vanila JS ту же функциональность, используя setInterval. Я понимаю, что мне нужно использовать setInterval, цикл и получить ширину, используя clientwidth. Но все мои попытки либо сразу очищают setInterval, либо не работают. Помогите пожалуйста найти оптимальное решение, спасибо.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вот версия JS — нам все еще нужно НЕКОТОРОЕ CSS.
Я просто УСТАНАВЛИВАЮ ширину и использую пару тройных чисел, чтобы увеличивать или уменьшать ее.
const line = document.querySelector('.line');
let width = 0;
let growing = true;
const intervalDuration = 30;
const totalDuration = 6000; // total duration of the animation in milliseconds
const maxSteps = totalDuration / intervalDuration; // number of steps in the animation cycle
const increment = 100 / maxSteps; // calculate increment once
const interval = setInterval(() => {
// Increment or decrement the width based on the growing state
width += growing ? increment : -increment;
// Switch direction if limits are reached
growing = (growing && width >= 100) || (!growing && width <= 0) ? !growing : growing;
line.style.width = `${width}%`;
}, intervalDuration);.box {
position: relative;
height: 3px;
margin-top: 20px;
background: transparent;
}
.line {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 100%;
background: red;
}<div class = "box">
<div class = "line"></div>
</div>30 миллисекунд — хорошее число для примерно 30 кадров в секунду. Я получил 6 секунд из вашей CSS-анимации. totalDuration/intervalDuration показывает, сколько шагов нам нужно, чтобы разделить 100%-ную длину. Но спасибо за указание, я изменил код, чтобы использовать 100/maxSteps для задания приращения/уменьшения.
Вы также можете использовать другую альтернативу с переменной CSS и JavaScript, как показано ниже. Если вы хотите достичь 100% с 0% за 3 секунды, вам нужно установить интервал 30 мс.
const line = document.querySelector('.line')
const root = document.querySelector(':root')
let lineWidth = 0
let increment = true
function incrementWidth(){
if (lineWidth<100 && increment){
lineWidth+=1
root.style.setProperty("--width", `${lineWidth}%`)
if (lineWidth===100){
increment=false
}
}
if (lineWidth > 0 && !increment){
lineWidth-=1
root.style.setProperty("--width", `${lineWidth}%`)
if (lineWidth===0){ increment=true}
}
}
let interval_ID = setInterval(()=>{
incrementWidth()
},30)
:root{
--width: 0%;
}
.box {
position: relative;
height: 3px;
margin-top: 20px;
background: transparent;
}
.line {
position: absolute;
top: 0;
left: 0;
width: var(--width);
height: 100%;
background: red;
} <div class = "box">
<div class = "line"></div>
</div>Привет Чувак! Удивительно и легко – молодец! Я до сих пор не могу понять, почему вы выбираете шаг 30 мс?
@yanballas, спасибо и добро пожаловать! 30 мс — это время, необходимое для достижения шага в 1 % на индикаторе выполнения из 100 %, чтобы вы достигли 100 % за 100 * 30 мс = 3000 мс = 3 с, как вы и хотели. Наслаждайтесь кодированием!
Привет! Действительно хорошее решение! Можете ли вы объяснить мне больше о интервалеDuration и maxSteps? Почему вы выбрали 30 и что означает maxSteps? Спасибо!