0

我正在构建一个 .NET Core Web 应用程序。我的目标是构建一个包含饼图的 Razor 组件,然后在我的项目中通过不同的数据输入重新使用该组件。问题是我无法在组件内添加配置每个饼图所需的脚本。

这是组件的外观:

@using PieChartProject.Models;

<div style="max-width:350px; max-height:195px;">
    <canvas id="myChart @Chart.Id"></canvas>
</div>

@code {

    [Parameter]
    public PieChartViewModel Chart{ get; set; }

}

这是我认为调用该组件的代码:


<div class="row">
   @foreach (var chart in Model.PieCharts)
   {
      <div class="col-md-6">
             @(await Html.RenderComponentAsync<PieChartRazorComponent>(RenderMode.ServerPrerendered, new { Chart = chart}))
      </div>
   }
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js"></script>

    <script>
            var ctx = document.getElementById('myChart').getContext('2d'); //this needs to be changed for every chart

            var myChart = new Chart(ctx, {
                type: 'pie',
                data: {
                    datasets: [{
                        data: [25,75], //this needs to be changed for every chart
                        backgroundColor: [
                            'rgba(255, 99, 132, 0.7)',
                            'rgba(54, 162, 235, 0.7)'
                        ],
                        borderColor: [
                            'rgba(256, 256, 256, 1)',
                            'rgba(256, 256, 256, 1)'
                        ],
                        borderWidth: 2,
                        //label: ''
                    }],
                    labels: ['Yes', 'No'] //this needs to be changed for every chart
                },
                options: {
                    legend: {
                        display: true,
                        position: 'bottom',
                        labels: {
                            generateLabels: function (chart) {

                                var data = chart.data;
                                if (data.labels.length && data.datasets.length) {
                                    return data.labels.map(function (label, i) {
                                        var meta = chart.getDatasetMeta(0);
                                        var ds = data.datasets[0];
                                        var arc = meta.data[i];
                                        var custom = arc && arc.custom || {};
                                        var getValueAtIndexOrDefault = Chart.helpers.getValueAtIndexOrDefault;
                                        var arcOpts = chart.options.elements.arc;
                                        var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
                                        var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
                                        var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);

                                        var value = chart.config.data.datasets[arc._datasetIndex].data[arc._index];

                                        return {
                                            text: label + " : " + value,
                                            fillStyle: fill,
                                            strokeStyle: stroke,
                                            lineWidth: bw,
                                            hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
                                            index: i
                                        };
                                    });
                                } else {
                                    return [];
                                }
                            }
                        }
                    }
                }
            });

    </script>

如果只有一个组件,这一切都很好,但我似乎无法找到一种方法让它与多个组件一起工作。

我在脚本标签中为每个饼图需要以某种方式更改的 3 个属性添加了注释。

我还找到并尝试了 mariusmuntean 的 Chart.Js Blazor 库,但我无法让它工作。我认为它没有为我显示任何图表,因为它需要在 Blazor 项目中使用,而不是在 .NET Core MVC 中使用?

只要我在 Razor 组件内创建饼图,任何类型的解决此问题的方法都是受欢迎的。

4

1 回答 1

0

有点晚了,但是对于如何在 Blazor Server 应用程序中创建饼图,我在同一条船上。我最终创建了一个简单的组件来制作 SVG 饼图并将其放入它自己的组件中。我在 GitHub 中创建了一个使用SVG Pie Chart的示例。还有一个小的修改,使其成为一个甜甜圈图表。您只需确保传递给组件的数据总计达到 100%。绘制一个总数大于 100% 的饼图是没有意义的。

代码很简单:

数据模型:

namespace SVG_Pie_Chart.Data
{
    public class PieDataModel
    {
        public double Percent { get; set; }
        public string Name { get; set; }
        public string Color { get; set; }
    }
}

零件:

@using SVG_Pie_Chart.Data
<svg style="display:block; margin:auto; vertical-align:central;" height="@height" width="@width" viewBox="0, 0, 2000, 2000">
    @foreach (var p in PieDataToPlot)
    {
        @(RotAngle = RotAngle + (((p.Percent / 100) * 360.0) - 90))
        <path d="@GenerateArc(1000, 1000, 800, p.Percent)" id="@RotAngle" fill="@p.Color" transform="rotate(@RotAngle,1000,1000)"></path>
        @(RotAngle += 90)
    }
</svg>
@code {

    [Parameter]
    public List<PieDataModel> PieData { get; set; }
    [Parameter]
    public int height { get; set; } = 90;
    [Parameter]
    public int width { get; set; } = 200;
    private double RotAngle { get; set; } = 0;
    private List<PieDataModel> PieDataToPlot = new List<PieDataModel>();

    protected override void OnInitialized()
    {

        if (PieData != null)
        {
            PieDataToPlot = PieData;
        }
        base.OnInitialized();
    }

    #region Svg Pie
    private double DegToRad(double AngDeg)
    {
        return (AngDeg * Math.PI) / 180.0;
    }
    struct CartesianPosition
    {
        public double x;
        public double y;
    }
    private string GenerateArc(double cx, double cy, double r, double percent)
    {
        CartesianPosition Cartesian;

        double angledeg = (percent / 100) * 360.0;
        double anglerad = DegToRad(angledeg);
        Cartesian.x = cx + (r * Math.Cos(anglerad));
        Cartesian.y = cy - (r * Math.Sin(anglerad));
        if (Convert.ToInt32(Cartesian.y) == cy)
        {
            Cartesian.y += 1.0;
        }

        if (angledeg > 180)
        {
            return "M " + cx.ToString() + " " + cy.ToString() + " " + (cx + r).ToString() + "," + (cy).ToString() + " A" + r.ToString() + " " + r.ToString() + ", 0, 1, 0, " + Cartesian.x.ToString() + "," + Cartesian.y.ToString() + " ";
        }
        else
        {
            return "M " + cx.ToString() + " " + cy.ToString() + " " + (cx + r).ToString() + "," + (cy).ToString() + " A" + r.ToString() + " " + r.ToString() + ", 0, 0, 0, " + Cartesian.x.ToString() + "," + Cartesian.y.ToString() + " ";
        }
    }
    #endregion
}

以及如何使用:

<SVGPie PieData="@PieData" height="200" width="300"></SVGPie>
<SVGDoughnut PieData="@PieData"></SVGDoughnut>
@code
{
    private List<PieDataModel> PieData = new List<PieDataModel>();
    protected override void OnInitialized()
    {
        GenerateSamplePieData();
        base.OnInitialized();
    }
    private void GenerateSamplePieData()
    {
        PieDataModel PDM = new PieDataModel();
        PDM.Color = "#ff0000";
        PDM.Name = "Section 1";
        PDM.Percent = 30.0;
        PieData.Add(PDM);

        PDM = new PieDataModel();
        PDM.Color = "#ffff00";
        PDM.Name = "Section 2";
        PDM.Percent = 20.0;
        PieData.Add(PDM);

        PDM = new PieDataModel();
        PDM.Color = "#0000ff";
        PDM.Name = "Section 3";
        PDM.Percent = 20.0;
        PieData.Add(PDM);

        PDM = new PieDataModel();
        PDM.Color = "#00ff00";
        PDM.Name = "Section 4";
        PDM.Percent = 30.0;
        PieData.Add(PDM);

    }
}

如前所述,确保您的百分比加起来不超过 100%。

于 2020-10-21T23:56:59.090 回答