StackedBar不同系列之间的边界 [英] StackedBar borders between different series
问题描述
我想要的是在StackedBar中的两个系列之间设置边界像这个图像蓝色和绿色之间的粗黑线
What i want is to set borders between two series in StackedBar Like this image The bold black line between blue and green
我无法想出任何想法来指定边框,我试图设置边框到系列的这个代码
I can not figure out any idea to specify the border, i tried to set the borders to the series throuh this code
chart.Series["series0"].BorderWidth = 2;
chart.Series["series0"].BorderColor = Color.Black;
chart.Series["series0"].BorderDashStyle = ChartDashStyle.Solid;
但结果我得到
这里是我的代码
double l = Convert.ToDouble(query1[i - 1][0]) - 10;
string n = query1[i - 1][1];
int count = 0;
for (double t = l; t < l + 10; t++)
{
//Next line Calc. the occurence of character in a text file
count = n.Split('C').Length - 1;
//Multiple the occurence by 10 so it become percent
chart.Series["series0"].Points.AddXY(t, count * 10);
chart.Series["series0"]["PointWidth"] = "1";
chart.Series["series0"].BorderWidth = 2;
chart.Series["series0"].BorderColor = Color.Black;
chart.Series["series0"].BorderDashStyle = ChartDashStyle.Solid;
count = n.Split('o').Length - 1;
chart.Series["series1"].Points.AddXY(t, count * 10);
chart.Series["series1"]["PointWidth"] = "1";
}
如何使用StackedBar实现第一个pic效果? ,如果我不能使用StackedBar,你建议使用什么图表类型?
How to achieve the first pic effect using StackedBar ? , if i can not using StackedBar, what chart type you suggest to use ??
推荐答案
可以很容易地形成这两个系列之间的边界。 (创建 LineAnnotations
以实现这将是一场噩梦..)
There are no built-in chart elements that could easily be made into a borderline between those two Series. (Creating LineAnnotations
to achieve this would be a nightmare..)
所以添加行的方式是将它们绘制到图表
的表面上。这是在 PostPaint
事件中自然完成的,只为这样的装饰。
So the way to add the lines is to draw them onto the surface of the Chart
. This is most naturally done in the PostPaint
event, provided just for such adornments.
这里 Axes
具有方便的功能,可以在数据值和像素位置之间进行转换。我们需要 ValueToPixelPosition
方法。
Here the Axes
have handy functions to convert between the data values and the pixel positions. We need the ValueToPixelPosition
method.
code>绘图逐渐变得有点复杂,因为我们接近的最终版本..
I will take you through variations of Chart
drawing that gradually get a little more complicated as we approach the final version..:
让我们开始一个简单的例子:让我们建立和装饰一个 StackedArea
chart;这里是绘图代码:
Let's start with a simple example: Let's build and adorn a StackedArea
chart; here is the drawing code:
private void chart2_PostPaint(object sender, ChartPaintEventArgs e)
{
Series s = chart1.Series[0];
ChartArea ca = chart1.ChartAreas[0];
var pp = s.Points.Select(x=>
new PointF( (float)ca.AxisX.ValueToPixelPosition(x.XValue),
(float)ca.AxisY.ValueToPixelPosition(x.YValues[0]) ) );
if (s.Points.Count > 1)
using (Pen pen = new Pen(Color.DarkOliveGreen, 4f))
e.ChartGraphics.Graphics.DrawLines(pen, pp.ToArray());
}
Points.Select
真的只是一个循环的简写;所以在创建像素点列表后,我们只需要绘制它。
The Points.Select
is really just a shorthand for a loop; so after creating the pixel point list we simply draw it.
现在,如您所见, StackedArea
是尖的,并且看起来不像 StackedBar
或 StackedColumn
图表。所以让我们通过添加一些额外的点来欺骗和纠正区域图:
Now, as you can see, as StackedArea
chart is pointy and doesn't look like a StackedBar
or StackedColumn
chart. So let's cheat and 'rectify' the area chart by adding a few extra points:
void rectifyArea(Series s)
{
for (int i = s.Points.Count - 1; i > 0; i--)
s.Points.InsertXY(i, i - 1, s.Points[i].YValues[0]);
}
结果:
现在没那么难了;不幸的是你不能把 StackedArea
从左到右而不是自下而上。因此,我们需要将图表类型更改为 Bar
类型。
Now that was not so hard; unfortunately you just can't turn a StackedArea
to go from left to right instead of bottom-up. So we need to change the chart type to a Bar
type eventually..
这里的挑战是找到右上角和下角角。我们有 DataPoint
值,但这些值位于中间。因此,我们需要添加/减去条纹宽度的一半,以获得角点。为此,我们需要 width 。
Here the challenge is to find the right upper and lower corners of those bars. We do have the DataPoint
values, but these are in the middle of the bars. So we need to add/subtract half of the Bars' width to get the corners. For this we need the width.
将 PointWidth
属性设置为 1
,我们真正需要的是像素宽度。我们最好通过减去两个相邻点的像素坐标得到它。
While you have set it with the PointWidth
property to 1
, what we really need is the pixel width. We best get it by subtracting the pixel coordinates of two neighbouring points.
这使得 PostPaint
,但仍然不过分复杂;我们将从 StackedColumn
图表开始,为每个数据点添加两个角点:
This makes the PostPaint
event a little longer, but still not overly complicated; we will start with a StackedColumn
chart, adding two corner points for each data point:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Series s = chart1.Series[0];
ChartArea ca = chart1.ChartAreas[0];
if (s.Points.Count <= 0) return;
// calculate width of a column:
int pp1 = (int)ca.AxisX.ValueToPixelPosition(s.Points[0].XValue);
int pp2 = (int)ca.AxisX.ValueToPixelPosition(s.Points[1].XValue);
float w2 = Math.Abs(pp2 - pp1) / 2f;
List<PointF> points = new List<PointF>();
for (int i = 0; i < s.Points.Count; i++)
{
DataPoint dp = s.Points[i];
points.Add(new PointF( (int)ca.AxisX.ValueToPixelPosition(dp.XValue) - w2,
(int)ca.AxisY.ValueToPixelPosition(dp.YValues[0]) ));
points.Add(new PointF( (int)ca.AxisX.ValueToPixelPosition(dp.XValue) + w2,
(int)ca.AxisY.ValueToPixelPosition(dp.YValues[0]) ));
}
if (points.Count > 1)
using (Pen pen = new Pen(Color.DarkOliveGreen, 4f))
e.ChartGraphics.Graphics.DrawLines(pen, points.ToArray());
}
现在这看起来与我们的假版 '。我们需要更改什么才能将其应用于 StackedBar
图表?几乎没有!我们需要照顾的唯一两件事情是
Now this looks pretty much identical to our fake version of the 'rectified area chart'. What will we need to change to apply this to a StackedBar
chart? Almost nothing! The only two things we need to take care of are
- y轴的方向。由于点向上移动,但GDI +图形的像素坐标向下移动,我们需要以相反的顺序创建两个角点。
- 我们需要反转x和y坐标,因为所有类型的
Bar
图表的轴都是相反的。 li>
- the direction of the y-axis. Since the points move upward but the pixel coordinates of GDI+ graphhics move downwards we need to create the two cornerpoints in the reverse order.
- And we need to reverse the x- and y coodinates, as the axes are reversed for all types of
Bar
charts.
以下是带有边框的两个堆叠图表:
Here are the two stacked charts with a border:
这是 StackBar
图表:
This is the loop for the StackBar
chart:
for (int i = 0; i < s.Points.Count; i++)
{
points.Add(new PointF( (float)ca.AxisY.ValueToPixelPosition(s.Points[i].YValues[0]),
(float)ca.AxisX.ValueToPixelPosition(s.Points[i].XValue) + w2));
points.Add(new PointF( (float)ca.AxisY.ValueToPixelPosition(s.Points[i].YValues[0]),
(float)ca.AxisX.ValueToPixelPosition(s.Points[i].XValue) - w2));
}
请注意,我用4像素的固定笔宽度绘制。要使其与图表
缩放,您可能需要动态计算笔宽度。
Note that I am drawing with a fixed pen width of 4 pixels. To make it scale with the Chart
you may want to calculate the pen width dynamically..
更新
要绘制边框您可以将代码放入一个循环,如下所示:
To draw borders on top of several series you can put the code into a loop like this:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Chart chart = chart1;
Series s0 = chart.Series[0];
ChartArea ca = chart.ChartAreas[0];
// calculate width of a bar:
int pp1 = (int)ca.AxisX.ValueToPixelPosition(s0.Points[0].XValue);
int pp2 = (int)ca.AxisX.ValueToPixelPosition(s0.Points[1].XValue);
float delta = Math.Abs(pp2 - pp1) / 2f;
for (int s = 0; s < chart.Series.Count; s++)
{
List<PointF> points = new List<PointF>();
for (int p = 0; p < chart.Series[s].Points.Count; p++)
{
DataPoint dp = chart.Series[s].Points[p];
double v = GetStackTopValue(chart, s, p);
points.Add(new PointF((float)ca.AxisY.ValueToPixelPosition(v),
(float)ca.AxisX.ValueToPixelPosition(dp.XValue) + delta));
points.Add(new PointF((float)ca.AxisY.ValueToPixelPosition(v),
(float)ca.AxisX.ValueToPixelPosition(dp.XValue) - delta));
}
using (Pen pen = new Pen(Color.DarkOliveGreen, 3f))
e.ChartGraphics.Graphics.DrawLines(pen, points.ToArray());
}
}
double GetStackTopValue(Chart chart, int series, int point)
{
double v = 0;
for (int i = 0; i < series + 1; i++)
v += chart.Series[i].Points[point].YValues[0];
return v;
}
这篇关于StackedBar不同系列之间的边界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!