练习项目,用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()