Идея о простых чартах
Idea of simple charts
Около 3-х месяцев тому назад у меня уже появлялась идея написать хэлпер для CodeIgniter'а с функционалом быстрого и легкого создания Open Flash Chart'ов в приложении, но тогда моя затея не увенчалась успехом из-за нехватки времении полного осознания того, что именно я хотел сделать.
About 3 months ago I got an idea of creating a helper for CodeIgniter with functional for fast and easy creation of Open Flash Charts in application. But my idea didn't crowned with success cos I didn't have enough time back then.
«ТЗ» для чартов
Requirements specification for charts
Теперь мои требования сформировались достаточно определенно. Создание чартов в приложении:
Creation of charts must:
-
Должно быть максимально простым и легким.
be simple and easy;
-
Должно занимать от 3-4 строчек кода.
take 3-4 lines of code;
-
Может быть для различных целей, а значит и виды их должны быть различными (простые графики, барчарты, круговые диаграммы и т.д.).
serve different purposes, so they must look different: simple diagrams, barcharts, piecharts, etc.;
-
Не должно требовать создания дополнительных методов контроллеров, например, для AJAX'овой подгрузки данных (но с этим пунктом на момент написания поста я не совсем согласен, этот функционал достаточно просто будет реализовать в будущих версиях расширения).
be created without creating additional methods of controllers (for ex. for AJAX loading of data);
-
Должно быть таким, чтобы в приложении они были красивыми!
be pretty!
Выбор технологии создания чартов был из OFC2 (первая версия уже морально устарела и сам разработчик говорит о том, что когда он создал вторую версию, учитывая ошибки и недоработки первой) и Yahoo Charts.
My chose was between OFC2 and Yahoo Charts.
Не буду заострять внимание на плюсах и минусах этих библиотек, но я уже пытался работать с OFC2 и они мне ближе по духу. За основу я взял их. А в дальнейшем это даже оказалось более удобным решением.
I didn't talk about advantages and disatvantages of this two libraries, but in past I'm already try to use OFC2 and I think that this library is more closer to my spirit.
Open Flash Charts 2 - то, что искали?
Open Flash Charts 2 - was I was looking for?
Open Flash Charts 2 - это небольшой набор файлов, для внешнего мира состоящий из флеш-ролика (260 Кб), и двух js-файлов общим весом ок. 25 Кб. Внутреннее содержание - различные библиотеки для PHP, Java, Python и других языков, которые облегчают подготовку данных для чарта. Плюсом этого набора является то, что будучи запрошенным единожды сам ролик в последующем не должен скачиваться - он может браться из кэша браузера. Этот вариант подходит, если приложение (сайт) будет насыщено различными графиками. Для одного графика, мне кажется, что лучше использовать просто создание картинки с помощью библиотеки GD.
Open Flash Charts 2 is a small set of files consisting of flash movie (260 Kb) and two js-files about 25 Kb for outer world. The inside consisting is different libraries for PHP, Java, Python and other languages, which make preparing of data for charts easy. The advantage of this set is that the movie doesn't have to be loaded after it is requested for the first time - it can be taken from browser cache. This is good if site has many different charts. If there is need of one chart, I think it is better to use a GD library.
Технология работы с OFC2 достаточно простая. С помощью JS мы создаем в необходимом нам элементе DOM-дерева объект чарта, который подгружает .swf ролик и передает ему некоторые параметры (такие как, размеры чарта, источник данных, текст сообщения загрузки).
It is easy to work with OFC2. In a necessary element of DOM-tree we create an Object of chart with JS, which loads an .swf movie and gives settings (size of chart, data source, text of a message).
В зависимости от переданного метода получения данных swf-объект может обратиться по переданному адресу для получения данных в формате JSON или вызвав определенную JS-функцию, которая вернёт данные так же в формате JSON. Кроме самих данных в источнике содержится информация о типе графика (линейный, круговой и т.д.), параметры легенды, параметры подписей к осям и т.д. В нашем случае интересна подгрузка данных прямо из тела документа, чтобы не потребовалось создавать дополнительный метод в контроллере, который бы отвечал за AJAX подгрузку данных чарту. Кроме того, на одной странице приложения может быть несколько чартов, что я решил созданием md5 хэша из случайного числа для кадого нового графика и вырезкой первых 4-х символов полученного хэша (мне кажется, что этого достаточно, но ведь всегда можно увеличить!). Эти 4 случайных символа встраиваются в код, а именно в имя идентификатора элемента DOM и имя функции-датасорса (источника данных).
.swf object can appeal to delivered address for recieving data in JSON format, or request a javascript function, which will give data in JSON, depending on methond of recieving data. The source of data also contains information of type of chart (linear, pie, etc.), legend options, axis' labels, etc. In my case it was interesting to load data right from the document's body, so we don't need an additional method in controller which would be responsible for AJAX loading of data for chart. Further, there can be several charts on one page, and this problem I solved by creation of md5 hash of random number for each new chart and cut of 4 symbols of hash (and I think it's enough for randomness of identificator name of element. But it can be enlarged at any time :). The name of DOM element and name of function-data source include this four symbols.
Примерно такой код у нас будет получаться на выходе (в теле документа, который будет передан браузеру клиента).
So we get this code like you can see below (in document's body which will be sent to client's browser).
var data_96a6 = { "elements": [ { "type": "pie", "colours": [ "#d01f3c", "#356aa0", "#C79810" ], "border": "2", "tip": "Label text #label# - #val# из #total#", "values": [ { "value": 33622, "label": "First value" }, { "value": 15749, "label": "Second value" }, { "value": 14486, "label": "Third value" }, { "value": 2084, "label": "Fourth value" } ] } ], "bg_colour": "#ffffff" }; function get_data_96a6() { return JSON.stringify(data_96a6); } swfobject.embedSWF( "/assets/267d71e3/open-flash-chart.swf", "chart_96a6", "250", "250", "9.0.0", "", { "get-data" : "get_data_96a6" } );
Кодо-вор или Робин Гуд опен сорса?
Code thieft or Robin the Hood of Open Source?
Беглый «гугл-осмотр» дал пищу для дальнейших действий и мыслей. Очень быстро нашелся хэлпер для CakePHP с нужным мне функционалом, да и к тому же под MIT-лицензией. Но он был заточен именно под Cake. Потребовалось достаточно в некоторых местах грубо переработать его под нужды Yii.
Quick "googling" gave food for next thoughts and operations. Very soon I found helper for CakePHP with the functional I needed and MIT licenced. It was made for Cake. So I had to remake it for Yii a bit.
Необходимо было учесть технологическую особенность Yii - механизм предварительной публикации внутренних компонентов в виде ассетов (assets), которая обеспечивает большую безопасность исполняемого приложения и его частей. Кроме того в реализации хэлпера для Cake использовались хэлперы вывода JavaScript кода, от них пришлось избавиться и переписать заново вывод. Однако внутренни методы, которые занимаются подготовкой данных для самого чарта почти не изменялись, единственным дополнением, которое я сделал, было изменение элемента $chartId с default на null, а при инициализации компонента происходит создание случайного имени этого графика.
I had to take into account a special feature of Yii - the mechanism of preliminary publishing inside components in form of assets, which ensures more safety of executing application and it's parts. The helpers of Java Script code output were also used in release of Cake helper. We had to get rid of it and remake the output. The inside methods which prepear data for charts, hadn't been changed a lot. The only one addition was changing the $chartId c default element to null, and the creation of random name of this chart goes on initialisation.
Долгожданные примеры
Examples screenshots
Перед использованием расширения openflashchart2 в приложении Yii, его необходимо создать:
Before using the expantion openflashchart2 in Yii application, we have to create it:
// Creating an Yii Extension component $flashChart = Yii::createComponent('application.extensions.openflashchart2.EOFC2');
И, поехали!
And go on!
Простейший чарт
Simple chart
// Minimum usage. You will always need at least this. $flashChart->begin(); $flashChart->setData(array(1,2,2,3,5,6,1,9,6,4,5,6,7,8,0,8,2,2,1,9)); $flashChart->renderData('line'); $flashChart->render(300, 200);

