当前项目:
因为我正在使用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}"
所以,回顾一下:
new Chart()
系统来实际构建图表,new Chart()
功能。但是,new Chart()
方法,结果图表可以作为Base64字符串流式传输到PDF文件,以便作为图像包含在PDF中,绕过WkHtmlToPdf的主要头痛对于身份验证背后的任何内容都有。我现在的问题是,对于散点图上的每一点,我需要能够引入一大块数据不其x值或它的y值,并在其标签中显示。它必须是该对象的正确名称,可以从数据库中提取,就像x-data或y-data一样。
连连呢?因为此时我很失落。我怀疑任何这样的答案都在于.AddSeries()
持有XML用于标签的额外内容,但我不知道从哪里开始。我已尽力向谷歌寻求答案,但我遇到的所有答案纯粹是为了在标签上添加x值或y值(或其中的一些变体)。