Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Создание Облака тегов aka Tag Clound


Автор: gta4kv 16.3.2008, 11:18
Привет!

Хотите предисловие? Будет вам предисловие!

Жил-был я. ( http://vingrad.ru/@gta4kv ) И делать мне видимо было нечего. 
А чем я занимаюсь когда мне нечего делать? Правильно! Пишу бесполезные статьи сюда.

Сегодня статья будет о довольно актуальной сейчас теме  - "Создание облака тегов".

Пожалуй начнем.

Сначала создаем класс:
Код

class wordCloud
{
}


Объявляем переменные:
Код

    private $maxWords = 20;
    private $maxLines = 5;
    private $nowWord = 0;
    private $nowLines = 0;
    private $wordsArray = array();
    private $count = 0;
    private $perLine = 10;
    private $nowElement = 1;


Создаем функцию __construct():
Код

function __construct( $words = false, $maxWords = 20, $maxLines = 5, $perLine = 10 )
{
     $this->maxWords = $maxWords;
     $this->maxLines = $maxLines;
     $this->perLine  = $perLine;
     
     if ( is_array( $words ) && $words !== false )
        {
            foreach ( $words as $key => $value )
            {
                $this->addWord( $value );
            }
        }
}

Здесь:
  • Перебираем все слова, добавляем их на "облако" с помощью $this->addWord().
  • Устанавливаем значения для maxWordsmaxLinesperLine. ( Максимум слов, максимум строк, и максимум элементов на строке соответственно ).
Теперь этот самый addWord():
Код


    function addWord( $word, $value = 1 )
    {
     $word = strtolower( $word );
     
     if ( array_key_exists( $word, $this->wordsArray ) )
     {
         $this->wordsArray[ $word ] += $value;
     }
     else
     {
         $this->wordsArray[ $word ] = $value;        
     }
    

     return $this->wordsArray[ $word ];
    }


Здесь:
  • "Складываем" слова в массив.
Теперь функция для "перемешивания облака".
Код

function shuffleCloud()
    {
     $keys = array_keys( $this->wordsArray );
        shuffle( $keys );

        if ( is_array( $keys ) && count( $keys ) )
        {
         $tmpArray        = $this->wordsArray;
         $this->wordsArray = array( );
           
         foreach ( $keys as $key => $value )
         {
                $this->wordsArray[ $value ] = $tmpArray[ $value ];   
         }
        }
    }

Тут вроде все понятно, просто перемешиваем массив.

Дальше нам пригодится функция подсчета массива. smile
Код

    function getCloudSize()
    {
     return array_sum( $this->wordsArray );
    }

Тут тоже вроде все понятно.

Так как размер букв у нас будет выходить из css нам понадобится функция которая будет выбирать нужный класс:
Код

function getClassFromPercent( $percent )
    {
     if ($percent >= 99)
     $class = 1;
        else if ($percent >= 70)
        $class = 2;
        else if ($percent >= 60)
        $class = 3;
        else if ($percent >= 50)
        $class = 4;
        else if ($percent >= 40)
        $class = 5;
        else if ($percent >= 30)
        $class = 6;
        else if ($percent >= 20)
        $class = 7;
        else if ($percent >= 10)
        $class = 8;
        else if ($percent >= 5)
        $class = 9;
        else
        $class = 0;

     return $class;
    }

Здесь:
  • В функцию передается процент, из этого выбирается css-класс.
Ну и теперь главная функция, вывод нашего облака:
Код

function showCloud( $returnType = "html" )
    {
    $this->shuffleCloud();
    $this->max = max( $this->wordsArray );

        if ( is_array( $this->wordsArray ) )
        {
         $return = ( $returnType == "html" ? "" : ( $returnType == "array" ? array( ) : "" ) );
         foreach ( $this->wordsArray as $word => $popularity )
         {
             $sizeRange = $this->getClassFromPercent( ( $popularity / $this->max ) * 100 );
             if ( $returnType == "array" )
             {
                    $return[ $word ][ 'word' ]        = $word;
                 $return[ $word ][ 'sizeRange' ] = $sizeRange;
                 if ( $currentColour )
                     $return[ $word ][ 'randomColour' ] = $currentColour;
             }
             else if ( $returnType == "html" )
             {
                 if( $this->nowLine  == $this->maxLines ) return;
                 if( $this->nowWord  == $this->maxWords ) return;
                 
                 print  "<span class='word size{$sizeRange}'>{$word}</span>\n";
                 
                    if( $this->nowElement == $this->perLine )
                    {
                        print  "\n<br />\n\n";
                        $this->nowElement = 0;
                        $this->nowLine++;
                    }
                    
                    $this->nowElement++;
                    $this->nowWord++;
             }
         }
     return $return;
     }   
    }

Здесь:
  • Выводим облако.
  • Если $returnType == html, то облако выводится как html, иначе просто складывается в массив ( само слово и размер ).
Осталось только "заюзать".
Код


<style>
<!–
.word {
    font-family: Tahoma;
    padding: 4px 4px 4px 4px;
    letter-spacing: 3px;
}
span.size1 {
    color: #000;
    font-size: 2.4em;
}
span.size2 {
    color: #333;
    font-size:2.2em;
}
span.size3 {
    color: #666;
    font-size: 2.0em;
}
span.size4 {
    color: #999;
    font-size: 1.0em;
}
span.size5 {
    color: #aaa;
    font-size: 1.6em;
}
span.size6 {
    color: #bbb;
    font-size: 1.4em;
}
span.size7 {
    color: #ccc;
    font-size: 1.2em;
}
span.size8 {
    color: #ddd;
    font-size: .8em;
}
span.size0 {
    color: #ccc;
    font-size: .6em;
}

</style>

<?
 $randomWords = array(
    "webmasterworld", "vingrad", "Computer", "C#",  "PC", "sex",  "music", "music", "music", "music", "sex",  "PHP", "C", "vingrad", "XHTML", "sex", "C#",  "eminem", "programming", "forums", "sex",  "webmasterworld", "vingrad", "sex", "C#", 
    "email", "sex",  "vingrad", "C#", "C#", "C#", "C#", "C#", "C#", "C#",  "forums", "C#",  "Computer", "GTA", "css", "mysql", "sql", "css", "mysql", "C#",  "sql", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", 
    "forums", "internet", "class", "vingrad", "object", "sex",  "C#",  "method", "music", "music", "music", "music", "gui", "sex",  "vingrad", "encryption"
    );

    $cloud = new wordCloud( $randomWords, 250, 3, 5 );
    $cloud->shuffleCloud(); 
    echo $cloud->showCloud();
?>
Здесь:
  • 10 css стилей.
  • Массив со словами.
  • Вывод нашего облака.
  • Если надо что бы облако всегда перемешивалось - вызываем функцию  $cloud->shuffleCloud();  до вывода облака.
Вот весь код, если кто где запутался:
Код

 <?
final class wordCloud
{
    private $maxWords = 20;
    private $maxLines = 5;
    private $nowWord = 0;
    private $nowLines = 0;
    private $wordsArray = array();
    private $count = 0;
    private $perLine = 10;
    private $nowElement = 1;
   
    function __construct( $words = false, $maxWords = 20, $maxLines = 5, $perLine = 10 )
    {
     $this->maxWords = $maxWords;
     $this->maxLines = $maxLines;
     $this->perLine  = $perLine;
     
     if ( is_array( $words ) && $words !== false )
        {
            foreach ( $words as $key => $value )
            {
                $this->addWord( $value );
            }
        }
    }

    function addWord( $word, $value = 1 )
    {
     $word = strtolower( $word );
   
     if ( array_key_exists( $word, $this->wordsArray ) )
     {
         $this->wordsArray[ $word ] += $value;
     }
     else
     {
            $this->wordsArray[ $word ] = $value;       
     }
   
        return $this->wordsArray[ $word ];
    }

    function shuffleCloud()
    {
     $keys = array_keys( $this->wordsArray );
        shuffle( $keys );

        if ( is_array( $keys ) && count( $keys ) )
        {
         $tmpArray        = $this->wordsArray;
         $this->wordsArray = array( );
           
         foreach ( $keys as $key => $value )
         {
                $this->wordsArray[ $value ] = $tmpArray[ $value ];   
         }
        }
    }

    function getCloudSize()
    {
        return array_sum( $this->wordsArray );
    }

    function getClassFromPercent( $percent )
    {
        if ($percent >= 99)
        $class = 1;
        else if ( $percent >= 70 )
        $class = 2;
        else if ( $percent >= 60 )
        $class = 3;
        else if ( $percent >= 50 )
        $class = 4;
        else if ( $percent >= 40 )
        $class = 5;
        else if ( $percent >= 30 )
        $class = 6;
        else if ( $percent >= 20 )
        $class = 7;
        else if ( $percent >= 10 )
        $class = 8;
        else if ( $percent >= 5 )
        $class = 9;
        else
        $class = 0;

     return $class;
    }
   
    function showCloud( $returnType = "html" )
    {
    $this->shuffleCloud();
    $this->max = max( $this->wordsArray );

        if ( is_array( $this->wordsArray ) )
        {
         $return = ( $returnType == "html" ? "" : ( $returnType == "array" ? array( ) : "" ) );
         foreach ( $this->wordsArray as $word => $popularity )
         {
             $sizeRange = $this->getClassFromPercent( ( $popularity / $this->max ) * 100 );
             if ( $returnType == "array" )
             {
                    $return[ $word ][ 'word' ]        = $word;
                 $return[ $word ][ 'sizeRange' ] = $sizeRange;
                 if ( $currentColour )
                     $return[ $word ][ 'randomColour' ] = $currentColour;
             }
             else if ( $returnType == "html" )
             {
                 if( $this->nowLine  == $this->maxLines ) return;
                 if( $this->nowWord  == $this->maxWords ) return;
                 
                 print  "<span class='word size{$sizeRange}'>{$word}</span>\n";
                 
                    if( $this->nowElement == $this->perLine )
                    {
                        print  "\n<br />\n\n";
                        $this->nowElement = 0;
                        $this->nowLine++;
                    }
                    
                    $this->nowElement++;
                    $this->nowWord++;
             }
         }
     return $return;
     }   
    }
}
?>


<style>
<!–
.word {
    font-family: Tahoma;
    padding: 4px 4px 4px 4px;
    letter-spacing: 3px;
}
span.size1 {
    color: #000;
    font-size: 2.4em;
}
span.size2 {
    color: #333;
    font-size:2.2em;
}
span.size3 {
    color: #666;
    font-size: 2.0em;
}
span.size4 {
    color: #999;
    font-size: 1.0em;
}
span.size5 {
    color: #aaa;
    font-size: 1.6em;
}
span.size6 {
    color: #bbb;
    font-size: 1.4em;
}
span.size7 {
    color: #ccc;
    font-size: 1.2em;
}
span.size8 {
    color: #ddd;
    font-size: .8em;
}
span.size0 {
    color: #ccc;
    font-size: .6em;
}

</style>

<?
 $randomWords = array(
    "webmasterworld", "vingrad", "Computer", "C#",  "PC", "sex",  "music", "music", "music", "music", "sex",  "PHP", "C", "vingrad", "XHTML", "sex", "C#",  "eminem", "programming", "forums", "sex",  "webmasterworld", "vingrad", "sex", "C#", 
    "email", "sex",  "vingrad", "C#", "C#", "C#", "C#", "C#", "C#", "C#",  "forums", "C#",  "Computer", "GTA", "css", "mysql", "sql", "css", "mysql", "C#",  "sql", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", "gta4kv for vingrad", 
    "forums", "internet", "class", "vingrad", "object", "sex",  "C#",  "method", "music", "music", "music", "music", "gui", "sex",  "vingrad", "encryption"
    );

    $cloud = new wordCloud( $randomWords, 250, 3, 5 );
    $cloud->shuffleCloud(); 
    echo $cloud->showCloud();
?>



© http://vingrad.ru/@gta4kv

Последнее обновлениеMonday, 14 April 2008.

ps. про плюсики не забываем, ога? smile)


