Перемещайте полосу прокрутки, прокручивая страницу

Взгляните на следующий код:

 function getScrollPercent() {
            const h = document.documentElement;
            const st = 'scrollTop';
            const sh = 'scrollHeight';
            const clientHeight = h.clientHeight;
            const scrollTop = h[st];
            const scrollHeight = h[sh];

            return scrollTop / (scrollHeight - clientHeight) * 100;
        }

        function update_scroll() {
            const scrollPercent = getScrollPercent();

            document.getElementById("scroll-line").style.height = `${scrollPercent}%`;
            document.getElementById("progress").textContent = Math.round(scrollPercent) + '%';
        }

        window.addEventListener('scroll', update_scroll);
        update_scroll();
 .content-site {
        height: 500vh;
    }

    #main_box {
        position: fixed;
        right: 50px;
        bottom: 80px;
    }

    #body_box {
        width: 100px;
        height: 100px;
        background: #b0ffcb;
        box-shadow: 0 0 4px #050030;
        border-radius: 50% !important;
        position: relative;
        overflow: hidden;
    }

    #progress {
        position: absolute;
        top: 40%;
        left: auto;
        z-index: 3;
        color: #f00;
        display: block;
        margin: 0 auto;
        width: 100%;
        text-align: center;
    }

    #scroll-line {
        width: 100%;
        position: absolute;
        top: 0;
        left: 0;
        border-radius: 50%;
        z-index: 2;
        background-color: #050030;
    }
    
    
    <div class = "content-site"></div>
  
  <footer>
        <div id = "main_box">
            <div id = "body_box">
                <div id = "scroll-line"></div>
                <p id = "progress"></p>
            </div>
        </div>
    </footer>

Как видите, я реализовал индикатор выполнения, который меняет состояние в зависимости от положения прокрутки страницы.

Теперь вместо изменения цвета фона элемента при прокрутке я хочу создать вокруг элемента кольцо прогресса, которое меняет свое состояние при прокрутке страницы.

Вот пример того, что я ищу:

https://codepen.io/christianmair/pen/dLVbze

Проблема с приведенным выше примером заключается в том, что он использует SVG, что делает код очень сложным.

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

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Более простое решение с SVG.

function getScrollPercent() {
  const h = document.documentElement;
  const st = 'scrollTop';
  const sh = 'scrollHeight';
  const clientHeight = h.clientHeight;
  const scrollTop = h[st];
  const scrollHeight = h[sh];
  return scrollTop / (scrollHeight - clientHeight) * 100;
}

function update_scroll() {
  const scrollPercent = getScrollPercent();
  const circle = document.querySelector('.progress-ring__circle');
  const radius = circle.r.baseVal.value;
  const circumference = 2 * Math.PI * radius;
  const offset = circumference - scrollPercent / 100 * circumference;
  circle.style.strokeDashoffset = offset;
  document.getElementById("progress").textContent = Math.round(scrollPercent) + '%';
}
window.addEventListener('scroll', update_scroll);
update_scroll();
.content-site {
  height: 500vh;
}

#main_box {
  position: fixed;
  right: 50px;
  bottom: 80px;
}

#body_box {
  width: 100px;
  height: 100px;
  background: #b0ffcb;
  box-shadow: 0 0 4px #050030;
  border-radius: 50% !important;
  position: relative;
  overflow: hidden;
}

#progress {
  position: absolute;
  top: 40%;
  left: auto;
  z-index: 3;
  color: #f00;
  display: block;
  margin: 0 auto;
  width: 100%;
  text-align: center;
}

.progress-ring__circle {
  fill: none;
  stroke: #050030;
  stroke-width: 8;
  stroke-dasharray: 265;
}

.progress-ring__background {
  fill: none;
  stroke: #b0ffcb;
  stroke-width: 8;
}

.progress-ring__circle,
.progress-ring__background {
  stroke-linecap: round;
}
<div class = "content-site"></div>

<footer>
  <div id = "main_box">
    <div id = "body_box">
      <svg class = "progress-ring" width = "100" height = "100">
                <circle class = "progress-ring__background" cx = "50" cy = "50" r = "42"></circle>
                <circle class = "progress-ring__circle" cx = "50" cy = "50" r = "42"></circle>
            </svg>
      <div id = "progress"></div>
    </div>
  </div>
</footer>

ОП хочет сделать это без SVG.

Parking Master 16.04.2024 02:36

@ParkingMaster Верно, но они сказали так, потому что это сложно. Я попробовал сделать простой вариант. В этом-то и дело.

Ghost 16.04.2024 03:38

Ох, я не дочитал :D

Parking Master 16.04.2024 06:08
Ответ принят как подходящий

Попробуйте conic-gradient и добавьте меньший круг, цвет фона которого такой же, как у #body_box.

background: conic-gradient(black 0deg, black calc(360deg * var(--scrollPercent)), transparent calc(360deg * var(--scrollPercent)), transparent 360deg);

function getScrollPercent() {
  const { clientHeight, scrollTop, scrollHeight } = document.documentElement;
  return scrollTop / (scrollHeight - clientHeight);
}

function update_scroll() {
  const scrollPercent = getScrollPercent();

  document.getElementById("scroll-line").style.setProperty("--scrollPercent", scrollPercent);
  document.getElementById("progress").textContent = Math.round(scrollPercent * 100) + "%";
}

window.addEventListener("scroll", update_scroll);
update_scroll();
.content-site {
  height: 500vh;
}

#main_box {
  position: fixed;
  right: 50px;
  bottom: 80px;
}

#body_box {
  --bg: #b0ffcb;
  width: 100px;
  height: 100px;
  background: var(--bg);
  box-shadow: 0 0 4px #050030;
  border-radius: 50% !important;
  position: relative;
  overflow: hidden;
}

#progress {
  position: absolute;
  top: 40%;
  left: auto;
  z-index: 3;
  color: #f00;
  display: block;
  margin: 0 auto;
  width: 100%;
  text-align: center;
}

#scroll-line {
  --scrollPercent: 0;
  width: 100%;
  z-index: 2;
  background: conic-gradient(black 0deg, black calc(360deg * var(--scrollPercent)), transparent calc(360deg * var(--scrollPercent)), transparent 360deg);
}

#scroll-line::before {
  content: "";
  display: block;
  width: calc(100% - 15px);
  background: var(--bg);
}

#scroll-line,
#scroll-line::before {
  aspect-ratio: 1;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
<div class = "content-site"></div>
<footer>
  <div id = "main_box">
    <div id = "body_box">
      <div id = "scroll-line"></div>
      <p id = "progress"></p>
    </div>
  </div>
</footer>

Спасибо. Это именно то, что я хотел, просто и практично.

Wp-PHP 16.04.2024 05:59

Другие вопросы по теме

Можно ли надежно внедрить кликабельное изображение или кнопку поверх элемента с помощью JavaScript?
Делаем задержку анимации, сделанной с помощью Animate css
Максимальная ширина не работает в электронной почте в формате html при доступе к Gmail из мобильного браузера?
Как иметь горизонтальную полосу прокрутки в таблице и вертикальную полосу прокрутки на основной странице, а также использовать фиксированную позицию для заголовка таблицы html?
Как избежать мерцания в слайд-шоу, созданном с помощью CSS-анимации?
Адаптивное изображение с текстом на любой ширине экрана
CSS 3: наложение изображения при наведении
Используя только CSS, есть ли способ ограничить текст внутри div ровно X количеством символов без использования многоточия?
Форма HTML/PHP внезапно перестала работать без изменения кода
Использование `text-overflow: ellipsis` в адаптивной таблице с динамической шириной?