在下周公子

  • 首页
  • 域名收藏
  • SEM搜索引擎营销
  • 操作系统
    • 服务器应用
  • 特色专题
    • 跑步运动
  • VPS主机推荐
  • 搜索
在下周公子
三十而立,学以致用
  1. 首页
  2. 编程之路
  3. 正文

使用Python生成一个,一米尺A4打印手工制作材料

2024年11月17日 546点热度 1人点赞 0条评论

这个是二年级学生的作业,之前是通过Adobe Illustrator手工绘制的,然后现在遇到老二的作业。想着使用reportlab的库玩一把自定义绘制。结果效果非常不错。

生成效果
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib import colors
import math


# 注册字体
regular_font_path = r"C:\Users\Mrs.Zhou\PycharmProjects\untitled\venv\Lib\site-packages\reportlab\fonts\HarmonyOS_Sans_SC_Regular.ttf"
Bold_font_path = r"C:\Users\Mrs.Zhou\PycharmProjects\untitled\venv\Lib\site-packages\reportlab\fonts\HarmonyOS_Sans_SC_Bold.ttf"
# 定义常量
OVERLAP = 5 * mm  # 粘贴重叠区域


def create_shapes(c):
    """创建形状绘制函数列表"""

    def draw_triangle(x, y, size):
        height = size * math.sqrt(3) / 2
        c.line(x, y, x + size, y)
        c.line(x + size, y, x + size / 2, y + height)
        c.line(x + size / 2, y + height, x, y)

    def draw_trapezoid(x, y, size):
        c.line(x, y, x + size, y)  # 底边
        c.line(x + size * 0.2, y + size, x + size * 0.8, y + size)  # 上边
        c.line(x, y, x + size * 0.2, y + size)  # 左边
        c.line(x + size, y, x + size * 0.8, y + size)  # 右边

    def draw_parallelogram(x, y, size):
        offset = size * 0.3
        c.line(x + offset, y, x + size + offset, y)  # 底边
        c.line(x, y + size, x + size, y + size)  # 上边
        c.line(x, y + size, x + offset, y)  # 左边
        c.line(x + size, y + size, x + size + offset, y)  # 右边

    def draw_rectangle(x, y, size):
        c.rect(x, y, size * 1.5, size, fill=0)

    def draw_circle(x, y, size):
        c.circle(x + size / 2, y + size / 2, size / 2, fill=0)

    def draw_square(x, y, size):
        c.rect(x, y, size, size, fill=0)

    return [
        draw_circle,
        draw_square,
        draw_triangle,
        draw_trapezoid,
        draw_parallelogram,
        draw_rectangle
    ]


def draw_ruler_segment(c, start_x, start_y, segment_start, is_first=False):
    ruler_width = 200 * mm  # 尺子长度
    ruler_height = 20 * mm  # 尺子宽度

    # 主体矩形(不包含粘贴区域)
    c.setFillColor(colors.white)
    c.setStrokeColor(colors.black)
    c.rect(start_x, start_y, ruler_height, ruler_width, fill=1)

    # 如果不是第一个尺子,在右侧添加粘贴区域
    if not is_first:
        c.setFillColor(colors.lightgrey)
        c.rect(start_x, start_y - OVERLAP, ruler_height, OVERLAP, fill=1)
        c.setFont("HarmonyOS_Sans_SC_Regular", 6)
        c.setFillColor(colors.black)
        c.drawString(start_x + 2 * mm, start_y - OVERLAP + 2 * mm, "粘贴区域")

    # 在起始位置标注单位
    if segment_start == 0:
        c.setFont("HarmonyOS_Sans_SC_Regular", 6)
        c.setFillColor(colors.black)  # 确保文字颜色为黑色
        c.drawString(start_x + 10 * mm, start_y + 2 * mm, "单位: mm")

    # 绘制刻度 (垂直方向)
    for i in range(201):  # 0-200mm
        y = start_y + i * mm
        if i % 10 == 0:  # 10mm(1cm)大刻度
            c.line(start_x, y, start_x + 10 * mm, y)
            # 在右侧标注数字(换算成厘米)
            c.setFont("HarmonyOS_Sans_SC_Regular", 8)
            c.setFillColor(colors.black)  # 确保文字颜色为黑色
            cm_value = (i + segment_start) // 10  # 转换为厘米
            c.drawString(start_x + 12 * mm, y - 1 * mm, str(cm_value))
        elif i % 5 == 0:  # 5mm中刻度
            c.line(start_x, y, start_x + 7 * mm, y)
        else:  # 1mm小刻度
            c.line(start_x, y, start_x + 4 * mm, y)