Автор: Хрипа 16.3.2008, 12:05
А исходник ктонить выложит ?

Добавлено @ 12:06
Кстати вопрос.
Откуда брать слова.
Я думаю их должен пользователь делать и слова берутся с базы.
Того что если каждый раз генерить по каому-то принцету то Нагрузка на серв и тормажения страници средствами Пыха.

Добавлено через 10 минут и 48 секунд
Скрипт конечно полезный однако есть недостатки.
Надо что бы вы его доработали и добавили настройку скрипта.
$CloudFormatLine = true;
$CloudPerLineItems = 20; // 20 Слов на одну строчку
-------------------------
$CloudFormatTable = true;
$CloudPerLineItems = 20; // Выводить вертикально по 20 строчек в каждой по 20 обьектов 
если фелсе то порядок идёт не горизантально а просто в строчку. 
-------------------------
Добавить надо работу не тока с индексированым массивом.
$isIndex = false; Бегим по мосиву уже в Foreach
-------------------------
Доработать скрипт что бы он это всё разлаживал без использования памяти
тойсть без ".=" если у меня будет 10 000 слов то страничка будет долго прогружатся.
Ну а так отлично будет скрипт полезным.

Автор: gta4kv 16.3.2008, 12:16
Цитата(Хрипа @ 16.3.2008,  12:05)
А исходник ктонить выложит ?

