Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 192 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /