You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PIL在圆形饼块的正确位置绘制文本?

修正PIL轮盘文本位置的解决方案

问题根源

你的代码存在两个核心问题导致文本位置偏移:

  1. 坐标系适配错误:PIL画布以左上角为原点,y轴向下延伸;而标准数学坐标系y轴向上,直接套用三角函数会导致垂直方向位置反转。
  2. 角度计算冗余:代码中额外添加的+5属于无效偏移,且三角函数的符号和应用逻辑未匹配PIL坐标系规则。

修正后的代码逻辑

先明确关键参数定义:

  • wheel_center:轮盘中心坐标,即(wheel_size/2, wheel_size/2)
  • target_radius:文本到中心的距离,即wheel_radius - 20
  • slice_mid_angle:当前饼块的正中间角度,取起始角与结束角的平均值

修正后的文本坐标计算代码:

import math
from PIL import Image, ImageDraw

# 假设已定义参数:wheel_size, wheel_radius, degree_1, degree_2, label, color, wheel_geometry

draw = ImageDraw.Draw(wheel_image)
# 绘制饼块
draw.pieslice(wheel_geometry, degree_1, degree_2, fill=color, outline="black", width=3)

# 计算饼块中间角度(去掉冗余的+5偏移)
slice_mid_angle = (degree_1 + degree_2) / 2
angle_rad = math.radians(slice_mid_angle)

# 适配PIL坐标系计算文本坐标
text_x = wheel_size/2 + target_radius * math.cos(angle_rad)
text_y = wheel_size/2 - target_radius * math.sin(angle_rad)

# 绘制文本(设置锚点为中心,确保文本居中对齐)
draw.text(
    xy=(text_x, text_y),
    text=str(label),
    fill="white",
    anchor="mm"
)

关键细节说明

  • 锚点设置:anchor="mm"让文本的中心对齐计算出的坐标,避免默认左上角锚点导致的偏移。
  • 坐标系适配:y坐标用wheel_center_y - target_radius * math.sin(angle_rad),抵消PIL坐标系y轴向下的影响。
  • 角度准确性:用(degree_1 + degree_2)/2直接获取饼块正中间角度,无需额外手动偏移。

完整可运行示例(含颜色数据)

import math
from PIL import Image, ImageDraw

# 轮盘基础参数
wheel_size = 400
wheel_radius = wheel_size // 2
wheel_geometry = (0, 0, wheel_size, wheel_size)
target_radius = wheel_radius - 20

# 饼块数据:(标签, 颜色, 角度占比)
slice_data = [
    (1, "#cc0011", 120),  # 红色,占120度
    (2, "#eeaa00", 120),  # 黄色,占120度
    (3, "#10aded", 120)   # 浅蓝色,占120度
]

# 创建空白画布
wheel_image = Image.new("RGB", (wheel_size, wheel_size), "white")
draw = ImageDraw.Draw(wheel_image)

current_angle = 0
for label, color, angle in slice_data:
    degree_1 = current_angle
    degree_2 = current_angle + angle
    # 绘制饼块
    draw.pieslice(wheel_geometry, degree_1, degree_2, fill=color, outline="black", width=3)
    # 计算中间角度与文本坐标
    slice_mid_angle = (degree_1 + degree_2) / 2
    angle_rad = math.radians(slice_mid_angle)
    text_x = wheel_size/2 + target_radius * math.cos(angle_rad)
    text_y = wheel_size/2 - target_radius * math.sin(angle_rad)
    # 绘制文本
    draw.text(
        xy=(text_x, text_y),
        text=str(label),
        fill="white",
        anchor="mm",
        # 可选:自定义字体大小
        # font=ImageFont.truetype("arial.ttf", 24)
    )
    current_angle += angle

# 保存或展示结果
wheel_image.save("wheel_with_labels.png")
wheel_image.show()

内容的提问来源于stack exchange,提问作者Programer Beginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:31:04