Добавлено @ 12:06
Кстати вопрос.
Откуда брать слова.
Я думаю их должен пользователь делать и слова берутся с базы.
Того что если каждый раз генерить по каому-то принцету то Нагрузка на серв и тормажения страници средствами Пыха.

Исходник есть, в последнем "коде". Я же специально написал - "Вот весь код, если кто где запутался"

Откуда брать слова это уже сами придумывайте. ;)

Добавлено через 1 минуту и 42 секунды
Цитата

Скрипт конечно полезный однако есть недостатки.
Надо что бы вы его доработали и добавили настройку скрипта.
$CloudFormatLine = true;
$CloudPerLineItems = 20; // 20 Слов на одну строчку
-------------------------
$CloudFormatTable = true;
$CloudPerLineItems = 20; // Выводить вертикально по 20 строчек в каждой по 20 обьектов 
если фелсе то порядок идёт не горизантально а просто в строчку. 
-------------------------
Добавить надо работу не тока с индексированым массивом.
$isIndex = false; Бегим по мосиву уже в Foreach
-------------------------
Доработать скрипт что бы он это всё разлаживал без использования памяти
тойсть без ".=" если у меня будет 10 000 слов то страничка будет долго прогружатся.
Ну а так отлично будет скрипт полезным.


Сделаю попозже.

