Chia sẻ về sử dụng thư viện highcharts

Xin chào mọi người, trước khi bắt đầu bài viết thì mình sẽ giới thiệu qua về bản thân cũng như nội dung chính sẽ đề cập ở dưới. Mình hiện đang là practice ở mảng ROR được 2 tháng. Vì thời gian tiếp cận với ROR cũng chưa lâu nên nội dung bài viết của mình sẽ không phải là hướng dẫn hoặc là giới thiệu một kĩ thuật, phương pháp hoặc là một cách dùng gem. Mà mình sẽ chia sẻ lại về một trong các lần được nhận các vấn đề mới(đối với mình là mới), cách mà một thực tập sinh tiếp cận vấn đề, các lỗi gặp phải cũng như là cách mình đã khắc phục.

OK, đi vào thẳng vấn đề của bài hôm nay.

Vấn đề chính

Sử dụng thư viện highcharts để vẽ biểu đồ

Giới thiệu nhanh

Highcharts là gì?

Highcharts là thư viện biểu đồ bằng Javascript giúp bạn dễ dàng tạo các loại biểu đồ khác nhau (line, spline, area, areaspline, column, bar, pie & scatter).

Nội dung biểu đồ sẽ vẽ.

Mình đang xây dựng một ứng dụng gửi report hàng ngày (Daily report system). Hàng ngày mỗi user sẽ gửi report về cho hệ thống , report phân loại theo Progess(Tutorials, Project 1, Project2, ...)

Và biểu đồ mình cần vẽ ra sẽ là biểu đồ thống kê lại số lượng report của từng progess theo ngày.

image.jpeg

Bắt tay vào làm

Đầu tiên mình import thư viện highcharts

Vào trang này coppy toàn bộ code cho vào một file highcharts.js sau đó link tới file js đó bằng cách thêm //= require highcharts vào application.js

Tiếp theo, chọn loại biểu đồ muốn vẽ

Bằng cách là vào trang này, lựa chọn loại biểu đồ. Ở đây, mình chọn biểu đồ cột để hiện thị số lượng report của từng progess theo ngày.

Sau khi chọn xong,

Ở trang index của dashboard của admin (trang mình sẽ vẽ biểu đồ), tạo một thẻ div

<div id="dn-chart-report"></div>

Tạo 1 file assets/javascripts/admin/dashboard.js

$(function () {
    $('#dn-chart-report').highcharts({
        chart: {
            type: 'column'
        },
        title: {
            text: 'World\'s largest cities per 2014'
        },
        subtitle: {
            text: 'Source: <a href="http://en.wikipedia.org/wiki/List_of_cities_proper_by_population">Wikipedia</a>'
        },
        xAxis: {
            type: 'category',
            labels: {
                rotation: -45,
                style: {
                    fontSize: '13px',
                    fontFamily: 'Verdana, sans-serif'
                }
            }
        },
        yAxis: {
            min: 0,
            title: {
                text: 'Population (millions)'
            }
        },
        legend: {
            enabled: false
        },
        tooltip: {
            pointFormat: 'Population in 2008: <b>{point.y:.1f} millions</b>'
        },
        series: [{
            name: 'Population',
            data: [
                ['Shanghai', 23.7],
                ['Lagos', 16.1],
                ['Istanbul', 14.2],
                ['Karachi', 14.0],
                ['Mumbai', 12.5],
                ['Moscow', 12.1],
                ['São Paulo', 11.8],
                ['Beijing', 11.7],
                ['Guangzhou', 11.1],
                ['Delhi', 11.1],
                ['Shenzhen', 10.5],
                ['Seoul', 10.4],
                ['Jakarta', 10.0],
                ['Kinshasa', 9.3],
                ['Tianjin', 9.3],
                ['Tokyo', 9.0],
                ['Cairo', 8.9],
                ['Dhaka', 8.9],
                ['Mexico City', 8.9],
                ['Lima', 8.9]
            ],
            dataLabels: {
                enabled: true,
                rotation: -90,
                color: '#FFFFFF',
                align: 'right',
                format: '{point.y:.1f}', // one decimal
                y: 10, // 10 pixels down from the top
                style: {
                    fontSize: '13px',
                    fontFamily: 'Verdana, sans-serif'
                }
            }
        }]
    });
});

Màn hình thu được sẽ là biểu đồ với các thông số fix cứng giống hệt như demo của trang demo bên trên. Với cá nhân thì đến đây mình suy nghĩ là đã hiển thị được biểu đồ ra rồi, rất là mừng 😃)

Vậy thì bước tiếp theo mình tiến đến sẽ là gì. Chính là custom được biểu đồ , trả về được đúng biểu đồ mình mong muốn.

Để custom được thì mình đã đọc thêm về các settings của highcharts tại đây và tại đây

Việc custom các settings của highcharts là hoàn toàn nhanh chóng và dễ dàng, theo ý kiến cá nhân mình thì biết một chút css thì sẽ càng làm biểu đồ đẹp hơn và đọc settings cũng dễ hơn.

Và vấn đề cuối cùng mình gặp phải đó là : Cách truyền dữ liệu vào biểu đồ .

Ở đây các bước đi của mình như sau. Đầu tiên, mình thấy ở phần dữ liệu fix cứng có dạng như sau

data : [['Shanghai', 23.7],['Lagos', 16.1]].

--> Mình sẽ cần trả dữ liệu sao cho khi dữ liệu truyền vào biểu đồ sẽ có dạng như trên.

Đầu tiên ở controller mình xử lý:

def index
    @data = Hash.new
    @progesses = Progess.all
    @date = params[:date] || Date.today
    @progesses.each do |progess|
      @data[progess.name] = progess.reports.where(report_date: @date).size
    end
end

Đoạn controller trên chưa thực sự là tốt nhưng nếu còn các bài viết sau thì mình sẽ cải thiện và tối ưu hơn.

--> mình có một hash là @data với dữ liệu như sau

{"Read Tutorial"=>1, "Project 1"=>1, "Project 2"=>0}

Ở bên view mình sửa lại một chút để có thể truyền được data qua biểu đồ

<div id="dn-chart-report" data-chart="<%= @data.map {|k,v| [k, v]} %>"></div>

Bên js chỉ cần nhận cái data-chart là xong rồi .

$(function () {
  var data_chart = $('#dn-chart-report').data('chart');
    $('#dn-chart-report').highcharts({
      chart: {
        type: 'column'
      },
      title: {
        text: 'Number of Report'
      },
      subtitle: {
        text: 'abc'
      },
      xAxis: {
        type: 'category'
      },
      yAxis: {
        allowDecimals: false,
        min: 0,
        title: {
            text: 'Report'
        }
      },
      legend: {
          enabled: false
      },
      credits: {
        enabled: false
      },
      tooltip: {
          pointFormat: 'Number of reports : <b>{point.y:.1f} reports</b>'
      },
      series: [{
        data: data_chart ,
        dataLabels: {
          enabled: true,
          color: '#FFFFFF',
          align: 'center',
          format: '{point.y:.1f}',
          y: 5,
          style: {
              fontSize: '16px',
              fontFamily: 'Verdana, sans-serif'
          }
        }
      }]
    });
});

Ở phần data , chỉ cần để vào đó data_chart (được mình get từ view qua)

Và kết quả là: altScreenshot from 2016-08-01 02:18:54.png

Trên đây là cách mà mình đã tiếp cận và giải quyết vấn đề , ở góc độ một thực tập sinh thì chắc chắn sẽ còn nhiều thiếu sót. Rất mong được mọi người tích cực góp ý và đánh giá về cách làm của mình. Cảm ơn mọi người!

All Rights Reserved