2012-04-17 142 views
4

是的,我知道(This post),如果你搜索,你會注意到事件AxisValueChanged似乎只存在於這一個線程。X軸自動變焦Y軸變焦

我的目標僅僅是當用戶在X軸上進行選擇時自動縮放Y軸,但我一直無法弄清楚。

我也嘗試過使用SelectionRangeChanged事件,但這個事件似乎有點破,因爲即時通訊無法弄清楚什麼是實際範圍選擇? (IE所以我可以找到最大/最小範圍)。

即時通訊使用MS圖(微軟圖表)

的最終目標是,當我放大X軸(這是一個快繩圖表),應該看到新的「最大」可見Y軸值和調整/縮小它

回答

5

如果我理解正確,給定X軸上的縮放範圍,則還想縮放Y軸上的相同範圍。如果是這樣,你可以這樣做:

void chart1_SelectionRangeChanged(object sender, CursorEventArgs e) 
{ 
    // Given the visible (zoomed) range on X, 
    // it zooms the same relative range on Y: 
    // i.e. if on the X axis, the range 5% - 30% is zoomed, 
    // it zooms the same range on Y. 
    var axisY = this.chart1.ChartAreas[0].AxisY; 

    var totalXRange = e.Axis.Maximum - e.Axis.Minimum; 
    var totalYRange = axisY.Maximum - axisY.Minimum; 

    var ySelectionStart = (e.Axis.ScaleView.ViewMinimum - e.Axis.Minimum) * 
          totalYRange/totalXRange; 
    var ySelectionEnd = (e.Axis.ScaleView.ViewMaximum - e.Axis.Minimum) * 
         totalYRange/totalXRange; 

    axisY.ScaleView.Zoom(ySelectionStart,ySelectionEnd); 
} 

正如你所說,該事件AxisValueChanged不存在;您鏈接的帖子可能意味着(現有)事件AxisViewChanged

顯然,您也可以使用AxisViewChanged來達到您的目的,並且調整我的代碼以利用該事件不應該那麼困難。

隨意問是否需要什麼幫助;)

編輯:

我修改了代碼,解釋你的目標。以下代碼計算對應於縮放X範圍內點的最大值和最小值的Y範圍:

void chart1_SelectionRangeChanged(object sender, CursorEventArgs e) 
{ 
    var axisY = this.chart1.ChartAreas[0].AxisY; 

    var xRangeStart = e.Axis.ScaleView.ViewMinimum; 
    var xRangeEnd = e.Axis.ScaleView.ViewMaximum; 

    // compute the Y values for the points crossing the range edges 
    double? yRangeStart = null; 
    var pointBeforeRangeStart = this.chart1.Series[0].Points.FirstOrDefault(x => x.XValue <= xRangeStart); 
    var pointAfterRangeStart = this.chart1.Series[0].Points.FirstOrDefault(x => x.XValue > xRangeStart); 
    if (pointBeforeRangeStart != null && pointAfterRangeStart != null) 
     yRangeStart = Interpolate2Points(pointBeforeRangeStart, pointAfterRangeStart, xRangeStart); 

    double? yRangeEnd = null; 
    var pointBeforeRangeEnd = this.chart1.Series[0].Points.FirstOrDefault(x => x.XValue <= xRangeEnd); 
    var pointAfterRangeEnd = this.chart1.Series[0].Points.FirstOrDefault(x => x.XValue > xRangeEnd); 
    if (pointBeforeRangeEnd != null && pointAfterRangeEnd != null) 
     yRangeEnd = Interpolate2Points(pointBeforeRangeEnd, pointAfterRangeEnd, xRangeEnd); 

    var edgeValues = new[] { yRangeStart, yRangeEnd }.Where(x => x.HasValue).Select(x => x.Value); 

    // find the points inside the range 
    var valuesInRange = this.chart1.Series[0].Points 
    .Where(p => p.XValue >= xRangeStart && p.XValue <= xRangeEnd) 
    .Select(x => x.YValues[0]); 

    // find the minimum and maximum Y values 
    var values = valuesInRange.Concat(edgeValues); 
    double yMin; 
    double yMax; 
    if (values.Any()) 
    { 
     yMin = values.Min(); 
     yMax = values.Max(); 
    } 
    else 
    { 
     yMin = this.chart1.Series[0].Points.Min(x => x.YValues[0]); 
     yMax = this.chart1.Series[0].Points.Max(x => x.YValues[0]); 
    } 

    // zoom Y-axis to [yMin - yMax] 
    axisY.ScaleView.Zoom(yMin, yMax); 
} 

// see: http://en.wikipedia.org/wiki/Linear_interpolation#Linear_interpolation_between_two_known_points 
public static double Interpolate2Points(DataPoint p1, DataPoint p2, double x) 
{ 
    var x0 = p1.XValue; 
    var y0 = p1.YValues[0]; 
    var x1 = p2.XValue; 
    var y1 = p2.YValues[0]; 
    return y0 + ((x - x0) * y1 - (x - x0) * y0)/(x1 - x0); 
} 
+0

完全像我解釋的那樣工作,我更新了一些解釋以使我的最終目標清晰。 Il personaly測試更多明天:)謝謝 – EKS 2012-04-17 20:30:57

+0

@EKS:編輯以說明您的更改;) – digEmAll 2012-04-17 21:38:04