图表注释:如何沿数据点的轴对齐注释

Sha*_*pas 5 c# vb.net charts

我已经将注释与数据点对齐;我想垂直对齐注释。

我读过此书,但无法弄清楚如何将图表宽度与数据点相关联。https://msdn.microsoft.com/zh-CN/library/dd456731.aspx

并且:MS图表注释拒绝与鼠标位置对齐

到目前为止,我添加了一张图表图片作为示例。

'create new chart
 chart1 = New DataVisualization.Charting.Chart

 'add chart areas
  chart1.ChartAreas.Add("NewChartArea")
  chart1.ChartAreas("NewChartArea").Area3DStyle.Enable3D = False
  chart1.ChartAreas("NewChartArea").AxisX.MajorGrid.Enabled = False 'turn chart background grid on and off
  chart1.ChartAreas("NewChartArea").AxisY.MajorGrid.Enabled = False 'turn chart background grid on and off
  chart1.ChartAreas("NewChartArea").AxisX.Title = "Activities of daily living" '----> title on the bottom for the x axis
  '[template] chart1.ChartAreas("NewChartArea").AxisX.LabelStyle.Angle = 45
  '[template] Chart1.Series(SeriesZeroChartName).Label = " my own label" ' -----> adds a label at the top of each bar

   For c As Integer = 2 To Me.DataGridViewResultsAdls.ColumnCount - 1

        Dim NextSeriesChartName As String
        NextSeriesChartName = DataGridViewResultsAdls.Columns(c).Name

        chart1.Series.Add(NextSeriesChartName)
        chart1.Series(NextSeriesChartName).ChartType = DataVisualization.Charting.SeriesChartType.Bar 'CHART CHANGER ******  change this value to change chart type
        chart1.Series(NextSeriesChartName).Points.Clear()
        chart1.Series(NextSeriesChartName).IsValueShownAsLabel = True '----> puts little labels ontop of each bar
        chart1.Series(NextSeriesChartName).SmartLabelStyle.Enabled = True


       ' fill each subsequent series with points
         For Count As Integer = 0 To DataGridViewResultsAdls.Rows.Count - 2
                Dim NextColumnName As String
                NextColumnName = DataGridViewResultsAdls.Columns(c).Name

                ' define X values
                Dim XLabelMyCustom As String
                XLabelMyCustom = DataGridViewResultsAdls.Item(0, Count).Value
                'define Y values
                Dim YLabelMyCustom As String
                YLabelMyCustom = DataGridViewResultsAdls.Item(NextColumnName, Count).Value

                ' add the point to the chart
                chart1.Series(NextSeriesChartName).Points.AddXY(XLabelMyCustom, YLabelMyCustom)

                ' create custom labels for the x axis
                chart1.ChartAreas("NewChartArea").AxisX.CustomLabels.Add(Count + 0.5, Count + 0.4 + 0.5, "Q2", 0, DataVisualization.Charting.LabelMarkStyle.None)
                chart1.ChartAreas("NewChartArea").AxisX.CustomLabels.Add(Count + 0.5 + 0.5, Count + 0.9 + 0.5, "Q1", 0, DataVisualization.Charting.LabelMarkStyle.None)
                chart1.ChartAreas("NewChartArea").AxisX.CustomLabels.Add(Count + 0.5, Count + 1, "Q3", 2, DataVisualization.Charting.LabelMarkStyle.LineSideMark)



                'Create a variable MyDataPoint to hold the current datapoint
                Dim MyDataPoint As DataPoint
                MyDataPoint = chart1.Series(NextSeriesChartName).Points(Count)
                'Create a new text annotation
                Dim MyTextAnnotation As TextAnnotation
                MyTextAnnotation = New TextAnnotation
                MyTextAnnotation.Text = "some notation"
                '[template] MyTextAnnotation.X =   <---- sets coordinates on screen for x
                '[template ]MyTextAnnotation.Y =   <---- sets coordinates on screen for y
                '[template] MyTextAnnotation.AnchorDataPoint = MyDataPoint  'sets the point where the notation will be
                '[template] chart1.Annotations.Add(MyTextAnnotation) ' adds the notation to the chart

                ' only add annotations to the chart once per series
                If c = 2 Then
                    MyTextAnnotation.AxisY = chart1.ChartAreas("NewChartArea").AxisY

                    ' [template] chart1.Series(NextSeriesChartName).Points.Item(Count).ToString  <--- output points to a string {x,y}


                    MyTextAnnotation.AnchorDataPoint = MyDataPoint  'sets the point where the notation will be
                    chart1.Annotations.Add(MyTextAnnotation) ' adds the notation to the chart
                    MyTextAnnotation.AnchorOffsetX = -10


                End If
            Next

        Next

        'Add chart to control and set dock to fill
        Me.PanelChartAdls.Controls.Add(chart1)
        chart1.Dock = DockStyle.Fill

    End If
Run Code Online (Sandbox Code Playgroud)

TaW*_*TaW 5

Chart控件中定位相当复杂。

首先,图表具有三个坐标系:

  • 数据值
  • 某些区域的百分比,最显着的ChartAreaInnerPlotPosition
  • Chart控件的像素ClientArea

实现对齐的最简单方法Annotations是首先将每个锚定到它的DataPoint:

MyTextAnnotation.AnchorDataPoint = MyDataPoint 
Run Code Online (Sandbox Code Playgroud)

接下来,您将 X-Position 覆盖为您喜欢的

MyTextAnnotation.X = someValue;
Run Code Online (Sandbox Code Playgroud)

一些注意事项:

  • 虽然由默认Annotation.Position会使用percentages,后锚定到一个数据点,它使用的来代替。所以使用50不会放在中间的某个地方,而是放在右边......

查看您的图表,我建议使用3.

  • 如果你的价值观不同,这个定位也会有所不同。当您调整图表大小时,轴将调整大小,注释也会移动。

顺便说一句:百分比与下一个外部容器有关:ChartAreasChart.ClientRectangleInnerPlotPostionChartArea和每个元素到它停靠到的容器。

  • Positions默认情况下设置为自动,以便它们的值NaN。要访问(当前)值,您可以调用ElementPosition.ToRectangleF().

  • 另请注意,有几个函数Chart's Axes可以转换值、像素和百分比位置。

但是,您需要找到一个有效的时间来调用这些函数;如果Chart未完成其布局,它们将返回null

您可以安全地在三个Paint事件之一中调用它们,也可以响应像鼠标事件这样的用户交互。

以下是如何使用它们将所有内容定位Annotations到(有点)固定的像素位置:

private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
    Axis AY = chart1.ChartAreas[0].AxisY;

    double pypx = AY.ValueToPosition(AY.PixelPositionToValue(30));

    foreach (TextAnnotation ta in chart1.Annotations)
    {
        ta.X = pypx;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,Annotations当调整图表大小或数据值增长或缩小时,它不会移动。至少不是很多;可以看到一些跳跃。要么是因为我错过了一些东西,要么是因为舍入问题。

但我建议使用更简单的方法将它们的 X 位置设置为轴上的固定值..:

MyTextAnnotation.X = 3;
Run Code Online (Sandbox Code Playgroud)

这会将它们放在您绘制的黄线上。