Использование HTML-таблиц для вывода диаграмм
Введение
При разработке некоторых видов скриптов, в частности - скриптов
голосований, бывает желательно организовать в них наглядный
вывод тех или иных статистических данных в виде диаграммы.
Обычно "графический" вывод CGI-скрипта организуется путем формирования
скриптом рисунка в одном из форматов веб-графики (чаще всего GIF или
PNG) и вставки ссылки на этот рисунок <IMG src="..."> на выводимую
HTML-страничку.
Однако написание программного кода по формированию рисунков
представляет значительные трудности, особенно для начинающих
программистов, т.к. это предполагает либо доскональное изучение
довольно сложных форматов графических файлов, либо использование
библиотек для работы с графикой, написанных другими.
Все это осложняется еще и тем, что алгоритм сжатия данных LZW,
используемый в GIF, является в настоящее время патентованным
и небесплатным для использования. Иными словами, разработчики
"железа" и ПО, которые используют данный алгоритм, должны платить
патентные отчисления фирме-держателю патента. А поскольку такой
порядок вещей совершенно неприемлем для разработчиков бесплатного ПО,
то разработанные графические библиотеки либо вовсе не поддерживают
формат GIF, либо поддерживают только формирование "несжатых" GIF-файлов.
Однако обязательно ли для вывода диаграмм на HTML-странице использовать
"настоящую" графику? Нет ли "альтернативных способов"? И
вообще, является ли использование графики лучшим и оптимальным путем
вывода диаграмм?
В этой статье я предлагаю "альтернативный способ" вывода
столбчатых (линейных) диаграмм, основанный на HTML-таблицах.
Этот способ, по моему мнению, отличается сравнительной
(а по сравнению с формированием графики - значительной) простотой
реализации и хорошим качеством "результата".
Теория
Как известно, язык HTML позволяет управлять практически всеми
параметрами таблиц. Суть предлагаемого метода заключается в том,
что HTML-таблицу можно "сформировать" таким образом, что она
будет выглядеть как вполне приличная диаграмма.
Например, так:
При этом разработчик ценой минимальных усилий может придать диаграмме
практически любой вид - изменить цвета столбцов (или даже залить их
рисунком), их ширину, расстояние между ними и т.д. Можно даже написать
на столбцах текст. Причем все это делается только лишь изменением
параметров и содержимого ячеек выводимой таблицы, а вся "техническая"
нагрузка по формированию на экране пользователя таблицы нужного вида
ложится на "плечи" броузера.
Выводимая диаграмма может быть горизонтальной или вертикальной.
Далее мы в этой статье будем рассматривать горизонтальные диаграммы
как наиболее простые и более наглядно иллюстрирующие идею.
Поскольку в горизонтальной диаграмме каждый столбец диаграммы
представлен строкой таблицы, то далее, чтобы не внести путаницы,
столбец таблицы я буду называть "столбец", а столбец диаграммы -
"столбик". :-)
Вывод CGI-скрипта, формирующего такую диаграмму, может быть вставлен
в страницу с помощью SSI или IFRAME. При этом надо иметь в виду,
что диаграмма, вставленная на страницу через SSI, является частью
самой страницы и, следовательно, сохраняется/отображается/кэшируется
вместе с ней. В одних случаях это преимущество, в других -
недостаток. Еще одним недостатком этого метода (на практике - не очень
существенным) является то, что таблицу, в отличие от рисунка,
нельзя масштабировать.
От теории к практике
Итак, как же нужно сделать таблицу, чтобы она выглядела как диаграмма?
В простейшем случае в качестве диаграммы можно построить таблицу
с двумя ячейками в каждой строке. Первая ячейка будет собственно столбиком
диаграммы (она видима и отображается нужным цветом или background-ом),
а вторая - невидимая. Как известно, броузер отображает только те
ячейки таблицы, у которых есть содержимое (непустые). Поэтому для
того, чтобы сделать видимой первую ячейку-"столбик", в нее нужно
поместить, по крайней мере, символ
Общая ширина этих двух ячеек для каждой строки должна быть
одинакова (ширина таблицы), а количество строк соответствует
количеству столбиков диаграммы (числу отображаемых значений).
И тут начинаются наши первые "подводные камни" на светлом пути
к великой цели :-). Дело в том, что броузер не может "просто так", без
ухищрений, построить таблицу, у которой в каждой строчке значения
ширины столбцов разные! Для каждой выводимой таблицы броузер вычисляет
ширины столбцов (одинаковые для каждой строки) и высоты строк
(одинаковые для каждого столбца).
Из этого положения есть два выхода:
Использовать для разных столбиков диаграммы
разные таблицы, каждая из одной строки.
Использовать возможность объединения ячеек: для каждой ячейки
HTML-таблицы можно задать, на сколько строк и/или на сколько столбцов
она "распространяется" (параметры rowspan и colspan тэга <TD>
соответственно).
Во втором случае необходимо построить таблицу, у которой ширины
столбцов соответствуют разности между соседними по величине
отображаемыми значениями, а нужную ширину видимой ячейки-"столбика"
в каждой строке получать "распространением" первой ячейки на
нужное количество столбцов.
Пример: для отображения диаграммы со столбиками 100, 300 и 400 пикселей
нам нужно построить таблицу с ширинами столбцов 100, 200 и 100.
Первый столбик диаграммы "займет" один столбец таблицы, второй - два
и третий - три. Соответственно, вторая, невидимая ячейка займет
столько столбцов, сколько осталось.
Соответственно, программный код по формированию "таблицы-диаграммы"
должен включать в себя алгоритм сортировки отображаемых значений
и вычисления нужных ширин столбцов таблицы.
Пример скрипта
А теперь рассмотрим практический пример скрипта для "табличного"
вывода диаграммы.
#!/usr/bin/perl
#Исходные данные для вывода диаграммы
#массив $data - данные для вывода (уже в пикселях).
#$val - количество выводимых столбцов (соотв количеству элементов $data).
$data[1]=200; $color[1]="#FF0000";
$data[2]=100; $color[2]="#00FF00";
$data[3]=150; $color[3]="#0000FF";
$data[4]=400; $color[4]="#00FFFF";
$data[5]=500; $color[5]="#FF00FF";
$data[6]=600; $color[6]="#FFFF00";
$val=6;
#Ниже расположен код сортировки выводимых на диаграмме значений
#В процессе его работы на основе массива @data создается отсортированный
#массив @stp и хэш %lvl с количеством столбцов таблицы для каждого
#столбика диаграммы
$rows=1;
$stp[0]=0;
$stp[1]=$data[1];
$lvl{$data[1]}=1;
$i=2;
while($i<=$val){
$p=0; $x=1;
while($x<=$rows && $p==0)
{
if ($data[$i]==$stp[$x]){$p=1;$lvl{$data[$i]}=$x;goto a1;};
if ($data[$i]<$stp[$x]){
#Вставка нового значения "в середину" массива @stp
for ($y=$rows+1;$y>=$x;$y=$y-1){$stp[$y+1]=$stp[$y];};
$stp[$x]=$data[$i];
#Корректируем хэш %lvl с учетом "сдвига" @stp
foreach $itm(keys %lvl){if ($lvl{$itm}>=$x){$lvl{$itm}=$lvl{$itm}+1;};};
$lvl{$data[$i]}=$x;
$rows=$rows+1;
$p=1;
};
$x++;
};
if ($p==0){$rows=$rows+1;$stp[$rows]=$data[$i]; $lvl{$data[$i]}=$rows};
$i++;
};
#А здесь мы, собственно, выводим таблицу
print "Content-Type: text/htmlnn";
print "<TABLE border=0>n<TR>";
#Выводим первую строку таблицы, задающую броузеру нужные ширины ячеек
#Она не будет отображаться, т.к. ячейки пустые
for ($k=1;$k<=$rows;$k=$k+1){
$w=$stp[$k]-$stp[$k-1];
print "<TD width=$w></TD>";
};
print "</TR>n";
#Выводим строки, содержащие диаграмму
for ($v=1;$v<=$val;$v=$v+1){
$tl=$lvl{$data[$v]};
$rst=$rows-$tl;
print "<TR>";
#Если видимая ячейка есть (выводимое значение не 0: $tl>0),
#то выводим ее:
if ($tl>0)
{print "<TD bgcolor=$color[$v] colspan=$tl> </TD>";};
#Если невидимая ячейка есть (выводимое значение не равно максимальному),
#то выводим ее:
if ($rst>0)
{print "<TD colspan=$rst></TD>";};
print "</TR>n";
};
print "</TR></TABLE>";
Т.к. приведенный здесь программный код в качестве исходных данных
использует уже "готовые" значения в пикселах (а не собственно выводимые
величины в их исходном виде), то перед его использованием необходимо
преобразовать выводимые величины (скажем, проценты) в количества
пикселей с учетом желаемой ширины диаграммы.
Допустим, нам надо вывести результаты голосования, которые передаются
в переменных $za, $prot, $vozd в значениях процентов.
$width=400; #Желаемая ширина диаграммы
$data[1]=($za/100)*$width;
$data[2]=($prot/100)*$width;
$data[3]=($vozd/100)*$width;
$val=3;
Управление толщиной столбцов
В ряде случаев Вам может понадобиться явно задать толщину столбиков
диаграммы, т.е. высоту строк таблицы. И здесь Вам встретится еще один
"подводный камень" данного решения. Дело в том, что параметры width
и height тэга <TD> задают не
однозначные, а минимальные значения ширины и высоты ячейки таблицы.
Т.е. если "по содержимому" ячейка меньше, чем указано в параметрах
width и height, то она "растягивается" до нужных размеров.
Наш пример вообще не задает в тэгах <TD> параметр height,
поэтому высота ячеек таблицы определяется размерами шрифта,
которым "написан" символ в видимой ячейке (несмотря на то,
что это символ пробела, он, как и любой другой символ, имеет свою
высоту) и отступом между "абзацем" и границами ячейки.
Соответственно, если не принять дополнительных мер, то на разных страницах и
у разных посетителей выглядеть несколько по-разному.
"Общим видом решения" этой задачи является минимизация собственной
высоты ячейки и задание ее высоты с помощью параметра height тэга
<TD>.
Самым "радикальным" способом уменьшения высоты является помещение в
видимую ячейку вместо & нетекстового содержимого,
скажем, картинки размером 1x1 пиксель:
<IMG width=1 height=1 src="trans.gif">
а в trans.gif поместить прозрачное изображение в 1 пиксель.
Тогда "собственная" высота ячеек получится очень мала (несколько пикселей)
и параметром height и Вы сможете однозначно задавать высоту ячеек таблицы-диаграммы,
а следовательно, и толщину столбиков.
Еще одним способ уменьшить "собственную" высоту ячеек - максимально
уменьшить размер шрифта в "видимой" ячейке.
© Андрей Черный, 2005
"AC-Power: все про Интернет и для него"
//www.angel07.webservis.ru/
- Интернет-пользователям
- PERL / CGI
- Хостинг
- Форум на тему всего этого :-)
|