Frage

Ich bin zur Implementierung einer Klasse namens SelectionBorder in WPF. Es ist aus der Shape-Klasse abgeleitet.

Es sieht im Wesentlichen wie folgt:

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!
       }
   }

}

Die Startpoint und Punkte Eigenschaften bestimmen die Ecken der Grenze. Die Grenze ist eine typische strich Linie Grenze (ein schwarzer Strich, ein unsichtbares Hub wie folgt aus: - - - -)

Das Problem, das ich jetzt habe, ist, dass, da die Eckpunkte frei sind wählbar, es ist ziemlich üblich, dass die Anzahl der Hübe (dh schwarz und unsichtbare Schläge) ist nicht einmal (in der Tat nicht einmal eine ganze Zahl) und damit der ersten Strich aussieht länger als die anderen (im Bild sichtbar). Das vielleicht scheint nicht so schlimm zu sein, aber ich mag später die Grenze animieren, so dass der Strich Kreis um den Inhalt. Wenn diese Animation zu tun wird der winzige Fehler in der statischen Sicht deutlich sichtbar und meiner Meinung nach ist sehr beunruhigend.

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

Das Problem ist, dass ich versuchte, eine StrokeLength zu bestimmen, die eine gerade Anzahl von Schlägen wie nah am Original StrokeLength wie möglich und schaffen bekommt. Aber das Problem, das ich habe laufen in ist, dass WPF (natürlich) nicht die ganze Präzision eines Doppel dezimal StrokeLength anzuzeigen und damit die resultierende Taktzahl ist ungleichmäßig wieder.

Gibt es für dieses Problem jede Abhilfe? Haben Sie wahrscheinlich eine andere Lösung für mein Problem?

Vielen Dank im Voraus!

EDIT: ich erneut getestet und überprüft den Code nach einer kleinen Pause für Fitness heute und schließlich kommt es nur auf sehr großen StrokeLengths. Ich plane StrokeLengths von 2 zu verwenden, wo die kleinen Animation Springen Angelegenheit viel kostet weniger, als ich ursprünglich dachte.

War es hilfreich?

Lösung 2

Ich habe gerade eine Weise, dass es viel einfacher zu erstellen so eine animierte SelectionBorder macht.

Statt die Animation zu schaffen durch eine selbst erstellte AnimationPoint durch Animation bewegt ich animiert gerade die StrokeDashOffset Eigenschaft nativ von der Shape-Klasse zur Verfügung gestellt und die Einstellung der StrokeDashArray die StrokeLength zu definieren.

Es wäre in XAML wie folgt aussehen:

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

Die Klasse sieht wie folgt aus:

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;
        }
    }
}

Andere Tipps

Sie können mehr als eine Ecke machen „un-matched“ in dieser Hinsicht. Zum Beispiel kann anstelle einem Punkt die „Quelle“ sein und mit „Ziel“ der animierten Striche, könnte man zwei Punkte holen. Man würde die „Quelle“, Striche erscheinen in zwei Richtungen von ihm weg zu marschieren, und ein anderer Punkt der „Ziel“, wo Striche zusammenlaufen und verschwinden.

GIMP zum Beispiel beseelt Auswahlleitungen auf diese Weise gestrichelte und scheint einen Punkt am nächsten an der linken unteren Ecke für die „Quelle“ zu holen und einen Punkt am nächsten an der oberen rechten für das „Ziel“.

Sie mit einem anderen Schema kommen konnten, wie gut.

Denken Sie daran, dass, während es dir störend aussehen, die meisten Nutzer nicht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top