系列专栏
系列文章
写在前面
Python语言实现李峋同款可写字版跳动的爱心的完整代码。
技术需求
-
Tkinter 图形用户界面 (GUI) 开发
- 使用
tkinter
库创建窗口、按钮、标签和绘图画布等 GUI 元素。 - 通过
Canvas
实现动态绘图,展示爱心的跳动动画。 - 使用窗口事件处理(如
protocol
绑定窗口关闭事件)增加交互性。
- 使用
-
数学函数绘图
- 通过参数方程
heart_function
描绘心形轮廓,利用正弦和余弦函数生成坐标点。 - 应用数学缩放和偏移操作调整爱心的大小和位置。
- 通过参数方程
-
随机生成与散点模拟
- 使用
random
模块实现随机数生成,制造爱心边缘和中心的扩散效果,增加视觉表现力。 - 利用随机分布和对数变换 (
scatter_inside
) 模拟爱心扩散区域的自然感。
- 使用
-
动态动画渲染
- 通过递归调用
after
方法实现帧刷新,生成连续动态效果。 - 在每一帧中动态计算并绘制不同的点,模拟爱心跳动的视觉效果。
- 通过递归调用
-
点的力场模拟
- 使用力场模型 (
calc_position
和shrink
) 模拟坐标点的运动轨迹,制造扩散和收缩的动态效果。 - 根据点到心形中心的距离计算力的大小和方向,增加动画的物理感。
- 使用力场模型 (
-
交互逻辑设计
- 设置“同意”和“拒绝”按钮,配合弹窗提示,实现趣味性互动。
- 通过点击事件触发心形动画,提升用户体验。
-
视觉样式和文字布局
- 使用画布背景色、字体样式和颜色(如
heartcolor
)增强界面美感。 - 利用
Label
元素和place
方法精确放置文字在窗口中心。
- 使用画布背景色、字体样式和颜色(如
-
模块化与类设计
- 封装了一个
Heart
类,专门负责爱心的点生成、动态计算和渲染,逻辑清晰、结构化强。 calc
方法和render
方法分别负责帧计算与绘制,职责分离,便于维护。
- 封装了一个
完整代码
import tkinter as tk
import tkinter.messagebox
import random
from math import sin, cos, pi, log
from tkinter.constants import *
width = 888
height = 500
heartx = width / 2
hearty = height / 2
side = 11
heartcolor = "pink" # 爱心颜色,可修改
word = "I Love You!" # 想要写的字,可修改
# 爱心类
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.random_halo = 1000
self.generate_frame = generate_frame
for 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))
@staticmethod
def 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 - dy
def calc(self, generate_frame):
ratio = 10 * curve(generate_frame / 10 * pi) # 圆滑的周期的缩放比例
halo_radius = int(4 + 6 * (1 + curve(generate_frame / 10 * pi)))
halo_number = int(3000 + 4000 * abs(curve(generate_frame / 10 * pi) ** 2))
all_points = []
heart_halo_point = set()
for _ in range(halo_number):
t = random.uniform(0, 2 * pi)
x, y = heart_function(t, shrink_ratio=11.6)
x, y = shrink(x, y, halo_radius)
if (x, y) not in heart_halo_point:
heart_halo_point.add((x, y))
x += random.randint(-14, 14)
y += random.randint(-14, 14)
size = random.choice((1, 2, 2))
all_points.append((x, y, size))
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_points
def render(self, render_canvas, render_frame):
for x, y, size in self.all_points[render_frame % self.generate_frame]:
render_canvas.create_rectangle(x, y, x + size, y + size, width=0, 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_ratio
y *= shrink_ratio
x += heartx
y += hearty
return int(x), int(y)
……
代码分析
这段代码是一个基于Python的Tkinter模块实现的互动式程序,主题是通过跳动的爱心动画来表达浪漫情感。以下从代码结构、主要功能模块、核心算法以及实现技巧等方面进行详细分析。
一、代码结构概览
代码结构清晰且功能分明,大致可以分为以下几个模块:
- 界面初始化与互动逻辑:
- 负责创建主窗口、弹出消息框,并引导用户进入爱心动画。
- 核心类
Heart
:- 负责爱心形状的坐标计算、动态扩散效果以及动画帧的生成。
- 数学函数与工具方法:
- 通过数学公式绘制爱心,并为动态效果提供支持。
- 动画渲染与绘制:
- 实现爱心形状的动态跳动,并在窗口中绘制动画。
- 主函数:
- 程序入口,负责引导用户操作。
二、核心功能分析
1. 用户交互界面
代码开头定义了一个简单的交互界面,用于向用户表达“求婚”意图:
root = tk.Tk()
root.title('❤')
root.resizable(0, 0)
root.wm_attributes("-toolwindow", 1)
- 界面标题:通过
root.title('❤')
,设置窗口标题为心形符号,增添浪漫氛围。 - 窗口属性:
root.resizable(0, 0)
禁止调整窗口大小,root.wm_attributes("-toolwindow", 1)
将窗口设置为工具窗口样式。 - 交互按钮:
好哦
按钮绑定了OK
方法,表示用户同意并进入动画界面。不要
按钮绑定了NO
方法,通过消息框提示用户“再给你一次机会”,强调必须点击同意才可继续。- 窗口关闭事件绑定到
closeWindow
方法,提示“逃避是没有用的哦”,进一步增强互动趣味性。
这部分代码设计了一个趣味性较强的“无法拒绝”的场景,为后续爱心动画营造铺垫。
2. 爱心动画的数学原理
(1)爱心函数 heart_function
- 该函数利用参数方程绘制爱心,
t
是参数范围,shrink_ratio
用于控制缩放比例。 - 数学方程细节:
- 横坐标公式:
16 * (sin(t) ** 3)
,通过三次方正弦曲线,确保爱心左右对称。 - 纵坐标公式:复杂的余弦叠加公式控制上下轮廓,使其具有自然的心形曲线。
- 横坐标公式:
(2)散点效果 scatter_inside
- 功能:在给定点
(x, y)
的基础上生成随机散点,模拟边缘和中心扩散效果。 - 原理:
- 利用随机数
random.random()
和对数函数log
实现随机偏移,beta
控制偏移范围。 - 偏移量根据距离中心点
(heartx, hearty)
的距离计算,呈现一种逐渐扩散的视觉效果。
- 利用随机数
(3)缩放函数 shrink
- 用于模拟爱心外边缘的扩散光环。
- 核心思想是通过引力公式,计算点向中心偏移的量,从而生成光晕效果。
3. 动态效果实现
(1)动态点计算
- 动态缩放比例
ratio
控制爱心的跳动,curve
函数生成平滑周期曲线,带来呼吸般的效果。
(2)光晕生成
- 光晕点以随机角度
t
和缩放比生成。 halo_number
随动态曲线调整,控制光晕点数量的变化。
4. 渲染与动画
(1)渲染实现
def render(self, render_canvas, render_frame):
for x, y, size in self.all_points[render_frame % self.generate_frame]:
render_canvas.create_rectangle(x, y, x + size, y + size, width=0, fill=heartcolor)
- 将动态点按帧渲染到
Canvas
画布上,通过循环绘制心形、扩散光晕和动态点。
(2)动画绘制
def draw(main: tk.Tk, render_canvas: tk.Canvas, render_heart: Heart, render_frame=0):
render_canvas.delete('all')
render_heart.render(render_canvas, render_frame)
main.after(160, draw, main, render_canvas, render_heart, render_frame + 1)
main.after()
定时调用,使每帧间隔160ms,带来平滑的跳动效果。render_frame
累加控制帧动画。
5. 爱心动画界面
进入动画后,窗口被设置为全屏效果:
root.geometry("%dx%d+%d+%d" % (width, height, x, y))
canvas = tk.Canvas(root, bg='black', height=height, width=width)
tk.Label(root, text=word, bg="black", fg="#FF99CC", font="Helvetic 25 bold").place(relx=.5, rely=.5, anchor=CENTER)
- 黑色背景衬托粉色爱心。
- 文本通过
tk.Label
居中显示,突出视觉中心。
三、总结
这段代码巧妙结合了数学公式和Tkinter界面功能,通过动态光效和跳动爱心的动画,生动地表达浪漫情感。亮点包括:
- 爱心函数:复杂的数学方程带来完美的心形曲线。
- 动态扩散效果:散点生成与光晕模拟为动画增添层次感。
- 人性化交互:有趣的“无法拒绝”逻辑增添趣味性。
通过这些实现,代码展示了Python在动态动画和界面设计中的强大能力,同时通过精心设计的互动流程和细腻的动画效果,完美达成情感表达的目标。
写在后面
我是一只有趣的兔子,感谢你的喜欢!