实现效果:
思路:封装一个自定义控件,添加NormalImage和HoverImage两个依赖属性,该控件可以识别鼠标从左、上、右、下哪条边进入进出,并根据方向设置出入动作。
步骤:
1、自定义控件MyImageButtom的封装
MyImageButtom.xaml
MyImageButtom.cs
public partial class MyImageButtom : UserControl
{
#region Property
public static DependencyProperty NormalImageProperty = DependencyProperty.Register("NormalImage", typeof(ImageSource), typeof(MyImageButtom), new PropertyMetadata(null));
public ImageSource NormalImage
{
get { return (ImageSource)GetValue(NormalImageProperty); }
set { SetValue(NormalImageProperty, value); }
}
public static readonly DependencyProperty HoverImageProperty = DependencyProperty.Register("HoverImage", typeof(ImageSource), typeof(MyImageButtom), new PropertyMetadata(null));
public ImageSource HoverImage
{
get { return (ImageSource)GetValue(HoverImageProperty); }
set { SetValue(HoverImageProperty, value); }
}
#endregion
private Rect LRect, TRect, RRect, BRect, DLRect, DTRect, DRRect, DBRect;//左、上、右、下四条边的矩形,用于判断进入进出图像
private bool IsCanMove;//是否移动
private Storyboard storyboard = new Storyboard();
DependencyProperty[] propertyChain;//动作设置属性
public MyImageButtom()
{
InitializeComponent();
}
///
/// 窗体加载
///
private void MyUserControl_Loaded(object sender, RoutedEventArgs e)
{
this.imgHover.RenderTransform = new RotateTransform();
propertyChain = new DependencyProperty[]
{
Image.RenderTransformProperty,
RotateTransform.AngleProperty
};
GetLTRBRect();
this.MouseEnter += MyImageButtom_MouseEnter;
this.MouseMove += MyImageButtom_MouseMove;
this.MouseLeave += MyImageButtom_MouseLeave;
}
///
/// 鼠标进入
///
private void MyImageButtom_MouseEnter(object sender, MouseEventArgs e)
{
IsCanMove = true;
}
///
/// 鼠标移动,判断从哪个方向进入
///
private void MyImageButtom_MouseMove(object sender, MouseEventArgs e)
{
if (!IsCanMove) return;
EntryDirection direction = EntryDirection.None;
Point tempEndPoint = e.GetPosition(this);
if (IsInRect(tempEndPoint.X, tempEndPoint.Y, LRect))
direction = EntryDirection.Left;
else if (IsInRect(tempEndPoint.X, tempEndPoint.Y, TRect))
direction = EntryDirection.Top;
else if (IsInRect(tempEndPoint.X, tempEndPoint.Y, RRect))
direction = EntryDirection.Right;
else if (IsInRect(tempEndPoint.X, tempEndPoint.Y, BRect))
direction = EntryDirection.Bottom;
AppearAnimate(direction);
IsCanMove = false;
}
///
/// 鼠标离开,判断从哪个方向离开
///
private void MyImageButtom_MouseLeave(object sender, MouseEventArgs e)
{
EntryDirection direction = EntryDirection.None;
Point tempEndPoint = e.GetPosition(this);
if (IsInRect(tempEndPoint.X, tempEndPoint.Y, DLRect))
direction = EntryDirection.Left;
else if (IsInRect(tempEndPoint.X, tempEndPoint.Y, DTRect))
direction = EntryDirection.Top;
else if (IsInRect(tempEndPoint.X, tempEndPoint.Y, DRRect))
direction = EntryDirection.Right;
else if (IsInRect(tempEndPoint.X, tempEndPoint.Y, DBRect))
direction = EntryDirection.Bottom;
DisappearAnimate(direction);
}
///
/// 获得4条边的矩形
///
public void GetLTRBRect()
{
int localArea = 10;
LRect = new Rect(0, 0, localArea, this.ActualHeight);
TRect = new Rect(0, 0, this.ActualWidth, localArea);
RRect = new Rect(this.ActualWidth - localArea, 0, localArea, this.ActualHeight);
BRect = new Rect(0, this.ActualHeight - localArea, this.ActualWidth, localArea);
DLRect = new Rect(-localArea, 0, localArea, this.ActualHeight);
DTRect = new Rect(0, -localArea, this.ActualWidth, localArea);
DRRect = new Rect(this.ActualWidth, 0, localArea, this.ActualHeight);
DBRect = new Rect(0, this.ActualHeight, this.ActualWidth, localArea);
}
///
/// 指定的坐标是否在矩形里
///
public bool IsInRect(double x, double y, Rect rect)
{
return x >= rect.X && x <= rect.X + rect.Width && y >= rect.Y && y <= rect.Y + rect.Height;
}
///
/// 鼠标进入出现动图
///
private void AppearAnimate(EntryDirection direction)
{
storyboard.Children.Clear();
DoubleAnimation RotateTransformAnimation;
switch (direction)
{
case EntryDirection.Left:
this.imgHover.RenderTransformOrigin = new Point(0, 1);
RotateTransformAnimation = new DoubleAnimation(-90, 0, new Duration(TimeSpan.FromMilliseconds(500)));
break;
case EntryDirection.Top:
this.imgHover.RenderTransformOrigin = new Point(0, 0);
RotateTransformAnimation = new DoubleAnimation(-90, 0, new Duration(TimeSpan.FromMilliseconds(500)));
break;
case EntryDirection.Right:
this.imgHover.RenderTransformOrigin = new Point(1, 1);
RotateTransformAnimation = new DoubleAnimation(90, 0, new Duration(TimeSpan.FromMilliseconds(500)));
break;
case EntryDirection.Bottom:
this.imgHover.RenderTransformOrigin = new Point(0, 1);
RotateTransformAnimation = new DoubleAnimation(90, 0, new Duration(TimeSpan.FromMilliseconds(500)));
break;
default:
return;
}
Storyboard.SetTarget(RotateTransformAnimation, this.imgHover);
Storyboard.SetTargetProperty(RotateTransformAnimation, new PropertyPath("(0).(1)", propertyChain));
storyboard.Children.Add(RotateTransformAnimation);
storyboard.Begin();
Canvas.SetZIndex(this.imgHover, 0);
}
///
/// 鼠标移出消失动图
///
private void DisappearAnimate(EntryDirection direction)
{
storyboard.Children.Clear();
DoubleAnimation RotateTransformAnimation;
switch (direction)
{
case EntryDirection.Left:
this.imgHover.RenderTransformOrigin = new Point(0, 1);
RotateTransformAnimation = new DoubleAnimation(0, -90, new Duration(TimeSpan.FromMilliseconds(500)));
break;
case EntryDirection.Top:
this.imgHover.RenderTransformOrigin = new Point(0, 0);
RotateTransformAnimation = new DoubleAnimation(0, -90, new Duration(TimeSpan.FromMilliseconds(500)));
break;
case EntryDirection.Right:
this.imgHover.RenderTransformOrigin = new Point(1, 1);
RotateTransformAnimation = new DoubleAnimation(0, 90, new Duration(TimeSpan.FromMilliseconds(500)));
break;
case EntryDirection.Bottom:
this.imgHover.RenderTransformOrigin = new Point(0, 1);
RotateTransformAnimation = new DoubleAnimation(0, 90, new Duration(TimeSpan.FromMilliseconds(500)));
break;
default:
return;
}
Storyboard.SetTarget(RotateTransformAnimation, this.imgHover);
Storyboard.SetTargetProperty(RotateTransformAnimation, new PropertyPath("(0).(1)", propertyChain));
storyboard.Children.Add(RotateTransformAnimation);
storyboard.Begin();
Canvas.SetZIndex(this.imgHover, 0);
}
///
/// 进入离开方向枚举
///
public enum EntryDirection
{
None,
Left,
Top,
Right,
Bottom
}
}
2、主窗体调用