如何根据我的系列值获得次轴的比例?
How Do I Get The Scale of The Secondary Axis to be Based on My Series Values?
我正在使用 System.Web.UI.DataVisualization
。 Charting 在 MVC 中创建图表。
我有一个图表显示 StackedColumn100 SeriesChartType
中的值,相应的 y 轴值位于左侧的主 y 轴上。
由于它是 100% 堆积柱系列,因此主要 y 轴的比例从 0 到 100。
然后我以线 SeriesChartType
的形式添加了一个二级系列,绑定到二级轴(在右侧)。我希望此轴根据系列中的值调整其比例,但事实并非如此。无论这个系列的最高值是多少,次要 y 轴也有 0 到 100 之间的刻度。
如果我通过以下方式手动设置次要 y 轴的最大值:
chart.ChartAreas[0].AxisY2.Maximum = 20;
。它有效,但我不想这样做,因为根据所使用的搜索条件,最大值可能会有很大差异。
我真的试图为此找到解决方案,但我做不到。根据文档和样本,比例似乎应该基于系列值,但我不明白它是如何工作的。任何帮助将不胜感激!
下面是重现问题的独立测试函数。我使用以下行从我的视图中调用该函数:
<p><img src="@Url.Action("CreateChart_TestSecondaryAxis")" /> </p>
public FileResult CreateChart_TestSecondaryAxis()
{
System.Web.UI.DataVisualization.Charting.Chart chart = new System.Web.UI.DataVisualization.Charting.Chart();
chart.Width = 800;
chart.Height = 400;
chart.BackColor = Color.FromArgb(211, 223, 240);
chart.BorderlineDashStyle = ChartDashStyle.Solid;
chart.BackSecondaryColor = Color.White;
chart.BackGradientStyle = GradientStyle.TopBottom;
chart.BorderlineWidth = 1;
chart.Palette = ChartColorPalette.BrightPastel;
chart.BorderlineColor = Color.FromArgb(26, 59, 105);
chart.RenderType = RenderType.BinaryStreaming;
chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
chart.AntiAliasing = AntiAliasingStyles.All;
chart.TextAntiAliasingQuality = TextAntiAliasingQuality.Normal;
ChartArea chartArea = new ChartArea();
chartArea.Name = "TestSecondaryAxis";
chartArea.BackColor = Color.Transparent;
chartArea.AxisX.IsLabelAutoFit = false;
chartArea.AxisY.IsLabelAutoFit = false;
chartArea.AxisX.LabelStyle.Font =
new Font("Verdana,Arial,Helvetica,sans-serif",
8F, FontStyle.Regular);
chartArea.AxisY.LabelStyle.Font =
new Font("Verdana,Arial,Helvetica,sans-serif",
8F, FontStyle.Regular);
chartArea.AxisY.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisY.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.Title = "Airport";
chartArea.AxisY.Title = "LandingConf";
chartArea.AxisY.TextOrientation = TextOrientation.Rotated270;
chartArea.AxisX.LabelStyle.IsEndLabelVisible = true;
chart.ChartAreas.Add(chartArea);
Series seriesPrimaryAxisConf3 = new Series();
seriesPrimaryAxisConf3.Name = "Conf 3";
seriesPrimaryAxisConf3.IsValueShownAsLabel = false;
seriesPrimaryAxisConf3.Color = Color.Blue;
seriesPrimaryAxisConf3.ChartType = SeriesChartType.StackedColumn100;
seriesPrimaryAxisConf3.BorderWidth = 2;
seriesPrimaryAxisConf3.ChartArea = "TestSecondaryAxis";
DataPoint point;
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { i };
seriesPrimaryAxisConf3.Points.Add(point);
}
chart.Series.Add(seriesPrimaryAxisConf3);
Series seriesPrimaryAxisConfFull = new Series();
seriesPrimaryAxisConfFull.Name = "Conf Full";
seriesPrimaryAxisConfFull.IsValueShownAsLabel = false;
seriesPrimaryAxisConfFull.Color = Color.Red;
seriesPrimaryAxisConfFull.ChartType = SeriesChartType.StackedColumn100;
seriesPrimaryAxisConfFull.BorderWidth = 2;
seriesPrimaryAxisConfFull.ChartArea = "TestSecondaryAxis";
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { 11-i };
seriesPrimaryAxisConfFull.Points.Add(point);
}
chart.Series.Add(seriesPrimaryAxisConfFull);
Series seriesSecondaryAxisNoOfFlights = new Series();
seriesSecondaryAxisNoOfFlights.Name = "NoOfFLights";
seriesSecondaryAxisNoOfFlights.IsValueShownAsLabel = false;
seriesSecondaryAxisNoOfFlights.Color = Color.Red;
seriesSecondaryAxisNoOfFlights.ChartType = SeriesChartType.Line;
seriesSecondaryAxisNoOfFlights.BorderWidth = 2;
seriesSecondaryAxisNoOfFlights.ChartArea = "TestSecondaryAxis";
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { i };
seriesSecondaryAxisNoOfFlights.Points.Add(point);
}
chart.Series.Add(seriesSecondaryAxisNoOfFlights);
chart.Series["NoOfFLights"].YAxisType = AxisType.Secondary;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.LineColor = Color.Transparent;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.MajorGrid.Enabled = false;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.MajorTickMark.Enabled = false;
MemoryStream ms = new MemoryStream();
chart.SaveImage(ms);
return File(ms.GetBuffer(), @"image/png");
}
MSChart 是一个很好的控件,但不幸的是 Microsoft 总是未能 正确地记录它。
随着 MSDN 的最新变化,事情变得 变得更糟 ,所以我实际上无法指出适用于各种 ChartTypes
的规则.
在你的情况下,我扣除了这个(相当古怪的)规则:
To attach a non 100%-series to an indepently scaled secondary y-axis
it must be the first series but the stacked series still must be added
first.
所以,如果你想得到这样的结果:
..您需要调整代码。以下是所需的更改和补充......:
首先我们必须插入线系列在前面但是在之后已添加 stack100 系列..:[=18=]
chart.Series.Insert(0, seriesSecondaryAxisNoOfFlights); // instead of adding it
接下来我们需要 owner-draw 行,否则它会 burried 在列下面。
像这样编写 PostPaint
事件:
private void Chart_PostPaint(object sender, ChartPaintEventArgs e)
{
Chart chart = sender as Chart; //*
Series s = chart.Series[0]; // make sure to pick the right one!
Axis ax = chart.ChartAreas[0].AxisX;
Axis ay = chart.ChartAreas[0].AxisY2; // !!
var pts = s.Points.Select(x =>
new PointF((float)ax.ValueToPixelPosition(x.XValue),
(float)ay.ValueToPixelPosition(x.YValues[0])));
using (Pen pen = new Pen(s.Color, s.BorderWidth))
e.ChartGraphics.Graphics.DrawLines(pen, pts.ToArray());
}
为此系列需要有效 x-values。所以添加这一行:
point.XValue = i; // set both x and y-values!
我还对轴定位添加了一些微调:
ChartArea ca = chart.ChartAreas["TestSecondaryAxis"];
ca.AxisY.Maximum = 100;
ca.AxisX.Minimum = 0.5;
ca.AxisX.IntervalOffset = 0.5;
我正在使用 System.Web.UI.DataVisualization
。 Charting 在 MVC 中创建图表。
我有一个图表显示 StackedColumn100 SeriesChartType
中的值,相应的 y 轴值位于左侧的主 y 轴上。
由于它是 100% 堆积柱系列,因此主要 y 轴的比例从 0 到 100。
然后我以线 SeriesChartType
的形式添加了一个二级系列,绑定到二级轴(在右侧)。我希望此轴根据系列中的值调整其比例,但事实并非如此。无论这个系列的最高值是多少,次要 y 轴也有 0 到 100 之间的刻度。
如果我通过以下方式手动设置次要 y 轴的最大值:
chart.ChartAreas[0].AxisY2.Maximum = 20;
。它有效,但我不想这样做,因为根据所使用的搜索条件,最大值可能会有很大差异。
我真的试图为此找到解决方案,但我做不到。根据文档和样本,比例似乎应该基于系列值,但我不明白它是如何工作的。任何帮助将不胜感激!
下面是重现问题的独立测试函数。我使用以下行从我的视图中调用该函数:
<p><img src="@Url.Action("CreateChart_TestSecondaryAxis")" /> </p>
public FileResult CreateChart_TestSecondaryAxis()
{
System.Web.UI.DataVisualization.Charting.Chart chart = new System.Web.UI.DataVisualization.Charting.Chart();
chart.Width = 800;
chart.Height = 400;
chart.BackColor = Color.FromArgb(211, 223, 240);
chart.BorderlineDashStyle = ChartDashStyle.Solid;
chart.BackSecondaryColor = Color.White;
chart.BackGradientStyle = GradientStyle.TopBottom;
chart.BorderlineWidth = 1;
chart.Palette = ChartColorPalette.BrightPastel;
chart.BorderlineColor = Color.FromArgb(26, 59, 105);
chart.RenderType = RenderType.BinaryStreaming;
chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
chart.AntiAliasing = AntiAliasingStyles.All;
chart.TextAntiAliasingQuality = TextAntiAliasingQuality.Normal;
ChartArea chartArea = new ChartArea();
chartArea.Name = "TestSecondaryAxis";
chartArea.BackColor = Color.Transparent;
chartArea.AxisX.IsLabelAutoFit = false;
chartArea.AxisY.IsLabelAutoFit = false;
chartArea.AxisX.LabelStyle.Font =
new Font("Verdana,Arial,Helvetica,sans-serif",
8F, FontStyle.Regular);
chartArea.AxisY.LabelStyle.Font =
new Font("Verdana,Arial,Helvetica,sans-serif",
8F, FontStyle.Regular);
chartArea.AxisY.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisY.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.Title = "Airport";
chartArea.AxisY.Title = "LandingConf";
chartArea.AxisY.TextOrientation = TextOrientation.Rotated270;
chartArea.AxisX.LabelStyle.IsEndLabelVisible = true;
chart.ChartAreas.Add(chartArea);
Series seriesPrimaryAxisConf3 = new Series();
seriesPrimaryAxisConf3.Name = "Conf 3";
seriesPrimaryAxisConf3.IsValueShownAsLabel = false;
seriesPrimaryAxisConf3.Color = Color.Blue;
seriesPrimaryAxisConf3.ChartType = SeriesChartType.StackedColumn100;
seriesPrimaryAxisConf3.BorderWidth = 2;
seriesPrimaryAxisConf3.ChartArea = "TestSecondaryAxis";
DataPoint point;
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { i };
seriesPrimaryAxisConf3.Points.Add(point);
}
chart.Series.Add(seriesPrimaryAxisConf3);
Series seriesPrimaryAxisConfFull = new Series();
seriesPrimaryAxisConfFull.Name = "Conf Full";
seriesPrimaryAxisConfFull.IsValueShownAsLabel = false;
seriesPrimaryAxisConfFull.Color = Color.Red;
seriesPrimaryAxisConfFull.ChartType = SeriesChartType.StackedColumn100;
seriesPrimaryAxisConfFull.BorderWidth = 2;
seriesPrimaryAxisConfFull.ChartArea = "TestSecondaryAxis";
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { 11-i };
seriesPrimaryAxisConfFull.Points.Add(point);
}
chart.Series.Add(seriesPrimaryAxisConfFull);
Series seriesSecondaryAxisNoOfFlights = new Series();
seriesSecondaryAxisNoOfFlights.Name = "NoOfFLights";
seriesSecondaryAxisNoOfFlights.IsValueShownAsLabel = false;
seriesSecondaryAxisNoOfFlights.Color = Color.Red;
seriesSecondaryAxisNoOfFlights.ChartType = SeriesChartType.Line;
seriesSecondaryAxisNoOfFlights.BorderWidth = 2;
seriesSecondaryAxisNoOfFlights.ChartArea = "TestSecondaryAxis";
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { i };
seriesSecondaryAxisNoOfFlights.Points.Add(point);
}
chart.Series.Add(seriesSecondaryAxisNoOfFlights);
chart.Series["NoOfFLights"].YAxisType = AxisType.Secondary;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.LineColor = Color.Transparent;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.MajorGrid.Enabled = false;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.MajorTickMark.Enabled = false;
MemoryStream ms = new MemoryStream();
chart.SaveImage(ms);
return File(ms.GetBuffer(), @"image/png");
}
MSChart 是一个很好的控件,但不幸的是 Microsoft 总是未能 正确地记录它。
随着 MSDN 的最新变化,事情变得 变得更糟 ,所以我实际上无法指出适用于各种 ChartTypes
的规则.
在你的情况下,我扣除了这个(相当古怪的)规则:
To attach a non 100%-series to an indepently scaled secondary y-axis it must be the first series but the stacked series still must be added first.
所以,如果你想得到这样的结果:
..您需要调整代码。以下是所需的更改和补充......:
首先我们必须插入线系列在前面但是在之后已添加 stack100 系列..:[=18=]
chart.Series.Insert(0, seriesSecondaryAxisNoOfFlights); // instead of adding it
接下来我们需要 owner-draw 行,否则它会 burried 在列下面。
像这样编写 PostPaint
事件:
private void Chart_PostPaint(object sender, ChartPaintEventArgs e)
{
Chart chart = sender as Chart; //*
Series s = chart.Series[0]; // make sure to pick the right one!
Axis ax = chart.ChartAreas[0].AxisX;
Axis ay = chart.ChartAreas[0].AxisY2; // !!
var pts = s.Points.Select(x =>
new PointF((float)ax.ValueToPixelPosition(x.XValue),
(float)ay.ValueToPixelPosition(x.YValues[0])));
using (Pen pen = new Pen(s.Color, s.BorderWidth))
e.ChartGraphics.Graphics.DrawLines(pen, pts.ToArray());
}
为此系列需要有效 x-values。所以添加这一行:
point.XValue = i; // set both x and y-values!
我还对轴定位添加了一些微调:
ChartArea ca = chart.ChartAreas["TestSecondaryAxis"];
ca.AxisY.Maximum = 100;
ca.AxisX.Minimum = 0.5;
ca.AxisX.IntervalOffset = 0.5;