【python】【绘制小程序】动态爱心绘制

背景介绍

  • 参考链接:https://blog.csdn.net/Python_HUHU/article/details/139703289
  • 点的背景颜色在开始修改;文字的颜色在最后修改。
  • 文字内容可以修改。

python 代码

import tkinter as tk
import random
from math import sin, cos, pi, log
from PIL import Image, ImageDraw, ImageFont  # 用于保存图片和生成GIFwidth = 888
height = 500
heartx = width / 2
hearty = height / 2
side = 11
heartcolor = "pink"  # 爱心颜色,可修改
# heartcolor = "gold"  # 爱心颜色,可修改class Heart:def __init__(self, generate_frame=20):self._points = set()  # 原始爱心坐标集合self._edge_diffusion_points = set()  # 边缘扩散效果点坐标集合self._center_diffusion_points = set()  # 中心扩散效果点坐标集合self.all_points = {}  # 每帧动态点坐标self.build(2000)self.generate_frame = generate_framefor frame in range(generate_frame):self.calc(frame)def build(self, number):for _ in range(number):t = random.uniform(0, 2 * pi)x, y = heart_function(t)self._points.add((x, y))for _x, _y in list(self._points):for _ in range(3):x, y = scatter_inside(_x, _y, 0.05)self._edge_diffusion_points.add((x, y))point_list = list(self._points)for _ in range(4000):x, y = random.choice(point_list)x, y = scatter_inside(x, y, 0.17)self._center_diffusion_points.add((x, y))@staticmethoddef calc_position(x, y, ratio):force = 1 / (((x - heartx) ** 2 + (y - hearty) ** 2) ** 0.520)  # 魔法参数dx = ratio * force * (x - heartx) + random.randint(-1, 1)dy = ratio * force * (y - hearty) + random.randint(-1, 1)return x - dx, y - dydef calc(self, generate_frame):ratio = 10 * curve(generate_frame / 10 * pi)  # 圆滑的周期的缩放比例all_points = []for x, y in self._points:x, y = self.calc_position(x, y, ratio)size = random.randint(1, 3)all_points.append((x, y, size))for x, y in self._edge_diffusion_points:x, y = self.calc_position(x, y, ratio)size = random.randint(1, 2)all_points.append((x, y, size))for x, y in self._center_diffusion_points:x, y = self.calc_position(x, y, ratio)size = random.randint(1, 2)all_points.append((x, y, size))self.all_points[generate_frame] = all_pointsdef render(self, draw, render_frame):for x, y, size in self.all_points[render_frame % self.generate_frame]:draw.rectangle([x, y, x + size, y + size], fill=heartcolor)def heart_function(t, shrink_ratio: float = side):x = 16 * (sin(t) ** 3)y = -(13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t))x *= shrink_ratioy *= shrink_ratiox += heartxy += heartyreturn int(x), int(y)def scatter_inside(x, y, beta=0.15):ratio_x = - beta * log(random.random())ratio_y = - beta * log(random.random())dx = ratio_x * (x - heartx)dy = ratio_y * (y - hearty)return x - dx, y - dydef curve(p):return 2 * (2 * sin(4 * p)) / (2 * pi)# 保存动态爱心为GIF并添加文字
def save_gif():frames = []heart = Heart()for frame in range(heart.generate_frame):img = Image.new('RGB', (width, height), 'black')draw = ImageDraw.Draw(img)# 绘制爱心heart.render(draw, frame)# 绘制中间的文字# text = "I Love You!"text = "Miss ❤ U"# font = ImageFont.truetype("arial.ttf", 40)  # 确保系统上有 Arial 字体文件或替换为可用的字体文件font = ImageFont.truetype("./font/DejaVu-Sans.ttf", 40)  # 确保系统上有 Arial 字体文件或替换为可用的字体文件# 获取文本的边界框bbox = draw.textbbox((0, 0), text, font=font)text_width, text_height = bbox[2] - bbox[0], bbox[3] - bbox[1]text_x = (width - text_width) / 2text_y = (height - text_height) / 2# draw.text((text_x, text_y), text, font=font, fill="#FF99CC")draw.text((text_x, text_y), text, font=font, fill="gold")frames.append(img)# 保存为 GIF 动画frames[0].save('./result/1_2_3_heart_animation_with_text.gif', save_all=True, append_images=frames[1:], duration=160, loop=0)if __name__ == '__main__':save_gif()

