Created
March 23, 2021 10:35
-
-
Save raitonoberu/21dacaee725806b60ddb45ec68147d30 to your computer and use it in GitHub Desktop.
Clone of the Fluent UI indeterminate ProgressBar (pygame)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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