12/08/2018, 13:41

Highchart advance with data (P1)

1.Giới thiệu Xin chào các bạn! Hôm nay mình xin giới thiệu tới các bạn một số kĩ thuật nâng cao trong khi sử dụng thư viện highchart và từng bước xây dựng một trang demo nho nhỏ để các bạn hiểu sâu hơn về thư viện highchart. Nếu bạn nào chưa biết highchart là gì thì mình xin được phép nhắc lại ...

1.Giới thiệu

Xin chào các bạn! Hôm nay mình xin giới thiệu tới các bạn một số kĩ thuật nâng cao trong khi sử dụng thư viện highchart và từng bước xây dựng một trang demo nho nhỏ để các bạn hiểu sâu hơn về thư viện highchart. Nếu bạn nào chưa biết highchart là gì thì mình xin được phép nhắc lại ngắn gọn như sau: "Highchart là một thư viện JQuerry hỗ trợ người dùng vẽ các loại biểu đồ thống kê, map ...". Các bạn có thể xem chi tiết các bước cài đặt và hiểu kĩ hơn qua bài Giới thiệu thư viện Highchart trước của tôi! Còn hôm nay tôi sẽ tiếp tục với phần truyền dữ liệu và một số settings advance hay ho hơn.

2.Truyền dữ liệu vào highchart

Để có thể thực hiện được điều này,trước tiên chúng ta cần tạo một project với rails. Sau đó khởi tạo dữ liệu ban đầu.

Ví dụ project demo của tôi ở đây là vẽ một biểu đồ hình màng nhện thể hiện các điểm đánh giá của một học sinh. (Ngoài lề một chút là tại sao tôi lại chọn biểu đồ màng nhện trong việc mô tả các điểm đánh giá của một học sinh: thì đó chính là kinh nghiệm chọn các loại biểu đồ phù hợp với từng yêu cầu của đầu bài đặt ra. Trên thực tế có rất nhiều loại biểu đồ khác nhau và mỗi loại chỉ thỏa mãn để miêu tả cho một hoặc một vài bài toán nhất định. Giống như khi chúng ta học môn địa lí hồi phổ thông. Đề bài thường ra là hãy vẽ biểu đồ thích hợp thể hiện một cái gì đó... thì kĩ năng chọn loại biểu đồ cũng rất quan trọng bên cạnh việc vẽ đẹp)

Quay trở lại với ví dụ demo của tôi. Biểu đồ hình màng nhện là một trong những biểu đồ mở rộng nên không có trong thư viện

<script src="https://code.highcharts.com/highcharts.js"></script>

Để vẽ được loại biểu đồ này bạn cần add thêm thư viện

<script src="https://code.highcharts.com/highcharts-more.js"></script>

Một ví dụ demo về biểu đồ màng nhện các bạn có thể xem ở đây

Như bạn đã thấy thì ở trong ví dụ dữ liệu để vẽ biểu đồ chính là phần series

    series: [{
                name: 'Allocated Budget',
                data: [43000, 19000, 60000, 35000, 17000, 10000],
                pointPlacement: 'on'
            }, {
                name: 'Actual Spending',
                data: [50000, 39000, 42000, 31000, 26000, 14000],
                pointPlacement: 'on'
            }]

Tương tự đối với mỗi học sinh chúng ta cũng phải truyền phần data giống với dạng bên trên để highchart nhận dạng và vẽ biểu đồ.

Trong project của chúng ta tôi fake ra dữ liệu có 10 student và mỗi student có 8 tiêu chí đánh giá là điểm các môn. math, literary, chemistry, physical, biological, foreign_language, information_technology, history. với điểm số từ 1-10

**spec/factories/user.rb **

    FactoryGirl.define do
      factory :user do
        name  {Faker::Name.name}
        birthday {Faker::Time.between(6000.days.ago, 5900.days.ago)}
        math {(1..10).to_a.sample}
        literary {(1..10).to_a.sample}
        chemistry {(1..10).to_a.sample}
        physical {(1..10).to_a.sample}
        biological {(1..10).to_a.sample}
        foreign_language {(1..10).to_a.sample}
        information_technology {(1..10).to_a.sample}
        history {(1..10).to_a.sample}
      end
    end

Trong trang view của từng user(trong code tôi đặt là user,các bạn có thể hiểu mỗi user là 1 student) tôi sẽ cho hiển thị biểu đồ đánh giá của user đó. trong controller ta lấy dữ liệu như sau:

**app/controllers/users_controller.rb **

    class UsersController < ApplicationController
      def show
        @user = User.find_by id: params[:id]
        @point = User.collect_point @user
      end
    end

Ở trong view sẽ nhận dữ liệu và truyền data vào trong Javascript

app/views/users/show.html.erb

    <%= @user.name %>
    <br>
    <%= @user.birthday %>
    <div id="student_point_chart" style="min-awidth: 800px; max-awidth: 1000px; height: 600px; margin: 0 auto" data-name="<%= @user.name %>" data-point="<%= @point %>"></div>

Ở trên chúng ta đã truyền data-name và data-point vào trong Javascript sẽ tương ứng thay vào trong highchart như sau.