绘制结果

在这里插入图片描述

进阶修改:周围环绕文字,修改背景颜色

import tkinter as tk
import random
from math import sin, cos, pi, log, atan2
from PIL import Image, ImageDraw, ImageFontwidth = 666
height = 460
heartx = width / 2
hearty = height / 2
side = 11
heartcolor = "pink"  # 爱心颜色,可修改
# heartcolor = "gold"  # 爱心颜色,可修改# 定义马卡龙蓝色
macaron_blue = "#A2C2E1"
cream_white = "#F5F5F5"
cyan_green = "#00FFFF"class Heart:def __init__(self, generate_frame=20):self._points = set()  # 原始爱心坐标集合self._edge_diffusion_points = set()  # 边缘扩散效果点坐标集合self._center_diffusion_points = set()  # 中心扩散效果点坐标集合self.all_points = {}  # 每帧动态点坐标self.build(2000)                            ### 周围点的数量self.generate_frame = generate_framefor frame in range(generate_frame):self.calc(frame)def build(self, number):for _ in range(number):t = random.uniform(0, 2 * pi)x, y = heart_function(t)self._points.add((x, y))for _x, _y in list(self._points):for _ in range(3):x, y = scatter_inside(_x, _y, 0.05)self._edge_diffusion_points.add((x, y))point_list = list(self._points)for _ in range(4000):x, y = random.choice(point_list)x, y = scatter_inside(x, y, 0.17)self._center_diffusion_points.add((x, y))@staticmethoddef calc_position(x, y, ratio):force = 1 / (((x - heartx) ** 2 + (y - hearty) ** 2) ** 0.520)  # 魔法参数dx = ratio * force * (x - heartx) + random.randint(-1, 1)dy = ratio * force * (y - hearty) + random.randint(-1, 1)return x - dx, y - dydef calc(self, generate_frame):ratio = 10 * curve(generate_frame / 10 * pi)  # 圆滑的周期的缩放比例all_points = []for x, y in self._points:x, y = self.calc_position(x, y, ratio)size = random.randint(1, 3)all_points.append((x, y, size))for x, y in self._edge_diffusion_points:x, y = self.calc_position(x, y, ratio)size = random.randint(1, 2)all_points.append((x, y, size))for x, y in self._center_diffusion_points:x, y = self.calc_position(x, y, ratio)size = random.randint(1, 2)all_points.append((x, y, size))self.all_points[generate_frame] = all_pointsdef render(self, draw, render_frame):for x, y, size in self.all_points[render_frame % self.generate_frame]:draw.rectangle([x, y, x + size, y + size], fill=heartcolor)def heart_function(t, shrink_ratio: float = side):x = 16 * (sin(t) ** 3)y = -(13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t))x *= shrink_ratioy *= shrink_ratiox += heartxy += heartyreturn int(x), int(y)def scatter_inside(x, y, beta=0.15):ratio_x = - beta * log(random.random())ratio_y = - beta * log(random.random())dx = ratio_x * (x - heartx)dy = ratio_y * (y - hearty)return x - dx, y - dydef curve(p):return 2 * (2 * sin(4 * p)) / (2 * pi)# 计算最小外接圆的半径
def calculate_bounding_circle_radius():max_distance = 0for t in range(0, 360):radian = t * pi / 180x, y = heart_function(radian)distance = ((x - heartx) ** 2 + (y - hearty) ** 2) ** 0.5if distance > max_distance:max_distance = distancereturn max_distance# 绘制外接圆上的文字
def draw_text_on_circle(draw, text, radius, font):# char_angle = 2 * pi / len(text)  # 每个字符的角度char_angle = pi / len(text)  # 每个字符的角度for i, char in enumerate(text):angle = i * char_angle  - pi + 0.19angle = angle * -1x = heartx + radius * cos(angle)y = hearty + radius * sin(angle)bbox = draw.textbbox((0, 0), char, font=font)text_width, text_height = bbox[2] - bbox[0], bbox[3] - bbox[1]# draw.text((x - text_width / 2, y - text_height / 2), char, font=font, fill="pink")draw.text((x - text_width / 2, y - text_height / 2), char, font=font, fill=cyan_green)# 保存动态爱心为GIF并添加文字
def save_gif():frames = []heart = Heart()circle_radius = calculate_bounding_circle_radius() + 20  # 外接圆半径,稍微大一些以避免重叠for frame in range(heart.generate_frame):# img = Image.new('RGB', (width, height), 'black')# img = Image.new('RGB', (width, height), cream_white)       ### 背景颜色修改img = Image.new('RGB', (width, height), macaron_blue)       ### 背景颜色修改draw = ImageDraw.Draw(img)# 绘制爱心heart.render(draw, frame)# 绘制中间的文字text = "爱 你 呦"font = ImageFont.truetype("./font/simsun.ttc", 40)bbox = draw.textbbox((0, 0), text, font=font)text_width, text_height = bbox[2] - bbox[0], bbox[3] - bbox[1]text_x = (width - text_width) / 2text_y = (height - text_height) / 2draw.text((text_x, text_y), text, font=font, fill="gold")# draw.text((text_x, text_y), text, font=font, fill="pink")# 绘制外接圆上的文字# circle_text = "十个勤天 做大做强"# circle_font = ImageFont.truetype("./font/simsun.ttc", 36)# draw_text_on_circle(draw, circle_text, circle_radius, circle_font)frames.append(img)# 保存为 GIF 动画frames[0].save('./result/1_2_3_heart_animation_with_text.gif', save_all=True, append_images=frames[1:], duration=160, loop=0)if __name__ == '__main__':save_gif()

