python实现的可爱卸载动画

news2025/4/26 1:36:50

在逛掘金时,掘金用户在B站看到的灵感进行的一个卸载窗口的动画效果的实用案例。人类是一种不断在学习的动物,并且是一种模仿能力学习能里比较强的动物。我这里是第三波的学习实践者咯!

相对VUE构建动画效果窗口,我更加喜欢用python来进行实现可爱卸载动画效果。其实,类似的软件卸载窗口,我们可以在一些常用的软件平台上进行看到,他们做的会更加的精美,同时在操作的过程当中也会流畅和丝滑太多。软件在用户在体验过程中进行最后的一次挽留用户的一次机会。

我们自己做的过程当中更多的是对功能的一个实现以及在实现过程当中的学习拓展,搞定后的满满的成就感。我们始终在孜孜不倦,同时又在乐此不疲。希望能够在不同的维度上为你带来一些灵感。

import tkinter as tk
from tkinter import ttk

class EmojiDialog:
    def __init__(self, parent):
        self.top = tk.Toplevel(parent)
        self.top.title("表情弹窗")
        self.top.geometry("640x480")
        self.top.configure(bg='#f5f5f7')  # 苹果风格背景颜色
        
        # 初始化状态变量
        self.hue_deg = 49
        self.cheek_alpha = 1.0
        self.eye_scale = 1.0
        self.mouth_radius = [5, 5, 5, 5]
        self.eye_pos = [90, 80, 10, 20]
        self.is_leaving = False

        # 创建画布
        self.canvas = tk.Canvas(self.top, width=600, height=400, bg='#f5f5f7', highlightthickness=0)
        self.canvas.pack(pady=20)

        # 绘制初始元素
        self.draw_emoji()

        # 绑定事件
        self.canvas.bind("<Motion>", self.on_mouse_move)
        self.canvas.bind("<Leave>", self.on_mouse_leave)

        # 自定义按钮样式
        self.style = ttk.Style()
        self.style.theme_use('clam')  # 使用'clam'主题,允许更多样式定制
        self.style.configure('TButton', 
                             background='#eaeaea',
                             foreground='black',
                             font=('Helvetica', 12, 'bold'),
                             padding=10,
                             relief='flat')
        self.style.map('TButton',
                       background=[('active', '#d0d0d0')])
        
        # 按钮容器
        button_frame = ttk.Frame(self.top, style='TFrame')
        button_frame.pack(pady=20)

        ttk.Button(button_frame, text="保留", command=self.some_command).pack(side=tk.LEFT, padx=10)
        ttk.Button(button_frame, text="卸载", command=self.some_command).pack(side=tk.LEFT, padx=10)

    def draw_emoji(self):
        self.canvas.delete("all")
        self.draw_head()
        self.draw_eyes()
        self.draw_mouth()
        self.draw_cheeks()

    def draw_head(self):
        base_color = self.hsl_to_rgb(self.hue_deg, 100, 65.29)
        color_hex = f"#{base_color[0]:02x}{base_color[1]:02x}{base_color[2]:02x}"
        self.canvas.create_oval(200, 80, 400, 280, outline="#e6d706", width=3, fill=color_hex)

    def draw_eyes(self):
        self.draw_eye(250, 140, self.eye_pos[0], self.eye_pos[1])  # 左眼
        self.draw_eye(350, 140, self.eye_pos[2], self.eye_pos[3])  # 右眼

    def draw_eye(self, x, y, dx, dy):
        self.canvas.create_oval(x - 25, y - 25, x + 25, y + 25, fill="white", outline="")
        scale_factor = 1 + (self.eye_scale - 1) / 3
        eye_size = 22 * scale_factor
        eye_x = x + (dx / 100) * 25 - eye_size / 2
        eye_y = y + (dy / 100) * 25 - eye_size / 2
        self.canvas.create_oval(eye_x, eye_y, eye_x + eye_size, eye_y + eye_size, fill="#5f0303", outline="")

    def draw_mouth(self):
        x, y = 300, 200
        r = self.mouth_radius
        self.canvas.create_rectangle(
            x - 45 + r[0], y - 20 + r[2],
            x + 45 - r[1], y + 30 - r[3],
            fill="#ad2424", outline="#ac0c0c", width=2, activedash=(5, 2)
        )

    def draw_cheeks(self):
        cheek_color = self.rgba_to_hex(250, 147, 147, self.cheek_alpha)
        self.canvas.create_oval(150, 200, 200, 250, fill=cheek_color, outline="")
        self.canvas.create_oval(400, 200, 450, 250, fill=cheek_color, outline="")

    def on_mouse_move(self, event):
        if self.is_leaving:
            return
        x = max(200, min(event.x, 400)) - 200
        y = max(80, min(event.y, 280)) - 80
        width, height = 200, 200

        self.hue_deg = 49 + 91 * (x / width)
        self.cheek_alpha = max(0.1, 1 - (x / (width - 50)))
        self.eye_scale = 1 + (x / width) / 3

        self.eye_pos = [
            (x / width) * 100, (y / height) * 100,
            (x / width) * 100, (y / height) * 100
        ]

        mr = x / width
        self.mouth_radius = [
            max(5, mr * 50), max(5, mr * 50),
            max(5, 50 - mr * 45), max(5, 50 - mr * 45)
        ]

        self.draw_emoji()

    def on_mouse_leave(self, event):
        self.is_leaving = True
        self.reset_state()
        self.draw_emoji()
        self.is_leaving = False

    def reset_state(self):
        self.hue_deg = 49
        self.cheek_alpha = 1.0
        self.eye_scale = 1.0
        self.mouth_radius = [5, 5, 5, 5]
        self.eye_pos = [90, 80, 10, 20]

    def hsl_to_rgb(self, h, s, l):
        h /= 360
        s /= 100
        l /= 100
        if s == 0:
            rgb = (l * 255, l * 255, l * 255)
        else:
            def hue_to_rgb(p, q, t):
                t += 1 if t < 0 else 0
                t -= 1 if t > 1 else 0
                if t < 1 / 6: return p + (q - p) * 6 * t
                if t < 1 / 2: return q
                if t < 2 / 3: return p + (q - p) * (2 / 3 - t) * 6
                return p

            q = l * (1 + s) if l < 0.5 else l + s - l * s
            p = 2 * l - q
            r = hue_to_rgb(p, q, h + 1 / 3)
            g = hue_to_rgb(p, q, h)
            b = hue_to_rgb(p, q, h - 1 / 3)
            rgb = (r * 255, g * 255, b * 255)
        return tuple(int(max(0, min(255, c))) for c in rgb)

    def rgba_to_hex(self, r, g, b, a):
        r = int(r * a + 255 * (1 - a))
        g = int(g * a + 255 * (1 - a))
        b = int(b * a + 255 * (1 - a))
        return f"#{r:02x}{g:02x}{b:02x}"

    def some_command(self):
        print("命令执行")