Чарт с двумя наборами данных
Chart with 2 datasets
// Minimum with 2 datasets $flashChart->begin(); $flashChart->setData(array(1,2,4,8),'{n}',false,'Apples'); $flashChart->setData(array(3,4,6,9),'{n}',false,'Oranges'); $flashChart->renderData('line',array('colour'=>'green'),'Apples'); $flashChart->renderData('line',array('colour'=>'orange'),'Oranges'); $flashChart->render(300,200);

Правим надписи и название
Customizing your chart and setting labels
// Customizing your chart and setting labels $flashChart->begin('SteppChart'); $flashChart->setTitle('Steppometer','{color:#880a88;font-size:15px;padding-bottom:20px;}'); $data['1']['Day']['date'] = 'October \'09'; $data['1']['Day']['count'] = '123'; $data['2']['Day']['date'] = 'November \'09'; $data['2']['Day']['count'] = 345; $data['3']['Day']['date'] = 'December \'09'; $data['3']['Day']['count'] = 500; $flashChart->setData($data); $flashChart->setNumbersPath('{n}.Day.count'); $flashChart->setLabelsPath('default.{n}.Day.date'); $flashChart->setLegend('x','Dato'); $flashChart->setLegend('y','Skritt', '{color:#AA0aFF;font-size:12px;}'); $flashChart->axis('x',array('tick_height' => 10,'3d' => -10)); $flashChart->axis('y',array('range' => array(0,600,100))); $flashChart->renderData(); $flashChart->render(400,300);

