2009-08-19 58 views
2

我目前在WPF中實現了一個名爲SelectionBorder的類。它來源於Shape類。通過小數四捨五入創建SelectionBorder:面部位?

它基本上是這樣的:

public class SelectionBorder : Shape 
{ 
    public Point StartPoint {get; set;} 
    public PointCollection Points {get; set;} 

    public double StrokeLength {get; set;} 

    protected override Geometry DefiningGeometry{ 
     get{ 
      //Magic! 
     } 
    } 

} 

:起點和積分性質確定邊界的角落。邊框是一個典型的描邊線條邊框(一個黑色筆畫,一個看不見的筆畫就是這樣的: - - - - )

我現在面臨的問題是,由於角點可自由選擇,所以計數筆畫(意思是黑色和不可見的筆畫)甚至不是(甚至不是一個整數),因此第一筆畫看起來比其他筆畫(圖片中可見)長。這可能似乎沒什麼大不了,但我後來想爲邊界設置動畫,以便筆畫圍繞着內容。當做這個動畫時,靜態視圖中的小缺陷變得清晰可見,在我看來,這是非常令人不安的。

alt text http://img14.imageshack.us/img14/2874/selectionborder.png

的問題是,我試圖確定StrokeLength是獲得儘可能接近原StrokeLength儘可能並創建一個連的筆畫數。然而,我遇到的問題是,WPF(顯然)不能顯示雙精度十進制StrokeLength的整體精度,因此生成的筆畫編號再次不平衡。

有沒有解決這個問題的方法?你可能有我的問題的另一種解決方案?

在此先感謝!

編輯:我今天重新測試並審查了休息一段時間後的代碼,之後它只發生在非常大的StrokeLengths上。我計劃使用2的StrokeLengths,其中跳動的小動畫比我原先想象的要少得多。

回答

0

我剛剛找到了一種方式,使它更容易創建這樣一個動畫SelectionBorder。

而不是通過動畫移動自創的AnimationPoint來創建動畫,而只是爲Shape類自然提供的StrokeDashOffset屬性設置動畫,並設置StrokeDashArray來定義StrokeLength。

它看起來像這樣的XAML:

<namespace:SelectionBorder StrokeDashArray="2" AnimationDuration="0:0:1" Stroke="Black" /> 

類看起來是這樣的:

public class SelectionBorder : Shape 
{ 
    private DoubleAnimation m_Animation; 
    private bool m_AnimationStarted; 

    public SelectionBorder() 
    { 
     IsVisibleChanged += OnIsVisibleChanged; 
    } 

    protected void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 
    { 
     if (Visibility == Visibility.Visible) 
     { 
      StartAnimation(); 
     } 
     else 
     { 
      StopAnimation(); 
     } 
    } 

    public void StartAnimation() 
    { 
     if (m_AnimationStarted) 
      return; 

     if (m_Animation == null) 
     { 
      m_Animation = CreateAnimation(); 
     } 

     BeginAnimation(StrokeDashOffsetProperty, m_Animation); 
     m_AnimationStarted = true; 
    } 

    protected virtual DoubleAnimation CreateAnimation() 
    { 
     DoubleAnimation animation = new DoubleAnimation(); 
     animation.From = 0; 
     if (StrokeDashArray.Count == 0) 
      animation.To = 4; 
     else 
      animation.To = StrokeDashArray.First() * 2; 
     animation.Duration = AnimationDuration; 
     animation.RepeatBehavior = RepeatBehavior.Forever; 
     return animation; 
    } 

    public void StopAnimation() 
    { 
     if (m_AnimationStarted) 
     { 
      BeginAnimation(StrokeDashOffsetProperty, null); 
      m_AnimationStarted = false; 
     } 
    } 

    #region Dependency Properties 

    public Duration AnimationDuration 
    { 
     get { return (Duration)GetValue(AnimationDurationProperty); } 
     set { SetValue(AnimationDurationProperty, value); } 
    } 

    public static readonly DependencyProperty AnimationDurationProperty = 
     DependencyProperty.Register("AnimationDuration", typeof(Duration), typeof(SelectionBorder), new UIPropertyMetadata(new Duration(TimeSpan.FromSeconds(0.5)))); 


    #endregion Dependency Properties 

    protected override Geometry DefiningGeometry 
    { 
     get 
     { 
      double width = (double.IsNaN(Width)) ? ((Panel)Parent).ActualWidth : Width; 
      double height = (double.IsNaN(Height)) ? ((Panel)Parent).ActualHeight : Height; 

      RectangleGeometry geometry = new RectangleGeometry(new Rect(0, 0, width, height)); 

      return geometry; 
     } 
    } 
} 
1

在這方面,您可以使多個角落「不匹配」。例如,您可以選擇2個點,而不是將一個點作爲動畫破折號的「源」和「目的地」。一個是「源頭」,破折號似乎在兩個方向上遠離它,另一個點是「目的地」,破折號匯聚和消失。

例如,GIMP以這種方式爲動畫選擇虛線,並似乎爲「源」選擇最接近左下角的點,併爲「目標」選擇最接近右上角的點。

你也可以想出其他一些方案。

只要記住,雖然它可能看起來令人不安,但大多數用戶不會在乎。

+0

你正確的地方,也許我是有點挑剔。 2個出發點的建議也非常好。謝謝! – chrischu 2009-08-19 19:29:46