class MainApp:
    def __init__(self, root):
        self.root = root
        self.root.geometry("300x200")
        self.root.configure(bg='#f5f5f7')  # 设置主窗口背景颜色
        ttk.Button(self.root, text="打开弹窗", command=self.open_dialog).pack(expand=True)

    def open_dialog(self):
        EmojiDialog(self.root)


if __name__ == "__main__":
    root = tk.Tk()
    app = MainApp(root)
    root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2310908.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

钣金加工行业数字化转型MES方案

一、 行业痛点&#xff1a;钣金加工行业普遍面临以下挑战&#xff1a; 订单多样化、小批量、定制化需求增多&#xff1a;传统生产模式难以适应快速变化的市场需求。 生产流程复杂、工序繁多&#xff1a;涉及切割、折弯、焊接、表面处理等多个环节&#xff0c;协同效率低。 生产…

pinginfoview网络诊断工具中文版

介绍 pinginfoview中文版本是一款实用的网络诊断工具&#xff0c;它专为中文用户设计&#xff0c;提供了方便易用的界面&#xff0c;使得在Windows环境下进行ping测试变得更加简单。该工具是由NirSoft开发的一款免费的桌面应用程序&#xff0c;尽管官方可能并未正式发布中文版…

关于服务器无法下载kcv_encoder.h5权重的解决方法