Scatter-чарт
Scatter
// Scatter $data = array(); for( $i=0; $i<360; $i+=5 ) { $data[] = array( 'x' => number_format(sin(deg2rad($i)), 2, '.', ''), 'y' => number_format(cos(deg2rad($i)), 2, '.', '') ); } $flashChart->begin(); $flashChart->setData($data); $flashChart->setTitle('Scatter'); $flashChart->axis('x',array('range' => array(-2,3,1))); $flashChart->axis('y',array('range' => array(-2,2,1))); $flashChart->renderData('scatter'); $flashChart->render(300,300);

Мой любимый вид графиков - Sketch :)
My favourite charts type - Sketch :)
// SKETCH - my favourite :) $flashChart->begin('Sketch Chart'); $flashChart->setTitle('Sketchometer','{color:#880a88;font-size:15px;padding-bottom:20px;}'); $data['1']['Day']['date'] = 'Oct \'09'; $data['1']['Day']['count'] = '321'; $data['2']['Day']['date'] = 'Nov \'09'; $data['2']['Day']['count'] = 345; $data['3']['Day']['date'] = 'Dec \'09'; $data['3']['Day']['count'] = 500; $flashChart->setData($data); $flashChart->setNumbersPath('{n}.Day.count'); $flashChart->setLabelsPath('default.{n}.Day.date'); $flashChart->setLegend('x','Dato'); $flashChart->setLegend('y','Skritt', '{color:#AA0aFF;font-size:12px;}'); $flashChart->axis('x',array('tick_height' => 10,'3d' => -10)); $flashChart->axis('y',array('range' => array(0,600,100))); $flashChart->renderData('sketch', array( 'colour' => '#81AC00', 'outline-colour' => '#567300', 'offset' => 5, 'fun_factor' => 7, )); $flashChart->render(300,300);

Интерактивные примеры
Interactive examples
Здесь можно увидеть чарты такими, как они будут выглядеть на странице Вашего приложения.
More interactive chart - as you can see it on your pages.
Здесь можно скачать расширение OpenFlashChart2 для Yii
Here you can download the OpenFlashChart2 Yii Extension
Скачать версию 0.1 (28 апреля 2009 года). Download version 0.1 (28 April 2009).

