Индикатор выполнения CSS, о котором вы не знали

HTML CSS
Индикатор выполнения CSS, о котором вы не знали
  • Автор: Чен большая голова
  • гитхаб:KRISACHAN

Индикатор выполнения — очень распространенная функция, ее несложно реализовать, обычно мы будем использоватьdivреализовать.

Как такое общее требование,whatwgНативного компонента точно не предусмотрено (хотя мы можем его и не использовать), так что давайте посмотрим, какие интересные реализации прогресс-бара есть у Kangkang.

Обычная версия — div flow

Это более обычная реализация, сначала посмотрите на эффект:

Исходный код выглядит следующим образом:

<style>
  .progress1 {
    height: 20px;
    width: 300px;
    background-color: #f5f5f5;
    border-bottom-right-radius: 10px;
    border-top-right-radius: 10px;
  }
  .progress1::before {
    counter-reset: progress var(--percent, 0);
    content: counter(progress) '%\2002';
    display: block;
    height: 20px;
    line-height: 20px;
    width: calc(300px * var(--percent, 0) / 100);
    font-size: 12px;
    color: #fff;
    background-color: #2486ff;
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    border-bottom-right-radius: 10px;
    border-top-right-radius: 10px;
  }
  .btn {
    margin-top: 30px;
  }
</style>
<div id="progress1" class="progress1"></div>
<button id="btn" class="btn">点我一下嘛~</button>
<script>
  'use strict';
  let startTimestamp = (new Date()).getTime();
  let currentPercentage = 0;
  let maxPercentage = 100;
  let countDelay = 100;
  let timer = null;
  let start = false;
  const percentageChange = () => {
    const currentTimestamp = (new Date()).getTime();
    if (currentTimestamp - startTimestamp >= countDelay) {
      currentPercentage++;
      startTimestamp = (new Date()).getTime();
      progress1.style = `--percent: ${currentPercentage}`;
    };
    if (currentPercentage < maxPercentage) {
      timer = window.requestAnimationFrame(percentageChange);
    } else {
      window.cancelAnimationFrame(timer);
    };
  };
  const clickHander = () => {
    if (!start) {
      start = true;
      percentageChange();
    };
  };
  btn.addEventListener('click', clickHander);
</script>

Суть этого метода заключается в использовании текущего блока в качестве контейнера для::beforeНаполните его содержанием. использовать<div>Преимущество в том, что реализация проста, совместимость надежна и масштабируемость высока, но ложка дегтя в том, что семантика меток не сильна.

Дополнительно — тип ввода="диапазон"

<input />очень полезный сменный элемент, отличающийсяtypeможет делать разные вещи. Второй заключается в использовании<input type="range" />быть реализованным. Сначала давайте посмотрим на эффект:

Исходный код выглядит следующим образом:

<style>
  .progress2[type='range'] {
    display: block;	
    font: inherit;
    height: 20px;
    width: 300px;
    pointer-events: none;
    background-color: linear-gradient(to right, #2376b7 100%, #FFF 0%);
  }
  .progress2[type='range'],
  .progress2[type='range']::-webkit-slider-thumb { 
    -webkit-appearance: none;
  };
  .progress2[type='range']::-webkit-slider-runnable-track {
    border: none;
    border-bottom-right-radius: 10px;
    border-top-right-radius: 10px;
    height: 20px;
    width: 300px;
  }
  .btn {
    margin-top: 30px;
  }
</style>
<input id="progress2" class="progress2" type='range' step="1" min="0" max="100" value="0"/>
<button id="btn" class="btn">点我一下嘛~</button>
<script>
  'use strict';
  let startTimestamp = (new Date()).getTime();
  let currentPercentage = 0;
  let maxPercentage = 100;
  let countDelay = 100;
  let timer = null;
  let start = false;
  let percentageGap = 10;
  const percentageChange = () => {
    const currentTimestamp = (new Date()).getTime();
    if (currentTimestamp - startTimestamp >= countDelay) {
      currentPercentage++;
      startTimestamp = (new Date()).getTime();
      progress2.value = currentPercentage;
      progress2.style.background = `linear-gradient(to right, #2376b7 ${currentPercentage}%, #FFF 0%`;
    };
    if (currentPercentage < maxPercentage) {
      timer = window.requestAnimationFrame(percentageChange);
    } else {
      window.cancelAnimationFrame(timer);
    };
  };
  const clickHander = () => {
    if (!start) {
      start = true;
      percentageChange();
    };
  };
  btn.addEventListener('click', clickHander);
</script>

После написания этой демонстрации я узнал,<input type="range" />Не подходит для этой функции. . Одной из них является сложность реализации, этоtypeКаждый элемент компонента можно стилизовать индивидуально, но эффект будет не очень.

Другое дело, потому чтоrangeУ него есть своя семантика — область видимости, поэтому он больше подходит для того, чтобы делать что-то вроде этого:

Выше демо из:developer.Mozilla.org/en-US/docs/…

Премиум - утка прогресса

Конечно, вышеперечисленные два способа имитируют индикатор выполнения, на самом деле нам не нужно имитировать, потому чтоwhatwgДля нас предусмотрены собственные метки индикатора выполнения -<progress>.

Давайте сначала посмотрим на эффект:

Реализация выглядит следующим образом:

<style>
  .progress3 {
    height: 20px;
    width: 300px;
    -webkit-appearance: none;
    display: block;
  }
  .progress3::-webkit-progress-value {
    background: linear-gradient(
      -45deg, 
      transparent 33%, 
      rgba(0, 0, 0, .1) 33%, 
      rgba(0,0, 0, .1) 66%, 
      transparent 66%
    ),
      linear-gradient(
        to top, 
        rgba(255, 255, 255, .25), 
        rgba(0, 0, 0, .25)
      ),
      linear-gradient(
        to left,
        #09c,
        #f44);
    border-radius: 2px; 
    background-size: 35px 20px, 100% 100%, 100% 100%;
  }
  .btn {
    margin-top: 30px;
  }
</style>
<progress id="progress3" class="progress3" max="100" value="0"></progress>
<button id="btn" class="btn">点我一下嘛~</button>
<script>
  'use strict';
  let startTimestamp = (new Date()).getTime();
  let currentPercentage = 0;
  let maxPercentage = 100;
  let countDelay = 100;
  let timer = null;
  let start = false;
  const percentageChange = () => {
    const currentTimestamp = (new Date()).getTime();
    if (currentTimestamp - startTimestamp >= countDelay) {
      currentPercentage++;
      startTimestamp = (new Date()).getTime();
      progress3.setAttribute('value', currentPercentage);
    };
    if (currentPercentage < maxPercentage) {
      timer = window.requestAnimationFrame(percentageChange);
    } else {
      window.cancelAnimationFrame(timer);
    };
  };
  const clickHander = () => {
    if (!start) {
      start = true;
      percentageChange();
    };
  };
  btn.addEventListener('click', clickHander);
</script>

Нативная метка прогресс-бара хоть и есть, но конкретная ее производительность в спецификации не указана, поэтому каждый производитель браузера может настроить ее под свои предпочтения, а стиль совершенно неуправляемый, так что метка хорошая. . Юзабилити не сильное, а жаль.

Ultimate Edition — метр сайго

Конечно, метки, способные реализовать функцию индикатора выполнения, помимо вышеперечисленных, также существуют.<meter>Этикетка. Первый взгляд на эффект:

код показывает, как показано ниже:

<style>
  .progress4 {
    display: block;	
    font: inherit;
    height: 50px;
    width: 300px;
    pointer-events: none;
  }
  .btn {
    margin-top: 30px;
  }
</style>
<meter id="progress4" class="progress4" low="60" high="80" min="0" max="100" value="0"></meter>
<button id="btn" class="btn">点我一下嘛~</button>
<script>
  'use strict';
  let startTimestamp = (new Date()).getTime();
  let currentPercentage = 0;
  let maxPercentage = 100;
  let countDelay = 100;
  let timer = null;
  let start = false;
  const percentageChange = () => {
    const currentTimestamp = (new Date()).getTime();
    if (currentTimestamp - startTimestamp >= countDelay) {
      currentPercentage++;
      startTimestamp = (new Date()).getTime();
      progress4.value = currentPercentage;
    };
    if (currentPercentage < maxPercentage) {
      timer = window.requestAnimationFrame(percentageChange);
    } else {
      window.cancelAnimationFrame(timer);
    };
  };
  const clickHander = () => {
    if (!start) {
      start = true;
      percentageChange();
    };
  };
  btn.addEventListener('click', clickHander);
</script>

Этот ярлык может быть незнакомым, на самом деле он связан с<input type="range">Семантика та же и используется для отображения скалярных или дробных значений известного диапазона. Разница в том. . . Со стилем сложнее.

Суммировать

В этой статье оцениваются 4 способа реализации индикатора выполнения, и вывод таков:<div>Пик сезона. . . Хотя иногда хочется провести семантику лейблов чуть изящнее, но ресурсы это не поддерживают, и это тоже очень смущает.

о, всемогущий<div>.

Все приведенные выше демонстрации можно посмотреть на моей кодовой ручке:код спрей.IO/Антияпонское производство 77/…