Автор: Feldmarschall 16.3.2008, 13:04
Прошу прощения за оффтопик.
функция getClassFromPercent напомнила http://nudnik.ru/entry/1154 smile
Уж хотя бы кратные 10 проценты можно было бы вычислять, типа 
Код

10-ceil($percent/10);

smile

Автор: gta4kv 14.4.2008, 15:36
Статья Updated.

Автор: Glip 14.4.2008, 22:45
Код

 if ( is_array( $words ) && $words !== false )

интересное условие. если первая часть true, то вторая автоматически true, а если первая часть false, то если не ошибаюсь при && дальше и не проверяется.
или я в чем-то не прав?

Автор: 02077461 22.4.2008, 12:15
В нашем-то веке и слова в массиве, а почему бы не использовать RANDOM? http://www.petefreitag.com/item/466.cfm
Простой пример -- у тебя 5000+ тагов, тебе нужно вывести X самых популярных из них. Сколько изменений нужно внести в твой код?. 
Ты показываешь хорошие примеры того, как не надо делать: делаешь рабочий код, который нельзя использовать в реальных условиях. 
Но, судя по тому, что делаешь это от нечего делать, лучше сделать было можно, но незачем. 

Автор: awers 22.4.2008, 12:30
02077461, вы конечно простите, но может сразу тогда и научить код работать с бд, готовить кофе и т.д.? Надо - доробатывайте )

Автор: Feldmarschall 22.4.2008, 12:42
А вот такой вопрос.
Кто-нибудь когда-нибудь в жизни пользовался облаком тегов? 
Ну вот целенаправленно выбирал тег по размеру и читал все записи?
или как-то по-другом упользовался?

Автор: 02077461 22.4.2008, 12:46
Цитата(awers @  22.4.2008,  12:30 Найти цитируемый пост)
02077461, вы конечно простите
 Прощаю. 
Цитата(awers @  22.4.2008,  12:30 Найти цитируемый пост)
но может сразу тогда и научить код работать с бд
 "Научить код", это уж слишком. Вообще-то использовать средства для работы с БД уже давно не ново, и использовать их нужно (не поверите) именно в коде.
Цитата(awers @  22.4.2008,  12:30 Найти цитируемый пост)
готовить кофе и т.д.
 Ыть... Если пишем код для кофеварки, то надо и кофе научить варить. 
Цитата(awers @  22.4.2008,  12:30 Найти цитируемый пост)
Надо - доробатывайте ) 
 При написании класса, библиотеки или чего угодно упор надо делать на то, что никто не полезет внутрь смотреть как там надо что-то доработать. Есть API, есть интерфейс класса, есть документация использования. Дорабатывать код -- это костыль.

Добавлено через 2 минуты и 34 секунды
Цитата(Feldmarschall @  22.4.2008,  12:42 Найти цитируемый пост)
Кто-нибудь когда-нибудь в жизни пользовался облаком тегов? 
 я пользовался, когда тестировал вывод облака тегов.
Даже из самого бесполезного кода можно вынести полезные уроки. Написанным тут пользоваться точно нельзя, но и не для этого оно по-видимому писалось. 
Очень бы хотелось что бы автор развил свой потенциал и начал его применять в нужном направлении. 

Автор: gta4kv 22.4.2008, 13:56
1. Оно не заточено под базу.
2. Как уже говорилось, надо - дорабатывайте.
Это всего лишь пример.

Автор: boogi 11.6.2008, 13:37
Код

function getClassFromPercent( $percent )
    {
     if ($percent >= 99)
     $class = 1;
        else if ($percent >= 70)
        $class = 2;
        else if ($percent >= 60)
        $class = 3;
        else if ($percent >= 50)
        $class = 4;
        else if ($percent >= 40)
        $class = 5;
        else if ($percent >= 30)
        $class = 6;
        else if ($percent >= 20)
        $class = 7;
        else if ($percent >= 10)
        $class = 8;
        else if ($percent >= 5)
        $class = 9;
        else
        $class = 0;
     return $class;
    }


Жесть.

Автор: gta4kv 11.6.2008, 14:55
boogi, раз вы столько просто до жести умный, как вы предложите это сделать лучше?

Автор: Feldmarschall 11.6.2008, 15:06
Я предлагал. 3 месяца назад

Автор: gta4kv 11.6.2008, 18:00
Feldmarschall, ыы. пропустил)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)