26 января 2013 г.

Использование Google Chart Tools в ASP.Net MVC

Вам приходилось рисовать графики и диаграммы на разрабатываемых сайтах? Мне, например, приходилось. Как всегда, в этом деле спасают разнообразные сторонние решения в виде плагинов и фреймворков.
Проблема в том, что до сих пор я не знал ни одного достойного варианта, который предоставлял бы широкий функционал, был прост в интеграции, и, конечно же, был бесплатным. Раньше можно было жить с бесплатными контролами диаграмм от Telerik, но поскольку лавочка прикрылась, а точнее переросла в Kendo DataViz, который стоит немалых денег, то пришлось искать друге решение.

Я был безмерно удивлен и счастлив, когда узнал, что сам Google предоставляет всем желающим API для визуализации данных. Этот чудный продукт называется Google Chart Tools, и включает в себя полный набор всего необходимого, с множеством вариаций графиков, с примерами, документацией и прочими плюшками.

Сегодня мы познакомимся с Google Chart Tools, и попробуем "внедрить" а наше ASP.NET MVC приложение графики для отображения данных.
Давайте создадим приложение, которое будет показывать 2 вида графиков. Разберемся, как эти графики можно настраивать, а также наполнять их данными.

Радует то, что для использования пакета, ничего не нужно скачивать и устанавливать.

Первым делом, поместим на наше представление пустой див-контейнер для диаграммы, и подключим скрипт - это API гугла:

   1:  <div id="chart_div"></div>
   2:   
   3:  <script type="text/javascript" src="https://www.google.com/jsapi">
   4:  </script>

Теперь о главном.
Нам необходимо написать скрипт, который будет подгружать из подключенного API нужный пакет, после чего настраивать диаграмму, наполнять ее данными, и отрисовывать на странице.

Привожу полный текст скрипта:

   1:  <script type="text/javascript">
   2:      // Подгружаем API
   3:      google.load('visualization', '1.0', { 'packages': ['corechart'] });
   4:   
   5:      // Устанавливаем callback
   6:      google.setOnLoadCallback(drawChart);
   7:   
   8:      function drawChart() {
   9:   
  10:          var options = {
  11:              'title': 'Blog Visitors',
  12:              'width': 400,
  13:              'height': 300
  14:          };
  15:   
  16:          var data = new google.visualization.DataTable();
  17:          data.addColumn('string', 'Country');
  18:          data.addColumn('number', 'Slices');
  19:   
  20:          $.getJSON('@Url.Action("GetProducts", "Home")', null
                                                        function (result) {
  21:              if (result.Countries.length) {
  22:                  $.each(result.Countries, function (index, c) {
  23:                      data.addRow(
  24:                          [c.Name, c.Value]
  25:                      );
  26:                  });
  27:                  // Отрисовка диаграммы
  28:                  var chart = new google.visualization.PieChart(
                                        document.getElementById('chart_div'));
  29:                  chart.draw(data, options);
  30:              };
  31:          });
  32:      }
  33:  </script>

После загрузки API, мы устанавливаем callback, тоесть функцию, которая отработает, когда API будет готов к работе. Эта функция у нас называется drawChart. В её начале мы создаем объект конфигурации диаграмм, заполняя его нужными свойствами и значениями (см. документацию).

После настройки, нам необходимо подготовить данные для отображения. Все диаграммы из Google Chart Tools работают с типом данных DataTable, который содержится в API, и хорошо описан в документации. По-сути, DataTable являет собой таблицу. Мы создаем новый DataTable, добавляем в него заголовки с описанием типов данных, которые будут содержаться в каждом столбце, а далее, заполняем таблицу построчно, используя метод DataTable.addRow(...).

Существует несколько вариантов заполнения таблицы данными. Мы воспользовались, как мне кажется, самым простым. Делаем ajax-запрос в метод GetProducts контроллера, и оттуда получаем набор данных в виде JSON:

   1:  public JsonResult GetProducts()
   2:  {
   3:      var result = new List<PieChartItem>();
   4:      result.Add(new PieChartItem { Name = "Ukraine", Value = 8 });
   5:      result.Add(new PieChartItem { Name = "Russia", Value = 6 });
   6:      result.Add(new PieChartItem { Name = "Belarus", Value = 6 });
   7:      result.Add(new PieChartItem { Name = "USA", Value = 4 });
   8:   
   9:      return Json(new { Countries = result }, JsonRequestBehavior.AllowGet);
  10:  }

Сразу хотелось бы сказать, что в документации также описан способ, с помощью которого можно напрямую связывать данные с результатом ajax-запроса на сервер. В таком случае, API берет на себя создание DataTable на основе JSON-ответа сервера. Но в таком сценарии есть один большой минус - приходящие с сервера json-данные должны быть строго описаны  конкретным образом. Например так:
Сами понимаете, что сформировать такой ответ на стороне сервера довольно хлопотное дело. Хотя, возможно оно того и стоит.

Вернемся к скрипту. После того, как DataTable наполнена, мы создаем новую диаграмму, с указанием её типа (круговая) и контейнера на странице, куда диаграмму нужно поместить. Обе эти вещи делаются строкой: google.visualization.PieChart(document.getElementById('chart_div')). Ну и в самом конце мы рисуем наш график, с передачей в него объекта параметров: chart.draw(data, options).

Для первой диаграммы этого вполне достаточно.
Смотрим на результат:
Также можно отметить и интерактивную составляющую диаграммы, а именно вид, при наведении курсора или выборе конкретного участка:
Вот такая круговая диаграмма у нас получилась. По-моему, вышло довольно неплохо.

Для закрепления, попробуем построить еще один график. На этот раз это будет график с областями.
И вот его реализация:

   1:  <script type="text/javascript">
   2:      google.load("visualization", "1", { packages: ["corechart"] });
   3:      google.setOnLoadCallback(drawChart);
   4:      function drawChart() {
   5:   
   6:          var options = {
   7:              title: 'Company Performance',
   8:              hAxis: {
   9:                  title: 'Year', titleTextStyle: { color: 'red' },
  10:              }
  11:          };
  12:   
  13:          var data = new google.visualization.DataTable();
  14:          data.addColumn('string', 'Year');
  15:          data.addColumn('number', 'Sales');
  16:          data.addColumn('number', 'Expenses');
  17:          data.addColumn('number', 'Rating');
  18:   
  19:          $.getJSON('@Url.Action("GetPerformance", "Home")', null
                                                      function (result) {
  20:              if (result.length) {
  21:                  $.each(result, function (index, r) {
  22:                      data.addRow(
  23:                          [r.Year, r.Sales, r.Expenses, r.Rating]
  24:                      );
  25:                  });
  26:                  var chart = new google.visualization.AreaChart(
                                       document.getElementById('chart_div'));
  27:                  chart.draw(data, options);
  28:              };
  29:          });
  30:      }
  31:  </script>

Мы добавили в опции подпись Year к горизонтальной оси. Теперь нам нужно больше данных, поэтому мы также добавили целых 4 столбца в DataTable, и наполнили таблицу результатом ajax-запроса к методу GetPerformance контроллера Home.
Последнее отличие - при создании диаграммы, на этот раз выбран AreaChart (график с областями), а не PieChart (круговая диаграмма), как в первый раз.

Вторая диаграмма:

Вот и все. Действительно, очень полезная штука.
Напомню, что это было лишь первое знакомство с Google Chart Tools. В документации есть еще уйма всего интересного. Все диаграммы можно расширять, кастомизировать, вешать на них события, реализовывать взаимодействие с пользователем и много-много другого.

_____
Исходники