生成结果

在这里插入图片描述

在这里插入图片描述

END

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

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

相关文章

学习篇 | Jupyter 使用(notebook hub)

1. JupyterHub 1.1 快速尝试 jupyterhub -f/path/jupyter_config.py --no-ssl1.2 长期后台运行 bash -c "nohup jupyterhub -f/path/jupyter_config.py --no-ssl" > ~/jupyterhub.log 2>&1 &1.3 帮助 jupyterhub --help2. Jupyter Notebook 2.1 快…

Cocos 3.8.3 实现外描边效果(逃课玩法)

本来想着用Cocos 的Shader Graph照搬Unity的思路来加外描边,发现不行,然后我就想弄两个物体不就行了吗,一个是放大的版本,再放大的版本上加一个材质,这个材质面剔除选择前面的面剔除就行了,果不其然还真行。…

如何使用ssm实现基于java web的防疫工作志愿者服务平台的设计与实现

TOC ssm693基于java web的防疫工作志愿者服务平台的设计与实现jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大,随着当前时代的信息化,科学化发展,让社会各行业领域都争相使用新的信息技术,对行业内的各种相关数据进…

详细解读,F5服务器负载均衡的技术优势

在现代大规模、高流量的网络使用场景中,为应对高并发和海量数据的挑战,服务器负载均衡技术应运而生。但凡知道服务器负载均衡这一名词的,基本都对F5有所耳闻,因为负载均衡正是F5的代表作,换句通俗易懂的话来说&#xf…

makefile和CMakeLists/C++包管理器

make 大家可能会很奇怪,都什么年代了,还学makefile,cmake都有些过时了,为什么还要再学这个呢? 我是这么看待这个问题的,cmake跨平台性还是很有有优势的,有着多年积累的底蕴,借助大模…

海尔嵌入式硬件校招面试题及参考答案

使用 QT 的经验及对控件和信号与槽机制的了解 我使用 QT 有一段时间了,在项目开发中积累了较为丰富的经验。 QT 中的控件丰富多样,涵盖了各种常见的界面元素需求。例如按钮、文本框、列表框、进度条等。这些控件具有良好的可定制性,可以通过属性设置、样式表等方式来调整外观…

基于springboot的驾校预约管理系统的设计与实现 (含源码+sql+视频导入教程)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的驾校预约管理系统5拥有三种角色:管理员、教练、学员 管理员:学员管理、教练管理、车辆管理、车辆关联、维修管理等 教练:学员查看/毕…

