小时候在安装盗版Windows7的时候,安装助手有一个鼠标滑过泛起涟漪的界面。这几天抽空用Python把这个效果实现了:
import tkinter as tk
from PIL import Image, ImageTk
import time
class RippleEffectSimulator:
def __init__(self, root):
self.root = root
self.root.title("Ripple Effect Simulator")
# 创建画布
self.canvas = tk.Canvas(root, width=650, height=975)
self.canvas.pack()
# 加载背景图片
# 加载背景图片
self.background_image = Image.open("pool.png")
self.background_image = self.background_image.resize((650, 975), Image.LANCZOS)
self.background_photo = ImageTk.PhotoImage(self.background_image)
self.canvas.create_image(0, 0, image=self.background_photo, anchor=tk.NW)
# 创建标签和按钮
self.label = tk.Label(root, text="Move the mouse to create ripple effects!")
self.label.pack()
self.reset_button = tk.Button(root, text="Reset", command=self.reset_simulation)
self.reset_button.pack()
# 绑定鼠标移动事件
self.canvas.bind("<Motion>", self.on_mouse_move)
self.circles = []
self.last_ripple_time = 0
self.ripple_interval = 0.1 # 50 ms between ripples
def on_mouse_move(self, event):
current_time = time.time()
if current_time - self.last_ripple_time >= self.ripple_interval:
self.add_ripple(event.x, event.y)
self.last_ripple_time = current_time
def add_ripple(self, x, y):
# Define multiple layers with different characteristics
layers = [
{'color': (255, 255, 255), 'max_radius': 20, 'speed': 20, 'width': 2, 'delay': 0}, # Blue
{'color': (173, 216, 230), 'max_radius': 30, 'speed': 15, 'width': 1, 'delay': 0.2}, # Light Blue
{'color': (0, 255, 255), 'max_radius': 40, 'speed': 10, 'width': 1, 'delay': 0.4} # Cyan
]
for layer in layers:
self.root.after(int(layer['delay'] * 1000), self.create_ripple_layer, x, y, layer['color'], layer['max_radius'], layer['speed'], layer['width'])
def create_ripple_layer(self, x, y, color, max_radius, speed, width):
start_time = time.time()
ripple_id = self.canvas.create_oval(x, y, x, y, outline="", width=width)
self.circles.append((ripple_id, start_time, x, y, color, max_radius, speed))
self.update_ripple(ripple_id, start_time, x, y, color, max_radius, speed)
def update_ripple(self, ripple_id, start_time, x, y, color, max_radius, speed):
current_time = time.time()
duration = current_time - start_time
radius = min(max_radius, duration * speed)
if radius >= max_radius:
self.canvas.delete(ripple_id) # Directly remove ripple when it reaches max radius
return
# Calculate color fading by interpolating with the background color (assuming background is blue-ish)
progress = radius / max_radius
faded_color = self.fade_to_background(color, progress)
self.canvas.itemconfig(ripple_id, outline=faded_color)
x0 = x - radius
y0 = y - radius
x1 = x + radius
y1 = y + radius
self.canvas.coords(ripple_id, x0, y0, x1, y1)
self.root.after(10, self.update_ripple, ripple_id, start_time, x, y, color, max_radius, speed)
def fade_to_background(self, color, progress):
"""Interpolates the color towards the background color (blueish)."""
bg_color = (135, 206, 235) # Assume a light blue background color
faded_color = tuple(int(c * (1 - progress) + bg_c * progress) for c, bg_c in zip(color, bg_color))
return f'#{faded_color[0]:02x}{faded_color[1]:02x}{faded_color[2]:02x}'
def reset_simulation(self):
self.canvas.delete("all")
self.canvas.create_image(0, 0, image=self.background_photo, anchor=tk.NW)
self.label.config(text="Move the mouse to create ripple effects!")
self.circles = []
self.last_ripple_time = 0 # Reset the last ripple time
if __name__ == "__main__":
root = tk.Tk()
app = RippleEffectSimulator(root)
root.mainloop()