如何使用PIL在圆形饼块的正确位置绘制文本?
修正PIL轮盘文本位置的解决方案
问题根源
你的代码存在两个核心问题导致文本位置偏移:
- 坐标系适配错误:PIL画布以左上角为原点,y轴向下延伸;而标准数学坐标系y轴向上,直接套用三角函数会导致垂直方向位置反转。
- 角度计算冗余:代码中额外添加的
+5属于无效偏移,且三角函数的符号和应用逻辑未匹配PIL坐标系规则。
修正后的代码逻辑
先明确关键参数定义:
wheel_center:轮盘中心坐标,即(wheel_size/2, wheel_size/2)target_radius:文本到中心的距离,即wheel_radius - 20slice_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
相关产品推荐
相关产品推荐

