Skip to content

Instantly share code, notes, and snippets.

@raitonoberu
Created March 23, 2021 10:35
Show Gist options
  • Save raitonoberu/21dacaee725806b60ddb45ec68147d30 to your computer and use it in GitHub Desktop.
Save raitonoberu/21dacaee725806b60ddb45ec68147d30 to your computer and use it in GitHub Desktop.
Clone of the Fluent UI indeterminate ProgressBar (pygame)
import pygame
import pygame.draw
import pygame.locals
from math import cos, pi
FILLED_COLOR = (108, 88, 123)
UNFILLED_COLOR = (204, 204, 204)
class ProgressBar(object):
def __init__(
self, x, y, w, h, step1=0.015, step2=0.025, velocity_scale=0.8, idle_frames=15
):
self.x = x
self.y = y
self.w = w
self.h = h
self.step1 = step1 # step of short line every frame
self.step2 = step2 # step of long line every frame
self.idle_frames = idle_frames # idle duration (in frames)
self.velocity_scale = velocity_scale
self.start_pos = (x, y)
self.end_pos = (x + w, y)
self.short = 0.4 # percentage of short line (0..1)
self.long = 80 / 130 # percentage of long line (0..1)
self.p1 = 0 # percentage of 1st point (0..1)
self.p2 = 0 # percentage of 2nd point (0..1)
self.cycle = 1 # short or large (1/-1)
self.idle = 0
def draw_line(self, surface, xy1, xy2, color):
pygame.draw.circle(surface, color, (xy1[0], xy1[1] + 1), self.h // 2)
pygame.draw.line(surface, color, xy1, xy2, self.h)
pygame.draw.circle(surface, color, (xy2[0], xy2[1] + 1), self.h // 2)
def coords(self, percentage):
# returns the coordinates of a point at a certain number of percentages
return (self.x + int(self.w * percentage), self.y)
def draw(self, surface):
# draw a white line
self.draw_line(surface, self.start_pos, self.end_pos, UNFILLED_COLOR)
# fill the line
if not self.idle:
self.draw_line(
surface, self.coords(self.p1), self.coords(self.p2), FILLED_COLOR
)
def calc_velocity(self, p):
return 1 + cos(pi * p - (pi / 2)) * self.velocity_scale
def update(self):
v1 = self.calc_velocity(self.p1)
v2 = self.calc_velocity(self.p2)
if self.idle != 0:
self.idle -= 1
return
if self.cycle == 1: # short line
self.p2 = min(self.p2 + self.step1 * v2, 1)
if self.p2 - self.p1 >= self.short or self.p2 == 1:
self.p1 = min(self.p1 + self.step1 * v1, 1)
if self.cycle == -1: # long line
self.p2 = min(self.p2 + self.step2 * v2, 1)
if self.p2 - self.p1 >= self.long or self.p2 == 1:
self.p1 = min(self.p1 + self.step2 * v1, 1)
if self.p1 == 1: # the end reached
self.idle = self.idle_frames
self.cycle *= -1
self.p1 = 0
self.p2 = 0
if __name__ == "__main__":
pygame.init()
clock = pygame.time.Clock()
display = pygame.display.set_mode((300, 150))
bar = ProgressBar(50, 50, 130, 4)
while True:
for event in pygame.event.get():
if event.type == pygame.locals.QUIT:
pygame.quit()
display.fill((255, 255, 255))
bar.update()
bar.draw(display)
pygame.display.update()
clock.tick(60)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment