这是一个很好的问题,但不幸的是没有像锁定两个这样的简单解决方案Axes
或设置一个值..
我们先来看看相关的玩家:
The Chart
控制有一个内在的Size
called ClientSize
, 哪一个是Chart.Size
减去边框。两种尺寸均以像素为单位进行测量。
里面可能有一个或多个ChartAreas https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.chartarea%28v=vs.110%29.aspx。每个都有一个Position
这是类型ElementPosition https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.elementposition%28v=vs.110%29.aspx.
每个里面ChartArea
是用于实际绘制点的区域;它被称为InnerPlotPosition https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.chartarea.innerplotposition(v=vs.110).aspx.
InnerPlotPosition 属性定义图表内的矩形
用于绘制数据的区域元素;它不包括刻度线,
轴标签等。
用于此属性的坐标(0,0 到 100,100)与
ChartArea 对象,而不是整个图表。
InnerPlotPosition 属性可用于对齐多个图表
地区。但是,如果一个图表区域有刻度线和轴标签,并且
另一个则不然,它们的轴线无法对齐。
- Both
ChartArea.Position
and ChartArea.InnerPlotPosition
不仅仅包含location but also the size地区;所有值都在percent外部区域,即ChartArea.InnerPlotPosition
是相对于ChartArea.Position
and ChartArea.Position
是相对于Chart.ClientSize
。所有百分比均来自0-100
.
So the ChartArea
包括Labels
and Legends
也Axes
and TickMarks
..
我们想要的是找到一种方法来使InnerPlotArea
正方形,即具有相同的宽度和高度以像素为单位。百分比不行!
让我们从一些简单的计算开始;如果这些是我们拥有的数据..:
// we'll work with one ChartArea only..:
ChartArea ca = chart1.ChartAreas[0];
ElementPosition cap = ca.Position;
ElementPosition ipp = ca.InnerPlotPosition;
..那么这些是两个区域的像素大小:
// chartarea pixel size:
Size CaSize = new Size( (int)( cap.Width * chart1.ClientSize.Width / 100f),
(int)( cap.Height * chart1.ClientSize.Height / 100f));
// InnerPlotArea pixel size:
Size IppSize = new Size((int)(ipp.Width * CaSize.Width / 100f),
(int)(ipp.Height * CaSize.Height / 100f));
理想情况下我们希望InnerPlotArea
呈正方形;因为不能很好地让较小的一侧增长(否则图表会透支),我们需要缩小较大的一侧。所以新的像素大小InnerPlotArea
is
int ippNewSide = Math.Min(IppSize.Width, IppSize.Height);
接下来是什么?自从Chart.Size
刚刚确定,我们不想搞乱它。我们也不应该搞乱ChartArea
: 还需要空间来容纳Legend
etc..
所以我们改变大小InnerPlotArea
..:
首先创建一个类级别变量来存储原始值InnerPlotPosition
:
ElementPosition ipp0 = null;
我们需要它保留原始百分比,即边距,以便在计算新百分比时使用它们。当我们调整图表时,当前的图表将已经被更改/扭曲。
然后我们创建一个函数来使InnerPlotArea
正方形,将其全部包裹起来:
void makeSquare(Chart chart)
{
ChartArea ca = chart.ChartAreas[0];
// store the original value:
if (ipp0 == null) ipp0 = ca.InnerPlotPosition;
// get the current chart area :
ElementPosition cap = ca.Position;
// get both area sizes in pixels:
Size CaSize = new Size( (int)( cap.Width * chart1.ClientSize.Width / 100f),
(int)( cap.Height * chart1.ClientSize.Height / 100f));
Size IppSize = new Size((int)(ipp0.Width * CaSize.Width / 100f),
(int)(ipp0.Height * CaSize.Height / 100f));
// we need to use the smaller side:
int ippNewSide = Math.Min(IppSize.Width, IppSize.Height);
// calculate the scaling factors
float px = ipp0.Width / IppSize.Width * ippNewSide;
float py = ipp0.Height / IppSize.Height * ippNewSide;
// use one or the other:
if (IppSize.Width < IppSize.Height)
ca.InnerPlotPosition = new ElementPosition(ipp0.X, ipp0.Y, ipp0.Width, py);
else
ca.InnerPlotPosition = new ElementPosition(ipp0.X, ipp0.Y, px, ipp0.Height);
}
您可以在调整大小之后或期间调用该函数。
private void chart1_Resize(object sender, EventArgs e)
{
makeSquare(chart1);
}
这里函数正在工作:
The original size:
Squeezed a little:
And made square again:
注意绿色如何ChartArea
预留足够的空间Labels
和Legend
以及轴的自动缩放如何仍然有效。但是 X 轴标签现在不适合放在一行中。还要注意如何ChartArea.BackColor
actually是的颜色InnerPlotArea
only!
请注意,您可能需要刷新变量ipp0
修改后反映变化的百分比ChartArea
布局,如放大、移动或删除Legends
或改变尺寸或角度Labels
etc..
当然,您可以修改该函数以传递任何其他比率来保留,而不是将绘图区域保持为正方形。