Pergunta

Atualmente, estou implementando uma classe chamada SelectionBorder em WPF. É derivada da classe Shape.

Ele basicamente se parece com isso:

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

}

O StartPoint e propriedades Pontos determinar os cantos da fronteira. A fronteira é uma fronteira típico linha afagado (um traço preto, um golpe invisível assim: - - - -)

O problema que tenho agora é que uma vez que os pontos de canto são livremente choosable é muito comum que a contagem de acidentes vasculares cerebrais (ou seja, cursos pretos e invisíveis) não é mesmo (na verdade nem mesmo um inteiro) e, portanto, os primeiros olhares AVC mais do que os outros (visível na foto). Esta talvez não parece ser um grande negócio, mas mais tarde eu quero animar a fronteira para que os cursos círculo em volta do conteúdo. Ao fazer esta animação a pequena falha na visão estática torna-se claramente visível e na minha opinião é altamente perturbador.

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

O problema é que eu tentei determinar um StrokeLength que fica tão perto do StrokeLength original possível e cria um número par de acidentes vasculares cerebrais. No entanto, o problema que eu tenho que correr para é que WPF (obviamente) não pode exibir toda a precisão de um StrokeLength dupla decimal e, portanto, o número derrame resultante é desigual, mais uma vez.

Existe alguma solução para este problema? Você provavelmente tem outra solução para o meu problema?

Agradecemos antecipadamente!

EDIT: Eu reanalisada e revisto o código depois de uma pequena pausa para fitness hoje e depois de tudo isso acontece apenas em muito grandes StrokeLengths. Eu pretendo usar StrokeLengths de 2 onde a pequena animação salto importa muito menos do que eu pensava inicialmente.

Foi útil?

Solução 2

Eu só encontrei uma maneira que faz a maneira mais fácil de criar uma tal SelectionBorder animado.

Em vez de criar a animação movendo uma AnimationPoint auto-criado através da animação Eu só animou a propriedade StrokeDashOffset nativamente fornecido pela classe Forma e definindo o StrokeDashArray para definir o StrokeLength.

Ele ficaria assim em XAML:

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

Os olhares classe como este:

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

Outras dicas

Você poderia fazer mais do que um canto "un-acompanhado" a esse respeito. Por exemplo, em vez de ter um ponto de ser a "fonte" e "destino" dos traços de animação, você poderia pegar 2 pontos. Uma delas seria a "fonte", traços que aparecem a marchar para longe dele, em 2 sentidos, e outro ponto ser o "destino", onde traços convergem e desaparecer.

GIMP, por exemplo, anima linhas de seleção frustradas desta forma e parece escolher um ponto mais próximo do canto inferior esquerdo para a "fonte" e um ponto mais próximo do canto superior direito para o "destino".

Você poderia chegar a algum outro esquema, também.

Basta lembrar que, embora possa parecer perturbador para você, a maioria dos usuários não vai se importar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top