我目前正在用WPF实现一个名为SelectionBorder的类。它是从Shape类派生的。
它基本上看起来像这样:
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!
}
}
}StartPoint和Points属性确定边框的角点。边框是典型的描边线条边框(一个黑色的描边,一个看不见的描边:-- -)
我现在的问题是,由于角点是可自由选择的,因此笔画(即黑色和不可见的笔画)的计数不是偶数(实际上甚至不是整数)是很常见的,因此第一个笔画看起来比其他笔画(在图片中可见)要长。这可能看起来不是什么大问题,但我稍后想要使边框具有动画效果,以便笔画环绕内容。当做这个动画时,静态视图中的小缺陷变得清晰可见,在我看来,这是非常令人不安的。
alt text http://img14.imageshack.us/img14/2874/selectionborder.png
问题是,我试图确定一个尽可能接近原始StrokeLength的StrokeLength,并创建偶数个笔画。然而,我遇到的问题是,WPF (显然)不能显示双十进制StrokeLength的整个精度,因此结果笔画数再次不均匀。
是否有解决此问题的方法?你有没有别的办法来解决我的问题?
提前感谢!
编辑:今天,为了适应,我重新测试和审查了代码,毕竟这只发生在非常大的StrokeLengths上。我计划使用StrokeLengths of 2,其中的小动画跳跃比我最初想象的要小得多。
发布于 2009-08-24 10:55:23
我刚刚找到了一种方法,可以让创建这样一个动画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;
}
}
}发布于 2009-08-19 17:15:38
在这一点上,你可能会使不止一个角落“不匹配”。例如,您可以选择2个点,而不是将一个点作为动画虚线的“源”和“目标”。一个是“源”,破折号似乎在两个方向上远离它,另一个点是“目的地”,破折号在那里汇聚和消失。
例如,GIMP以这种方式对选择虚线进行动画处理,并且似乎为“源”选择了最靠近左下角的点,为“目标”选择了最接近右上角的点。
你也可以想出一些其他的方案。
只需记住,虽然它看起来可能会让你感到困扰,但大多数用户并不会在意。
https://stackoverflow.com/questions/1299706
复制相似问题