Files
2026-07-28 03:21:34 +08:00

173 lines
7.2 KiB
Python

import tkinter as tk
from tkinter import Canvas
import ttkbootstrap as ttk
from PIL import Image, ImageTk, ImageDraw
import math
class DVDAnimation:
def __init__(self, root):
self.root = root
self.root.title("DVD插入动画")
# 设置窗口大小和居中
window_width = 800
window_height = 600
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x = (screen_width - window_width) // 2
y = (screen_height - window_height) // 2
self.root.geometry(f"{window_width}x{window_height}+{x}+{y}")
# 创建画布
self.canvas = Canvas(root, width=window_width, height=window_height, bg='black')
self.canvas.pack()
# 图片尺寸
self.dvd_player_width = 400
self.dvd_player_height = 300
self.dvd_width = 200
self.dvd_height = 200
self.icon_width = 100
self.icon_height = 100
self.icon_cer_width = 200
self.icon_cer_height = 200
# 位置参数
self.dvd_player_x = (window_width - self.dvd_player_width) // 2
self.dvd_player_y = (window_height - self.dvd_player_height) // 2
# 加载图片
self.load_images()
# 动画参数
self.animation_steps = 50
self.current_step = 0
self.dvd_start_x = window_width
self.dvd_end_x = self.dvd_player_x + self.dvd_player_width // 2 - self.dvd_width // 2
# 开始动画
self.animate()
def load_images(self):
"""加载图片"""
try:
# 加载您的图片
self.dvd_player_img = Image.open('1.png').resize((self.dvd_player_width, self.dvd_player_height), Image.Resampling.LANCZOS)
self.dvd_img = Image.open('2.png').resize((self.dvd_width, self.dvd_height), Image.Resampling.LANCZOS)
self.icon_img = Image.open('3.png').resize((self.icon_width, self.icon_height), Image.Resampling.LANCZOS)
self.icon_cer_img = Image.open('2.5.png').resize((self.icon_cer_width, self.icon_cer_height), Image.Resampling.LANCZOS)
except FileNotFoundError:
print("请将您的图片命名为1.png、2.png、3.png并放在同一目录下")
self.root.destroy()
return
# 转换为Tkinter可用的格式
self.dvd_player_photo = ImageTk.PhotoImage(self.dvd_player_img)
self.dvd_photo = ImageTk.PhotoImage(self.dvd_img)
self.icon_photo = ImageTk.PhotoImage(self.icon_img)
self.icon_cer_photo = ImageTk.PhotoImage(self.icon_cer_img)
# 创建叠加后的DVD图片
self.create_combined_dvd_image()
def create_combined_dvd_image(self):
"""创建DVD和ICON叠加的图片,保持透明度"""
# 创建一个临时画布来叠加图片
combined = Image.new('RGBA', (self.dvd_width, self.dvd_height), (0, 0, 0, 0))
# 先放置DVD
combined.paste(self.dvd_img, (0, 0), self.dvd_img)
# 计算ICON的位置(居中)
icon_x = (self.dvd_width - self.icon_width) // 2 + 60
icon_y = (self.dvd_height - self.icon_height) // 2
# 处理ICON的透明度,使其与DVD的透明区域匹配
for x in range(self.icon_width):
for y in range(self.icon_height):
dvd_x = icon_x + x
dvd_y = icon_y + y
if 0 <= dvd_x < self.dvd_width and 0 <= dvd_y < self.dvd_height:
# 获取DVD对应位置的alpha值
dvd_alpha = self.dvd_img.getpixel((dvd_x, dvd_y))[3]
if dvd_alpha > 0: # 只在DVD不透明的区域绘制ICON
icon_pixel = self.icon_img.getpixel((x, y))
if icon_pixel[3] > 0: # ICON也不透明
# 混合颜色
alpha_ratio = icon_pixel[3] / 255.0
new_r = int(icon_pixel[0] * alpha_ratio)
new_g = int(icon_pixel[1] * alpha_ratio)
new_b = int(icon_pixel[2] * alpha_ratio)
new_a = min(dvd_alpha, icon_pixel[3])
combined.putpixel((dvd_x, dvd_y), (new_r, new_g, new_b, new_a))
# 计算ICON的位置(居中)
icon_x = (self.dvd_width - self.icon_cer_width) // 2
icon_y = (self.dvd_height - self.icon_cer_height) // 2
# 处理ICON的透明度,使其与DVD的透明区域匹配
for x in range(self.icon_cer_width):
for y in range(self.icon_cer_height):
dvd_x = icon_x + x
dvd_y = icon_y + y
if 0 <= dvd_x < self.dvd_width and 0 <= dvd_y < self.dvd_height:
# 获取DVD对应位置的alpha值
dvd_alpha = self.dvd_img.getpixel((dvd_x, dvd_y))[3]
if dvd_alpha > 0: # 只在DVD不透明的区域绘制ICON
icon_pixel = self.icon_cer_img.getpixel((x, y))
if icon_pixel[3] > 0: # ICON也不透明
# 混合颜色
alpha_ratio = icon_pixel[3] / 255.0
new_r = int(icon_pixel[0] * alpha_ratio)
new_g = int(icon_pixel[1] * alpha_ratio)
new_b = int(icon_pixel[2] * alpha_ratio)
new_a = min(dvd_alpha, icon_pixel[3])
combined.putpixel((dvd_x, dvd_y), (new_r, new_g, new_b, new_a))
self.combined_dvd_photo = ImageTk.PhotoImage(combined)
def animate(self):
"""执行动画"""
if self.current_step <= self.animation_steps:
# 清除画布
self.canvas.delete("all")
# 计算当前DVD位置
progress = self.current_step / self.animation_steps
# 使用缓动函数使动画更平滑
eased_progress = 1 - (1 - progress) ** 3
current_x = self.dvd_start_x - (self.dvd_start_x - self.dvd_end_x) * eased_progress
# DVD的Y位置(插入一半的效果)
dvd_y = self.dvd_player_y + self.dvd_player_height // 2 - self.dvd_height // 2
# 绘制DVD机(最高图层)
self.canvas.create_image(self.dvd_player_x, self.dvd_player_y,
anchor=tk.NW, image=self.dvd_player_photo)
# 绘制组合的DVD图片
self.canvas.create_image(current_x, dvd_y,
anchor=tk.NW, image=self.combined_dvd_photo)
# 更新动画步骤
self.current_step += 1
# 继续动画
self.root.after(30, self.animate)
def main():
root = ttk.Window(themename="darkly")
app = DVDAnimation(root)
root.mainloop()
if __name__ == "__main__":
main()