应手动计算每个字符宽度并累加间距:用 imagettfbbox 测宽,$x += ($bbox[2]−$bbox[0]) + $spacing,避免固定步进或 imagestring;需校验字体加载、使用绝对路径、utf-8 字符计数。

PHP GD 生成验证码时字母 X 轴间距太挤怎么办
默认用 imagestring 或 imagettftext 画字符时,字符是“紧贴着”排的,没有自动留白,视觉上像粘连。根本原因不是字体问题,而是你没控制每个字符的绘制起始 x 坐标。
用 imagettftext 手动算每个字符的 x 偏移
不能直接循环调用 imagettftext 并固定增量(比如每次 +15),因为不同字母宽度不同(如 “i” 和 “W”),固定步进会导致错位或重叠。得先用 imagettfbbox 测每个字符实际像素宽:
$char = 'A'; $bbox = imagettfbbox($font_size, 0, $font_file, $char); $width = $bbox[2] - $bbox[0]; // 右上角x - 左上角x $x += $width + $spacing; // $spacing 是你想要的字间距(如 5)
-
$spacing建议设为 2–8,太小看不出效果,太大显得松散 - 别用
imagestring:它只支持内置点阵字体,无法测宽,也无法调间距 - 确保
$font_file路径正确,否则imagettfbbox返回 false,后续计算崩
中文或混合字符时额外注意宽度一致性
中文字体通常等宽,但英文/数字在同字体下仍不等宽。如果验证码含大小写字母+数字(如 '2XkP'),必须对每个字符单独测宽——不能按“平均字符宽”粗略估算。
- 避免用
strlen()算字符串长度来推断总宽度:中文字符在 UTF-8 下占 3 字节,strlen会误判个数 - 改用
mb_strlen($str, 'UTF-8')获取真实字符数,再逐个imagettfbbox - 如果发现某些字符(如 “O”、“0”)视觉宽度接近,可人工微调
$spacing补偿,比如画完 “0” 后多加 1px
字体加载失败导致间距计算全乱
imagettfbbox 返回 false 时,$width 变成 0,后续所有 $x 坐标塌缩到起点,结果就是所有字符堆在左上角——看着像“间距为 0”,其实是计算中断了。
- 加一行判断:
if (!$bbox) { error_log("Font load failed: $font_file"); } - 确认 PHP 开启了
php-gd扩展,且支持 FreeType(gd_info()['FreeType Support'] === true) - 路径别用相对路径,用
__DIR__ . '/fonts/arial.ttf'更可靠
字体文件权限、GD 版本差异、中文编码处理,这些环节任何一个出错,都会让“调间距”变成调谜题。真要稳定,宁可多写两行测宽逻辑,也别信“+15 就够了”这种经验数。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











