这个是二年级学生的作业,之前是通过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,有没有能直接下载的文件。
有,我顺带分享下。【下载地址】