练习项目,用turtle绘图库画个八卦。
关于八卦的具体细节,在画之前,除了知道这叫八卦外(曾一度叫它太极,没想到外面多了几行就不一样了),一无所知,画完后也不过多认识了个阴阳,所以,表述中基本都是口语字词,还有位置什么的是不是准确,也不知道,有熟悉之人可以在评论区科普下,不甚感激。
开始前先罗列下下手逻辑:内,太极部分;外,八卦部分。
作图中碰到的主要问题:
- 初始化画笔原点,以便于开始下一个命令清晰画笔位置和朝向;
- 初始作图起点,保证整体处于画布中间;
- 卦象的画法。
上面三个问题中,卦象的画法花费时间最近,最开始是用:使用for循环画三个同心逐级变小的八边形,再用辐射擦除的方法来完成的:
整体看起来,没什么问题,但是总觉得有些难看。
更给目标:保持每一卦的线段长短一致,中间断点一致,在每一卦的外围加上卦名。
1.引入库
代码如下:turtle
from turtle import *
2.代码
代码如下:
# python 3.6
# pycharm
from turtle import *
# 返回原点
def rset():
pensize(1)
pencolor('black')
penup()
home()
pendown()
# 设置画笔偏移,初始化八卦和太极的画笔起始点,保持整体居中
def offset(off_set, angle=0, mode='taiji'):
# off_set太极时为大圆半径,八卦时要大于半径,否则会与太极重合。
# angle默认为0,mode默认为‘taiji’,画太极的时候,不需要设置,默认即可;画卦的时候angle=angl,mode=‘bagua’。
penup()
home() # 回到原点,朝向东
if mode == 'taiji': # 太极
right(90)
fd(off_set)
seth(0) # 朝向东
else: # 八卦
left(angle) # 每画一卦旋转45度的倍数,开始下一卦。
fd(off_set)
left(90)
pendown()
# 太极生成
def taiji(radius, pen_size=2, color='black'):
rset() # 初始化画笔
pensize(pen_size)
pencolor(color)
offset(radius) # 画笔偏移至起始点
fillcolor('black') # 填充颜色
begin_fill() # 开始填充
circle(radius, 180) # 画大圆的半圆
circle(radius / 2, 180) # 画s型
circle(-radius / 2, 180) # 画s型
end_fill() # 结束填充
circle(-radius, 180) # 画大圆的另一半圆
# 上面小圆
begin_fill()
fillcolor('white')
penup()
home() # 返回原点,默认朝东
left(90)
fd(radius * 0.7) # 初始化小圆画笔起始点
right(90)
pendown()
circle(-radius * 0.2) # 画小圆
end_fill()
rset()
# 下面小圆
penup()
begin_fill()
fillcolor('black')
right(90)
fd(radius * 0.7)
left(90)
pendown()
circle(radius * 0.2)
end_fill()
# 八卦生成
def bagua(off_set, side, gua_lis):
pensize(side / 2)
for j, k in enumerate(gua_lis): # 枚举八卦列表,获取元素和下标,下标拿来判断旋转多少度
angl = j * 45 # 偏移角度:0,45,90,135,180,225,270,315,360
rset() # 初始化到原点
offset(off_set, angle=angl, mode='bagua') # 偏移到八卦画笔,此时画笔位于线段中间点,下面3行代码初始到线段开头
pencolor('white')
pensize(5)
bk(side / 2)
for i in k: # 遍历每一卦的集合,1为阳也就是完整线段,0为阴,带断点的线段
pencolor('black')
if i == 1:
fd(side)
elif i == 0:
fd(side * (1 / 3))
penup()
fd(side * (1 / 3))
pendown()
fd(side * (1 / 3))
elif isinstance(i, str) and j <= 4: # 判断集合内内容,为字符串时,且为前5卦时,直接用write方法打印
penup()
fd(side / 2)
pendown()
write(i, align='center', font=('楷体', 15, "bold")) # align有三个选项:’left‘,’center‘,’right‘,i后面两项可不填
else: # 后3卦,多偏移了一些距离,再用write方法打印,避免文字与卦重叠,影响效果
penup()
fd(side / 2)
right(90)
fd(15)
pendown()
write(i, align='center', font=('楷体', 15, "bold"))
penup() # 每画完一卦中的一条线后,回到中点,向外移动后,开始画下一段线段
bk(side / 2)
right(90)
fd(side / 2)
left(90)
bk(side / 2)
pendown()
gua_lis = [(1, 1, 0, '兑'), (0, 0, 0, '坤'), (1, 0, 1, '离'), (0, 1, 1, '巽'), (1, 0, 0, '震'), (0, 0, 1, '艮'),
(0, 1, 0, '坎'), (1, 1, 1, '乾')]
taiji(50)
bagua(70, 30, gua_lis)
hideturtle()
done()