最近租服务器跑实验代码&#xff0c;在模型初次加载时会下载stable diffusion的一系列预训练权重&#xff0c;但服务器一直卡在 Downloading data from https://huggingface.co/fchollet/stable-diffusion/resolve/main/kcv_encoder.h5 &#xff0c;最后报错 File /usr/local/…

计算光学成像与光学计算概论

计算光学成像所涉及研究的内容非常广泛&#xff0c;虽然计算光学成像的研究内容是发散的&#xff0c;但目的都是一致的&#xff1a;如何让相机记录到客观实物更丰富的信息&#xff0c;延伸并扩展人眼的视觉感知。总的来说&#xff0c;计算光学成像现阶段已经取得了很多令人振奋…

Linux——Docker容器内MySQL密码忘记了如何查看

目录 查看正在运行的MySQL的容器ID 方法一&#xff1a;查看MySQL容器的日志里的密码 方法二&#xff1a;通过环境变量密码登录 方法三&#xff1a;修改密码 查看正在运行的MySQL的容器ID docker ps 方法一&#xff1a;查看MySQL容器的日志里的密码 docker logs [MySQL的容器…

Varjo XR-4 混合现实驾驶仿真解决方案

企业级虚拟与混合现实解决方案提供商Varjo今日宣布&#xff0c;其XR-4系列设备已与VI-grade的车辆开发平台VI-WorldSim实现兼容。自2025.1版本起&#xff0c;VI-WorldSim将通过虚幻引擎5的OpenXR接口支持Varjo XR-4系列头显。 VI-WorldSim是一个集成式图形环境&#xff0c;可加…

颠覆传统软件测试!Browser Use WebUI+DeepSeek:软件测试行业的革命性突破

