From 29169802fd42ea0e026e5d3673fe8a9609164c59 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Sat, 22 Jun 2024 23:13:57 +0530 Subject: [PATCH] Polar Area Chart updates --- ...rtDocumentation_00_API_Documentation.razor | 0 .../PolarAreaChartDocumentation_01.razor | 0 .../PolarAreaChart_Demo_01_Examples.razor | 10 +- .../ChartComponents/PolarAreaChart.razor.cs | 26 ++-- .../PolarAreaChart/PolarAreaChartDataset.cs | 126 +++++++++++++++++- .../wwwroot/blazorexpress.chartjs.js | 119 +++++++++++++++++ 6 files changed, 261 insertions(+), 20 deletions(-) rename BlazorExpress.ChartJS.Demo.RCL/Components/Pages/{PolarCharts => PolarAreaCharts}/PolarAreaChartDocumentation_00_API_Documentation.razor (100%) rename BlazorExpress.ChartJS.Demo.RCL/Components/Pages/{PolarCharts => PolarAreaCharts}/PolarAreaChartDocumentation_01.razor (100%) rename BlazorExpress.ChartJS.Demo.RCL/Components/Pages/{PolarCharts => PolarAreaCharts}/PolarAreaChart_Demo_01_Examples.razor (91%) diff --git a/BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarCharts/PolarAreaChartDocumentation_00_API_Documentation.razor b/BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarAreaCharts/PolarAreaChartDocumentation_00_API_Documentation.razor similarity index 100% rename from BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarCharts/PolarAreaChartDocumentation_00_API_Documentation.razor rename to BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarAreaCharts/PolarAreaChartDocumentation_00_API_Documentation.razor diff --git a/BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarCharts/PolarAreaChartDocumentation_01.razor b/BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarAreaCharts/PolarAreaChartDocumentation_01.razor similarity index 100% rename from BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarCharts/PolarAreaChartDocumentation_01.razor rename to BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarAreaCharts/PolarAreaChartDocumentation_01.razor diff --git a/BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarCharts/PolarAreaChart_Demo_01_Examples.razor b/BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor similarity index 91% rename from BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarCharts/PolarAreaChart_Demo_01_Examples.razor rename to BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor index efeda15..5573a93 100644 --- a/BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarCharts/PolarAreaChart_Demo_01_Examples.razor +++ b/BlazorExpress.ChartJS.Demo.RCL/Components/Pages/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor @@ -8,7 +8,7 @@ @code { private PolarAreaChart pieChart = default!; - private PieChartOptions pieChartOptions = default!; + private PolarAreaChartOptions pieChartOptions = default!; private ChartData chartData = default!; private string[]? backgroundColors; @@ -45,7 +45,7 @@ foreach (var dataset in chartData.Datasets) { - if (dataset is PieChartDataset pieChartDataset + if (dataset is PolarAreaChartDataset pieChartDataset && pieChartDataset is not null && pieChartDataset.Data is not null) { @@ -86,8 +86,8 @@ var data = new List(); foreach (var dataset in chartData.Datasets) { - if (dataset is PieChartDataset pieChartDataset) - data.Add(new PieChartDatasetData(pieChartDataset.Label, random.Next(0, 100), backgroundColors![dataLabelsCount])); + if (dataset is PolarAreaChartDataset pieChartDataset) + data.Add(new PolarAreaChartDatasetData(pieChartDataset.Label, random.Next(0, 100), backgroundColors![dataLabelsCount])); } chartData = await pieChart.AddDataAsync(chartData, GetNextDataLabel(), data); @@ -109,7 +109,7 @@ return datasets; } - private PieChartDataset GetRandomPieChartDataset() + private PolarAreaChartDataset GetRandomPieChartDataset() { datasetsCount += 1; return new() { Label = $"Team {datasetsCount}", Data = GetRandomData(), BackgroundColor = GetRandomBackgroundColors() }; diff --git a/BlazorExpress.ChartJS/ChartComponents/PolarAreaChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/PolarAreaChart.razor.cs index 02faa32..d8a624f 100644 --- a/BlazorExpress.ChartJS/ChartComponents/PolarAreaChart.razor.cs +++ b/BlazorExpress.ChartJS/ChartComponents/PolarAreaChart.razor.cs @@ -4,7 +4,7 @@ public partial class PolarAreaChart : ChartComponentBase { #region Fields and Constants - private const string _jsObjectName = "window.blazorexpress.chartjs.polar"; + private const string _jsObjectName = "window.blazorexpress.chartjs.polarArea"; #endregion @@ -31,8 +31,8 @@ public override async Task AddDataAsync(ChartData chartData, string d throw new ArgumentNullException(nameof(data)); foreach (var dataset in chartData.Datasets) - if (dataset is BarChartDataset barChartDataset && barChartDataset.Label == dataLabel) - if (data is BarChartDatasetData barChartDatasetData) + if (dataset is PolarAreaChartDataset barChartDataset && barChartDataset.Label == dataLabel) + if (data is PolarAreaChartDatasetData barChartDatasetData) barChartDataset.Data?.Add(barChartDatasetData.Data); await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetData", Id, dataLabel, data); @@ -72,15 +72,15 @@ public override async Task AddDataAsync(ChartData chartData, string d chartData.Labels.Add(dataLabel); foreach (var dataset in chartData.Datasets) - if (dataset is BarChartDataset barChartDataset) + if (dataset is PolarAreaChartDataset barChartDataset) { - var chartDatasetData = data.FirstOrDefault(x => x is BarChartDatasetData barChartDatasetData && barChartDatasetData.DatasetLabel == barChartDataset.Label); + var chartDatasetData = data.FirstOrDefault(x => x is PolarAreaChartDatasetData barChartDatasetData && barChartDatasetData.DatasetLabel == barChartDataset.Label); - if (chartDatasetData is BarChartDatasetData barChartDatasetData) + if (chartDatasetData is PolarAreaChartDatasetData barChartDatasetData) barChartDataset.Data?.Add(barChartDatasetData.Data); } - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetsData", Id, dataLabel, data?.Select(x => (BarChartDatasetData)x)); + await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetsData", Id, dataLabel, data?.Select(x => (PolarAreaChartDatasetData)x)); return chartData; } @@ -96,10 +96,10 @@ public override async Task AddDatasetAsync(ChartData chartData, IChar if (chartDataset is null) throw new ArgumentNullException(nameof(chartDataset)); - if (chartDataset is BarChartDataset) + if (chartDataset is PolarAreaChartDataset) { chartData.Datasets.Add(chartDataset); - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDataset", Id, (BarChartDataset)chartDataset); + await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDataset", Id, (PolarAreaChartDataset)chartDataset); } return chartData; @@ -109,9 +109,9 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch { if (chartData is not null && chartData.Datasets is not null) { - var datasets = chartData.Datasets.OfType(); + var datasets = chartData.Datasets.OfType(); var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.initialize", Id, GetChartType(), data, (BarChartOptions)chartOptions, plugins); + await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.initialize", Id, GetChartType(), data, (PolarAreaChartOptions)chartOptions, plugins); } } @@ -119,9 +119,9 @@ public override async Task UpdateAsync(ChartData chartData, IChartOptions chartO { if (chartData is not null && chartData.Datasets is not null) { - var datasets = chartData.Datasets.OfType(); + var datasets = chartData.Datasets.OfType(); var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.update", Id, GetChartType(), data, (BarChartOptions)chartOptions); + await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.update", Id, GetChartType(), data, (PolarAreaChartOptions)chartOptions); } } diff --git a/BlazorExpress.ChartJS/Models/ChartDataset/PolarAreaChart/PolarAreaChartDataset.cs b/BlazorExpress.ChartJS/Models/ChartDataset/PolarAreaChart/PolarAreaChartDataset.cs index e13b8df..05ba54b 100644 --- a/BlazorExpress.ChartJS/Models/ChartDataset/PolarAreaChart/PolarAreaChartDataset.cs +++ b/BlazorExpress.ChartJS/Models/ChartDataset/PolarAreaChart/PolarAreaChartDataset.cs @@ -4,14 +4,136 @@ public class PolarAreaChartDataset : ChartDataset { #region Properties, Indexers + /// + /// Arc background color. + /// + /// + /// Default value is 'rgba(0, 0, 0, 0.1)'. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? BackgroundColor { get; set; } + + /// + /// Supported values are 'center' and 'inner'. + /// When 'center' is set, the borders of arcs next to each other will overlap. + /// When 'inner' is set, it is guaranteed that all borders will not overlap. + /// + /// + /// Default value is 'center'. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? BorderAlign { get; set; } // TODO: change this to enum + + /// + /// Arc border color. + /// + /// + /// Default value is '#fff'. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? BorderColor { get; set; } + + /// + /// Arc border length and spacing of dashes. + /// + /// + /// Default value is . + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? BorderDash { get; set; } + + /// + /// Arc border offset for line dashes. + /// + /// + /// Default value is 0.0. + /// + public double BorderDashOffset { get; set; } + + /// + /// Arc border join style. + /// Supported values are 'round', 'bevel', 'miter'. + /// + /// + /// Default value is . + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? BorderJoinStyle { get; set; } // TODO: change this to enum + + /// + /// Arc border width (in pixels). + /// + /// + /// Default value is 2. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? BorderWidth { get; set; } + + /// + /// By default the Arc is curved. If , the Arc will be flat. + /// + /// + /// Default value is . + /// + public bool Circular { get; set; } = true; + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public PieChartDatasetDataLabels Datalabels { get; set; } = new(); /// - /// The label for the dataset which appears in the legend and tooltips. + /// Arc background color when hovered. + /// + /// + /// Default value is . + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? HoverBackgroundColor { get; set; } + + /// + /// Arc border color when hovered. + /// + /// + /// Default value is . + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? HoverBorderColor { get; set; } + + /// + /// Arc border length and spacing of dashes when hovered. /// + /// + /// Default value is . + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? HoverBorderDash { get; set; } + + /// + /// Arc border offset for line dashes when hovered. + /// + /// + /// Default value is . + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public double? HoverBorderDashOffset { get; set; } + + /// + /// Arc border join style when hovered. + /// Supported values are 'round', 'bevel', 'miter'. + /// + /// + /// Default value is . + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? HoverBorderJoinStyle { get; set; } // TODO: change this to enum + + /// + /// Arc border width when hovered (in pixels). + /// + /// + /// Default value is . + /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Label { get; set; } + public List? HoverBorderWidth { get; set; } #endregion } diff --git a/BlazorExpress.ChartJS/wwwroot/blazorexpress.chartjs.js b/BlazorExpress.ChartJS/wwwroot/blazorexpress.chartjs.js index 2b86efe..2212eca 100644 --- a/BlazorExpress.ChartJS/wwwroot/blazorexpress.chartjs.js +++ b/BlazorExpress.ChartJS/wwwroot/blazorexpress.chartjs.js @@ -589,3 +589,122 @@ window.blazorexpress.chartjs.pie = { } }, } + +window.blazorexpress.chartjs.polarArea = { + addDatasetData: (elementId, dataLabel, data) => { + let chart = window.blazorexpress.chartjs.get(elementId); + if (chart) { + const chartData = chart.data; + const chartDatasetData = data; + + if (!chartData.labels.includes(dataLabel)) + chartData.labels.push(dataLabel); + + const chartDatasets = chartData.datasets; + + if (chartDatasets.length > 0) { + let datasetIndex = chartDatasets.findIndex(dataset => dataset.label === chartDatasetData.datasetLabel); + if (datasetIndex > -1) { + chartDatasets[datasetIndex].data.push(chartDatasetData.data); + chart.update(); + } + } + } + }, + addDatasetsData: (elementId, dataLabel, data) => { + let chart = window.blazorexpress.chartjs.get(elementId); + if (chart && data) { + const chartData = chart.data; + + if (!chartData.labels.includes(dataLabel)) { + chartData.labels.push(dataLabel); + + if (chartData.datasets.length > 0 && chartData.datasets.length === data.length) { + data.forEach(chartDatasetData => { + let datasetIndex = chartData.datasets.findIndex(dataset => dataset.label === chartDatasetData.datasetLabel); + chartData.datasets[datasetIndex].data.push(chartDatasetData.data); + chartData.datasets[datasetIndex].backgroundColor.push(chartDatasetData.backgroundColor); + }); + chart.update(); + } + } + } + }, + addDataset: (elementId, newDataset) => { + let chart = window.blazorexpress.chartjs.get(elementId); + if (chart) { + chart.data.datasets.push(newDataset); + chart.update(); + } + }, + create: (elementId, type, data, options, plugins) => { + let chartEl = document.getElementById(elementId); + let _plugins = []; + + if (plugins && plugins.length > 0) { + // register `ChartDataLabels` plugin + if (plugins.includes('ChartDataLabels')) { + _plugins.push(ChartDataLabels); + + // set datalabel background color + options.plugins.datalabels.backgroundColor = function (context) { + return context.dataset.backgroundColor; + }; + } + } + + // https://www.chartjs.org/docs/latest/configuration/#configuration-object-structure + const config = { + type: type, + data: data, + options: options, + plugins: _plugins + }; + + const chart = new Chart( + chartEl, + config + ); + }, + get: (elementId) => { + let chart; + Chart.helpers.each(Chart.instances, function (instance) { + if (instance.canvas.id === elementId) { + chart = instance; + } + }); + + return chart; + }, + initialize: (elementId, type, data, options, plugins) => { + let chart = window.blazorexpress.chartjs.polarArea.get(elementId); + if (chart) return; + else + window.blazorexpress.chartjs.polarArea.create(elementId, type, data, options, plugins); + }, + resize: (elementId, width, height) => { + let chart = window.blazorexpress.chartjs.polarArea.get(elementId); + if (chart) { + chart.canvas.parentNode.style.height = height; + chart.canvas.parentNode.style.width = width; + } + }, + update: (elementId, type, data, options) => { + let chart = window.blazorexpress.chartjs.polarArea.get(elementId); + if (chart) { + if (chart.config.plugins && chart.config.plugins.findIndex(x => x.id == 'datalabels') > -1) { + // set datalabel background color + options.plugins.datalabels.backgroundColor = function (context) { + return context.dataset.backgroundColor; + }; + } + + chart.data = data; + chart.options = options; + chart.update(); + } + else { + console.warn(`The chart is not initialized. Initialize it and then call update.`); + } + }, +}