Программа: создание гистограмм результатов голосования

Показ результатов голосования может быть более наглядным при использовании красочной гистограммы, вместо простой распечатки результатов в виде текста. Функция, представленная в примере 15.4, использует библиотеку GD для создания изображения, которое показывает совокупные ответы на вопрос, поставленный на голосование.

Пример 15.4. Графические гистограммы

Function pc_bar_chart($question, $answers) {
// определяем цвета для рисования полос
$colors = array(array(255,102,0), array(0,153,0),
array(51,51,204), array(255,0,51),
array(255,255,0), array(102,255,255),
array(153,0,204));
$total = array_sum($answers['votes']);
// определяем значения для промежутков и других магических чисел
$padding = 5;
$line_width = 20;
$scale = $line_width * 7.5;
$bar_height = 10;
$x = $y = $padding;// размещаем большую палитру для рисования, поскольку мы не знаем
// заранее длину изображения
$image = ImageCreate(150, 500);
$bg_color = ImageColorAllocate($image, 224, 224, 224);
$black = ImageColorAllocate($image, 0, 0, 0);
// печатаем вопрос
$wrapped = explode("\n", wordwrap($question, $line_width));
foreach ($wrapped as $line) {
ImageString($image, 3, $x, $y , $line, $black);
$y += 12;
}
$y += $padding;
// печатаем ответы
for ($i = 0; $i < count($answers['answer']); $i++) {
// формируем процентное соотношение
$percent = sprintf('%1.1f', 100*$answers['votes'][$i]/$total);
$bar = sprintf('%d', $scale*$answers['votes'][$i]/$total);
// выбираем цвет
$c = $i % count($colors); // обрабатываем случаи с большим
количеством полос, чем цветов
$text_color = ImageColorAllocate($image, $colors[$c][0],
$colors[$c][1], $colors[$c][2]);
// рисуем полосу и числа с процентами
ImageFilledRectangle($image, $x, $y, $x + $bar,
$y + $bar_height, $text_color);
ImageString($image, 3, $x + $bar + $padding, $y,
"$percent%", $black);
$y += 12;
// печатаем ответ
$wrapped = explode("\n", wordwrap($answers['answer'][$i],
$line_width));
foreach ($wrapped as $line) {
ImageString($image, 2, $x, $y, $line, $black);
$y += 12;
}
$y += 7;
}
// обрезаем изображение с помощью его копирования
$chart = ImageCreate(150, $y);
ImageCopy($chart, $image, 0, 0, 0, 0, 150, $y);
// доставляем изображение
header ('Content-type: image/png');
ImagePNG($chart);
// удаляем
ImageDestroy($image);ImageDestroy($chart);
}

Для вызова этой программы создайте массив, содержащий два параллельных массива: $answers['answer'] и $answer['votes'].


Элемент $i каждого массива хранит текст ответа и общее количество голосов, поданных за ответ $i.

// Акт II. Сцена II.
$question = 'What a piece of work is man?';
$answers['answer'][] = 'Noble in reason';
$answers['votes'][] = 29;
$answers['answer'][] = 'Infinite in faculty';
$answers['votes'][] = 22;
$answers['answer'][] = 'In form, in moving, how express and admirable';
$answers['votes'][] = 59;
$answers['answer'][] = 'In action how like an angel';
$answers['votes'][] = 45;
pc_bar_chart($question, $answers);

В данном случае ответы назначаются вручную, но в реальном голосовании эта информация может извлекаться из базы данных.

Эта программа представляет собой хорошее начало, но поскольку она использует встроенные в GD шрифты, здесь имеется большое количество внедренных в программу магических чисел, соответствующих высоте и ширине шрифтов. Кроме того, пространственные промежутки между ответами жестко зашиты в программе. Если вы модифицируете программу для использования более продвинутых шрифтов, таких как PostScript или TrueType, то вам придется обновить алгоритм, управляющий этими числами.
В начале функции определяется группа комбинаций RGB; они используются в качестве цветов для рисования полос.


Объявлено множествоконстант, например: $line_width представляет максимальное количество символов в строке, переменная $bar_height определяет высоту полос, а $scale определяет масштаб длины полосы как функцию от самой длинной строки. Переменная $padding нужна для того, чтобы отодвинуть результаты на пять пикселов от границы области отображения.

Затем мы создаем очень большую область отображения для рисования диаграммы; позднее мы обрежем область отображения снизу, но заранее трудно определить, насколько большим будет общий размер. По умолчанию фоновый цвет гистограммы (224, 224, 224), или светло-серый.

Для того чтобы разумно ограничить ширину диаграммы, мы используем функцию wordwrap() для разбиения переменной $question на строки меньшего размера и ограничиваем их символом \n с помощью функции explode(). Это дает нам массив строк с правильными размерами, которые мы будем печатать в цикле по одной строке за раз.

Напечатав вопрос, переходим к ответам. Во-первых, форматируем числа результатов с помощью функции sprintf(). Чтобы отформатировать общий процент голосов, поданных за определенный ответ, в виде числа с плавающей точкой и одним десятичным разрядом, указываем формат %1.1f.


Для определения длины полосы, соответствующей этому числу, задаем подобное число, но умножаем его не на 100, а на магическое число $scale, а затем возвращаем целое значение.

Цвет текста извлекается из массива $colors, содержащего RGB-тройки. Затем мы вызываем функцию ImageFilledRectangle() для рисования полосы и функцию ImageString() для рисования текста с процентами справа от полосы. После закрашивания мы печатаем ответ, используя тот же алгоритм, что и для печати вопроса.

Когда все ответы напечатаны, общий размер гистограммы сохраняется в переменной $y. Теперь мы можем корректно уменьшить размер рисунка, но у нас нет функции ImageCrop(). Чтобы выйти из положения, мы создаем новую область соответствующего размера и применяем функцию ImageCopy() к той части оригинального изображения, которую мы хотим сохранить. Затем выдаем изображение соответствующего размера в формате PNG, используя функцию ImagePNG(), и удаляем все из памяти с помощью двух вызовов функции ImageDestroy().

Как упоминалось в начале этого раздела, это простая, разработанная «на скорую руку» программа для печати гистограмм. Она работает и решает некоторые проблемы, например выполняет перенос строк, но она не абсолютно безупречна. К примеру, она не очень хорошо настраивается. Многие установки зашиты непосредственно в коде. Тем не менее она демонстрирует, как совместно применять множество функций из библиотеки GD для создания полезного графического приложения.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Безопасная работа с изображениями
Построение динамических изображений
Рисование дуг, эллипсов и окружностей
Рисование линий, прямоугольников и многоугольников
Рисование текста

Вернуться в раздел: PHP / 15. Графика