How to Create a Sonic Wave Animation in Python Tkinter
In this Python Tutorial we will see How to Create a Sonic Wave animation that features animated bars with dynamic colors, glow effects, and smooth sine wave motion Using Python Tkinter.
What We Are Gonna Use In This Project:
- Python Programming Language.- Tkinter (GUI).
- VS Editor.
- VS Editor.
Project Source Code:
import tkinter as tk
import math
import time
import colorsys
class SonicWave(tk.Canvas):
def __init__(self, master=None, **kwargs):
# Configuration
self.BAR_COUNT = 7
self.BAR_WIDTH = 5
self.BAR_GAP = 10
self.BAR_HEIGHT = 65
self.ANIMATION_DELAY = 1500 # milliseconds for full cycle
# Dark background color
bg_color = "#111122"
# Set canvas dimensions
width = self.BAR_COUNT * (self.BAR_WIDTH + self.BAR_GAP) + 40
height = self.BAR_HEIGHT + 60
# Initialize the canvas with our background color
super().__init__(master, width=width, height=height, bg=bg_color,
highlightthickness=0, **kwargs)
# Define colors
self.colors = [
"#00eeff", # blue
"#b300ff", # purple
"#ff00ff", # pink
"#0aff0a", # green
"#ff3300" # orange
]
# Initialize bar heights and animation state
self.bar_heights = [0.2] * self.BAR_COUNT
self.hue_shift = 0.0
# Start the animation
self.is_running = True
self.animate()
def get_color_with_shift(self, base_color, offset=0):
"""Apply a hue shift to a color for dynamic color effects"""
# Convert hex to RGB
r = int(base_color[1:3], 16) / 255.0
g = int(base_color[3:5], 16) / 255.0
b = int(base_color[5:7], 16) / 255.0
# Convert RGB to HSV
h, s, v = colorsys.rgb_to_hsv(r, g, b)
# Apply the hue shift
h = (h + self.hue_shift + offset) % 1.0
# Convert back to RGB
r, g, b = colorsys.hsv_to_rgb(h, s, v)
# Convert to hex
return f"#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}"
def animate(self):
"""Main animation loop"""
if not self.is_running:
return
self.update_bar_heights()
self.draw_spinner()
# Schedule the next animation frame
self.after(30, self.animate)
def update_bar_heights(self):
"""Update the heights of each bar based on a sine wave function"""
current_time = time.time() * 1000 # Convert to milliseconds
# Update each bar's height based on sine wave function
for i in range(self.BAR_COUNT):
# Calculate phase offset for each bar
phase_offset = i * (math.pi / 8)
# Use sine wave to animate heights (0.2 to 1.0 range)
progress = (current_time % self.ANIMATION_DELAY) / self.ANIMATION_DELAY
angle = 2 * math.pi * progress + phase_offset
self.bar_heights[i] = 0.2 + 0.8 * abs(math.sin(angle))
# Gradually shift the hue
self.hue_shift = (self.hue_shift + 0.005) % 1.0
def create_text_shadow(self, x, y, text, font_config):
# Create shadow text (slight offset, darker color)
shadow_color = "#555555"
self.create_text(x+2, y+2, text=text, fill=shadow_color, font=font_config)
# Create main text with a fixed color
main_color = "#FFFFFF" # Use white color
self.create_text(x, y, text=text, fill=main_color, font=font_config)
def draw_spinner(self):
"""Draw the spinner with visual elements"""
# Clear the canvas
self.delete("all")
# Calculate layout dimensions
total_width = self.BAR_COUNT * (self.BAR_WIDTH + self.BAR_GAP) - self.BAR_GAP
start_x = (self.winfo_width() - total_width) // 2
base_y = (self.winfo_height() + self.BAR_HEIGHT) // 2 - 10
# Draw "SONIC WAVE" text label
# Ensure the text is positioned in a visible area
text_y = min(base_y + self.BAR_HEIGHT // 2 + 20, self.winfo_height() - 20)
self.create_text_shadow(
self.winfo_width() // 2,
text_y,
"SONIC WAVE",
("Arial", 13, "bold")
)
# Draw bars
for i in range(self.BAR_COUNT):
x = start_x + i * (self.BAR_WIDTH + self.BAR_GAP)
height = int(self.bar_heights[i] * self.BAR_HEIGHT)
y = base_y - height
# Get color based on current animation state with dynamic hue shifting
bar_color = self.get_color_with_shift(self.colors[i % len(self.colors)],
i * 0.05)
# Draw the bar
self.create_rectangle(
x, y, x + self.BAR_WIDTH, base_y,
fill=bar_color, outline="", width=0
)
# Create a glow effect by drawing multiple rectangles
for j in range(1, 5):
# Create outlines for glow effect
self.create_rectangle(
x - j, y - j, x + self.BAR_WIDTH + j, base_y + j,
outline=bar_color, width=1
)
def stop_animation(self):
"""Method to stop the animation when no longer needed"""
self.is_running = False
class AppFrame(tk.Frame):
"""A frame to hold the spinner with UI elements"""
def __init__(self, master=None, **kwargs):
super().__init__(master, **kwargs)
self.config(bg="#0d0d18", padx=25, pady=25)
self.pack(fill=tk.BOTH, expand=True)
# Create a background
self.create_background()
# Add the spinner
self.spinner = SonicWave(self)
self.spinner.pack(pady=10)
# Add a version or title or any text label
version_label = tk.Label(
self,
text="v2.0",
bg="#0d0d18",
fg="#444444",
font=("Arial", 8)
)
version_label.pack(side=tk.BOTTOM, anchor=tk.SE, padx=5, pady=5)
def create_background(self):
"""Create a background frame"""
gradient_frame = tk.Frame(self, width=300, height=250, bg="#0d0d18")
gradient_frame.place(x=0, y=0, relwidth=1, relheight=1)
def main():
root = tk.Tk()
root.title("Sonic Wave")
# Set dark theme for the window
root.configure(bg="#0a0a14")
# Create our app frame
app_frame = AppFrame(root)
# Set window size and position
root.geometry("300x250")
root.eval('tk::PlaceWindow . center') # Center the window
# Make the window non-resizable for consistent layout
root.resizable(False, False)
# Handle window close event
def on_closing():
app_frame.spinner.stop_animation()
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_closing)
# Start the main event loop
root.mainloop()
if __name__ == "__main__":
main()
The Final Result:
Download Projects Source Code