5

Inspired by this code, I am trying to create a simple bar chart able to dynamically create, resize both bars and texts depends on the the $data, $height and $weight:

<?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);

Using 300x200 its okay:

enter image description here

But using 600x400:

enter image description here

What Can I do to fix that?

celsowm
  • 846
  • 9
  • 34
  • 59

3 Answers3

2

You create the $font_size base on $padding, the $font_size will grow fast in the case size of chart grow

Instead of it, make the $font_size depend on the $height and Y position of the bars, it should work fine, please try this script instead

<?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);

Just small change on $font_size = ($height - $y2) / 2.5;

Vo Kim Nguyen
  • 1,613
  • 10
  • 14
  • Notice: Undefined variable: font_size in C:\wamp64\www\curso\gd\graphs\bar\webmax.php on line 38 – celsowm Nov 15 '19 at 18:10
2

There is only Font Size Calculations Which can be fixed earlier code:

$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;

after changing it dynamic it would be as under:

$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;

Except this change nothing is required.

Vineet1982
  • 7,730
  • 4
  • 32
  • 67
1

Try if this works.

Basically your font size was height/100 which was working when height was 200, but when you have doubled the height, we need to change the font size to match it as well.

See if this is the desired result 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);

Also Please note to format it better you can change other variables also which are based on height or width, to something more dynamic than a static divider of 100.

Angad Arora
  • 719
  • 10
  • 25