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.
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:
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:
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