Индикатор прогресса чтения на jQuery

Виджет, который содержит список статей, с индикатором прогресса чтения на SVG, CSS и jQuery.

Сложность

Мы создадим подобный индикатор прогресса чтения, но будем использовать SVG для анимации индикатора.

HTML разметка

В разметке нам понадобится два тега, первый <article> для контента, второй <aside> для предложенных статей

<div class="cd-articles">
   <article>
      <header>
         <img src="/img/img-1.png" alt="article image">
         <h1>20 Star Wars Secrets Revealed: From Leia’s ‘Cocaine Nail’ to the Ronald Reagan Connection</h1>
      </header>
      
      <p>
         Lorem ipsum dolor sit amet, consectetur adipisicing elit. Perferendis maxime id, sunt, eum sed blanditiis aliquid! Minus assumenda tempore perspiciatis, numquam est aliquam, quis molestias enim consequuntur suscipit similique cumque ut natus facilis laboriosam quidem, nesciunt quasi doloribus tenetur. Quas doloremque suscipit, molestias odit, et quasi? Quas hic numquam, vitae?
      </p>
      <!-- additional content here -->
   </article>
 
   <article>
      <!-- article content here -->
   </article>
 
   <!-- additional articles here -->
 
   <aside class="cd-read-more">
      <ul>
         <li>
            <a href="/index.html">
               <em>20 Star Wars Secrets Revealed</em>
               <b>by J. Morrison</b>
               <svg x="0px" y="0px" width="36px" height="36px" viewBox="0 0 36 36"><circle fill="none" stroke="#2a76e8" stroke-width="2" cx="18" cy="18" r="16" stroke-dasharray="100 100" stroke-dashoffset="100" transform="rotate(-90 18 18)"></circle></svg>
            </a>
         </li>
 
         <!-- additional links to articles -->
      </ul>
   </aside> <!-- .cd-read-more -->
</div> <!-- .cd-articles -->

Добавление CSS стилей

Элемент <aside> будет отображаться только на устройствах с большим экраном (от 1100px), зададим для него абсолютную позицию и зафиксируем в правом верхнем углу контейнера .cd-articles, чтобы он всегда был на виду при прокрутке.

@media only screen and (min-width: 1100px) {
  .cd-articles {
    position: relative;
    width: 970px;
    padding-right: 320px;
  }
}
 
.cd-read-more {
  /* hide on mobile */
  display: none;
}
@media only screen and (min-width: 1100px) {
  .cd-read-more {
    display: block;
    width: 290px;
    position: absolute;
    top: 3em;
    right: 0;
  }
  .cd-read-more.fixed {
    position: fixed;
    right: calc(50% - 485px);
  }
}

Чтобы создать эффект прогресса, нам понадобится два SVG атрибута - stroke-dasharray и stroke-dashoffset. Мы создадим круг в виде пунктирной линии, атрибут stroke-dasharray позволяет указать длину тире и пробелов пунктирной линии, атрибут stroke-dashoffset указывает точку отсчета. По умолчанию зададим параметры stroke-dasharray="100 100" и stroke-dashoffset="100" (где 100, окружность SVG круга). Таким образом, длинна тире и пробела равна окружности круга, для создания эффекта прогресса мы анимируем атрибут stroke-dashoffset от 100 до 1.

Обработка событий

На устройствах с большим разрешением экрана (от 1100px), мы связываем функции updateArticle() и updateSidebarPosition() с событиями прокрутки: первая функция проверяет какую статью читает пользователь и обновляет атрибут stroke-dashoffset для отображения прогресса, вторая функция, обновляет атрибут sidebar position. И наконец функция changeUrl() обновляет URL в соответствии с читаемой статьей.

function updateArticle() {
   var scrollTop = $(window).scrollTop();
 
   articles.each(function(){ //articles = $('.cd-articles').children('article');
      var article = $(this),
         articleSidebarLink = articleSidebarLinks.eq(article.index()).children('a'); //articleSidebarLinks = $('.cd-read-more').find('li')
 
      if( articleTop > scrollTop) { //articleTop = $(this).offset().top
         articleSidebarLink.removeClass('read reading');
      } else if( scrollTop >= articleTop && articleTop + articleHeight > scrollTop) { //articleHeight = $(this).outerHeight()
         var dashoffsetValue = svgCircleLength*( 1 - (scrollTop - articleTop)/articleHeight); //svgCircleLength = 100
         articleSidebarLink.addClass('reading').removeClass('read').find('circle').attr({ 'stroke-dashoffset': dashoffsetValue });
         changeUrl(articleSidebarLink.attr('href'));
      } else {
         articleSidebarLink.removeClass('reading').addClass('read');
      }
   });
}
 
function updateSidebarPosition() {
   var scrollTop = $(window).scrollTop();
 
   if( scrollTop < articlesWrapperTop) { //$('.cd-articles').offset().top
      aside.removeClass('fixed').attr('style', ''); //aside = $('.cd-read-more')
   } else if( scrollTop >= articlesWrapperTop && scrollTop < articlesWrapperTop + articlesWrapperHeight - windowHeight) { // articlesWrapperHeight = $('.cd-articles').outerHeight()
      aside.addClass('fixed').attr('style', '');
   } else {
      if( aside.hasClass('fixed') ) aside.removeClass('fixed').css('top', articlesWrapperHeight + articlePaddingTop - windowHeight + 'px');//articlePaddingTop = Number($('.cd-articles').children('article').eq(1).css('padding-top').replace('px', ''))
   }
}

ДЕМО СКАЧАТЬ Перевод статьи Reading Progress Indicator

 

Тэги: SVGindicator

Вход

Уважаемый пользователь! Мы обнаружили, что вы используете AdBlock и вынуждены скрыть часть материалов на нашем сайте. Siteacademy существует и развивается за счет доходов от рекламы. Просим внести наш сайт в список исключений или отключить Блокировщик рекламы на нашем сайте.