本文转自网络文章,已获取原文作者授权。 原文作者:逆境清醒
这篇文章是python 绘制爱心动画的源码集锦合集,每篇都附有原作者的名字博客链接。使用时将代码复制后在相关的编程语言环境下运行。
代码仅供学习参考,请尊重原作者的创作和版权!
如果代码作者转载地址有错,请原作者留言,我会更正相应的代码原作者博客链接。
一、代码效果预览索引图
本文收集的python绘制的爱心动画源代码,主要涉及的模块有turtle、tkinter、math等。代码涉及的库,学习研究运行前需确保代码需要的库函数有安装。
11、空心立体爱心 12、李峋同款爱心代码【有声版】 8、最先复现李峋爱心代码的作者 9、跳动爱心 10、爱心 5、粒子组成爱心,中间加字 6、粒子组成爱心 7、粒子组成爱心 1、(弧线型)(显示文字) 2、(直线型)(显示文字) 3、(弧线型)(输入显示文字) 4、爱心树
python字符画爱心 此部分的代码会显示在终端,如果你没有打开终端会看不到效果。如果你没有专业的代码编辑器,只想试试效果,运行方式:1、安装python配置好环境2、将代码完整复制,保存成:你的文件名.py3、同时按window+R键,输入cmd,打开命令提示符窗口输入:python 你的文件名.py(1)一行代码画爱心 (2)用字符输出 I 爱 U (2种形式) (2)用字符输出 I 爱 U (2种形式) (3)输出五个爱心(Dear I love you forever! )五个单词填充而成 (4)爱心 (5)爱心
二、爱心源代码集锦
如果你没有专业的代码编辑器,只想试试效果,运行方式:
1、安装python配置好环境
2、将代码完整复制,保存成:你的文件名.py
3、同时按window+R键,输入cmd,打开命令提示符窗口
输入:python 你的文件名.py(注:python后面有空格)
(1)、爱心图形1(弧线型)(显示的文字写在代码里) 转载地址:https://blog.csdn.net/qq_55342245/article/details/120904578
import turtle
import time
def LittleHeart ( ) :
for i in range ( 200 ) :
turtle. right( 1 )
turtle. forward( 2 )
love= 'I Love you'
me = '卧槽,这年轻人。'
turtle. setup( width= 900 , height= 600 )
turtle. color( 'red' , 'red' )
turtle. pensize( 5 )
turtle. speed( 1000000 )
turtle. up( )
turtle. hideturtle( )
turtle. goto( 0 , - 180 )
turtle. showturtle( )
turtle. down( )
turtle. speed( 5 )
turtle. begin_fill( )
turtle. left( 140 )
turtle. forward( 224 )
LittleHeart( )
turtle. left( 120 )
LittleHeart( )
turtle. forward( 224 )
turtle. end_fill( )
turtle. pensize( 5 )
turtle. up( )
turtle. hideturtle( )
turtle. goto( 0 , 0 )
turtle. showturtle( )
turtle. color( '#CD5C5C' , 'pink' )
turtle. write( love, font= ( 'gungsuh' , 30 , ) , align= "center" )
turtle. up( )
turtle. hideturtle( )
if me != '' :
turtle. color( 'black' , 'pink' )
time. sleep( 2 )
turtle. goto( 180 , - 180 )
turtle. showturtle( )
turtle. write( me, font= ( 20 , ) , align= "center" , move= True )
window= turtle. Screen( )
window. exitonclick( )
(2)、爱心图形2(直线型)(显示的文字写在代码里) 转载地址:https://blog.csdn.net/qq_55342245/article/details/120904578
import turtle
import math
turtle. pen( )
t= turtle
t. up( )
t. goto( 0 , 150 )
t. down( )
t. color( 'red' )
t. begin_fill( )
t. fillcolor( 'red' )
t. speed( 1 )
t. left( 45 )
t. forward( 150 )
t. right( 45 )
t. forward( 100 )
t. right( 45 )
t. forward( 100 )
t. right( 45 )
t. forward( 100 )
t. right( 45 )
t. forward( 250 + math. sqrt( 2 ) * 100 )
t. right ( 90 )
t. speed( 2 )
t. forward( 250 + 100 * math. sqrt( 2 ) )
t. right( 45 )
t. forward( 100 )
t. right( 45 )
t. forward( 100 )
t. right( 45 )
t. forward( 100 )
t. right( 45 )
t. forward( 150 )
t. end_fill( )
t. goto( - 10 , 0 )
t. pencolor( 'white' )
t. pensize( 10 )
t. goto( - 50 , 0 )
t. goto( - 50 , 80 )
t. up ( )
t. goto( - 100 , 0 )
t. down( )
t. goto( - 160 , 0 )
t. goto( - 130 , 0 )
t. goto( - 130 , 80 )
t. goto( - 160 , 80 )
t. goto( - 100 , 80 )
t. up( )
t. goto( 10 , 25 )
t. down( )
t. right( 45 )
t. circle( 25 , extent= 180 )
t. goto( 60 , 55 )
t. circle( 25 , extent= 180 )
t. goto( 10 , 25 )
t. up( )
t. goto( 75 , 80 )
t. down( )
t. goto( 100 , 0 )
t. goto( 125 , 80 )
t. up( )
t. goto( 180 , 80 )
t. down( )
t. goto( 140 , 80 )
t. goto( 140 , 0 )
t. goto( 180 , 0 )
t. up( )
t. goto( 180 , 40 )
t. down( )
t. goto( 140 , 40 )
t. up( )
t. goto( - 40 , - 30 )
t. down( )
t. goto( - 40 , - 80 )
t. circle( 40 , extent= 180 )
t. goto( 40 , - 30 )
t. hideturtle( )
window= turtle. Screen( )
window. exitonclick( )
(3)、爱心图形3(弧线型)(通过输入方式显示文字) 请输入表白语句,然后回车,(例如"I Love You"):请输入要表白的人(例如"李思思"): 转载地址:https://changxin.blog.csdn.net/article/details/109842795
import turtle
import time
def LittleHeart ( ) :
for i in range ( 200 ) :
turtle. right( 1 )
turtle. forward( 2 )
love= input ( '请输入表白语句,然后回车,(例如"I Love You"):\n' )
me= input ( '请输入要表白的人(例如"李思思"):\n' )
if love== '' :
love= 'I Love you'
turtle. setup( width= 900 , height= 600 )
turtle. color( 'red' , 'pink' )
turtle. pensize( 15 )
turtle. speed( 1000 )
turtle. up( )
turtle. hideturtle( )
turtle. goto( 0 , - 180 )
turtle. showturtle( )
turtle. down( )
turtle. speed( 500 )
turtle. begin_fill( )
turtle. left( 140 )
turtle. forward( 224 )
LittleHeart( )
turtle. left( 120 )
LittleHeart( )
turtle. forward( 224 )
turtle. end_fill( )
turtle. pensize( 12 )
turtle. up( )
turtle. hideturtle( )
turtle. goto( 0 , - 20 )
turtle. showturtle( )
turtle. color( '#CD5C5C' , 'pink' )
turtle. write( love, font= ( 'gungsuh' , 50 , ) , align= "center" )
turtle. up( )
turtle. hideturtle( )
if me != '' :
turtle. color( 'black' , 'pink' )
time. sleep( 1 )
turtle. goto( 180 , - 180 )
turtle. showturtle( )
turtle. write( me, font= ( 20 , 25 ) , align= "center" , move= True )
window= turtle. Screen( )
window. exitonclick( )
(4)、用python绘制爱心树 转载地址:https://blog.csdn.net/qq_55342245/article/details/120904578
import turtle
import random
def love ( x, y) :
lv = turtle. Turtle( )
lv. hideturtle( )
lv. up( )
lv. goto( x, y)
def curvemove ( ) :
for i in range ( 20 ) :
lv. right( 10 )
lv. forward( 2 )
lv. color( 'red' , 'pink' )
lv. speed( 10000000 )
lv. pensize( 1 )
lv. down( )
lv. begin_fill( )
lv. left( 140 )
lv. forward( 22 )
curvemove( )
lv. left( 120 )
curvemove( )
lv. forward( 22 )
lv. write( "YZ" , font= ( "Arial" , 12 , "normal" ) , align= "center" )
lv. left( 140 )
lv. end_fill( )
def tree ( branchLen, t) :
if branchLen > 5 :
if branchLen < 20 :
t. color( "green" )
t. pensize( random. uniform( ( branchLen + 5 ) / 4 - 2 , ( branchLen + 6 ) / 4 + 5 ) )
t. down( )
t. forward( branchLen)
love( t. xcor( ) , t. ycor( ) )
t. up( )
t. backward( branchLen)
t. color( "brown" )
return
t. pensize( random. uniform( ( branchLen + 5 ) / 4 - 2 , ( branchLen + 6 ) / 4 + 5 ) )
t. down( )
t. forward( branchLen)
ang = random. uniform( 15 , 45 )
t. right( ang)
tree( branchLen - random. uniform( 12 , 16 ) , t)
t. left( 2 * ang)
tree( branchLen - random. uniform( 12 , 16 ) , t)
t. right( ang)
t. up( )
t. backward( branchLen)
myWin = turtle. Screen( )
t = turtle. Turtle( )
t. hideturtle( )
t. speed( 1000 )
t. left( 90 )
t. up( )
t. backward( 200 )
t. down( )
t. color( "brown" )
t. pensize( 32 )
t. forward( 60 )
tree( 100 , t)
myWin. exitonclick( )
(5)、粒子系统组成爱心,中间加字 注释调参改变下面这里的代码 text=“”位置 改成自己想要的文字, 不想要可以直接去掉代码text:想要表现的文本 fg:文字颜色 bg文字的背景颜色(其实有瑕疵的因为文字是更上一层的图层会有覆盖) text1 = Label(root, text=“By SilverPriest ᏊˊꈊˋᏊ”, font=(“Helvetica”, 18), fg=“#c12bec”,bg = “black”) text1.place(x=650, y=500) text2 = Label(root, text=“爱你”,font = (“Helvetica”, 18), fg = “#c12bec” ,bg = “black”) # text2.place(x=460, y=350) https://blog.csdn.net/CL_Young/article/details/127893960
import random
from math import sin, cos, pi, log
from tkinter import *
CANVAS_WIDTH = 980
CANVAS_HEIGHT = 720
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
IMAGE_ENLARGE = 11
HEART_COLOR_LIST = [ "#d974ff" , "#be77fa" , "#a478f3" , "#8b78ea" , "#7377e0" ,
"#4871c6" , "#5c74d3" , "#fa6ea9" , "#dc6db1" , "#ec2c2c" ,
"#e91e41" , "#8b4593" , "#2bd3ec" , "#00be93" , "#2bec62" ]
def heart_function ( t, shrink_ratio: float = IMAGE_ENLARGE) :
"""
create a heart
:param shrink_ratio: ratio
:param t: parameter
:return: x, y
"""
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 += CANVAS_CENTER_X
y += CANVAS_CENTER_Y
return int ( x) , int ( y)
def scatter_inside ( x, y, beta= 1.15 ) :
"""
random inner spreading
:param x: orig x
:param y: orig y
:param beta: strength
:return: new x, y
"""
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) :
"""
shrink
:param x: orig x
:param y: orig y
:param ratio: ratio
:return: new x,y
"""
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) :
"""
tune beating period
:param p: parameter
:return: sin
"""
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.05 )
self. _edge_diffusion_points. add( ( x, y) )
point_list = list ( self. _points)
for _ in range ( 6000 ) :
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 - CANVAS_CENTER_X) ** 2 + ( y - CANVAS_CENTER_Y) ** 2 ) ** 0.520 )
dx = ratio * force * ( x - CANVAS_CENTER_X) + random. randint( - 1 , 1 )
dy = ratio * force * ( y - CANVAS_CENTER_Y) + 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 + 6000 * 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= random. choice( HEART_COLOR_LIST) )
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( 70 , draw, main, render_canvas, render_heart, render_frame + 1 )
if __name__ == '__main__' :
root = Tk( )
canvas = Canvas( root, bg= 'black' , height= CANVAS_HEIGHT, width= CANVAS_WIDTH)
canvas. pack( )
heart = Heart( )
draw( root, canvas, heart)
text1 = Label( root, text= "By SilverPriest ᏊˊꈊˋᏊ" , font= ( "Helvetica" , 18 ) , fg= "#c12bec" , bg = "black" )
text1. place( x= 650 , y= 500 )
text2 = Label( root, text= "爱你" , font = ( "Helvetica" , 18 ) , fg = "#c12bec" , bg = "black" )
text2. place( x= 460 , y= 350 )
root. mainloop( )
(6)、粒子系统组成爱心 https://blog.csdn.net/CL_Young/article/details/127808312
import random
from math import sin, cos, pi, log
from tkinter import *
CANVAS_WIDTH = 840
CANVAS_HEIGHT = 680
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
IMAGE_ENLARGE = 11
HEART_COLOR = "#EEAEEE"
def heart_function ( t, shrink_ratio: float = IMAGE_ENLARGE) :
"""
“爱心函数生成器”
:param shrink_ratio: 放大比例
:param t: 参数
:return: 坐标
"""
x = 17 * ( sin( t) ** 3 )
y = - ( 16 * cos( t) - 5 * cos( 2 * t) - 2 * cos( 3 * t) - cos( 3 * t) )
x*= IMAGE_ENLARGE
y*= IMAGE_ENLARGE
x += CANVAS_CENTER_X
y += CANVAS_CENTER_Y
return int ( x) , int ( y)
def scatter_inside ( x, y, beta= 0.15 ) :
"""
随机内部扩散
:param x: 原x
:param y: 原y
:param beta: 强度
:return: 新坐标
"""
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) :
"""
抖动
:param x: 原x
:param y: 原y
:param ratio: 比例
:return: 新坐标
"""
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) :
"""
自定义曲线函数,调整跳动周期
:param p: 参数
:return: 正弦
"""
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.05 )
self. _edge_diffusion_points. add( ( x, y) )
point_list = list ( self. _points)
for _ in range ( 10000 ) :
x, y = random. choice( point_list)
x, y = scatter_inside( x, y, 0.27 )
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.420 )
dx = ratio * force * ( x - CANVAS_CENTER_X) + random. randint( - 1 , 1 )
dy = ratio * force * ( y - CANVAS_CENTER_Y) + random. randint( - 1 , 1 )
return x - dx, y - dy
def calc ( self, generate_frame) :
ratio = 15 * 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= - 15 )
x, y = shrink( x, y, halo_radius)
if ( x, y) not in heart_halo_point:
heart_halo_point. add( ( x, y) )
x += random. randint( - 60 , 60 )
y += random. randint( - 60 , 60 )
size = random. choice( ( 1 , 1 , 2 ) )
all_points. append( ( x, y, size) )
all_points. append( ( x+ 20 , y+ 20 , size) )
all_points. append( ( x- 20 , y - 20 , size) )
all_points. append( ( x+ 20 , y - 20 , size) )
all_points. append( ( x - 20 , y + 20 , 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= 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( 1 , draw, main, render_canvas, render_heart, render_frame + 1 )
if __name__ == '__main__' :
root = Tk( )
canvas = Canvas( root, bg= 'black' , height= CANVAS_HEIGHT, width= CANVAS_WIDTH)
canvas. pack( )
heart = Heart( )
draw( root, canvas, heart)
root. mainloop( )
(7)、粒子系统组成爱心 https://blog.csdn.net/CL_Young/article/details/1270831
import random
from math import sin, cos, pi, log
from tkinter import *
CANVAS_WIDTH = 640
CANVAS_HEIGHT = 480
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
IMAGE_ENLARGE = 11
HEART_COLOR = "pink"
def heart_function ( t, shrink_ratio: float = IMAGE_ENLARGE) :
"""
“爱心函数生成器”
:param shrink_ratio: 放大比例
:param t: 参数
:return: 坐标
"""
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 += CANVAS_CENTER_X
y += CANVAS_CENTER_Y
return int ( x) , int ( y)
def scatter_inside ( x, y, beta= 0.15 ) :
"""
随机内部扩散
:param x: 原x
:param y: 原y
:param beta: 强度
:return: 新坐标
"""
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) :
"""
抖动
:param x: 原x
:param y: 原y
:param ratio: 比例
:return: 新坐标
"""
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) :
"""
自定义曲线函数,调整跳动周期
:param p: 参数
:return: 正弦
"""
return 4 * ( 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.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 - CANVAS_CENTER_X) ** 2 + ( y - CANVAS_CENTER_Y) ** 2 ) ** 0.520 )
dx = ratio * force * ( x - CANVAS_CENTER_X) + random. randint( - 1 , 1 )
dy = ratio * force * ( y - CANVAS_CENTER_Y) + 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 )
x, y = shrink( x, y, halo_radius)
if ( x, y) not in heart_halo_point:
heart_halo_point. add( ( x, y) )
x += random. randint( - 11 , 11 )
y += random. randint( - 11 , 11 )
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. _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( )
canvas = Canvas( root, bg= 'black' , height= CANVAS_HEIGHT, width= CANVAS_WIDTH)
canvas. pack( )
heart = Heart( )
draw( root, canvas, heart)
root. mainloop( )
(8)、最先复现“李峋爱心”代码的作者 电视剧 【点燃我,温暖你】让“李峋爱心”红起来,网上有很多转载的,原来的作者是谁,我一直找不到,刚刚才发现作者Littlesbai,“李峋爱心代码”发布博客时间是 2022.11.08,而且文中有对代码优化的部分,应该是最先复现“李峋爱心”代码的作者。原创不易,请大家多支持原创作者。 转载地址:李峋爱心代码_Littlesbai的博客-CSDN博客
import random
from math import sin, cos, pi, log
from tkinter import *
CANVAS_WIDTH = 640
CANVAS_HEIGHT = 480
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
IMAGE_ENLARGE = 11
HEART_COLOR = "#FF99CC"
def center_window ( root, width, height) :
screenwidth = root. winfo_screenwidth( )
screenheight = root. winfo_screenheight( )
size = '%dx%d+%d+%d' % ( width, height, ( screenwidth - width) /
2 , ( screenheight - height) / 2 )
root. geometry( size)
def heart_function ( t, shrink_ratio: float = IMAGE_ENLARGE) :
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 += 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.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 - CANVAS_CENTER_X) ** 2 +
( y - CANVAS_CENTER_Y) ** 2 ) ** 0.520 )
dx = ratio * force * ( x - CANVAS_CENTER_X) + random. randint( - 1 , 1 )
dy = ratio * force * ( y - CANVAS_CENTER_Y) + 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) )
self. all_points[ 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( "爱心" )
center_window( root, CANVAS_WIDTH, CANVAS_HEIGHT)
canvas = Canvas( root, bg= 'black' , height= CANVAS_HEIGHT, width= CANVAS_WIDTH)
canvas. pack( )
heart = Heart( )
draw( root, canvas, heart)
Label( root, text= "你想要替换的文字" , bg= "black" , fg= "#FF99CC" , font= "Helvetic 20 bold" ) . place(
relx= .5 , rely= .5 , anchor= CENTER)
root. mainloop( )
(9)、跳动爱心此代码需要用到import pgzrun,安装方式不是pgzrun,而是pgzero ,请留意 pip install pgzero 以下文字转自作者: https://blog.csdn.net/qq_40523737/article/details/127967411 1、用pgzero 库。然后结合最后那个极坐标爱心曲线代码,先绘制出曲线上离散的点。 2. 把点的数量增加,同时沿着原点到每个点的径向加一个随机数,并且这个随机数是按照正态分布来的(半个正态分布),大概率分布在曲线上,向曲线内部递减。这样,就得到这样一个随机分布的爱心效果。 3. 下面就是让点动起来,将每个点自定义成了一个Particle类的实例。从原理上来说,就是给每个点加一个缩放系数,这个系数是根据时间变化的正弦函数,看起来就会像呼吸的节律一样。 4. 剧中爱心跳动时,靠中间的点波动的幅度更大,有一种扩张的效果。所以再根据每个点距离原点的远近,再加上一个系数,离得越近,系数越大。 5. 最后再用同样的方法画一个更大一点的爱心,这个爱心不需要跳动,只要每一帧随机绘制就可以了。 合在一起,搞定! 总结一下,就是在原本的基础爱心曲线上加上一个正态分布的随机量、一个随时间变化的正弦函数和一个跟距离成反比的系数,外面再套一层更大的随机爱心,就得到类似剧中的跳动爱心效果。 电视剧里的代码真能运行吗?_Crossin的编程教室的博客-CSDN博客
import pgzrun
from math import pi, sin, cos
import random
class Particle ( ) :
def __init__ ( self, pos, size, f) :
self. pos = pos
self. pos0 = pos
self. size = size
self. f = f
def draw ( self) :
global L
screen. draw. filled_rect( Rect( ( L* self. f* self. pos[ 0 ] + 400 , - L* self. f* self. pos[ 1 ] + 300 ) , self. size) , 'hot pink' )
def update ( self, t) :
df = 1 + ( 4 - 3 * self. f) * sin( t * 3 ) / 12
self. pos = self. pos0[ 0 ] * df, self. pos0[ 1 ] * df
tt = [ 105 , 102 , 98 , 115 , 117 , 33 , 112 , 103 , 33 , 106 , 108 , 118 , 111 , 33 , 46 , 33 , 68 , 115 , 112 , 116 , 116 , 106 , 111 , 30341 , 32535 , 31244 , 25946 , 23461 ]
no_p = 20000
dt = 2 * pi/ no_p
particles = [ ]
t = 0
c = 0
while t < 2 * pi:
c += 1
sigma = 0.15 if c % 5 else 0.3
f = 1 - abs ( random. gauss( 1 , sigma) - 1 )
x = 16 * sin( t) ** 3
y = 13 * cos( t) - 5 * cos( 2 * t) - 2 * cos( 3 * t) - cos( 4 * t)
size = ( random. uniform( 0.5 , 2.5 ) , random. uniform( 0.5 , 2.5 ) )
particles. append( Particle( ( x, y) , size, f) )
t += dt
def draw ( ) :
screen. clear( )
for p in particles:
p. draw( )
if L == 10 :
t = 0
while t < 2 * pi:
f = random. gauss( 1.1 , 0.1 )
x = 16 * sin( t) ** 3
y = 13 * cos( t) - 5 * cos( 2 * t) - 2 * cos( 3 * t) - cos( 4 * t)
size = ( random. uniform( 0.5 , 2.5 ) , random. uniform( 0.5 , 2.5 ) )
screen. draw. filled_rect( Rect( ( 10 * f* x + 400 , - 10 * f* y + 300 ) , size) , 'hot pink' )
t += dt * 3
screen. draw. filled_rect( Rect( ( - 10 * 11 + 400 , 11 * 20 + 200 ) , ( 2 , 2 ) ) , 'hot pink' )
TITLE = '' . join( [ chr ( i- 1 ) for i in tt] )
status = 0
L = 100
elapsed = 0
def update ( dt) :
global elapsed, L, status
elapsed += dt
if status == 0 :
L -= dt * 200
if L <= 10 :
status = 1
L = 10
elif status == 2 :
L += dt * 200
for p in particles:
p. update( elapsed)
TITLE = 'heart of ikun - Crossin的编程教室'
pgzrun. go( )
import pgzrun
from math import pi, sin, cos
no_p = 100
dt = 2 * 3 / no_p
t = 0
x = [ ]
y = [ ]
while t <= 2 * 3 :
x. append( 16 * sin( t) ** 3 )
y. append( 13 * cos( t) - 5 * cos( 2 * t) - 2 * cos( 3 * t) - cos( 4 * t) )
t += dt
def draw ( ) :
screen. clear( )
for i in range ( len ( x) ) :
screen. draw. filled_rect( Rect( ( x[ i] * 10 + 400 , - y[ i] * 10 + 300 ) , ( 4 , 4 ) ) , 'pink' )
pgzrun. go( )
11、空心立体爱心
import turtle as t
t. penup( )
t. seth( - 90 )
t. fd( 160 )
t. pendown( )
t. pensize( 20 )
t. colormode( 255 )
for j in range ( 10 ) :
t. speed( 0 )
t. pencolor( 20 * j, 2 * j, 20 * j)
t. seth( 130 )
t. fd( 215 )
for i in range ( 23 ) :
t. circle( - 80 , 10 )
t. seth( 100 )
for i in range ( 23 ) :
t. circle( - 80 , 10 )
t. fd( 215 )
t. hideturtle( )
t. done( )
import random
import pyttsx3
from pygame import mixer
from math import sin, cos, pi, log
from tkinter import *
CANVAS_WIDTH = 1920
CANVAS_HEIGHT = 1080
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
IMAGE_ENLARGE = 15
HEART_COLOR = "#Fd789f"
def speak_voice ( message, speak_mode= 0 ) :
"""
“文字转语音”
:param message: 文本消息
:param speak_mode: 语音包,0 中文女声,1 英文女声,2 英文男声
"""
engine = pyttsx3. init( )
voices = engine. getProperty( 'voices' )
rate = engine. getProperty( 'rate' )
engine. setProperty( 'rate' , rate - 100 )
engine. setProperty( 'volume' , 0.8 )
engine. setProperty( 'voice' , voices[ speak_mode] . id )
engine. say( message)
engine. runAndWait( )
def heart_voice ( file_path, playback_mode= - 1 ) :
"""
“噗噗的心跳声”
:param file_path: mp3文件路径
:param playback_mode: 播放模式,-1 为循环播放
"""
mixer. init( )
mixer. music. load( file_path)
mixer. music. play( playback_mode)
def heart_function ( t, shrink_ratio: float = IMAGE_ENLARGE) :
"""
“爱心函数生成器”
:param shrink_ratio: 放大比例
:param t: 参数
:return: 坐标
"""
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 += CANVAS_CENTER_X
y += CANVAS_CENTER_Y
return int ( x) , int ( y)
def scatter_inside ( x, y, beta= 0.15 ) :
"""
随机内部扩散
:param x: 原x
:param y: 原y
:param beta: 强度
:return: 新坐标
"""
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) :
"""
抖动
:param x: 原x
:param y: 原y
:param ratio: 比例
:return: 新坐标
"""
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) :
"""
自定义曲线函数,调整跳动周期
:param p: 参数
:return: 正弦
"""
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.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 - CANVAS_CENTER_X) ** 2 + ( y - CANVAS_CENTER_Y) ** 2 ) ** 0.520 )
dx = ratio * force * ( x - CANVAS_CENTER_X) + random. randint( - 1 , 1 )
dy = ratio * force * ( y - CANVAS_CENTER_Y) + 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= 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)
speak_voice( "请收下我的心!" )
heart_voice( "mp3/51miz-S283175-043A2FE9.mp3" )
root. mainloop( )
三、python字符画爱心
此部分的代码会显示在终端,如果你没有打开终端会看不到效果。如果你没有专业的代码编辑器,只想试试效果,运行方式:
1、安装python配置好环境
2、将代码完整复制,保存成:你的文件名.py
3、同时按window+R键,输入cmd,打开命令提示符窗口
输入:python 你的文件名.py
(1)、一行代码画爱心 print(‘\n’.join([‘’.join([(‘Love’[(x-y)%len(‘Love’)] if ((x0.05)**2+(y 0.1)**2-1)**3-(x0.05)*2 (y 0.1)**3<=0 else’ ') for x in range(-30,30)]) for y in range(15,-15,-1)]))
`a = [ `
`'' . join( `
`[ `
`( `
`'Love' [ ( x- y) % len ( 'Love' ) ] `
`if ( ( x* 0.05 ) ** 2 + ( y* 0.1 ) ** 2 - 1 ) ** 3 - ( x* 0.05 ) ** 2 * ( y* 0.1 ) ** 3 <= 0 else ' ' `
`) `
`for x in range ( - 30 , 30 ) `
`] `
`) `
`for y in range ( 15 , - 15 , - 1 ) `
`] `
`print ( '\n' . join( a) ) `
(2)、用字符输出 I 爱 U (2种形式)
import time
y = 2.5
while y>= - 1.6 :
x = - 3.0
while x<= 4.0 :
if ( x* x+ y* y- 1 ) ** 3 <= 3.6 * x* x* y* y* y or ( x> - 2.4 and x< - 2.1 and y< 1.5 and y> - 1 ) or ( ( ( x< 2.5 and x> 2.2 ) or ( x> 3.4 and x< 3.7 ) ) and y> - 1 and y< 1.5 ) or ( y> - 1 and y< - 0.6 and x< 3.7 and x> 2.2 ) :
print ( ' ' , end= "" )
else :
print ( '*' , end= "" )
x += 0.1
print ( )
time. sleep( 0.25 )
y -= 0.2
参考:https://blog.csdn.net/qq_55342245/article/details/120904578
import time
y = 2.5
while y>= - 1.6 :
x = - 3.0
while x<= 4.0 :
if ( x* x+ y* y- 1 ) ** 3 <= 3.6 * x* x* y* y* y or ( x> - 2.4 and x< - 2.1 and y< 1.5 and y> - 1 ) or ( ( ( x< 2.5 and x> 2.2 ) or ( x> 3.4 and x< 3.7 ) ) and y> - 1 and y< 1.5 ) or ( y> - 1 and y< - 0.6 and x< 3.7 and x> 2.2 ) :
print ( '*' , end= "" )
else :
print ( ' ' , end= "" )
x += 0.1
print ( )
time. sleep( 0.25 )
y -= 0.2
(3)、输出五个爱心,由Dear I love you forever! 五个单词填充而成 转载地址:https://blog.csdn.net/qq_55342245/article/details/120904578
import time
sentence = "Dear, I love you forever!"
for char in sentence. split( ) :
allChar = [ ]
for y in range ( 12 , - 12 , - 1 ) :
lst = [ ]
lst_con = ''
for x in range ( - 30 , 30 ) :
formula = ( ( x* 0.05 ) ** 2 + ( y* 0.1 ) ** 2 - 1 ) ** 3 - ( x* 0.05 ) ** 2 * ( y* 0.1 ) ** 3
if formula <= 0 :
lst_con += char[ ( x) % len ( char) ]
else :
lst_con += ' '
lst. append( lst_con)
allChar += lst
print ( '\n' . join( allChar) )
time. sleep( 1 )
(4)、字符输出爱心曲线公式爱心1
用是这个爱心曲线公式,然后遍历一个1517的方阵,计算每个坐标是在曲线内还是曲线外,在内部就输出#或 ,外部就是-电视剧里的代码真能运行吗?_Crossin的编程教室的博客-CSDN博客 for y in range(9, -6, -1): for x in range(-8, 9): print(‘## ’[(x+10)%4] if (xx+y y-25)**3 < 25x xy y*y else ‘_’, end=’ ') print()
(5)、字符输出爱心曲线公式爱心2
用是这个爱心曲线公式,然后遍历一个15*17的方阵,计算每个坐标是在曲线内还是曲线外
原文链接:https://blog.csdn.net/weixin_69553582/article/details/127941542