我有一个 Blazor 服务器应用程序,我在其中通过 JSInterop 将 Chart.js 库用于我的图表。 在折线图中我显示了 20 个测量值 当所有 20 个值都存在并且我打开图表时,图表工作正常。 该图表绘制了 20 个值的曲线。
但我想使用该图表作为实时图表。这意味着当每秒有一个新的数据值进入数据数组时,我想更新图表。这怎么可能?
这是我的代码:
图表所在的我的 Razor 页面
@page "/wmi_performance2"
@inject TagService TagService
@using System.IO
@inject IJSRuntime JSRuntime
<Chart Id="bar1" Type="@Chart.ChartType.Bar"
Data="@CPU_Load_array"
Labels="@Measuring_points_array">
</Chart>
共享/组件文件夹中的我的 Chart.razor
@using System.IO
@inject IJSRuntime JSRuntime
@using Microsoft.JSInterop;
@inject IJSRuntime jsInvoker
<canvas id="@Id"></canvas>
@code {
public enum ChartType
{
Pie,
Bar
}
[Parameter]
public string Id { get; set; }
[Parameter]
public ChartType Type { get; set; }
[Parameter]
public string[] Data { get; set; }
[Parameter]
public string[] BackgroundColor { get; set; }
[Parameter]
public string[] Labels { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Here we create an anonymous type with all the options
// that need to be sent to Chart.js
try{
var config = new
{
Type = Type.ToString().ToLower(),
Options = new
{
Responsive = true,
Scales = new
{
YAxes = new[]
{
new { Ticks = new {
BeginAtZero=true
} }
}
}
},
Data = new
{
Datasets = new[]
{
new { Data = Data, BackgroundColor = BackgroundColor}
},
Labels = Labels
}
};
await JSRuntime.InvokeVoidAsync("setup", Id, config);
}
catch(Exception e)
{
using (StreamWriter sw = File.AppendText((Pages.CommonClass.error_path)))
{
sw.WriteLine("Chart.JS Error: " + e + Environment.NewLine);
}
}
}
}
我的chart.js在wwwroot下
window.setup = (id, config) => {
var ctx = document.getElementById(id).getContext('2d');
new Chart(ctx, config);
}
最佳答案
通常,您会像所有其他 JS 互操作调用一样使用 JSRuntime 的 InvokeAsnyc
或 InvokeVoidAsync
方法。这是一个简单的例子。
JavaScript 部分:
window.setupChart = (id, config) => {
var ctx = document.getElementById(id).getContext('2d');
new Chart(ctx, config);
}
Blazor C# 部分:
[Inject]
public IJSRuntime JSRunTime { get; set; }
public string id = "chartCanvas"; // ID for canvas: <canvas id="@Id"></canvas>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var config = new
{
Type = "line",
Options = new { ... },
Data = new { ... }
}
await JSRuntime.InvokeVoidAsync("setupChart", id, config);
}
}
它工作正常,但您无法更新图表或无法向其中添加任何内容。
解决方案是 Blazor 中的 IJSObjectReference
。这正是这个函数的用途。
您需要将之前的代码更改为以下内容:
JavaScript 部分:
window.setupChart = (id, config) => {
var ctx = document.getElementById(id).getContext('2d');
return new Chart(ctx, config);
},
window.updateChart = (chartRef, visible) => {
// Example: make visible/hidden the 4th dataset in the chart
chartRef.data.datasets[3].hidden = visible;
chartRef.update();
}
Blazor C# 部分:
[Inject]
public IJSRuntime JSRunTime { get; set; }
private IJSObjectReference? chartInstance;
public string id = "chartCanvas";
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var config = new
{
Type = "line",
Options = new { ... },
Data = new { ... }
}
chartInstance = await JSRuntime.InvokeAsync<IJSObjectReference>("setupChart", id, config);
}
}
public async Task UpdateChart()
{
await JSRuntime.InvokeVoidAsync("updateChart", chartInstance, false);
}
就这样,您可以更新现有图表。
并且不要忘记在您的 razor 组件中实现 @implements IAsyncDisposable
并处置它:
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (chartInstance is not null)
{
await chartInstance.DisposeAsync();
}
}
关于c# - 我在 Blazor 应用程序中使用 Chart.js 和 JSInterop。当数据集中有新数据时,如何更新图表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74232991/