Анимация индикатора выполнения в виде пунктирной линии

Я создаю компонент индикатора прогресса/объема с помощью Angular/Tailwind, где процентные приращения представляют собой цветные круги. Все серые кружки означают 0%, все синие — 100%, 10 из 20 — 50% и т. д.

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

Я экспериментировал с clip-path, пытаясь создать серию «окон», где круги представляют собой прозрачные секции, раскрывающие цвет за ними, но у меня не получилось сделать это правильно.

Вот мой код для статической версии:

export class ProgressBarComponent implements OnInit {
  @Input() min = 0;
  @Input() max = 100;
  @Input() value = 0;
  @Input() step = 5;
  @Input() dotSize: 'xs' | 'sm' | 'md' | 'lg' | 'xl' = 'lg';
  @Input() dotSpacing = 0; // Gap between dots in pixels

  @Output() valueChange = new EventEmitter<number>();

  public dots = Array.from(
    { length: Math.floor(this.max / this.step) },
    (_, i) => i * this.step + this.step,
  );
  public dotPixels = 0;

  ngOnInit(): void {
    switch (this.dotSize) {
      case 'xs':
        this.dotPixels = 6;
        break;
      case 'sm':
        this.dotPixels = 8;
        break;
      case 'md':
        this.dotPixels = 10;
        break;
      case 'lg':
        this.dotPixels = 12;
        break;
      case 'xl':
        this.dotPixels = 16;
        break;
    }
  }

  public onDotClick(value: number) {
    this.valueChange.emit(value);
  }
}
<div class = "progress-bar-wrapper flex items-center">
  <ng-container *ngFor = "let dotVal of dots; let i = index">
    <div
      class = "dot py-1 hover:cursor-pointer"
      [style.padding-left] = "dotSpacing / 2 + 'px'"
      [style.padding-right] = "dotSpacing / 2 + 'px'"
      (click) = "onDotClick(dotVal)"
    >
      <svg
        class = "{{
          value >= dotVal || (i === 0 && value > min)
            ? 'fill-accent'
            : 'fill-zinc-600'
        }}"
        [attr.width] = "dotPixels + 'px'"
        [attr.height] = "dotPixels + 'px'"
      >
        <circle
          [attr.cx] = "dotPixels / 2"
          [attr.cy] = "dotPixels / 2"
          [attr.r] = "dotPixels / 2"
          stroke-width = "1"
        />
      </svg>
    </div>
  </ng-container>
</div>

Как это должно выглядеть, если значение меньше одной ячейки? Например, 33%.

Karson Jo 23.07.2024 04:06

@KarsonJo это заданные приращения, поэтому промежуточных значений не будет.

Michael Stowe 23.07.2024 04:16
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
1
2
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете визуализировать два набора точек: один в качестве фона и один для обозначения прогресса. Список точек, обозначающих прогресс, можно width контролировать, чтобы изменить количество отображаемых точек. Кроме того, поскольку width можно перемещать, добиться эффекта анимации также относительно легко.

<script src = "https://cdn.tailwindcss.com/3.4.5"></script>

<div class = "flex h-dvh items-center justify-center bg-zinc-900">
  <article class = "group/volume mx-auto">
    <header class = "flex justify-between text-lg font-semibold text-amber-100">
      <h1>Volume</h1>
      <div class = "">35%</div>
    </header>
    <section class = "relative mx-2 my-4">
      <div class = "flex gap-2 text-zinc-600">
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
        <div class = "h-4 w-4 rounded-full bg-current"></div>
      </div>
      <div class = "absolute inset-0 flex gap-2 overflow-hidden text-blue-300 transition-[width] duration-1000 ease-out w-[35%] group-hover/volume:w-[70%]">
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
        <div class = "h-4 w-4 shrink-0 rounded-full bg-current"></div>
      </div>
    </section>
  </article>
</div>

(👆Запустите фрагмент и наведите курсор, чтобы увидеть эффект)

Вы также можете просмотреть этот пример на Tailwind Play


В моем примере я использую наведение мыши для запуска анимации, чтобы избежать написания JavaScript. В вашем конкретном случае вы можете установить width элемента на основе фактического процентного значения. Для такого типа динамических изменений рекомендуется устанавливать style элемента напрямую, а не использовать служебные классы Tailwind.

Это выглядит великолепно! Именно то, что я ищу.

Michael Stowe 23.07.2024 23:14

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