WPF路径动画(动态逆向动画)
生活随笔
收集整理的這篇文章主要介紹了
WPF路径动画(动态逆向动画)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
WPF 中的Path.Data 不再多介紹,M開始坐標點 C弧度坐標點 L 直線坐標點
<Path x:Name="path0" Data="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100" Height="135.32" Stretch="Uniform" Stroke="#FF61E70A" StrokeThickness="2" HorizontalAlignment="Center" VerticalAlignment="Center" />?
<Path x:Name="path0" Data="M95,50 L324.67997,50 324.67997,119.67997 234.67998,119.67997 234.67998,184.68002 344.67999,184.68002 394.68,134.67999 C394.68,134.67999 394.68,189.68005 394.68,129.68002 394.68,69.679984 434.68002,89.679985 434.68002,89.679985L477.18005,132.18003 477.18005,164.68004 419.68006,164.6800" Height="135.32" Stretch="Uniform" Stroke="#FF61E70A" StrokeThickness="2" HorizontalAlignment="Center" VerticalAlignment="Center" />個人寫了關于Path.Data數據反向,意思就是把Path的數據逆轉,但是圖形是沒有變化的
Xaml代碼如下:
<Window x:Class="WPFPathReverse.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WPFPathReverse"mc:Ignorable="d"Title="MainWindow" Height="600" Width="500"><Grid><Grid.RowDefinitions><RowDefinition Height="50"></RowDefinition><RowDefinition></RowDefinition><RowDefinition></RowDefinition></Grid.RowDefinitions><StackPanel Orientation="Horizontal"><Button Content="正向動畫" Width="80" Margin="5" Click="btnPositive_Click"></Button><Button Content="反向動畫" Width="80" Margin="5" Click="btnRevPositive_Click"></Button></StackPanel><Canvas Grid.Row="1" ><Path x:Name="path0" Data="M1,1 L230.67997,1 230.67997,70.67997 140.67998,70.67997 140.67998,135.68002 300.68,85.67999 C300.68,85.67999 300.68,140.68005 300.68,80.68002 300.68,20.679984 340.68002,40.679985 340.68002,40.679985 L383.18005,83.18003 383.18005,115.68004 325.68006,115.68" Height="136.68" Stretch="None" Stroke="#FF61E70A" StrokeThickness="2" Width="384.18" /></Canvas><Canvas x:Name="canvas" Grid.Row="2"></Canvas></Grid> </Window> View CodeCode代碼如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes;namespace WPFPathReverse {/// <summary>/// MainWindow.xaml 的交互邏輯/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();this.Loaded += MainWindow_Loaded;}private void MainWindow_Loaded(object sender, RoutedEventArgs e){string data = this.path0.Data.ToString();var result = ConvertReverseData(data);Path newpath = new Path();newpath.Data = PathGeometry.CreateFromGeometry(Geometry.Parse(result));newpath.HorizontalAlignment = HorizontalAlignment.Center;newpath.VerticalAlignment = VerticalAlignment.Center;newpath.Stretch = this.path0.Stretch;newpath.Stroke = new SolidColorBrush(Colors.Red);newpath.StrokeThickness = 2;newpath.Width = this.path0.Width;newpath.Height = this.path0.Height;canvas.Children.Add(newpath);}/// <summary>/// 反向Data數據/// </summary>/// <param name="data"></param>/// <returns></returns>string ConvertReverseData(string data){data = data.Replace("M", "").Replace(" ", "/");Regex regex = new Regex("[a-z]", RegexOptions.IgnoreCase);MatchCollection mc = regex.Matches(data);//item1 從上一個位置到當前位置開始的字符 (match.Index=原始字符串中發現捕獲的子字符串的第一個字符的位置。)//item2 當前發現的匹配符號(L C Z M)List<Tuple<string, string>> tmpList = new List<Tuple<string, string>>();int curPostion = 0;for (int i = 0; i < mc.Count; i++){Match match = mc[i];if (match.Index != curPostion){string str = data.Substring(curPostion, match.Index - curPostion);tmpList.Add(new Tuple<string, string>(str, match.Value));}curPostion = match.Index + match.Length;if (i + 1 == mc.Count)//last {tmpList.Add(new Tuple<string, string>(data.Substring(curPostion), match.Value));}}//char[] spChar = new char[2] { 'C', 'L' };//var tmpList = data.Split(spChar);List<string[]> spList = new List<string[]>();for (int i = 0; i < tmpList.Count; i++){var cList = tmpList[i].Item1.Split('/');spList.Add(cList);}List<string> strList = new List<string>();for (int i = spList.Count - 1; i >= 0; i--){string[] clist = spList[i];for (int j = clist.Length - 1; j >= 0; j--){if (j == clist.Length - 2)//對于第二個元素增加 L或者C的標識 {var pointWord = tmpList[i - 1].Item2;//獲取標識strList.Add(pointWord + clist[j]);}else{strList.Add(clist[j]);}}}string reverseData = "M" + string.Join(" ", strList);return reverseData;}private void btnPositive_Click(object sender, RoutedEventArgs e){MatrixStory(0, this.path0.Data.ToString());}private void btnRevPositive_Click(object sender, RoutedEventArgs e){string data = this.path0.Data.ToString();var result = ConvertReverseData(data);MatrixStory(1, result);}/// <summary>/// /// </summary>/// <param name="orientation">0正向 1反向</param>/// <param name="data">路徑數據</param>private void MatrixStory(int orientation, string data){Border border = new Border();border.Width = 10;border.Height = 10;border.Visibility = Visibility.Collapsed;if (orientation==0){border.Background = new SolidColorBrush(Colors.Blue);}else{border.Background = new SolidColorBrush(Colors.Green);}this.canvas.Children.Add(border);Canvas.SetLeft(border, -border.Width / 2);Canvas.SetTop(border, -border.Height / 2);border.RenderTransformOrigin = new Point(0.5, 0.5);MatrixTransform matrix = new MatrixTransform();TransformGroup groups = new TransformGroup();groups.Children.Add(matrix);border.RenderTransform = groups;//NameScope.SetNameScope(this, new NameScope());string registname = "matrix" + Guid.NewGuid().ToString().Replace("-", "");this.RegisterName(registname, matrix);MatrixAnimationUsingPath matrixAnimation = new MatrixAnimationUsingPath();matrixAnimation.PathGeometry = PathGeometry.CreateFromGeometry(Geometry.Parse(data));matrixAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));matrixAnimation.DoesRotateWithTangent = true;//旋轉//matrixAnimation.FillBehavior = FillBehavior.Stop;Storyboard story = new Storyboard();story.Children.Add(matrixAnimation);Storyboard.SetTargetName(matrixAnimation, registname);Storyboard.SetTargetProperty(matrixAnimation, new PropertyPath(MatrixTransform.MatrixProperty));#region 控制顯示與隱藏ObjectAnimationUsingKeyFrames ObjectAnimation = new ObjectAnimationUsingKeyFrames();ObjectAnimation.Duration = matrixAnimation.Duration;DiscreteObjectKeyFrame kf1 = new DiscreteObjectKeyFrame(Visibility.Visible, TimeSpan.FromMilliseconds(1));ObjectAnimation.KeyFrames.Add(kf1);story.Children.Add(ObjectAnimation);//Storyboard.SetTargetName(border, border.Name);Storyboard.SetTargetProperty(ObjectAnimation, new PropertyPath(UIElement.VisibilityProperty));#endregionstory.FillBehavior = FillBehavior.Stop;story.Begin(border, true);}} } View Code執行效果如下:
?
寫這個Path反轉的目的是動態生成動畫的時候,可以逆向執行動畫,而不必為逆向動畫重新畫一個Path.
上面代碼中反轉Path有bug(各種不同的Path數據格式,下面是修復后的代碼)
?
string ConvertReverseData(string data){data = data.Replace("M", "");Regex regex = new Regex("[a-z]", RegexOptions.IgnoreCase);MatchCollection mc = regex.Matches(data);//item1 從上一個位置到當前位置開始的字符 (match.Index=原始字符串中發現捕獲的子字符串的第一個字符的位置。)//item2 當前發現的匹配符號(L C Z M)List<Tuple<string, string>> tmpList = new List<Tuple<string, string>>();int curPostion = 0;for (int i = 0; i < mc.Count; i++){Match match = mc[i];if (match.Index != curPostion){string str = data.Substring(curPostion, match.Index - curPostion);tmpList.Add(new Tuple<string, string>(str, match.Value));}curPostion = match.Index + match.Length;if (i + 1 == mc.Count)//last {tmpList.Add(new Tuple<string, string>(data.Substring(curPostion), match.Value));}}List<string[]> spList = new List<string[]>();Regex regexnum = new Regex(@"(\-?\d+\.?\d*)", RegexOptions.IgnoreCase);for (int i = 0; i < tmpList.Count; i++){//處理坐標數據 ex M 96 288 C 576 0, 0 0, 480 288//ex M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100//ex M95,50 L324.67997,50 324.67997,119.67997 234.67998,119.67997 234.67998,184.68002 //344.67999,184.68002 394.68,134.67999 C394.68,134.67999 394.68,189.68005//394.68,129.68002 394.68,69.679984 434.68002,89.679985 434.68002,89.679985// L477.18005,132.18003 477.18005,164.68004 419.68006,164.6800MatchCollection childMcs = regexnum.Matches(tmpList[i].Item1);if (childMcs.Count % 2 != 0){//分組數據有問題continue;}int groups = childMcs.Count / 2;var strTmp = new string[groups];for (int j = 0; j < groups; j++){string cdatas = childMcs[j * 2] + "," + childMcs[j * 2 + 1];//重組數據strTmp[j] = cdatas;}spList.Add(strTmp);}#region 逆向數據List<string> strList = new List<string>();for (int i = spList.Count - 1; i >= 0; i--){string[] clist = spList[i];for (int j = clist.Length - 1; j >= 0; j--){if (j == clist.Length - 2 && i > 0)//對于第二個元素增加 L或者C的標識 {var pointWord = tmpList[i - 1].Item2;//獲取標識strList.Add(pointWord + clist[j]);}else{strList.Add(clist[j]);//M10,50 L44.679973,69.679973 C43.627604,76.057983 43.410881,76.928271 41.082803,81.687898if (clist.Length == 1 && i > 0)//說明只有一個元素 ex L44.679973,69.679973 {strList.Add(tmpList[i - 1].Item2);}}}}string reverseData = "M" + string.Join(" ", strList);#endregionreturn reverseData;} View Code?
如果大家在使用過程中還有發現算法bug,請在下方評論并把data貼出來。粘貼格式如下:
<Path x:Name="path0" Data="M 96 288 C 576 0, 0 0, 480 288" Stretch="None" Stroke="#FF61E70A" StrokeThickness="2" />?
?源代碼下載
轉載于:https://www.cnblogs.com/ligl/p/5665306.html
總結
以上是生活随笔為你收集整理的WPF路径动画(动态逆向动画)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shiro的简单使用
- 下一篇: mvn本地生成jar包放在mvn项目依赖