La creación de SelectionBorder: Un poco en la cara por redondeo decimal?

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

  •  18-09-2019
  •  | 
  •  

Pregunta

Actualmente estoy poniendo en práctica una clase llamada SelectionBorder en WPF. Se deriva de la clase Shape.

Básicamente es el siguiente:

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

}

el punto de inicio y puntos de propiedades determinan las esquinas de la frontera. La frontera es una frontera típica línea acariciado (un trazo negro, un golpe invisible así: - - - -)

El problema que tengo ahora es que desde los puntos de las esquinas son de libre choosable que es bastante común que el conteo de golpes (lo que significa trazos negros e invisibles) no es ni siquiera (de hecho, ni siquiera un entero) y por tanto las primeras miradas accidente cerebrovascular más largo que los otros (visibles en la imagen). Esto tal vez no parece ser un gran problema, pero más tarde Quiero animar la frontera de manera que los golpes círculo alrededor del contenido. Al hacer esta animación la pequeña falla en la visión estática hace claramente visible y en mi opinión es muy preocupante.

texto alternativo http://img14.imageshack.us/img14/2874/selectionborder .png

El problema es que he tratado de determinar una StrokeLength que llegue lo más cerca a la StrokeLength original como sea posible y crea un número par de golpes. Sin embargo, el problema que he encontrado es que WPF (obviamente) no puede mostrar toda la precisión de un decimal StrokeLength doble y por lo tanto el número de carreras resultante no es uniforme una vez más.

¿Hay alguna solución para este problema? No es probable que tenga otra solución para mi problema?

Gracias de antemano!

EDIT: comprobarse de nuevo y revisado el código después de un pequeño descanso para la aptitud de hoy y después de todo lo que ocurre sólo en muy grandes StrokeLengths. Voy a utilizar StrokeLengths de 2 en el que el salto de la animación importa mucho menos de lo que se pensaba originalmente.

¿Fue útil?

Solución 2

Me acabo de una manera que hace que sea más fácil manera de crear un SelectionBorder tales animada.

En lugar de crear la animación moviendo un AnimationPoint auto-creada a través de la animación animado acabo la propiedad StrokeDashOffset forma nativa proporcionada por la clase Shape y ajuste de la StrokeDashArray para definir el StrokeLength.

Se vería así en XAML:

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

La clase es el siguiente:

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

Otros consejos

Se podría hacer más de una esquina "no coincide" en ese sentido. Por ejemplo, en lugar de tener un solo punto de ser la "fuente" y "destino" de los guiones de animación, usted podría escoger 2 puntos. Una de ellas sería la "fuente", apareciendo guiones para marchar lejos de él en 2 direcciones, y otro punto de ser el "destino", donde convergen guiones y desaparecen.

GIMP, por ejemplo, anima a la selección líneas discontinuas en este camino y parece que escoger un punto más cercano a la parte inferior izquierda de la "fuente" y un punto más cercano a la parte superior derecha para el "destino".

Se podría llegar a algún otro esquema, también.

Sólo recuerde que, aunque pueda parecer molesto para usted, la mayoría de los usuarios no se preocupan.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top