前置信息 硬件配置 处理器 : Intel(R) Core(TM) i5-8265U CPU 1.60GHz (四核 / 八逻辑处理器) 主板 : 20N8002UCD 内存 : 8GB(RMSA3260ME78HAF-2666 DDR4 2667 MT/s) 显示适配器 : Lexa PRO [Radeon 540/540X/550/550X / RX 540X/550/550X]/WhiskeyLake-U GT2 [UHD Graphics…

中学学习难点管理思维魔方

中学学习难点管理思维魔方 点&#xff1a;识别难点 预习难点学习难点考试错漏 线 难题整理 导图笔记 集中训练 各个突破询问老师同学个人深入思考反复阅读练习 题目改型 举一反三一题多问一题多解 面&#xff1a;定期确认 导出难题&#xff0c;重新完成 体&#xf…

使用开放数据、ArcGIS 和 Sklearn 测量洛杉矶的城市相似性

城市规划人员希望找到具有相似城市结构&#xff08;街道网络、建筑结构、土地使用类型、人口密度&#xff09;和人口统计数据&#xff08;收入、文化、年龄&#xff09;的地方。在本文中&#xff0c;我将介绍我为量化邻里相似性而确定的方法和决策&#xff0c;并展示数据科学方…

线上虚拟展厅有哪些应用场景?

虚拟展厅利用数字技术和三维建模技术创建一个虚拟的展览环境&#xff0c;使参观者可以通过计算机、智能手机、平板电脑等设备远程参观展览。其应用场景十分广泛&#xff0c;具体来说包括以下几个方面&#xff1a; 艺术展览&#xff1a; 通过线上虚拟展厅&#xff0c;人们可以…

[MySQL初阶]MySQL(5)内置函数详解

标题&#xff1a;[MySQL初阶]MySQL&#xff08;5&#xff09;内置函数详解 水墨不写bug 文章目录 一、日期函数1. current_date()2. current_time()3. current_timestamp()4. date(datetime)5. date_add(date, interval expr unit)6. date_sub(date, interval expr unit)7. dat…

EasyDSS视频推拉流/直播点播平台:Mysql数据库接口报错502处理方法

视频推拉流/视频直播点播EasyDSS互联网直播平台支持一站式的上传、转码、直播、回放、嵌入、分享功能&#xff0c;具有多屏播放、自由组合、接口丰富等特点。平台可以为用户提供专业、稳定的直播推流、转码、分发和播放服务&#xff0c;全面满足超低延迟、超高画质、超大并发访…

.NET 10首个预览版发布:重大改进与新特性概览!

前言 .NET 团队于2025年2月25日发布博文&#xff0c;宣布推出 .NET 10 首个预览版更新&#xff0c;重点改进.NET Runtime、SDK、Libraries 、C#、ASP.NET Core、Blazor 和.NET MAUI 等。 .NET 10介绍 .NET 10 是 .NET 9 的后继版本&#xff0c;将作为长期支持维护 &#xff…

【python】gunicorn配置

起因&#xff1a;因为cpu利用率低导致我去缩容&#xff0c;虽然缩容之后cpu利用率上升维持在60%左右&#xff0c;但是程序响应耗时增加了。 解释&#xff1a;因为cpu干这件活本身不累&#xff0c;但在干这件活的时候不能去干其他事情&#xff0c;导致并发的请求不能及时响应&am…

基于WebAssembly的云原生运行时:重新定义轻量化微服务架构

引言&#xff1a;颠覆性的运行时革命 Fastly边缘计算平台每天处理2000亿次Wasm请求&#xff0c;冷启动时间低于1ms。字节跳动采用Wasm实现广告算法热更新&#xff0c;发布耗时从分钟级降至秒级。CNCF 2024调研显示Wasm在边缘计算场景渗透率达42%&#xff0c;单实例内存开销仅为…

25年社工考试报名时间⏰附报名全流程✅

目前&#xff0c;湖北、重庆、云南、天津、山西、内蒙、四川、北京八地已发布考务通知。 1、湖北&#xff1a;3月11日9:00—3月26日20:00 2、重庆&#xff1a;3月13日9:00—3月24日17:00 3️⃣云南&#xff1a;3月10日09:00—3月20日17:00 4、天津&#xff1a;3月10日0:00至…

下载PyCharm 2024.3.4 (Community Edition)来开发测试python

1、下载PyCharm 2024.3.4 (Community Edition) 如果你使用的是联想电脑&#xff0c;可以直接在联想应用商店里下载&#xff0c;这样比较省事。 如果你使用的不是联想电脑&#xff0c;当然也可能是别的应用商店里下载。 也可以直接在官网下载&#xff1a; 下载 PyCharm&…

01-二分-查找(洛谷)

链接&#xff1a; P2249 【深基13.例1】查找 - 洛谷 题目 思路 没啥好说的&#xff0c;就是二分的模板要熟练掌握&#xff1b;详细参考代码随想录 本道题要注意的就是不能直接套模板&#xff0c;因为有重复元素&#xff0c;所以要单独处理一下边界。 代码 #include<bi…

linux发送邮件结合cron

Linux发送邮件结合cron定时任务 配置邮件发送&#xff08;以QQ邮箱为例&#xff0c;其他同理&#xff09; 一、获取qq邮箱授权码 登录qq邮箱 进行手机验证或者令牌啥的会获取到一个授权码 二、使用mailx发邮件 安装软件 yum -y install mailx编辑配置文件 vim /etc/mail…

C语言基础2

一、变量的作用域 局部变量的作用域是变量所在的局部范围&#xff0c;全局变量的作用域是整个工程。 int main() { { int a 10; printf("a %d\n", a); } printf("a %d\n", a); //报错位置 return 0; } 这里会发生报错&#xff1a; “a”: 未声明的…