Skip to content

Commit cd75bfd

Browse files
committed
提交代码
1 parent 4b30ceb commit cd75bfd

File tree

3 files changed

+390
-0
lines changed

3 files changed

+390
-0
lines changed

xianhuan/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Python技术 公众号文章代码库
1010

1111
## 实例代码
1212

13+
[好家伙,令女神尖叫的李峋同款爱心代码来了!](https://github.com/JustDoPython/python-examples/tree/master/xianhuan/shrinkheart):好家伙,令女神尖叫的李峋同款爱心代码来了!
14+
1315
[这个神器,让你的代码运行快上100倍!](https://github.com/JustDoPython/python-examples/tree/master/xianhuan/taichi):这个神器,让你的代码运行快上100倍!
1416

1517
[几个有趣且有用的Python自动化脚本](https://github.com/JustDoPython/python-examples/tree/master/xianhuan/pyscripts):几个有趣且有用的Python自动化脚本

xianhuan/shrinkheart/shrinkheart.py

+192
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import random
2+
from math import sin, cos, pi, log
3+
from tkinter import *
4+
5+
# 画布的宽
6+
CANVAS_WIDTH = 840
7+
# 画布的高
8+
CANVAS_HEIGHT = 680
9+
# 画布中心的X轴坐标
10+
CANVAS_CENTER_X = CANVAS_WIDTH / 2
11+
# 画布中心的Y轴坐标
12+
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
13+
# 放大比例
14+
IMAGE_ENLARGE = 11
15+
16+
HEART_COLOR = "#EEAEEE"
17+
18+
"""
19+
爱心函数生成器
20+
-shrink_ratio: 放大比例
21+
-t: 参数
22+
"""
23+
def heart_function(t, shrink_ratio: float = IMAGE_ENLARGE):
24+
# 基础函数
25+
x = 17 * (sin(t) ** 3)
26+
y = -(16 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(3 * t))
27+
28+
# 放大
29+
x*=IMAGE_ENLARGE
30+
y*=IMAGE_ENLARGE
31+
# 移到画布中央
32+
x += CANVAS_CENTER_X
33+
y += CANVAS_CENTER_Y
34+
35+
return int(x), int(y)
36+
37+
"""
38+
随机内部扩散
39+
-x: 原x
40+
-y: 原y
41+
-beta: 强度
42+
"""
43+
def scatter_inside(x, y, beta=0.15):
44+
ratio_x = - beta * log(random.random())
45+
ratio_y = - beta * log(random.random())
46+
47+
dx = ratio_x * (x - CANVAS_CENTER_X)
48+
dy = ratio_y * (y - CANVAS_CENTER_Y)
49+
50+
return x - dx, y - dy
51+
52+
53+
"""
54+
抖动
55+
-x: 原x
56+
-y: 原y
57+
-ratio: 比例
58+
"""
59+
def shrink(x, y, ratio):
60+
61+
force = -1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.6) # 这个参数...
62+
dx = ratio * force * (x - CANVAS_CENTER_X)
63+
dy = ratio * force * (y - CANVAS_CENTER_Y)
64+
return x - dx, y - dy
65+
66+
67+
"""
68+
自定义曲线函数,调整跳动周期
69+
-p: 参数
70+
"""
71+
def curve(p):
72+
# 可以尝试换其他的动态函数,达到更有力量的效果(贝塞尔?)
73+
return 2 * (2 * sin(4 * p)) / (2 * pi)
74+
75+
76+
# 爱心类
77+
class Heart:
78+
def __init__(self, generate_frame=20):
79+
# 原始爱心坐标集合
80+
self._points = set()
81+
# 边缘扩散效果点坐标集合
82+
self._edge_diffusion_points = set()
83+
# 中心扩散效果点坐标集合
84+
self._center_diffusion_points = set()
85+
# 每帧动态点坐标
86+
self.all_points = {}
87+
self.build(2000)
88+
89+
self.random_halo = 1000
90+
91+
self.generate_frame = generate_frame
92+
for frame in range(generate_frame):
93+
self.calc(frame)
94+
95+
def build(self, number):
96+
# 爱心
97+
for _ in range(number):
98+
# 随机不到的地方造成爱心有缺口
99+
t = random.uniform(0, 2 * pi)
100+
x, y = heart_function(t)
101+
self._points.add((x, y))
102+
103+
# 爱心内扩散
104+
for _x, _y in list(self._points):
105+
for _ in range(3):
106+
x, y = scatter_inside(_x, _y, 0.05)
107+
self._edge_diffusion_points.add((x, y))
108+
109+
# 爱心内再次扩散
110+
point_list = list(self._points)
111+
for _ in range(10000):
112+
x, y = random.choice(point_list)
113+
x, y = scatter_inside(x, y, 0.27)
114+
self._center_diffusion_points.add((x, y))
115+
116+
@staticmethod
117+
def calc_position(x, y, ratio):
118+
# 调整缩放比例
119+
force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.420) # 魔法参数
120+
121+
dx = ratio * force * (x - CANVAS_CENTER_X) + random.randint(-1, 1)
122+
dy = ratio * force * (y - CANVAS_CENTER_Y) + random.randint(-1, 1)
123+
124+
return x - dx, y - dy
125+
126+
def calc(self, generate_frame):
127+
# 圆滑的周期的缩放比例
128+
ratio = 15 * curve(generate_frame / 10 * pi)
129+
130+
halo_radius = int(4 + 6 * (1 + curve(generate_frame / 10 * pi)))
131+
halo_number = int(3000 + 4000 * abs(curve(generate_frame / 10 * pi) ** 2))
132+
133+
all_points = []
134+
135+
# 光环
136+
heart_halo_point = set()
137+
# 光环的点坐标集合
138+
for _ in range(halo_number):
139+
# 随机不到的地方造成爱心有缺口
140+
t = random.uniform(0, 2 * pi)
141+
# 魔法参数
142+
x, y = heart_function(t, shrink_ratio=-15)
143+
x, y = shrink(x, y, halo_radius)
144+
if (x, y) not in heart_halo_point:
145+
# 处理新的点
146+
heart_halo_point.add((x, y))
147+
x += random.randint(-60, 60)
148+
y += random.randint(-60, 60)
149+
size = random.choice((1, 1, 2))
150+
all_points.append((x, y, size))
151+
all_points.append((x+20, y+20, size))
152+
all_points.append((x-20, y -20, size))
153+
all_points.append((x+20, y - 20, size))
154+
all_points.append((x - 20, y +20, size))
155+
156+
# 轮廓
157+
for x, y in self._points:
158+
x, y = self.calc_position(x, y, ratio)
159+
size = random.randint(1, 3)
160+
all_points.append((x, y, size))
161+
162+
# 内容
163+
for x, y in self._edge_diffusion_points:
164+
x, y = self.calc_position(x, y, ratio)
165+
size = random.randint(1, 2)
166+
all_points.append((x, y, size))
167+
168+
for x, y in self._center_diffusion_points:
169+
x, y = self.calc_position(x, y, ratio)
170+
size = random.randint(1, 2)
171+
all_points.append((x, y, size))
172+
173+
self.all_points[generate_frame] = all_points
174+
175+
def render(self, render_canvas, render_frame):
176+
for x, y, size in self.all_points[render_frame % self.generate_frame]:
177+
render_canvas.create_rectangle(x, y, x + size, y + size, width=0, fill=HEART_COLOR)
178+
179+
180+
def draw(main: Tk, render_canvas: Canvas, render_heart: Heart, render_frame=0):
181+
render_canvas.delete('all')
182+
render_heart.render(render_canvas, render_frame)
183+
main.after(1, draw, main, render_canvas, render_heart, render_frame + 1)
184+
185+
186+
if __name__ == '__main__':
187+
root = Tk()
188+
canvas = Canvas(root, bg='black', height=CANVAS_HEIGHT, width=CANVAS_WIDTH)
189+
canvas.pack()
190+
heart = Heart()
191+
draw(root, canvas, heart)
192+
root.mainloop()

0 commit comments

Comments
 (0)