Création SelectionBorder: Un peu au visage par l'arrondissement décimal?

StackOverflow https://stackoverflow.com/questions/1299706

  •  18-09-2019
  •  | 
  •  

Question

Je suis actuellement implémenté une classe appelée SelectionBorder dans WPF. Il est dérivé de la classe Shape.

Il ressemble fondamentalement à ceci:

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

}

Les propriétés StartPoint et points déterminent les coins de la frontière. La frontière est une frontière de ligne caressa typique (un trait noir, un coup invisible comme ça: - - - -)

Le problème que j'ai maintenant est que, puisque les points d'angle sont choosable librement il est assez fréquent que le nombre de coups (ce qui signifie traits noirs et invisibles) est même pas (en fait même pas un entier) et donc les premiers regards de course plus que les autres (visibles dans l'image). Cela ne semble peut-être pas être une grosse affaire, mais je veux plus tard pour animer la frontière afin que le cercle des coups autour du contenu. Lorsque vous effectuez cette animation la faille minuscule dans la vue statique devient clairement visible et à mon avis, est très inquiétante.

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

Le problème est que j'ai essayé de déterminer une longueur de course qui obtient aussi près du original que possible longueur de course et crée un nombre pair de coups. Cependant, le problème que j'ai rencontré est que WPF (évidemment) ne peut pas afficher la précision d'un ensemble à double décimale et longueur de course donc le nombre d'accidents vasculaires cérébraux résultant est inégale encore une fois.

Y at-il de solution à ce problème? Avez-vous probablement une autre solution pour mon problème?

Merci d'avance!

EDIT: Je retesté et passé en revue le code après une petite pause pour le fitness aujourd'hui et après tout ce qu'il se passe seulement sur de très grandes StrokeLengths. Je prévois d'utiliser StrokeLengths de 2 où le petit saut d'animation ne soit beaucoup moins que ce que je pensais à l'origine.

Était-ce utile?

La solution 2

Je viens de trouver une manière qui le rend beaucoup plus facile de créer une telle SelectionBorder animée.

Au lieu de créer l'animation en déplaçant un AnimationPoint auto-créé par l'animation que je viens animé la propriété StrokeDashOffset fourni nativement par la classe de forme et le réglage de la StrokeDashArray pour définir la longueur de course.

Il ressemblerait à ceci en XAML:

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

La classe ressemble à ceci:

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

Autres conseils

Vous pouvez faire plus d'un coin « non adapté » à cet égard. Par exemple, au lieu d'avoir un point être la « destination » « source » et des traits animés, vous pouvez choisir 2 points. On serait la « source », des tirets apparaissent à marcher loin dans 2 directions, et un autre point être la « destination », où convergent les tirets et disparaissent.

GIMP, par exemple, anime la sélection lignes pointillées de cette façon et semble choisir un point le plus proche de la partie inférieure gauche de la « source » et un point plus proche de la partie supérieure droite de la « destination ».

Vous pouvez venir avec un autre système, aussi bien.

Il suffit de se rappeler que, même si cela peut paraître dérangeant pour vous, la plupart des utilisateurs ne se préoccuperont pas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top