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

<<:  Youtube Analytics API 教学 - 告一个段落

>>:  Day 26 - 设定 OSPF

Day 15 : 特徵工程 tf.Tramsform 介绍

特徵工程是机械学习相当重要的一环,有处理数据以及实行 ML/DL 任务经验者对特徵工程一定不陌生,...

Re: 新手让网页 act 起来: Day11 - React Hooks 之 useState (2)

在上一篇介绍了使用 hooks 的基本规则,以及 useState 的使用方式。今天来针对 init...

前端工程师也能开发全端网页:挑战 30 天用 React 加上 Firebase 打造社群网站|Day22 修改会员名称

连续 30 天不中断每天上传一支教学影片,教你如何用 React 加上 Firebase 打造社群...

【day14】 Fab X 跳页Animation

好的! 我们今天主要要来设定Fab,以及跳页的动画! 1.先在我们的DashboardFragme...

用这9种技巧让你的部落格有个好名字

一、前言 经营部落格,会是一个长期的网路事业,在初期有许多部分我认为就应该思考好,在整个经营路上才...