app/assets/javascripts/chart.js

    $(function () {

      $('#chart').highcharts({

        chart: {
          polar: true,
          type: 'line'
        },

        title: {
          text: 'Student Points',
          x: -80
        },

        pane: {
          size: '80%'
        },

        xAxis: {
          categories: ['Math', 'Literary', 'Chemistry', 'Physical', 'Biological', 'Foreign Language',
                  'Information Technology', 'History'],
          tickmarkPlacement: 'on',
          lineWidth: 0
        },

        yAxis: {
          gridLineInterpolation: 'polygon',
          lineWidth: 0,
          min: 0
        },

        tooltip: {
          shared: true,
          pointFormat: '<span style="color:{series.color}">{series.name}: <b>${point.y:,.0f}</b><br/>'
        },

        legend: {
          align: 'right',
          verticalAlign: 'top',
          y: 70,
          layout: 'vertical'
        },

        series: [{
          name: $("#chart").data("name"),
          data: $("#chart").data("point"),
          pointPlacement: 'on'
        }]
      });
    });

Chúng ta chú ý đến phần data truyền vào ở đây là từ thẻ div có id="chart" nên trong đây cũng sẽ nhận là

    $("#chart").data("name")
    //và
    $("#chart").data("point")

Như vậy là tôi đã truyền xong dữ liệu từ database vào trong chart và thu được biểu đồ của một user như sau.

chart2.png

chart3.png

3.Load nhiều dữ liệu

Tôi sẽ tạo ra một trang index và load tất cả dữ liệu của student ra trên 1 chart duy nhất.

Các bạn đã biết muốn truyền dữ liệu vào chart thì chúng ta cần truyền vào phần series nhưng chúng ta không thể viết các vòng lặp ở trong $$"#chart").highcharts() được mà chúng ta sẽ phải dùng cách khác. Có một cách hay cho chúng ta đó chính là dùng function addSeries được hỗ trợ.

Ví dụ chúng ta lấy tất cả dữ liệu ra và lưu vào 1 mảng dưới dạng sau. [id1, name2, point1, point2, ... , point8, id2, name2, ....]

Để có thể lấy dữ liệu của toàn bộ user ra dưới dạng trên thì chúng ta cần phải viết một hàm để lấy ra. Trong controller:

app/controllers/users_controller.rb

    class UsersController < ApplicationController
      def index
        @users = User.all
        @data = User.all_data @users
      end
    end

app/models/user.rb

    class User < ActiveRecord::Base
      class << self
        def all_data users
          data = []
          users.each do |user|
            data << [user.id, user.name, user.math, user.literary, user.chemistry, user.physical, user.biological,
              user.foreign_language, user.information_technology, user.history]
          end
          data
        end
      end
    end

Trong view chúng ta sẽ chỉ cần truyền một biến duy nhất.

app/views/users/index.html.erb

    <%= javascript_include_tag "all_chart"%>
    <%- if @data.present? %>
      <h1>Data load success!</h1>
    <% end %>
    <div id="all_chart" style="min-awidth: 800px; max-awidth: 1000px; height: 600px; margin: 0 auto" data-all-user="<%= @data.flatten %>"></div>

Và ở trong javascript chúng ta cần xử lí dữ liệu như sau

app/assets/javascripts/all_chart.js

    $(function () {
      var data = $("#all_chart").data("all-user");
      $('#all_chart').highcharts({
       ..............................
      });

      var chart = $('#all_chart').highcharts();
      for (var i=0; i < data.length/10; i++){
        var arr = [];
        for (var j=2; j<10; j++){
          arr.push(data[i*10+j]);
        }

        chart.addSeries({
          name: data[i*10+1],
          data: arr,
        });
      }
    });

Ở đây tôi đã xử lí dữ liệu truyền vào từ view bằng cách lấy ra từng 10 phần tử trong mảng(dữ liệu của 1 user) rồi sử dụng hàm chart.addSeries sẽ thu được một biểu đồ dữ liệu dưới dạng sau:

chart1.png

Như vậy là tôi đã truyền xong tất cả dữ liệu của 10 student lưu trong bảng user ra chart. Với chart này các bạn có thể dễ dàng tắt bớt view của một số user đi để so sánh 2 hay nhiều điểm của những user bất kì, ví dụ so sánh user 1 và user 2 thì chúng ta sẽ ẩn 8 người còn lại đi và biểu đồ sẽ thu được ở dạng sau:

chart4.png

Nhìn vào đây chúng ta rất dễ để so sánh giữa hai người này về điểm ở các môn học.

4.Lời kết và tài liệu tham khảo

Thư viện highchart cung cấp cho chúng ta khá đầy đủ về các đạng biểu đồ thống kê mà chúng ta cần, việc của chúng ta là gọi nó ra và lắp đúng dữ liệu muốn hiển thị là xong.Chúc các bạn có thể áp dụng thành công vào trong project của các bạn để có những biểu đồ thống kê đẹp mắt và hữu ích. Tất cả source code được upload tại đây

Tất cả tài liệu tham khảo các bạn có thể đọc tại trang chủ của highchart

http://www.highcharts.com/

Nếu bạn có bất kì khó khăn gì trong việc nhúng highchart vào project Rails thì có thể comment bên dưới hoặc inbox cho tôi qua địa chỉ email hoangtrinh.hv92@gmail.com

Hẹn gặp lại lại các bạn trong bài viết tiếp theo với các kĩ thuật nâng cao tiếp theo!

-- Hoàng Văn Trình AS Việt Nhật K55 Đại học Bách Khoa Hà Nội

0