在代码的世界里,浪漫也能通过代码来实现。今天我们就来详细讲解如何使用 Python 实现一个跳动的爱心,也就是李洵同款的跳动爱心效果。通过这个项目,我们可以学习到 Python 的图形绘制、数学函数的运用以及动画的实现。
要实现跳动的爱心效果,我们主要分为以下几个步骤:
import random
from math import sin, cos, pi, log
from tkinter import *
这里我们导入了 random
库用于生成随机数,math
库中的三角函数和对数函数用于计算爱心的形状,tkinter
库用于创建图形界面。
CANVAS_WIDTH = 640
CANVAS_HEIGHT = 640
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
IMAGE_ENLARGE = 11
HEART_COLOR = "#Fd798f"
这些常量定义了画布的大小、中心点的位置、图像的放大倍数以及爱心的颜色。
def heart_function(t, shrink_ratio: float = IMAGE_ENLARGE):
x = 16 * (sin(t) ** 3)
y = -(15 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(3 * t))
x *= shrink_ratio
y *= shrink_ratio
x += CANVAS_CENTER_X
y += CANVAS_CENTER_Y
return int(x), int(y)
这个函数根据参数 t
计算爱心上的点的坐标,通过三角函数的组合来实现爱心的形状。shrink_ratio
参数用于调整爱心的大小。
def scatter_inside(x, y, beta=0.15):
ratio_x = -beta * log(random.random())
ratio_y = -beta * log(random.random())
dx = ratio_x * (x - CANVAS_CENTER_X)
dy = ratio_y * (y - CANVAS_CENTER_Y)
return x - dx, y - dy
这个函数用于在爱心内部随机生成扩散点,通过对数函数和随机数来实现扩散效果。
def shrink(x, y, ratio):
force = -1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.6)
dx = ratio * force * (x - CANVAS_CENTER_X)
dy = ratio * force * (y - CANVAS_CENTER_Y)
return x - dx, y - dy
这个函数用于收缩点的位置,根据点到中心点的距离来计算收缩的力度。
def curve(p):
return 2 * (2 * sin(4 * p)) / (2 * pi)
这个函数用于生成一个周期性的曲线,用于控制爱心的跳动效果。
Heart
类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.3)
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.2)
self._center_diffusion_points.add((x, y))
@staticmethod
def calc_position(x, y, ratio):
force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.520)
dx = ratio * force * (x - CANVAS_CENTER_X) + random.randint(-2, 2)
dy = ratio * force * (y - CANVAS_CENTER_Y) + random.randint(-2, 2)
return x - dx, y - dy
def calc(self, generate_frame):
ratio = 15 * curve(generate_frame / 15 * pi)
halo_radius = int(4 + 6 * (1 + curve(generate_frame / 15 * pi)))
halo_number = int(3000 + 4000 * abs(curve(generate_frame / 15 * 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.5)
x, y = shrink(x, y, halo_radius)
if (x, y) not in heart_halo_point:
heart_halo_point.add((x, y))
x += random.randint(-16, 16)
y += random.randint(-16, 16)
size = random.choice((2, 2, 1))
all_points.append((x, y, size))
for x, y in self._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._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=HEART_COLOR)
Heart
类是整个程序的核心,负责生成爱心的点、计算点的位置和大小,并将其绘制到画布上。具体来说:
__init__
方法:初始化爱心的点集,并调用 build
方法生成点,然后调用 calc
方法计算每一帧的点的位置。build
方法:生成爱心的基本点、边缘扩散点和中心扩散点。calc_position
方法:计算点的位置,根据点到中心点的距离和收缩比例来调整点的位置。calc
方法:计算每一帧的点的位置和大小,通过曲线函数来控制跳动效果。render
方法:将每一帧的点绘制到画布上。def draw(main: Tk, render_canvas: 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)
if __name__ == '__main__':
root = Tk()
root.title("")
canvas = Canvas(root, bg="black", height=CANVAS_HEIGHT, width=CANVAS_WIDTH)
canvas.pack()
heart = Heart()
draw(root, canvas, heart)
root.mainloop()
draw
函数用于绘制动画,通过定时调用自身来更新画面。在主程序中,我们创建了一个 Tkinter 窗口和画布,实例化了 Heart
类,并调用 draw
函数开始绘制动画。
import random
from math import sin, cos, pi,log
from tkinter import *
CANVAS_WIDTH = 640
CANVAS_HEIGHT = 640
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
IMAGE_ENLARGE = 11
HEART_COLOR ="#Fd798f"
def heart_function(t,shrink_ratio:float = IMAGE_ENLARGE):
x = 16*(sin(t)**3)
y = -(15*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(3*t))
x*=shrink_ratio
y*=shrink_ratio
x+=CANVAS_CENTER_X
y+=CANVAS_CENTER_Y
return 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-CANVAS_CENTER_X)
dy=ratio_y*(y-CANVAS_CENTER_Y)
return x-dx,y-dy
def shrink(x,y,ratio):
force=-1/(((x-CANVAS_CENTER_X)**2+(y-CANVAS_CENTER_Y)**2)**0.6)
dx=ratio*force*(x-CANVAS_CENTER_X)
dy=ratio*force*(y-CANVAS_CENTER_Y)
return x-dx,y-dy
def curve(p):
return 2*(2*sin(4*p))/(2*pi)
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.3)
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.2)
self._center_diffusion_points.add((x,y))
@staticmethod
def calc_position(x,y,ratio):
force=1/(((x-CANVAS_CENTER_X)**2+(y-CANVAS_CENTER_Y)**2)**0.520)
dx=ratio*force*(x-CANVAS_CENTER_X)+random.randint(-2,2)
dy=ratio*force*(y-CANVAS_CENTER_Y)+random.randint(-2,2)
return x-dx,y-dy
def calc(self,generate_frame):
ratio=15*curve(generate_frame/15*pi)
halo_radius=int(4+6*(1+curve(generate_frame/15*pi)))
halo_number=int(3000+4000*abs(curve(generate_frame/15*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.5)
x,y=shrink(x,y,halo_radius)
if (x,y) not in heart_halo_point:
heart_halo_point.add((x,y))
x+=random.randint(-16,16)
y+=random.randint(-16,16)
size=random.choice((2,2,1))
all_points.append((x,y,size))
for x,y in self._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._edge_diffusion_points:
x,y=self.calc_position(x,y,ratio)
size=random.randint(1,2)
all_points.append((x,y,size))
# self.all_point[generate_frame]=all_points
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=HEART_COLOR)
def draw(main: Tk,render_canvas: 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)
if __name__=='__main__':
root=Tk()
root.title("")
canvas=Canvas(root,bg="black",height=CANVAS_HEIGHT,width=CANVAS_WIDTH)
canvas.pack()
heart = Heart()
draw(root,canvas,heart)
root.mainloop()
通过以上步骤,我们使用 Python 实现了一个跳动的爱心效果。这个项目不仅展示了 Python 在图形绘制和动画实现方面的强大功能,还让我们学习到了数学函数在计算机图形学中的应用。你可以根据自己的需求调整代码中的参数,如爱心的颜色、大小、跳动的频率等,让爱心更加个性化。
希望这个教程能帮助你实现属于自己的浪漫代码!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有