《進擊吧!Blazor!》系列入門教程 第一章 7.圖表

MicrosoftReactor發表於2021-03-14

《進擊吧!Blazor!》是本人與張善友老師合作的Blazor零基礎入門教程視訊,此教程能讓一個從未接觸過Blazor的程式設計師掌握開發Blazor應用的能力。
視訊地址:https://space.bilibili.com/483888821/channel/detail?cid=151273
Blazor WebAssembly 是單頁應用 (SPA) 框架,用於使用 .NET 生成互動式客戶端 Web 應用,採用 C# 代替 JavaScript 來編寫前端程式碼
本系列文章因篇幅有限,省略了部分程式碼,完整示例程式碼:https://github.com/TimChen44/Blazor-ToDo

作者:陳超超
Ant Design Blazor 專案貢獻者,擁有十多年從業經驗,長期基於.Net技術棧進行架構與開發產品的工作,現就職於正泰集團。
郵箱:timchen@live.com
歡迎各位讀者有任何問題聯絡我,我們共同進步。

圖表的作用我就不扯了,想要讓系統高大上就少不了它,作為一個加分項,我們自然也要給我們ToDo引用來一波。

Chart控制元件選擇

目前還沒有比較優秀的Blazor原生Chart控制元件,這也是我們將來需要提升Blazor生態的重要任務之一。

但是無需失望,Blazor支援C#呼叫JS,反之亦可,所以社群中有不少通過此技術對現有JS版本的Chart控制元件二次分裝的Blazor元件可用。

這裡我就推薦本人封裝G2Plot後的Blazor元件ant-design-charts-blazor。

文件地址:https://ant-design-blazor.gitee.io/zh-CN/charts/introduce
原始碼地址:https://github.com/ant-design-blazor/ant-design-charts-blazor
技術實現方式介紹:https://zhuanlan.zhihu.com/p/163808856

改造ToDo

引用元件

  • 通過命令或視覺化介面為ToDo.Client新增AntDesign.Charts元件
$ dotnet add package AntDesign.Charts

在這裡插入圖片描述

  • wwwroot/index.html(WebAssembly) 或 Pages/_Host.razor(Server) 中引入靜態檔案:
<script src="https://unpkg.com/@antv/g2plot@latest/dist/g2plot.js"></script>
<script src="_content/AntDesign.Charts/ant-design-charts-blazor.js"></script>
  • _Imports.razor 中加入名稱空間
@using AntDesign.Charts

將Charts名稱空間加入全域性引用,擁有使用時省略完整命名路徑的好處,但是請注意當Chart中的元件與其他元件重名時,不論Chart元件還是其他元件都需要補上完整命名路徑,考慮到Chart使用的頁面並不多,所以本人的習慣不會將他加入 _Imports.razor中。

統計頁

我們用柱狀圖做一個每日代辦事項數量統計圖

ChartAmountDto.cs

ToDo.Shared專案中建立用於顯示資料的實體。

public class ChartAmountDto
{
    public string Day { get; set; }
    public string Type { get; set; }
    public int Value { get; set; }
}

Day欄位儲存日期文字。
Type儲存重要度資訊,包含“普通”,“重要”兩個值,圖表中也是用這個進行分組顯示。
Value儲存具體的數值。

ChartController.cs

ToDo.Server專案新建ChartController控制器,用於提供圖表所需的資料。

[ApiController]
[Route("api/[controller]/[action]")]
public class ChartController
{
    TodoContext Context;

    public ChartController(TodoContext context)
    {
        Context = context;
    }

    //每日待辦數量
    public List<ChartAmountDto> GetAmountDto()
    {
        return Context.Task.GroupBy(x => new { x.PlanTime, x.IsImportant }).Select(x => new ChartAmountDto()
        {
            Day = x.Key.PlanTime.ToString("yy-MM-dd"),
            Type = x.Key.IsImportant ? "普通" : "重要",
            Value = x.Count(),
        }).ToList();
    }
}

通過對計劃日期和重要度進行分組,然後對分組結果進行計數,介面返回的部分資料結構如下

[
	{"day":"20-09-25","value":2,"type":"重要"},
	{"day":"20-10-10","value":9,"type":"重要"},
	{"day":"20-10-11","value":6,"type":"重要"},
	{"day":"20-10-14","value":2,"type":"重要"},
	{"day":"20-10-17","value":6,"type":"重要"},
	{"day":"21-01-28","value":1,"type":"重要"}
]
Statistics.razor

