ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

python-pptx 参数化批量生成平行线画法课件与分步动画

2026/9/18 12:17:50 拓冰建站 浏览量
python-pptx 参数化批量生成平行线画法课件与分步动画 简介这是一份面向初中数学课堂的PPT课件主题为“相交线与平行线”章节中的数学活动——平行线的画法适用于教师备课演示与学生课后复习。课件从平移三角板“一放、二靠、三推、四画”的传统作图入手延伸到同位角相等、内错角相等、同旁内角互补、同一平面内垂直于同一直线等判定方法并收录李强、张明、王玲等同学构造平行线的不同思路含折纸法与尺规作图探究。压缩包内共1个PPT文件体积约1.69MB打开即可直接放映或修改。目前已有117人学习浏览。借助其中的课堂小结与“设计一幅作品”实践作业读者可梳理判定定理与垂线知识的综合应用体会一题多解的思维路径也可作为公开课、说课或分层作业设计的参考素材。1. 一份「平行线的画法」课件为什么值得用脚本生成数学活动课讲平行线的画法一份课件里通常要塞下这些元素方格纸底图、一条已知直线 a、直线外一点 P、三角尺平移的四个步骤、过点 P 作出的平行线 b、直角标记与平行符号。手工做一页不难难的是变式——把已知直线换成斜率为负的、把点 P 挪到直线下方、换一组网格间距六个变式重画一遍坐标全靠鼠标肉眼估改一处位置整页跟着错位。把这套东西程序化的收益在于斜率 k、截距 b、点 P 坐标、网格间距全部变成函数参数改一行数据就能再出一页分步动画也不用一帧帧复制按步骤数循环画到第 n 步即可。这份「平行线的画法」课件本质上是一道几何作图题的可视化而几何作图恰好是最适合参数化的那类内容。适合谁看要给教研组批量出课件的老师、做教育类工具的开发以及想把几何图形生成接进自动化流水线的人。下面从坐标系换算讲起一路做到过点作平行线的完整函数、批量变式和渲染校验。2. python-pptx 里把数学坐标映射成幻灯片坐标2.1 幻灯片坐标系与 EMU一条平行线为什么要换算两次手工画线时拖一根直线到画布上右键看位置属性数字是一堆七位数这就是 EMUEnglish Metric Unit。python-pptx 里所有位置和尺寸都走这个单位1 厘米等于 360000 EMU1 英寸等于 914400 EMU。它存在的意义是让厘米、英寸、点三种度量在同一套整数坐标里不丢精度。麻烦的是方向。数学坐标系原点在左下y 轴向上幻灯片坐标系原点在左上y 轴向下。写平行线的画法时如果直接把(0, 0)当原点往 add_connector 里塞画出来的直线会上下颠倒斜率 k 为正的直线看上去在往下走。所以中间必须有一层转换函数先把数学坐标平移到某个「数学原点」对应的幻灯片位置再把 y 取反。这一步不做封装后面每画一条线都要手算一次减法改一个画布尺寸全盘重来。封装成两行函数是整套代码里性价比最高的投入。2.2 数学坐标转 EMU 的转换函数与最小可运行脚本先建一个空白演示文稿把页面尺寸设成 16:9再把数学原点放在左下角附近留出坐标轴的标注空间。下面的代码可以直接跑from pptx import Presentation from pptx.util import Emu, Pt from pptx.dml.color import RGBColor from pptx.enum.shapes import MSO_CONNECTOR, MSO_SHAPE EMU_PER_CM 360000 # 1 厘米对应的 EMU SLIDE_W int(33.87 * EMU_PER_CM) # 16:9 宽屏宽 33.87 cm SLIDE_H int(19.05 * EMU_PER_CM) ORIGIN (int(4.0 * EMU_PER_CM), int(15.5 * EMU_PER_CM)) # 数学原点的幻灯片位置 SCALE EMU_PER_CM # 1 个数学单位 1 厘米 def m2e(x, y): 数学坐标(单位 cmy 向上) - 幻灯片 EMU 坐标(y 向下) return Emu(int(ORIGIN[0] x * SCALE)), Emu(int(ORIGIN[1] - y * SCALE)) def add_line(slide, p1, p2, colorRGBColor(0x33, 0x33, 0x33), width2.0): 按数学坐标画一条直线段返回 connector 形状 x1, y1 m2e(*p1) x2, y2 m2e(*p2) conn slide.shapes.add_connector(MSO_CONNECTOR.STRAIGHT, x1, y1, x2, y2) conn.line.color.rgb color conn.line.width Pt(width) return conn prs Presentation() prs.slide_width Emu(SLIDE_W) prs.slide_height Emu(SLIDE_H) slide prs.slides.add_slide(prs.slide_layouts[6]) # 6 号版式是空白页 add_line(slide, (-1, 1.0), (7, 3.0)) # 直线 ay 0.25x 1.25 add_line(slide, (-3, 4.0), (6, 6.25)) # 直线 by 0.25x 4.75与 a 同斜率 prs.save(平行线的画法.pptx)逻辑说明m2e做的是「先缩放、再平移、再翻转 y」三步add_line把两个数学坐标点转换后交给 add_connector。两条直线的斜率都是 0.25截距不同所以视觉上严格平行这是后面所有变式的基础模型。参数说明参数含义调整建议ORIGIN数学原点在幻灯片上的落点原点越靠右下正半轴可用空间越小一般留出 3~4 cm 边距SCALE一个数学单位对应多少 EMU想让网格更疏就调大比如1.5 * EMU_PER_CMcolor线条 RGB 颜色已知直线用深灰待作的平行线用红色讲课时对比明显width线宽单位 pt投影场景下 2.0~2.5 pt 比较稳低于 0.75 pt 部分渲染器会吞掉2.3 网格底图用循环画方格纸而不是插图片数学活动课上讲平行线的画法方格纸是默认背景。用插图的方式会把 PPT 撑大而且缩放后线条发虚。常见做法是用两层循环直接画浅色细线def add_grid(slide, xmax, ymax, step1.0, colorRGBColor(0xD9, 0xE2, 0xF3)): 在正半轴范围内画方格纸step 为网格间距(数学单位) x 0.0 while x xmax: add_line(slide, (x, 0), (x, ymax), colorcolor, width0.75) x step y 0.0 while y ymax: add_line(slide, (0, y), (xmax, y), colorcolor, width0.75) y step这里的 step 就是变式里最常改的参数间距 1.0 适合测量型作图间距 0.5 能让「斜率」看起来更细腻。网格线统一用 0.75 pt 的浅蓝颜色和主线条拉开距离避免学生分不清哪条是已知直线。需要注意的是循环次数xmax 取 12 时正半轴就有 13 条竖线配合 13 条横线是 26 个形状几十页课件叠起来文件体积会明显上涨超过 10 cm 的网格范围建议改用图片背景。3. 把「平行线的画法」四步作图拆成可复用的形状函数3.1 一贴二靠三移四画每一步对应哪些形状教材上过直线外一点作平行线的标准表述是四步一贴把三角尺的一条直角边贴在已知直线上二靠把直尺靠紧三角尺的另一条边三移沿着直尺平移三角尺到点 P 的位置四画沿着三角尺贴过直线的那条边画出平行线。把这四步搬进 PPT每步对应的形状是可以明确列出来的步骤画面元素python-pptx 对应一贴已知直线 a 三角尺connector MSO_SHAPE.RIGHT_TRIANGLE二靠三角度旁多一条直尺细长矩形或第二条 connector三移三角尺平移到 P 附近修改三角尺形状的left/top四画沿三角尺边画出直线 b 平行符号connector 文本框「∥」把这张表当接口约定后面写函数时每个形状归属哪一步就清楚了。三角尺用RIGHT_TRIANGLE而不是画三条线拼出来好处是它有填充色能形成半透明的遮挡感平移过程在视觉上更像实物。3.2 用 add_connector 画直线、用 tailEnd 加箭头画射线时要带箭头而 python-pptx 没有直接的箭头属性得操作底层 XML。这里有一个必须注意的顺序问题a:ln元素的子元素有固定的 schema 顺序prstDash虚线在tailEnd箭头之前。如果先加了箭头再设虚线生成的 XML 顺序错乱部分版本的 PowerPoint 会直接报文件损坏。from pptx.oxml.ns import qn def add_arrow(slide, p1, p2, colorRGBColor(0xC0, 0x39, 0x2B), width2.5): 画一条带箭头的射线注意箭头必须在颜色/线宽/虚线之后设置 conn add_line(slide, p1, p2, colorcolor, widthwidth) ln conn.line._get_or_add_ln() tail ln.makeelement(qn(a:tailEnd), {type: triangle, w: med, len: med}) ln.append(tail) return conn逻辑说明_get_or_add_ln()拿到的是线条属性节点makeelement构造出箭头节点后追加。type取值triangle、stealth、arrow是三种常见箭头样式w和len控制宽窄与长短取值sm/med/lg。参数说明射线长度在数学上无所谓但视觉上建议从点 P 出发画到画布边缘多出 0.5 cm 的位置避免箭头刚好压在页边。如果同一页要画多条带箭头的线把add_arrow包装成列表推导会更快但注意每条线都是独立形状层级按添加顺序堆叠。3.3 过直线外一点作平行线的完整函数把前面的零件组装起来核心是斜截式的平移关系已知直线 y kx b过点 P(px, py) 的平行线斜率相同截距 b2 py - k·px。这个式子就是全部几何原理代码里不需要任何迭代求解。def draw_parallel(slide, k, b, px, py, x_span(-2.0, 8.0), known_colorRGBColor(0x33, 0x33, 0x33)): 过点 P 作直线 ykxb 的平行线返回(已知直线, 平行线, 点标记) b2 py - k * px # 平行线截距 x0, x1 x_span known add_line(slide, (x0, k * x0 b), (x1, k * x1 b), colorknown_color) parallel add_line(slide, (x0, k * x0 b2), (x1, k * x1 b2), colorRGBColor(0xC0, 0x39, 0x2B)) cx, cy m2e(px, py) dot slide.shapes.add_shape(MSO_SHAPE.OVAL, cx - Emu(45000), cy - Emu(45000), Emu(90000), Emu(90000)) dot.fill.solid() dot.fill.fore_color.rgb RGBColor(0xC0, 0x39, 0x2B) dot.line.fill.background() return known, parallel, dot逻辑说明x_span控制两条直线在画面上的横向覆盖范围取相同的取值范围能保证视觉上平行关系明显点 P 用直径约 0.25 cm 的实心圆表示45000EMU 恰好是半径这样圆点圆心落在数学坐标上而不是左上角落在坐标上是画点最容易搞错的地方。参数说明k为 0 时是水平线k不存在时是竖直线后者不能走斜截式需要单独分支处理——把 x 作为常量直接画两条 x 相等的竖线。变式里如果要考「垂直于同一条直线的两条直线平行」还得再加一个垂直分支先过 P 作已知直线的垂线再过 P 作垂线的垂线这套逻辑用斜率相乘等于 -1 的判据即可只是点 P 落在已知直线上时垂足会重合需要提前判断。4. 批量生成变式课件与分步动画页4.1 变式数据表斜率、点坐标、网格间距怎么定义变式不写在代码里写成数据。一行一个变式包含斜率、截距、点的坐标和网格间距改数据不改逻辑VARIANTS [ # k, b, px, py, step, 说明 (0.25, 1.25, 4.0, 6.0, 1.0), # 点在直线上方正斜率 (-0.5, 4.00, 2.0, 1.5, 1.0), # 负斜率点在下方 (0.0, 3.00, 5.0, 5.0, 0.5), # 水平线加密网格 (1.0, 0.50, 1.0, 4.0, 0.5), # 45 度观察斜率与格点关系 ]字段的选择不是随意定的。step放进数据表是因为水平线的变式里间距 1.0 会让「平行」看起来太稀疏学生不容易看出两条线等距而斜率为 1 时0.5 的网格恰好能显示直线过格点。把这一列留在表里就不用为某个特例去改函数默认值。说明这一列只是给编写者看的注释实际生成时不参与这样以后回看数据表能立刻知道每个变式想考什么。4.2 一次生成 20 页分步动画的循环写法分步动画不用复制幻灯片而是每页从头重画一遍用step参数控制画到第几步。python-pptx 没有原生的复制幻灯片接口绕开它的代价只是几毫秒的重绘时间def build_deck(variants, steps4, out平行线的画法.pptx): prs Presentation() prs.slide_width, prs.slide_height Emu(SLIDE_W), Emu(SLIDE_H) for idx, (k, b, px, py, step) in enumerate(variants, 1): for s in range(1, steps 1): slide prs.slides.add_slide(prs.slide_layouts[6]) add_grid(slide, 12, 10, stepstep) draw_parallel(slide, k, b, px, py) # 第 1 步已知直线与点 P if s 2: add_triangle(slide, k, b) # 第 2 步贴三角尺 if s 3: add_ruler(slide, k, b, px, py) # 第 3 步靠直尺并平移 if s 4: add_parallel_mark(slide, k, b, px, py) # 第 4 步画线并标平行符号 prs.save(out) return out逻辑说明外层循环遍历变式内层循环遍历步骤共len(variants) * steps页。每一页都是独立绘制的视觉上前后页形成连续动画。参数说明steps固定为 4如果想加上「标出直角」这一步把它改成 5 并在函数里补一个分支即可。生成 20 页左右时文件通常在 1 MB 以内如果变式数量上到 50 个建议拆成多个文件单个 PPT 页数过多会让放映时的内存占用明显上升。另外每条线的端点坐标建议在生成后统一四舍五入到整数 EMU浮点误差累积会让本该重合的两条线出现 1 像素的错位。4.3 用 LibreOffice 无头导出 PDF 做批量校验生成完不能只靠打开文件看第一页。用无头模式批量转 PDF再渲染成图片扫一眼能一次性抓住所有变式的坐标问题soffice --headless --convert-to pdf --outdir out/ 平行线的画法.pptx pdftoppm -r 80 -png out/平行线的画法.pdf out/page第一条命令输出 PDF第二条把每页渲染成 80 DPI 的 PNG。重点看三处点 P 是否落在预期象限、两条直线在画面边缘是否等距、网格线有没有压住主线条。斜率为负的变式最容易出问题因为m2e的 y 翻转会让视觉上的「下方」对应数学上的负 y点 P 的 py 取 1.5 时在画面上其实偏下和正斜率变式的直觉相反渲染一遍就能确认。5. 参数化平行线课件的排错与精度控制5.1 中文字体不生效要处理 rFonts 的 a:ea 节点python-pptx 里设置run.font.name只会写入a:latin节点中文会因为缺少a:ea而回退到主题字体。这里同样有 schema 顺序要求a:latin在a:ea之前所以必须先设font.name再追加 ea 节点。def set_cjk_font(run, name微软雅黑): run.font.name name # 先生成 a:latin rPr run._r.get_or_add_rPr() ea rPr.find(qn(a:ea)) if ea is None: ea rPr.makeelement(qn(a:ea), {}) rPr.append(ea) # a:ea 必须排在 a:latin 之后 ea.set(typeface, name)平行符号「∥」和角的度数标注都走这个函数。字号建议 18~24 pt太小在投影上认不出太大又会盖住图形。5.2 线宽、端点与重叠形状的层级问题几个反复踩到的坑列成对照表比翻文档快现象原因处理方式网格线盖住已知直线后添加的形状在上层先画网格再画直线和三角尺三角尺平移后盖住点 P填充不透明设置fill.fore_color后把shape.fill.transparency调高或改用无填充直线端点对不齐坐标取整方式不一致统一在m2e内部用int()截断不在调用处二次取整斜线边缘有锯齿导出分辨率低PDF 转换时加--resolution 300形状层级完全由添加顺序决定python-pptx 没有 z-order 属性可用靠调整代码顺序解决最省事。5.3 视觉回归用渲染结果反查数学坐标参数化的最后一步是把渲染结果当断言用。同一组变式重复生成时把 PNG 的尺寸、指定坐标处的像素颜色取出来比对能抓住「某次改了 SCALE 导致点 P 跑出画布」这类问题。from PIL import Image img Image.open(out/page-03.png).convert(RGB) w, h img.size # 取样已知直线在画面左三分之一处的颜色应为深灰主线条 sample img.getpixel((w // 3, int(h * 0.55))) assert sample ! (255, 255, 255), f该位置没有线条检查斜率与 ORIGIN: {sample}采样点的位置要选在直线上所以它依赖ORIGIN和SCALE改这两个参数后采样点要同步调整否则断言会误报。更稳的做法是先用 matplotlib 按同样的数学公式画一张参照图再把 PPT 渲染图和参照图做一次缩放对齐后的像素差统计差异超过阈值就人工看一眼。这一步不需要接进 CI本地跑一次就够了——毕竟平行线的画法这类课件变式数量通常也就几十个出了问题肉眼比脚本更快。本文还有配套的精品资源点击获取