使用 gd 调整字体大小和填充以创建动态条形图

Resizing font size and padding using gd to create a dynamic bar chart

受此 code 的启发,我正在尝试创建一个简单的条形图,能够根据 $data 动态创建、调整条形和文本的大小, $身高$体重:

<?php

$width = 300;
$height = 200;

$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';

$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
        'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];

$columns = count($data);
$padding = ($width+$height)/100;

$column_width = $width / $columns;

$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);

imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);

$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {

    $font_size = ($height / 100) * $padding;
    $column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
    $string = $array_keys[$i];

    $x1 = $i * $column_width;
    $y1 = $height - $column_height;
    $x2 = (($i + 1) * $column_width) - $padding;
    $y2 = $height - ($padding*4);
    $maxChars = ($font_size * 2) / $padding;

    if (strlen($string) > ($maxChars)) {
        $string = substr($string, 0, $maxChars) . '...';
    }

    imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
    imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
  $string);

    imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
    imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
    imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}

header("Content-type: image/png");
imagepng($image);
imagedestroy($image);

使用 300x200 没问题:

但使用 600x400:

我该怎么做才能解决这个问题?

您在$padding的基础上创建了$font_size$font_size在图表大小增长

的情况下会快速增长

取而代之,让 $font_size 依赖于条形图的 $heightY 位置,它应该可以正常工作,请试试这个脚本

<?php

$width = 600;
$height = 400;

$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';

$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
        'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];

$columns = count($data);
$padding = ($width+$height)/100;

$column_width = $width / $columns;

$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);

imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);

$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {

    $column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
    $string = $array_keys[$i];

    $x1 = $i * $column_width;
    $y1 = $height - $column_height;
    $x2 = (($i + 1) * $column_width) - $padding;
    $y2 = $height - ($padding*4);
    $maxChars = ($font_size * 2) / $padding;

    if (strlen($string) > ($maxChars)) {
        $string = substr($string, 0, $maxChars) . '...';
    }
    $font_size = ($height - $y2) / 2.5;
    imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
    imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
  $string);

    imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
    imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
    imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}

header("Content-type: image/png");
imagepng($image);
imagedestroy($image);

只是 $font_size = ($height - $y2) / 2.5;

的小改动

尝试一下是否可行。

基本上您的字体大小是 height/100,当高度为 200 时它是有效的,但是当您将高度增加一倍时,我们也需要更改字体大小以匹配它。

看看这是不是你想要的结果MaxInfo.Tech

<?php

$width = 600;
$height = 400;

$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';

$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
        'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];

$columns = count($data);
$padding = ($width+$height)/100;

$column_width = $width / $columns;

$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);

imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);

$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {

    $font_size = ($height / 200) * $padding;
    $column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
    $string = $array_keys[$i];

    $x1 = $i * $column_width;
    $y1 = $height - $column_height;
    $x2 = (($i + 1) * $column_width) - $padding;
    $y2 = $height - ($padding*4);
    $maxChars = ($font_size * 2) / $padding;

    if (strlen($string) > ($maxChars)) {
        $string = substr($string, 0, $maxChars) . '...';
    }

    imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
    imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
  $string);

    imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
    imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
    imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}

header("Content-type: image/png");
imagepng($image);
imagedestroy($image);

另请注意,为了更好地格式化它,您还可以将其他基于高度或宽度的变量更改为比 100 的静态分隔符更动态的变量。

只有字体大小计算可以在前面的代码中修复:

$font_size = ($height / 100) * $padding;           //Changing this line
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];

$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;

动态更改后如下:

$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];

$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$font_size = ($x2 - $x1) / 4;                //Changed line and location
$maxChars = ($font_size * 2) / $padding;

除此更改外,不需要任何其他内容。