再次重温 Spring 中 Bean 的生命周期

Bean的生命周期 Spring中的bean的生命周期主要包含四个阶段:实例化Bean --> Bean属性填充 --> 初始化Bean -->销毁Bean 首先是实例化Bean,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要…

Java 序列化:为什么你应该手动定义 serialVersionUID?@Serial 注解有什么作用?

最近在优化一个Java项目时,遇到了一个关于类序列化的问题。项目中有一个需要实现 Serializable 接口的类,我发现有一段代码使用了 Serial 注解,并且还定义了 serialVersionUID,具体如下: Serial private static final…

hive-拉链表

目录 拉链表概述缓慢变化维拉链表定义 拉链表的实现常规拉链表历史数据每日新增数据历史数据与新增数据的合并 分区拉链表 拉链表概述 缓慢变化维 通常我们用一张维度表来维护维度信息,比如用户手机号码信息。然而随着时间的变化,某些用户信息会发生改…

SpringSecurity-用户认证

1、用户认证 1.1 用户认证核心组件 我们系统中会有许多用户,确认当前是哪个用户正在使用我们系统就是登录认证的最终目的。这里我们就提取出了一个核心概念:当前登录用户/当前认证用户。整个系统安全都是围绕当前登录用户展开的,这个不难理…

数字安全二之密钥结合消息摘要

HMACSHA256的定义 HMACSHA256是一种使用 SHA-256 哈希算法的 HMAC(基于哈希的消息认证码,Hash-based Message Authentication Code) 机制。它结合了【散列函数】 和 【密钥】,用于确保消息的完整性和真实性 HMAC 与 SHA-256 的作…

大数据新视界 --大数据大厂之HBase 在大数据存储中的应用与表结构设计

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

如何进行Ubuntu磁盘空间深度清理?

近期使用AutoDL算力云,发现系统盘只有30G,数据盘只有50G,跑一个稍微大一点的模型,马上空间就拉爆了,现在做一个磁盘深度清理操作,看看效果。 清理前磁盘占用如下: 在 Ubuntu 系统中进行磁盘深度…

如何选择适合的编程工具提高工作效率

---  随着科技的发展,编程已经成为各行各业不可或缺的一部分。在忙碌的工作环境中,如何选择合适的编程工具成为了每个开发者提升工作效率的关键。智能的代码编辑器、强大的版本控制工具、还是那些让你事半功倍的自动化脚本?让我们一起探讨&…

GO入门之值传递于引用(指针、内存地址)传递扫盲

GO入门之值传递于引用(指针、内存地址)传递扫盲 Go 语言中,值传递和引用(指针)传递是两个关键的概念。通过案例可以很好地展示两者的区别。 值传递与引用传递的区别: 值传递:传递的是变量的副…

LabVIEW软件出现Bug如何解决

在LabVIEW开发中,程序出现bug是不可避免的。无论是小型项目还是复杂系统,调试与修复bug都是开发过程中的重要环节。下文介绍如何有效解决LabVIEW软件中的bug,包括常见错误类型、调试工具、错误处理机制。 1. 常见Bug类型分析 在LabVIEW中&am…

Github 2024-09-26 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2024-09-26统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10C项目1Prometheus监控系统和时间序列数据库 创建周期:4149 天开发语言:Go协议类型:Apache License 2.0Star数量:52463 个Fork数量:…

WGS1984快速度确定平面坐标系UTM分带(快速套表、公式计算、软件范围判定)

之前我们介绍了坐标系3带6带快速确定带号及中央经线(快速套表、公式计算、软件范围判定)就,讲的是CGCS2000 高斯克吕格的投影坐标系。 那还有我们经常用的WGS1984的平面坐标系一般用什么投影呢? 对于全球全国的比如在线地图使用&#xff1a…

计算机视觉硬件整理(四):相机与镜头参数介绍

文章目录 前言一、工业相机常用分类二、工业相机的基本参数三、工业相机的接口四、工业镜头的参数五、工业镜头的选择要点 前言 随着科技的飞速发展,工业自动化和智能制造在当今社会扮演着越来越重要的角色。在这个背景下,工业相机作为一种关键的视觉检…