*C#(WPF)--矩阵拖动和矩阵动画(拖动展开,不足动画效果)
最近在研发新的项目,遇到了一个桌面模式下的难点--展开动画。之前动画这方面没做过,也许很多人开始做的时候也会遇到相关问题,因此我把几个重点及实际效果图总结展示出来:
我的开发环境是在VS2017下进行的,这个工具条主要功能是:一个工具条,可进行拖拉。可进行拖拉展开,可在拖动之后不足展开并反向继续展开剩下的部分;
一、【拖动】 拖动的核心代码是通过矩阵进行定位和拖动的,定位是以父容器为模板的。以下是核心代码(及效果图):
1 /// <summary> 2 /// 这里TitleBar代指最顶上的操作Bar 3 /// 桌面模式下默认展开工具栏-动画 4 /// </summary> 5 private void DesktopToolWindowClick() 6 { 7 8 9 //添加行为 10 var behaviors = System.Windows.Interactivity.Interaction.GetBehaviors(this); 11 behaviors.Clear(); 12 13 behaviors = System.Windows.Interactivity.Interaction.GetBehaviors(this); 14 behaviors.Clear(); 15 16 17 //添加拖拉事件 18 this._OnMouse = new MoveInContainerBehavior(MoveInContainerBehavior.MoveModes.Free, new Rect(0, 0, WindowsWidth, WindowsHeight)); 19 behaviors.Add(this._OnMouse); 20 } 21 22 /// <summary> 23 /// 加载用户控件的时候订阅事件 24 /// </summary> 25 private void _OnRegisterUserControl() 26 { 27 28 //订阅鼠标按下控件的事件; 29 _OnMouse.MouseLeftButtonDown += new MoveInContainerBehavior.MouseLeftButtonDownEventHandler(_OnMouseDownEvent); 30 //订阅鼠标拖动控件的事件; 31 _OnMouse.MouseMove += new MoveInContainerBehavior.MouseMoveEventHandler(_OnMouseMoveEvent); 32 //订阅鼠标释放控件的事件; 33 _OnMouse.MouseLeftButtonUp += new MoveInContainerBehavior.MouseLeftButtonUpEventHandler(_OnMouseReleseEvent); 34 35 } 36 37 /// <summary> 38 /// 用该事件控制弹窗位置 39 /// </summary> 40 /// <param name="sender"></param> 41 /// <param name="e"></param> 42 private void _ToolBar_Opened(object sender, EventArgs e) 43 { 44 //计算出控件移动的距离 45 var Windows_Lengh = _UserControl_XEnd + this.PopMenu.ActualWidth; 46 if (this._UserControl.ActualWidth + Windows_Lengh >= WindowsWidth) 47 { 48 this._ToolBar.Placement = System.Windows.Controls.Primitives.PlacementMode.Left; 49 this._ToolBar.HorizontalOffset = -5; 50 } 51 else 52 { 53 this._ToolBar.Placement = System.Windows.Controls.Primitives.PlacementMode.Right; 54 this._ToolBar.HorizontalOffset = 5; 55 } 56 }
二、【拖拉改变样式】 通过样式库调用可以在动画开始的时候就更换主题样式通过backup更改样式而不是UI直接改变,以下是核心代码(及效果图):
1 #region 更改样式为【展开时候的样式】 2 this._GridMain.Margin = new Thickness(0, -46, 0, 0); 3 this._GridRowsF.Height = new GridLength(47); 4 this.TitleBar.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4a94ff")); 5 this.TitleBar.Opacity = 1; 6 this.TitleBar.Margin = new Thickness(-7, -3, -7, 0); 7 this.Circle_Bar.Stroke = Brushes.White; 8 this.Circle_Bar.Margin = new Thickness(0, -3, 0, 0); 9 this._UserControl.Style = this.FindResource("Style.UserControl.PresentationMode.Desktop.Expand.UserControlStyles") as Style; 10 #endregion
三、【拖拉展开-边缘充足】 进行一个动画 那就是直接按照自定义的动画时间进行展开,以下是核心代码(及效果图)使用GridLengthAnimation动画类自行百度,下面是经过二次编译的类调用方法:
1 #region 尝试展开工具条--向下展开 2 GridLengthAnimation ExpandAnimate = new GridLengthAnimation(); 3 ExpandAnimate.From = new GridLength(0, GridUnitType.Pixel); 4 ExpandAnimate.To = new GridLength(_GridRowsSLength, GridUnitType.Pixel); 5 ExpandAnimate.Duration = TimeSpan.FromSeconds(0.3); 6 ExpandAnimate.AutoReverse = false; 7 this._GridMain.RowDefinitions[1].BeginAnimation(RowDefinition.HeightProperty, ExpandAnimate); 8 9 10 11 12 #endregion
四、【拖拉展开-边缘不足】 进行两个动画 1-先展开到边缘动画 2-再反弹反方向展开动画,以下是核心代码(及效果图):
1 #region 先往下展开,展开结束之后再启用往上增加动画 2 GridLengthAnimation ExpandAnimate = new GridLengthAnimation(); 3 ExpandAnimate.From = new GridLength(0, GridUnitType.Pixel); 4 ExpandAnimate.To = new GridLength(WindowsHeight - ParentPoint.Y - 68, GridUnitType.Pixel); 5 ExpandAnimate.Duration = TimeSpan.FromSeconds(0.15); 6 ExpandAnimate.AutoReverse = false; 7 ExpandAnimate.Completed += StartMatrixExpandAnimate_Completed; 8 this._GridMain.RowDefinitions[1].BeginAnimation(RowDefinition.HeightProperty, ExpandAnimate); 9 10 #endregion 11 12 /// <summary> 13 /// 当展开动画结束之后开始执行反向动画 14 /// </summary> 15 /// <param name="sender"></param> 16 /// <param name="e"></param> 17 private void StartMatrixExpandAnimate_Completed(object sender, EventArgs e) 18 { 19 //删除动画 20 this._GridMain.RowDefinitions[1].BeginAnimation(RowDefinition.HeightProperty, null); 21 22 #region 向上移动动画 23 // 1-向上移动 24 Storyboard storyboard = new Storyboard(); 25 storyboard.FillBehavior = FillBehavior.Stop; 26 MatrixTransform matrixTransformOfOwner = this.RenderTransform as MatrixTransform; 27 if (matrixTransformOfOwner == null) 28 { 29 matrixTransformOfOwner = new MatrixTransform(this.RenderTransform.Value); 30 this.RenderTransform = matrixTransformOfOwner; 31 } 32 this._oldTransform = this.RenderTransform; 33 Matrix matrixOfOwner = this.RenderTransform.Value; 34 Matrix fromMatrix = matrixOfOwner; 35 Matrix toMatrix = new Matrix(); 36 toMatrix.OffsetX = ParentPoint.X; 37 toMatrix.OffsetY = WindowsHeight - _GridRowsSLength - 68; 38 39 MatrixAnimation matrixAnimation = new MatrixAnimation(fromMatrix, toMatrix, TimeSpan.FromSeconds(0.3)); 40 matrixAnimation.Completed += (s, ex) => { UnlockProperty(toMatrix); }; 41 42 Storyboard.SetTarget(matrixAnimation, this); 43 Storyboard.SetTargetProperty(matrixAnimation, new PropertyPath("(UIElement.RenderTransform).(MatrixTransform.Matrix)")); 44 45 storyboard.Children.Add(matrixAnimation); 46 storyboard.Begin(); 47 48 #endregion 49 50 51 52 }
五、【拖拉展开-到达边缘时】进行一个动画 反弹反方向展开动画,类似【四】 直接上效果图就不贴代码了。
本文暂时不展示提供Demo下载,提供一个思路供大家参考。
工作的事情要做就要做到最好,做到极致,做到无人能及。