ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Python turtle绘图实战:从五角星到皮卡丘的代码拆解

Python turtle绘图实战:从五角星到皮卡丘的代码拆解 简介一份Python绘图特效源代码合集包含32个py脚本压缩包仅24KB适合Python初学者、编程爱好者以及想用代码绘制趣味图形的学习者。资源围绕Matplotlib、Seaborn、Plotly等常用绘图库展开覆盖五角星、爱心、彩色五角星、圣诞树、四叶草、太阳花、小黄人、皮卡丘、叮当猫等30余种图形既有静态图案也有动态效果可帮助理解坐标系统、几何建模、RGB颜色调节和动画生成等核心概念。每个脚本独立成文件结构简洁便于逐段阅读和二次修改能够直观地看到不同绘图函数的调用方式与参数效果。目前已有1558人学习适合作为创意编程入门素材或课堂趣味练习也能为后续数据可视化项目积累技巧。代码中还涉及类封装、文件读写等基础内容通过有趣的案例降低学习门槛让绘图过程更有成就感。1. 用30个脚本看懂Python绘图从五角星到皮卡丘的代码路径一个zip包里塞进30个.py文件覆盖五角星、爱心、圣诞树、小黄人、皮卡丘、海绵宝宝很多人第一反应是花架子玩具。但把每个脚本拆开看之后会发现这批代码几乎把turtle绘图的全部核心机制——坐标定位、角度计算、颜色填充、循环迭代、函数封装——都用了一遍。对刚入门Python的人来说画一个五角星和写一个爬虫的难度不在同一个量级前者能让你快速理解程序是如何控制一个状态不断变化的对象这正是后续学GUI、做游戏、搞数据可视化的共同底座。这篇文会挑出几个有代表性的脚本讲清楚绘制原理、关键参数怎么调以及踩坑点在哪。资源里的脚本有的几十行有的上百行逐行读太累抓住几个核心套路就够了。2. turtle坐标体系与几何计算五角星和爱心不是画出来的是算出来的2.1 海龟绘图的底层机制方向、距离与状态turtle是Python标准库不需要额外安装。它模拟一只海龟在画布上爬行爬过的路径就是画出来的线。很多人一开始不习惯的地方在于它用的不是笛卡尔直角坐标的从A点到B点而是当前朝向 前进距离 转弯角度的相对运动模式。import turtle t turtle.Turtle() t.speed(5) t.forward(100) # 朝当前方向前进100像素 t.left(90) # 向左转90度 t.forward(100) t.right(45) # 向右转45度 t.backward(50) # 倒退50像素 turtle.done()这段代码的核心逻辑是海龟每执行一次forward位置就更新一次每次left或right朝向就改变一次。注意left(90)是绝对角度旋转不是转到一个绝对方向所以连续调用两次left(45)等效于一次left(90)。理解这一点后面画五角星、螺旋线才不容易绕晕。画布坐标系原点在正中心x轴向右为正y轴向上为正。海龟初始位置在原点初始朝向是正右方。turtle.setup(width, height)可以设置画布尺寸但绘制逻辑里很少直接依赖它更多是靠forward和left的组合控制。2.2 用循环和角度计算绘制正多边形与五角星五角星看起来复杂其实就是一个走五条边、每次转144度的循环。内角计算是几何常识正五边形的每个外角是72度五角星是隔点连线所以每次转弯角度是180 - 36 144度。import turtle t turtle.Turtle() t.speed(3) t.pensize(2) t.pencolor(gold) for _ in range(5): t.forward(150) # 边长150像素 t.right(144) # 右转144度形成五角星的尖角 t.hideturtle() turtle.done()为什么是144度五角星五个顶点均匀分布在圆周上相邻两个顶点与圆心连线的夹角是360 / 5 72度。但画笔走的是隔一个顶点连线所以海龟在顶点处的转向是外角的两倍即144度。这也是小海龟绘图里最容易出错的地方——角度不是凭空试出来的是用几何关系推出来的。参数方面pensize控制线条粗细pencolor支持颜色名或#RRGGBB十六进制色值。speed(0)是最高速度绘制复杂图形时建议用speed(8)以上否则等得让人失去耐心。2.3 填充、抬笔与颜色模式让图形从线条变成色块只画线条是线稿要变成特效图就得填充颜色。turtle的填充逻辑是begin_fill()开始记录路径图形闭合后调用end_fill()一次性填充。这一对方法必须成对出现而且图形必须是闭合的否则填充结果不可预期。import turtle t turtle.Turtle() turtle.colormode(255) # 启用RGB整数值模式 t.speed(6) t.penup() # 抬笔移动时不画线 t.goto(-100, 0) # 移动到目标坐标 t.pendown() # 落笔开始绘制 t.begin_fill() t.fillcolor(255, 182, 193) # 浅粉色 for _ in range(5): t.forward(120) t.right(144) t.end_fill() t.hideturtle() turtle.done()colormode(255)表示后面fillcolor、pencolor接受0到255的RGB整数值不加这个设置只能用0到1的浮点数很多人卡在这一步。penup和pendown是绘图里最高频的操作作用是移动到新位置时不留下痕迹。画多元素组合图时必须养成的习惯是先抬笔、再移动、最后落笔。批量填充场景建议把常用颜色整理成常量或字典比如COLORS {red: (255, 99, 71), pink: (255, 182, 193)}。用RGB三元组比字符串颜色名更可控尤其在需要色阶渐变的时候。下表是turtle高频方法及参数含义画任何图形前先过一遍这个表能省不少调试时间。方法参数作用forward(d)d像素距离沿当前方向前进backward(d)d像素距离沿当前方向后退left(a)/right(a)a角度值向左/右旋转角度penup()/pendown()无抬笔/落笔goto(x, y)x,y绝对坐标移动到指定坐标pensize(w)w线宽设置线条粗细speed(s)s0-100最快1-10递增begin_fill()/end_fill()无配合fillcolor填充闭合区域colormode(m)m1或255颜色模式切换3. 拆解四类典型脚本几何图形、爱心曲线、彩虹渐变与角色分层3.1 彩色五角星随机颜色与循环嵌套的经典组合资源里的彩色五角星.py是入门必读。它通常在单个五角星的基础上加了两个变化一是每次绘制用随机颜色二是多个五角星分布在画布不同位置。随机颜色的标准写法是random.randint(0, 255)配合colormode(255)。import turtle import random t turtle.Turtle() turtle.colormode(255) t.speed(8) def draw_star(size, x, y): t.penup() t.goto(x, y) t.pendown() color (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) t.fillcolor(color) t.pencolor(color) t.begin_fill() for _ in range(5): t.forward(size) t.right(144) t.end_fill() for i in range(8): x random.randint(-200, 200) y random.randint(-200, 200) size random.randint(30, 80) draw_star(size, x, y) t.hideturtle() turtle.done()draw_star把画一个五角星封装成函数三个参数分别控制大小和位置这样主循环只需生成随机参数并调用即可。把绘制逻辑写进函数而不是全部堆在全局代码里是这个脚本最值得学的地方——后面画皮卡丘、小黄人时每个部件都是一个函数。随机颜色的坑在于RGB三个分量如果都取大值颜色会偏白如果都取小值颜色会偏黑。想要鲜艳的效果可以让分量落在(50, 255)区间或者固定其中一个分量为0。3.2 爱心与表白系列参数方程与坐标映射爱心.py和一箭穿心.py是表白系脚本的核心。爱心的绘制方法有几种资源里最常见的是用参数方程生成一系列坐标点然后用goto连线。经典爱心参数方程是x 16 * sin³(t) y 13 * cos(t) - 5 * cos(2t) - 2 * cos(3t) - cos(4t)其中t从0变化到2π。这个方程的来源是数学上对心形线的拟合近似工程上的意义是任何一条曲线只要能写出参数方程就能用turtle逐点连接画出来。import turtle import math t turtle.Turtle() t.speed(10) t.penup() turtle.colormode(255) t.fillcolor(255, 0, 0) scale 10 # 放大倍数 t.begin_fill() for i in range(360): # 分成360个点 rad math.radians(i) # 角度转弧度 x 16 * math.sin(rad) ** 3 y 13 * math.cos(rad) - 5 * math.cos(2 * rad) - 2 * math.cos(3 * rad) - math.cos(4 * rad) t.goto(x * scale, y * scale) t.end_fill() t.hideturtle() turtle.done()这个脚本的关键在三点。第一math.radians把角度转弧度turtle的旋转方法用角度但math库的三角函数全用弧度混用会得到完全错乱的图。第二循环360次意味着每1度取一个采样点步长越小曲线越平滑同时绘制时间越长性能敏感时可以先200次预览再500次出图。第三坐标乘以scale缩放直接画的话爱心宽度只有16像素小到几乎看不见。参数方程画图是理解程序绘图和手工绘图本质区别的分水岭手工绘图靠鼠标拖拽程序绘图靠数学表达式驱动。这种思路可以延伸到正弦波、玫瑰线、李萨如曲线素材包里虽然没有这些但掌握这一个脚本后面自己扩展并不难。3.3 彩虹与渐变同心弧绘制和RGB插值彩虹.py的核心不是画圆而是画多段圆弧叠加。彩虹是同心半圆颜色按红橙黄绿蓝靛紫排列。用turtle.circle(radius, extent)可以画圆弧extent参数控制画多大角度180就是半圆。import turtle t turtle.Turtle() t.speed(8) t.pensize(20) # 粗线条模拟色带 colors [red, orange, yellow, green, blue, indigo, violet] radius 200 for color in colors: t.pencolor(color) t.penup() t.goto(0, -radius) # 移动到圆弧底部起点 t.pendown() t.circle(radius, 180) # 画半圆 radius - 20 # 半径递减形成同心弧 t.hideturtle() turtle.done()这段代码的理解重点在t.goto(0, -radius)。circle的画法是从当前点开始逆时针画圆圆心在当前点正下方radius处。要让圆弧按同心圆排列每画完一条弧就要把起始点往下移保证圆心固定在同一位置。半径每次递减20像素刚好等于pensize的粗细色带能无缝衔接。画出来的不是严格渐变而是离散色阶。如果要真正的连续渐变需要对RGB做线性插值——把一个颜色到另一个颜色之间均匀切分N个色阶每个色阶画一条弧def lerp_color(c1, c2, t): return tuple(int(c1[i] (c2[i] - c1[i]) * t) for i in range(3)) for i in range(50): ratio i / 49 color lerp_color((255, 0, 0), (0, 0, 255), ratio) t.pencolor(color) ...3.4 皮卡丘、小黄人与机器猫分层绘制与局部坐标这类角色脚本比几何图形复杂一个量级但套路高度一致先画大轮廓再叠加细节。以皮卡丘为例绘制顺序通常是脸黄色圆/椭圆→ 耳朵黑色尖端→ 眼睛 → 腮红 → 嘴巴。每个部件用一个函数或代码块实现内部用绝对坐标goto定位。这里给一个简化的头部模型展示分层逻辑import turtle t turtle.Turtle() turtle.colormode(255) t.speed(8) def draw_face(): t.penup() t.goto(0, -80) t.pendown() t.fillcolor(255, 220, 0) # 皮卡丘黄 t.begin_fill() t.circle(80) t.end_fill() def draw_eye(x, y): t.penup() t.goto(x, y) t.pendown() t.dot(18, (30, 30, 30)) # 黑眼珠 t.dot(6, (255, 255, 255)) # 高光 draw_face() draw_eye(-30, 20) draw_eye(30, 20) t.hideturtle() turtle.done()dot(size, color)是画实心圆点的快捷方法比circlefill省事很多。高光点偏移的5-6像素看似不起眼但正是角色眼神的来源。画多部件角色最值得注意的问题是所有坐标都基于全局坐标系计算如果整体位置需要平移所有坐标都得跟着改。解决方法是把整个角色的绘制包进一个函数函数接收(x, y)基准点参数内部所有坐标都加上这个偏移量。皮卡丘.py这类脚本的价值不在于像素级还原而在于帮你建立分层绘制的思维模型。角色越复杂越要克制一个循环画完所有东西的冲动。每层独立控制、独立测试出问题才能快速定位是哪一层的事情。4. matplotlib对照从turtle到数据可视化两套坐标系的关键差异4.1 画笔坐标系 vs 数据坐标系turtle适合教学和趣味绘图但真放到数据可视化场景里主力工具是matplotlib。二者的核心差异在于坐标系的语义turtle是海龟的绝对位置朝向驱动matplotlib是数据值的映射驱动。同样是画五角星matplotlib的做法是计算五个顶点的坐标然后直接连线填充。import matplotlib.pyplot as plt import numpy as np angles np.linspace(0, 2 * np.pi, 6)[:-1] # 5个等分角度 x np.cos(angles) # 顶点x坐标 y np.sin(angles) # 顶点y坐标 fig, ax plt.subplots(figsize(4, 4)) ax.fill(x, y, colorgold, alpha0.8, edgecolorblack) ax.set_aspect(equal) # 保证纵横比一致否则圆会变椭圆 plt.show()这里np.linspace(0, 2 * np.pi, 6)[:-1]生成5个角度去掉最后一个重复点x和y分别是顶点在单位圆上的坐标连起来就是五角星的外圈五个点。注意这画的是正五边形而非真正的五角星因为五角星需要每两个点跳一个连线。正确的做法是把角度序列改成每隔2π/5取两个分支或者直接用angles np.linspace(0, 2 * np.pi, 6)[:-1] * 2乘2后每个点跨两格。这个细节初看容易懵实际跑一遍对比就清楚了。两套工具怎么选需要交互式探索、数据标注、坐标轴刻度用matplotlib需要一笔一画展示绘制过程、有复现动画感的需求用turtle。素材包里全是turtle脚本但学完这批代码再去碰matplotlib对坐标映射、填充闭合区域这些概念是有迁移收益的。4.2 plt画图显示中文问题字体配置的一次性解决方案资源里的脚本涉及中文场景不多但plt画图显示中文问题是搜索高频词这里一并解决。matplotlib默认字体不含中文字形直接写中文会显示成方块。标准解法是设置rcParams指定系统中文字体。import matplotlib.pyplot as plt import matplotlib as mpl # 方案一直接指定字体族 plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] plt.rcParams[axes.unicode_minus] False # 负号显示修正 # 方案二更规范的做法先查可用字体再动态选择 from matplotlib import font_manager font_names {f.name for f in font_manager.fontManager.ttflist} candidate [SimHei, Microsoft YaHei, Noto Sans CJK SC, PingFang SC] for name in candidate: if name in font_names: mpl.rcParams[font.sans-serif] [name] breakaxes.unicode_minus必须设为False否则坐标轴的负号会显示为方框。方案二的逻辑是先扫描系统里所有可用字体再从候选列表里挑第一个命中项适配不同系统的字体名差异。4.3 python画图横坐标太密集刻度间隔与旋转策略用matplotlib画时间序列或大量分类数据时横坐标标签叠在一起是常见现象。默认情况下pandas的DataFrame.plot()会根据数据量自动决定刻度但经常不够稀疏。手动干预有三种策略设置间隔、旋转角度、自定义格式化。import matplotlib.pyplot as plt import numpy as np x np.arange(0, 100) y np.random.randn(100).cumsum() fig, ax plt.subplots(figsize(10, 4)) ax.plot(x, y) ax.set_xticks(range(0, 100, 10)) # 每10个单位留一个刻度 ax.tick_params(axisx, rotation45) # 旋转45度防重叠 ax.xaxis.set_major_locator(plt.MaxNLocator(8)) # 另一种方式最多8个刻度 plt.tight_layout() plt.show()MaxNLocator(8)是更省心的方法它根据坐标轴宽度自动计算合适的刻度数量不用手工数着设步长。旋转参数rotation45适合分类标签比较长的场景。如果还觉得挤可以进一步用ax.xaxis.set_ticklabels只保留首尾几个标签或者把横坐标类型转为字符串并用plt.xticks(ticks, labels)手动筛选。这个问题在画股票K线、传感器时序数据时几乎必踩记住一条原则优先用MaxNLocator限制数量再结合旋转最后才是手工枚举刻度。5. 把这批turtle脚本改造成可复用组件封装、参数化和动画扩展资源包里30个脚本全是独立的顶层代码直接跑没问题但真要放进自己的项目里还得做两个改造封装成类、支持外部参数。一个实用的重构方向是把图形类型与绘制行为分离用命令行参数或函数入参控制画什么、画多大、用什么颜色。import turtle import math class ShapeDrawer: def __init__(self, color(255, 105, 180), speed8, scale10): turtle.colormode(255) self.t turtle.Turtle() self.t.speed(speed) self.t.pencolor(color) self.t.fillcolor(color) self.scale scale def star(self, size): for _ in range(5): self.t.forward(size) self.t.right(144) def heart(self): self.t.begin_fill() for i in range(360): rad math.radians(i) x 16 * math.sin(rad) ** 3 y 13 * math.cos(rad) - 5 * math.cos(2 * rad) - 2 * math.cos(3 * rad) - math.cos(4 * rad) self.t.goto(x * self.scale, y * self.scale) self.t.end_fill() def reset(self, x0, y0): self.t.penup() self.t.goto(x, y) self.t.pendown() def done(self): self.t.hideturtle() turtle.done() sd ShapeDrawer(color(220, 20, 60), scale12) sd.reset(-80, 0) sd.heart() sd.done()这个封装把画笔初始化、颜色设置、坐标重置收进类的方法里调用方只需要关注画什么。重置到起点单独抽成reset方法是因为画多个图形时每次都要抬笔、移位、落笔三连抽出来比每次手动写三行清晰得多。给类增加__init__参数后可以通过命令行或配置文件动态传值不用改代码就能换颜色和大小。想进一步做成动画用turtle自带的ontimer回调注册函数实现一定时间间隔内不断改变海龟位置不过更推荐的做法是改用matplotlib的FuncAnimation做动态效果性能上限高不少也能输出gif或mp4格式。这批脚本真正的价值在于它把所有绘图的基本功拆成了30个小而完整的样例每个样例对应一个独立的知识点。把它们按几何计算、参数方程、分层绘制、批量生成四条线重新整理遇到新图形需求时就能从自己的代码库里找到对应的模板改参数而不是重头开始试错。本文还有配套的精品资源点击获取
返回列表