iT邦幫忙

2021 iThome 鐵人賽

DAY 26
0
Modern Web

使用 Kotlin 快速開發 Web 程式 -- Vaadin系列 第 26

Vaadin Pro Components 圖表初探 - day26

目標

使用 Pro Components 製作圖表
https://ithelp.ithome.com.tw/upload/images/20211011/20138680nL2DtjChvs.png
螢幕截圖

https://ithelp.ithome.com.tw/upload/images/20211011/20138680W47OLN1WFR.png
匯出png圖

Vaadin Charts

Vaadin Charts 是 Vaadin Pro 訂閱的一部份,屬付費功能 (收費標準),Vaadin 提供 14 天免費試用,具學生身份者可透過 GitHub Student Developer Pack 免費使用付費功能。

https://ithelp.ithome.com.tw/upload/images/20211011/20138680VW2LX8ohn3.png
若有商業需求,付費版的組件可大大節省開發時間,其實還是相當划算的。

製作圖表

製作圖表最重要的是先思考這張圖的目的是什麼,再決定以什麼方式呈現。此測試案例裡,筆者希望:

  1. 本系列文資料庫沿用
  2. 資料不要太複雜
  3. 從一張圖表中可看出每學期各科的成績變化

所以選定以長條圖展示,接著要產出資料了。

資料

前例中,學生成績資料表如下 :

 create TABLE Grade(
     id bigint auto_increment PRIMARY KEY,
     mandarin DOUBLE NOT NULL,
     description VARCHAR(50) NOT NULL,
     english DOUBLE NOT NULL,
     math DOUBLE NOT NULL,
     pe DOUBLE NOT NULL,
     student_id bigint not null REFERENCES Student(id)
 )

從學生成績資料表Grade以學期分群計算各科平均,小數點計算到小數2位,得出結果 List<GradeStatistics>

data class GradeStatistics(
    var description: String? = null,
    var range: String? = null,
    var a_english: Double? = null,
    var a_math: Double? = null,
    var a_mandarin: Double? = null,
    var a_pe: Double? = null

) {
    companion object {
        fun getStatistics(): List<GradeStatistics> = db {
            handle.createQuery("select description, round(AVG(english),2) as a_english, round(AVG(math),2) as a_math, round(AVG(mandarin),2) as a_mandarin, round(AVG(pe),2) as a_pe from grade group by description")
                .mapToBean(GradeStatistics::class.java)
                .list()
        }
    }
}

導入 Charts 套件

implementation("com.vaadin:vaadin-charts-flow:21.0.2")

產生圖表

val list = GradeStatistics.getStatistics()
val chart  = Chart(ChartType.COLUMN)
val conf = chart.configuration
with(conf){
    title = Title("學生統計圖")
    subTitle = Subtitle("平均成績走勢")
    isExporting = true
}

X軸

將學期做為X軸,setCategories()傳入參數為字串陣列或字串組

val x = XAxis()
x.setCategories(*list.map { it.description }.toTypedArray())
conf.addxAxis(x)

長條圖

每組長條圖有4欄,分別為國文、英文、數學、體育成績,以下一一將資料填入

var dataSeries = DataSeries()
var poltOption = PlotOptionsColumn()
with(dataSeries){
    plotOptions = poltOption
    name = "國文"
    setData(*list.map { it.a_mandarin }.toTypedArray())
}
conf.addSeries(dataSeries)

dataSeries = DataSeries()
poltOption = PlotOptionsColumn()
with(dataSeries){
    plotOptions = poltOption
    name = "英文"
    setData(*list.map { it.a_english }.toTypedArray())
}
conf.addSeries(dataSeries)

dataSeries = DataSeries()
poltOption = PlotOptionsColumn()
with(dataSeries){
    plotOptions = poltOption
    name = "數學"
    setData(*list.map { it.a_math }.toTypedArray())
}
conf.addSeries(dataSeries)

dataSeries = DataSeries()
poltOption = PlotOptionsColumn()
with(dataSeries){
    plotOptions = poltOption
    name = "體育"
    setData(*list.map { it.a_pe }.toTypedArray())
}
conf.addSeries(dataSeries)

完成設定後將chart加入ui

val plotOptions = PlotOptionsLine()
plotOptions.marker = Marker(false)
conf.setPlotOptions(plotOptions)
add(chart)

資料來源

本示例由程式自動產生100筆學生資料,各5個學期成績,分數區間如下 :

  • 國文 : 30-100
  • 英文 : 10-100
  • 數學 : 0-100
  • 體育 : 60-100

上一篇
看焰火囉~ Vaadin 內嵌 iFrame 不跑版自動縮放 - day25
下一篇
使用 Vaadin Directory 組件 - day27
系列文
使用 Kotlin 快速開發 Web 程式 -- Vaadin30

尚未有邦友留言

立即登入留言