ToDo.Client專案新增Statistics.razor並填入以下程式碼

@page "/statistics"

<Spin Spinning="isLoading">
    <AntDesign.Charts.StackedColumn @ref="@amountChart" Config="amountConfig" TItem="ChartAmountDto" />
</Spin>

AntDesign.Charts.StackedColumn 通過完整的路徑新增圖表控制元件。
@ref="@amountChart" 提供了一種引用元件例項的方法,隨後可以申明一個變數存放元件的引用。
Config="amountConfig" 配置圖表顯示配置。
TItem="ChartAmountDto" 定義圖表資料型別。

新增Statistics.razor.cs檔案。

public partial class Statistics
{
    [Inject] public HttpClient Http { get; set; }
    bool isLoading = false;
    IChartComponent amountChart;
    readonly StackedColumnConfig amountConfig = new StackedColumnConfig
    {
        Title = new Title
        {
            Visible = true,
            Text = "每日代辦數量統計"
        },
        ForceFit = true,
        Padding = "auto",
        XField = "day",
        YField = "value",
        YAxis = new ValueAxis
        {
            Min = 0,
        },
        Meta = new
        {
            day = new
            {
                Alias = "日期"
            },
        },
        Color = new[] { "#ae331b", "#1a6179" },
        StackField = "type"
    };

    protected async override Task OnInitializedAsync()
    {
        isLoading = true;
        var amountData = await Http.GetFromJsonAsync<List<ChartAmountDto>>($"api/Chart/GetAmountDto");
        await amountChart.ChangeData(amountData);
        await base.OnInitializedAsync();

        isLoading = false;
    }
}

IChartComponent amountChart;變數用來存放元件例項引用,之後我們就可能使用這個物件對Chart元件進行各類操作。

StackedColumnConfig amountConfig定義了堆積柱狀圖的配置

  • Text = "每日代辦數量統計" 定義了標題文字
  • XField = "day" X軸繫結的欄位名
  • YField = "value" Y軸繫結的欄位名

注意:此處繫結欄位名是區分大小寫的,通常c#的dto類欄位名會採用大駝峰,然而將dto轉json預設模式下會將欄位名改成小駝峰格式,所以注意此處欄位名的差異。

  • Meta = new { day = new { Alias = "日期" } } 定義day欄位所在州軸顯示的文字
  • Color = new[] { "#ae331b", "#1a6179" } 柱狀圖的顏色,如果不指定,元件會使用預設顏色
  • StackField = "type"定義了堆砌的欄位

更多的屬性配置可以詳見G2Plot元件的文件:https://antv-g2plot.gitee.io/zh/examples/gallery

MainLayout.razor

新增統計選單項

<MenuItem RouterLink="/statistics" RouterMatch="NavLinkMatch.Prefix">
    統計
</MenuItem>
執行效果

在這裡插入圖片描述

迷你圖

圖表,圖表,有圖有表,所以我們需要將我們的圖表與我們的代辦列表集合。

我們的代辦記錄中有計劃日期和截至日期,所以我們可以結合當前日期就能做出一個剩餘時間進度迷你圖。

TaskItem

TaskItem.razor中新增以下程式碼

<div class="chart">
    @{
        double progress = 0;
        if (Item.IsFinish == false && Item.Deadline.HasValue)
            progress = (double)Item.Deadline.Value.Subtract(DateTime.Now).TotalHours / (double)Item.Deadline.Value.Subtract(Item.PlanTime).TotalHours;
    }
    <AntDesign.Charts.RingProgress Data="progress" Config="progressConfig"></AntDesign.Charts.RingProgress>
</div>

我們先計算剩餘時間,結果數值區間在0~1之間,然後使用RingProgress元件顯示,如果已經完成的任務預設值為0。
AntDesign.Charts.RingProgress 圓形進度迷你圖。
Data="progress" 圖表數值
Config="progressConfig" 圖表配置

最後新增一些樣式,位置上美化一下

.task-card-item .chart {
    margin-left: 8px;
}

TaskItem.razor.cs中新增迷你圖配置

readonly RingProgressConfig progressConfig = new RingProgressConfig
{
    Width = 30,
    Height = 30,
};
執行效果

隨著時間流逝,剩餘時間減少,圓形精度藍色部分會越來越少
在這裡插入圖片描述

次回預告

下次將迎來Todo應用的最終回,我們通過一些虛擬場景來演示如何部署Blazor應用。

學習資料

更多關於Blazor學習資料:https://aka.ms/LearnBlazor

相關文章