Я создаю компонент индикатора прогресса/объема с помощью 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>
@KarsonJo это заданные приращения, поэтому промежуточных значений не будет.
Вы можете визуализировать два набора точек: один в качестве фона и один для обозначения прогресса. Список точек, обозначающих прогресс, можно 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.
Это выглядит великолепно! Именно то, что я ищу.
Как это должно выглядеть, если значение меньше одной ячейки? Например, 33%.