def draw_decorations(c, x, y, height):
    # 获取所有可用的装饰图形
    shapes = create_shapes(c)
    import random

    # 在尺子右侧区域绘制装饰(按固定间隔分布)
    shape_positions = range(30, 190, 30)  # 每30mm放置一个装饰,从30mm开始
    for pos in shape_positions:
        shape = random.choice(shapes)
        # 将装饰放在刻度和数字标注区域之后
        dec_x = x + 12 * mm  # 从刻度和数字之后开始
        dec_y = y + pos * mm + 2 * mm  # 固定间隔的垂直位置
        shape(dec_x, dec_y, 3 * mm)  # 统一使用3mm作为基准尺寸


def create_rulers_pdf(output_path):
    # 创建PDF文档 - A4纸张
    c = canvas.Canvas(output_path, pagesize=(210 * mm, 297 * mm))

    # 注册字体
    pdfmetrics.registerFont(TTFont('HarmonyOS_Sans_SC_Regular', regular_font_path))
    pdfmetrics.registerFont(TTFont('HarmonyOS_Sans_SC_Bold', Bold_font_path))

    # 标题
    c.setFont("HarmonyOS_Sans_SC_Bold", 16)
    c.setFillColor(colors.black)  # 确保文字颜色为黑色
    c.drawString(50 * mm, 280 * mm, "一米尺手工制作材料")

    # 说明文字
    c.setFont("HarmonyOS_Sans_SC_Regular", 10)
    c.drawString(20 * mm, 270 * mm, "1. 请沿虚线剪切每个尺子部分")
    c.drawString(20 * mm, 260 * mm, "2. 将灰色区域涂抹胶水,按数字顺序依次粘贴连接")
    c.drawString(20 * mm, 250 * mm, "3. 注意对齐刻度,完成后即可得到一把1米长的尺子")

    # 绘制5个尺子段 (水平排列)
    x_positions = [20 * mm, 50 * mm, 80 * mm, 110 * mm, 140 * mm , 170 * mm]
    start_y = 40 * mm

    for i, x in enumerate(x_positions):
        is_first = (i == 0)
        draw_ruler_segment(c, x, start_y, i * 200, is_first)
        draw_decorations(c, x, start_y, 200 * mm)

        # 添加剪切线标记 (虚线)
        c.setDash([2, 2])
        if not is_first:
            # 如果不是第一个尺子,剪切线要包含粘贴区域
            c.line(x - 2 * mm, start_y - OVERLAP - 2 * mm, x - 2 * mm, start_y + 202 * mm)
        else:
            c.line(x - 2 * mm, start_y - 2 * mm, x - 2 * mm, start_y + 202 * mm)
        c.line(x + 22 * mm, start_y - 2 * mm, x + 22 * mm, start_y + 202 * mm)
        c.setDash([])

        # 添加序号标记
        c.setFont("HarmonyOS_Sans_SC_Bold", 12)
        c.setFillColor(colors.black)  # 确保文字颜色为黑色
        c.drawString(x + 6 * mm, start_y - 10 * mm , f"[{i + 1}]")

    # 保存PDF
    c.save()


# 生成PDF文件
output_file = "ruler_template.pdf"
create_rulers_pdf(output_file)

如此你就完美的完成了上述作业!如果你想说,我就不想跑Python,有没有能直接下载的文件。

有,我顺带分享下。【下载地址】

标签: 暂无
最后更新:2024年11月17日

zhou

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

COPYRIGHT © 2021 zhoubin.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

浙ICP备09065757号-10