C#Scatter Plot Chart - 如何添加非值的数据点标签?

时间:2018-06-05 17:28:33

标签: c# asp.net asp.net-mvc charts asp.net-mvc-5

当前项目:

  • DotNet 4.7.1
  • MVC 5
  • C#7.3

因为我正在使用MVC,并且因为我需要通过Base64字符串将所有图形输出为图像以便将它们流式传输到PDF中,所以我的过程有点僵硬且具体。我(很可能)无法改变我的工作方式,因为PDF生成目前落后于用户身份验证,并且试图抓取/包含该PDF外部的图像将是一个噩梦要处理 - 因为WkHtmlToPdf确实如此 在用户的上下文中运行,使其获取受访问保护的内容非常困难;并且保护PDF和图表生成 以防止意外访问。

我的问题集中在散点图上,我可以在其中引入数据点,但我对如何引入标签没有任何线索。我的问题不在于实际引入数据点标签本身 - 如果我想要标签中的X值或Y值,那就非常简单了。

不,我想要的是各个数据点本身的字符串名称在标签中。因为每个数据点本身代表整个系统之外的特定对象,并且这些对象具有名称,例如“Bob”或“Eastern”。

所以我开始在控制器中构建我的散点图,它也构建了PDF:

private async Task<string> ScatterPlot() {
  var o = await BuildOthers();
  var d = await BuildDistrict();
  var av = await BuildAverages();
  var myChart = new Chart(1000, 600, ScatterPlotTheme(av.Item1, av.Item2))
    .AddSeries("Other", "Point", xValue: o.Item1, xField: "Injury Rate", yValues: o.Item2, yFields: "Duration Days")
    .AddSeries("District", "Point", xValue: d.Item1, xField: "Injury Rate", yValues: d.Item2, yFields: "DurationDays")
    .GetBytes("png");
  return "data:image/png;base64," + Convert.ToBase64String(myChart);
}

BuildOthers()BuildDistrict()代表引入的散布图数据的两个块:所有其他点(用于比较)和被判断的主要点/对象。这允许我有两组具有不同颜色和形状点的散点图数据。

我以相同的方式填充每个:通过使用数据填充元组。所述数据涉及两个数据:平均发生率和平均时间发生时间,每个表示该对象/数据点的3年移动平均值。

因此,对于散点图中的任何一个点,它表示特定对象,该对象基于其平均出现率(x轴)和平均时间周期(y轴)在图上具有位置。此时,我需要在分散图中引入的是在标签中用于点识别的对象的通用名称。

我需要做的BuildAverages()是为了引入水平和垂直十字准线的带状线以展示所有基础数​​据的3年平均值所需要的一些技巧。所有对象都是聚合的。

因为我需要将此图表构建为new Chart()以便将其作为Base64字符串进行流式传输,所以我没有简单的方法来格式化它(这种方法的格式化工具很遗憾)。但是,我能够在最初的new Chart()声明中将主题作为XML文件附加,我做了。通常这将是XML文件的简单文件名声明,但由于我需要动态带状线(只能通过XML添加),我需要使XML文件本身是半动态的。我是通过为带状线位置放置占位符来实现的:

<?xml version="1.0" encoding="utf-8" ?>
<Chart BackColor="255, 255, 255">
  <Series>
    <Series Name="District" MarkerSize="15" Color="255, 0, 0" ChartType="Point" MarkerStyle="Diamond">
      <SmartLabelStyle Enabled="True" />
    </Series>
    <Series Name="Other" MarkerSize="8" ChartType="Point" MarkerStyle="Circle">
      <SmartLabelStyle Enabled="True" />
    </Series>
  </Series>
  <ChartAreas>
    <ChartArea Name="Default" BackColor="224, 224, 224" BorderColor="0, 0, 0" BorderDashStyle="Solid">
      <AxisY Interval="5" Minimum="0">
        <MajorGrid LineColor="192, 192, 192" />
        <StripLines>
          <StripLine BackColor="0, 150, 0" StripWidth="0.15" Interval="0.0" IntervalOffset="{y}" />
        </StripLines >
      </AxisY>
      <AxisX Interval="0.5" Minimum="0">
        <LabelStyle Format="#.##" />
        <MajorGrid LineColor="192, 192, 192" />
        <StripLines>
          <StripLine BackColor="0, 150, 0" StripWidth="0.01" Interval="0.0" IntervalOffset="{x}" />
        </StripLines >
      </AxisX>
    </ChartArea>
  </ChartAreas>
</Chart>

然后将XML文件作为字符串预加载并在将字符串汇总到new chart()之前对字符串本身进行替换:

private string ScatterPlotTheme(decimal x, decimal y) {
  using(var s = new StreamReader(Server.MapPath("~/Content/pdf/xml/ScatterPlotTheme.xml"), Encoding.UTF8)) {
    return s.ReadToEnd().Replace(@"{x}", $"{x}").Replace(@"{y}", $"{y}");
  }
}

特别注意我如何在XML文件中使用带状线,以便我可以直接将它们作为修改目标:

 IntervalOffset="{x}"

所以,回顾一下:

  1. 我使用标准(但功能有限)C#new Chart()系统来实际构建图表,
  2. 我使用静态XML文件格式化图表,以便格式化选项远远超出new Chart()功能。但是,
  3. 因为我使用new Chart()方法,结果图表可以作为Base64字符串流式传输到PDF文件,以便作为图像包含在PDF中,绕过WkHtmlToPdf的主要头痛对于身份验证背后的任何内容都有。
  4. 我现在的问题是,对于散点图上的每一点,我需要能够引入一大块数据其x值它的y值,并在其标签中显示。它必须是该对象的正确名称,可以从数据库中提取,就像x-data或y-data一样。

    连连呢?因为此时我很失落。我怀疑任何这样的答案都在于.AddSeries()持有XML用于标签的额外内容,但我不知道从哪里开始。我已尽力向谷歌寻求答案,但我遇到的所有答案纯粹是为了在标签上添加x值或y值(或其中的一些变体)。

0 个答案:

没有答案