За последние 24 часа нас посетили 15924 программиста и 1548 роботов. Сейчас ищут 778 программистов ...

Скрипт диаграммы (графика)

Тема в разделе "Решения, алгоритмы", создана пользователем Redfern89, 2 мар 2023.

Метки:
  1. Redfern89

    Redfern89 Новичок

    С нами с:
    2 мар 2023
    Сообщения:
    5
    Симпатии:
    4
    Доброго времени суток! Выкладываю на ваше обозрение/пользование скрипт для вывода диаграммы.

    PHP:
    1. <?php
    2.     $minW = 500;
    3.     $minH = 500;
    4.     $bg = 0xFFFFFF;
    5.     $innerP = 0;
    6.     $title = @$_GET['title'];
    7.     $padding = 5;
    8.     $barW = @$_GET['bar_w'];
    9.     $barW = (!empty($barW)) ? (is_numeric($barW) ? $barW : 90) : 90;
    10.     $spacing = ($barW / 2);
    11.     $gridAmount = 11;
    12.     $gridHeight = ($barW);
    13.     $fs = (int)($barW / 3);
    14.  
    15.     $y_axis = @$_GET['y_axis'];
    16.     $y_axis = $y_axis == 'true'    ? true : false;
    17.     $data = @$_GET['data'];
    18.     $data = (!empty($data)) ? explode(',', $data) : [];
    19.     $font = dirname(__FILE__) . '/arial.ttf';
    20.     $labels = @$_GET['labels'];
    21.     $labels = (!empty($labels)) ? explode(',', $labels) : [];
    22.     $labelsH = array();
    23.     $yAxis = array();
    24.     $yAxisW = array();
    25.     $yAxisRects = array();
    26.     $values = array();
    27.     $labelsRects = array();
    28.     $labelsHMin = 0;
    29.     $labelsHMax = 0;
    30.     $yAxisMaxW = 0;
    31.     $yAxisMinW = 0;
    32.     $innerH = 0;
    33.     $outerH = 0;
    34.     $titleFS = 0;
    35.     $titlePaddingBottom = 0;
    36.  
    37.     if (!empty($data)) {
    38.         for ($i = 0; $i < count($data); $i++) {
    39.             if (preg_match('/^\d+$/', $data[$i])) $values[] = (int)$data[$i];
    40.             if (preg_match('/^-\d+$/', $data[$i])) $values[] = (int)$data[$i];
    41.             if (preg_match('/(\d+)\.(\d+)/', $data[$i])) $values[] = (float)$data[$i];
    42.             if (preg_match('/^-\d+.\d+$/', $data[$i])) $values[] = (float)$data[$i];
    43.         }
    44.     }
    45.  
    46.     if (!empty($values)) {
    47.         $min = min($values);
    48.         $max = max($values);
    49.         $sum = array_sum($values);
    50.         $cnt = count($values);
    51.         $innerW = (int)(($cnt * ($barW)) + ($cnt * $spacing)) + $spacing;
    52.         $outerW = $innerW;
    53.         $innerH    = (int)($gridAmount * $gridHeight);
    54.         $outerH    = (int)$innerH;
    55.         for ($i = 0; $i < count($labels); $i++) {
    56.             $bbox = imagettfbbox($fs, 90, $font, $labels[$i]);
    57.             $labelsH[] = (int)-$bbox[3];
    58.             $labelsRects[] = $bbox;
    59.         }
    60.      
    61.         if ($y_axis) {
    62.             for ($i = 0; $i < $gridAmount; $i++) {
    63.                 $lbl = sprintf('%.d%%', ($i * (100) / ($gridAmount -1)));
    64.                 $yAxis[] = $lbl;
    65.                 $bbox = imagettfbbox($fs, 0, $font, $lbl);
    66.                 $yAxisW[] = $bbox[2] - $bbox[0];
    67.             }
    68.         }
    69.         if (!empty($labelsH)) {
    70.             $labelsHMax = max($labelsH);
    71.             $labelsHMin = min($labelsH);
    72.             $outerH = $innerH + ($labelsHMax + ($padding * 2) + $fs);
    73.         }
    74.      
    75.         if (!empty($yAxisW) && $y_axis) {
    76.             $yAxisMaxW = max($yAxisW);
    77.             $yAxisMinW = min($yAxisW);
    78.             $outerW = $innerW + ($yAxisMaxW + ($padding * 4));
    79.         }
    80.      
    81.         $xOffset = 0;
    82.         if (!empty($title)) {
    83.             $titleFS = $outerH / 10;
    84.             $titlePaddingBottom = (int)($titleFS / 2);
    85.             $outerH = $outerH + $titleFS + $titlePaddingBottom;
    86.             $titleBbox = imagettfbbox($titleFS, 0, $font, $title);
    87.             $titleW    = ($titleBbox[2] - $titleBbox[0]);
    88.             if ($outerW < $titleW) {
    89.                 $outerW = $titleW;
    90.                 $xOffset = ($titleW - $outerW);
    91.             }
    92.         }
    93.      
    94.         $img    = imagecreatetruecolor($outerW, $outerH);
    95.         imagefill($img, 0, 0, 0xFFFFFF);
    96.      
    97.         if (!empty($title)) {
    98.             $x = (int)(($outerW / 2) - (($titleBbox[2] - $titleBbox[0]) / 2));
    99.             $y = (int)$titleFS;
    100.             imagettftext($img, $titleFS, 0, $x, $y, 0, $font, $title);
    101.         }
    102.      
    103.         for ($i = 0; $i < $gridAmount; $i++) {
    104.             $x1 = $y_axis ? $yAxisMaxW + ($padding * 4) : 0;
    105.             $x2 = $y_axis ? (int)($innerW + $yAxisMaxW + ($padding * 4)) : $innerW;
    106.             $y1 = (int)($i * $gridHeight) + ($titleFS + $titlePaddingBottom);
    107.             $y2 = (int)$y1 + $gridHeight;
    108.             $bg = ($i % 2) ? 0xf7f7f7 : 0xf0f0f0;
    109.             imagefilledrectangle($img, $x1, $y1, $x2, $y2, $bg);
    110.         }
    111.      
    112.         if ($y_axis) {
    113.             for ($i = 0; $i < $gridAmount; $i++) {
    114.                 $x = (int)(($padding * 2) + (($yAxisMaxW / 2) - $yAxisW[$i] / 2));
    115.                 $y = (int)((($innerH + ($titleFS + $titlePaddingBottom)) - ($i * ($gridHeight))) - (($gridHeight / 2) - ($fs / 2)));
    116.                 imagettftext($img, $fs, 0, $x, $y, 0, $font, $yAxis[$i]);          
    117.             }
    118.         }
    119.      
    120.         if ($y_axis) {
    121.             imageline($img, $yAxisMaxW + ($padding * 4), ($titleFS + $titlePaddingBottom), $yAxisMaxW + ($padding * 4), $innerH + ($titleFS + $titlePaddingBottom), 0);
    122.             imageline($img, $yAxisMaxW + ($padding * 4), $innerH + ($titleFS + $titlePaddingBottom), $innerW + $yAxisMaxW + ($padding * 4), $innerH + ($titleFS + $titlePaddingBottom), 0);
    123.         }
    124.      
    125.         for ($i = 0; $i < count($values); $i++) {
    126.             $val = $values[$i];
    127.             $minH = (int)($barW);
    128.             $maxH = (int)($innerH - $minH);
    129.             $barH = (int)(($val - $min) * ($maxH - $minH) / ($max - $min) + $minH);
    130.             $x1 = $y_axis ? (int)($i * ($barW + $spacing)) + $spacing + $yAxisMaxW + ($padding * 4) : (int)($i * ($barW + $spacing)) + $spacing;
    131.             $x2 = (int)$x1 + $barW;
    132.             $y1 = (int)(($innerH + ($titleFS + $titlePaddingBottom)) - $barH);
    133.             $y2 = (int)($innerH + ($titleFS + $titlePaddingBottom))- $padding;
    134.          
    135.             if ($val > 0) {
    136.                 $rectColor = imagecolorallocatealpha($img, 32, 143, 175, 20);
    137.                 $topEllipseColor = 0x72b8cc;
    138.                 $bottomEllipseColor = 0x208faf;
    139.             } else if ($val < 0) {
    140.                 $rectColor = imagecolorallocatealpha($img, 255, 60, 60, 20);
    141.                 $topEllipseColor = 0xff8686;
    142.                 $bottomEllipseColor = 0xff3c3c;
    143.             } else if ($val == 0) {
    144.                 $rectColor = imagecolorallocatealpha($img, 207, 189, 0, 20);
    145.                 $topEllipseColor = 0xffea09;
    146.                 $bottomEllipseColor = 0xcfbd00;              
    147.             }
    148.          
    149.             imagefilledrectangle($img, $x1, $y1, $x2, (int)($y2 - (($barW / 2) / 2)), $rectColor);
    150.             imagefilledellipse($img, (int)($x1 + ($barW / 2)), $y1, $barW, (int)($barW / 2), $topEllipseColor);
    151.             imagefilledellipse($img, (int)($x1 + ($barW / 2)), (int)((($innerH + ($titleFS + $titlePaddingBottom)) - $padding) - ($barW / 2) / 2), $barW, (int)($barW / 2), $bottomEllipseColor);
    152.          
    153.             $bbox = imagettfbbox($fs, 0, $font, $val);
    154.             $textW = (int)$bbox[2] - (int)$bbox[0];
    155.             $x = (int)($x1 + (($barW / 2) - ($textW / 2))) -2;
    156.             $y = (int)(($y1) - (($barW / 2) / 2)) - ($fs / 2);
    157.          
    158.             imagettftext($img, $fs, 0, $x, $y, 0xFFFFFF, $font, $val);
    159.             imagettftext($img, $fs, 0, $x-1, $y-1, $topEllipseColor, $font, $val);
    160.          
    161.             $labelText = (isset($labels[$i]) ? $labels[$i] : '');
    162.             $labelH = (isset($labelsH[$i]) ? $labelsH[$i] : 0);
    163.             $labelX = (int)($x2 - $fs);
    164.             $labelY = (int)((($innerH + ($titleFS + $titlePaddingBottom)) + $labelsHMax) - (($labelsHMax / 2) - ($labelH / 2)) + ($fs / 2));
    165.          
    166.             imagettftext($img, $fs, 90, $labelX, $labelY, 0, $font, $labelText);
    167.         }
    168.     }
    169.  
    170.     header('Content-Type: image/png');
    171.     imagepng($img);
    172.     imagedestroy($img);
    173. ?>
    Пример использования
    Код (Text):
    1.  
    2. http://site/dia.php?data=11,9,18,-5,0,-4,3,8,1,3,8,1&labels=January,February,March,April,May,June,July,August,September,October,November,December&y_axis=true&title=Test%20diagram&bar_w=60
    Описание параметров
    1. data - Данные через запятую
    2. labels - Метки через запятую
    3. y_axis - Показать/Скрыть метки по вертикали
    4. title - Заголовок
    5. bar_w - Ширина столбца
    Так-же для работы скрипта нужен файл шрифта, который будет лежать в папке рядом со скриптом. В моей случае это arial.ttf

    Ширина и высота получившегося в итоге изображения зависит от количества данных в диаграмме, ширины столбца и длины меток. Все настраивается само

    PS.
    Если вы решите как-то это доработать/улучшить - большая просьба выложить сюда, спасибо
    :)

    Пример работы скрипта

    [​IMG]
     
    #1 Redfern89, 2 мар 2023
    Последнее редактирование: 2 мар 2023
    [vs] и musicman3 нравится это.
  2. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    Если оно вам нужно - то конечно гуд.. молодец
    но чтоб пользоваться... увольте.... 100500 бибилотек на js которые строят диаграммы, графики и прочие вещи прямо на лету, очень гибко настраиваются итд посмотрите тот-же chartJS
     
    musicman3 нравится это.
  3. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    146
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Согласен с ADSoft. В настоящее время графики на PHP уже не строят, так как они имеют значительный минус - они не интерактивны. А на JS легко можно сделать живую диаграмму. Но потрудился, уже молодец.
     
  4. antoniii

    antoniii Активный пользователь

    С нами с:
    16 мар 2022
    Сообщения:
    419
    Симпатии:
    71
    @Redfern89 сделай интерфейс, чтобы данные можно было настраивать в пользовательском режиме, а запрос к скрипту делался без перезагрузки.