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="" 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.,134.67999 394.68,189.68005
394.68,129.68002 394.68,69.679984 434.68002,89.679985 434.68002,89.679985
L477.,132.18003 477.18005,164.68004 419.68006,164.6800" Height="135.32"
Stretch="Uniform" Stroke="#FF61E70A" StrokeThickness="" 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="" Width="">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=""></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="正向动画" Width="" Margin="" Click="btnPositive_Click"></Button>
<Button Content="反向动画" Width="" Margin="" Click="btnRevPositive_Click"></Button>
</StackPanel>
<Canvas Grid.Row="" >
<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="" Width="384.18" />
</Canvas> <Canvas x:Name="canvas" Grid.Row=""></Canvas>
</Grid>
</Window>

Code代码如下

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 = ;
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 = ;
for (int i = ; 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 + == 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 = ; i < tmpList.Count; i++)
{
var cList = tmpList[i].Item1.Split('/');
spList.Add(cList);
}
List<string> strList = new List<string>();
for (int i = spList.Count - ; i >= ; i--)
{
string[] clist = spList[i];
for (int j = clist.Length - ; j >= ; j--)
{
if (j == clist.Length - )//对于第二个元素增加 L或者C的标识
{
var pointWord = tmpList[i - ].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(, this.path0.Data.ToString());
} private void btnRevPositive_Click(object sender, RoutedEventArgs e)
{
string data = this.path0.Data.ToString();
var result = ConvertReverseData(data);
MatrixStory(, 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 = ;
border.Height = ;
border.Visibility = Visibility.Collapsed;
if (orientation==)
{
border.Background = new SolidColorBrush(Colors.Blue);
}
else
{
border.Background = new SolidColorBrush(Colors.Green);
} this.canvas.Children.Add(border);
Canvas.SetLeft(border, -border.Width / );
Canvas.SetTop(border, -border.Height / );
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());
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());
ObjectAnimation.KeyFrames.Add(kf1);
story.Children.Add(ObjectAnimation);
//Storyboard.SetTargetName(border, border.Name);
Storyboard.SetTargetProperty(ObjectAnimation, new PropertyPath(UIElement.VisibilityProperty));
#endregion
story.FillBehavior = FillBehavior.Stop;
story.Begin(border, true);
}
}
}

执行效果如下:

写这个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 = ;
for (int i = ; 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 + == 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 = ; 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.6800
MatchCollection childMcs = regexnum.Matches(tmpList[i].Item1);
if (childMcs.Count % != )
{
//分组数据有问题
continue;
}
int groups = childMcs.Count / ;
var strTmp = new string[groups];
for (int j = ; j < groups; j++)
{
string cdatas = childMcs[j * ] + "," + childMcs[j * + ];//重组数据
strTmp[j] = cdatas;
}
spList.Add(strTmp);
} #region 逆向数据
List<string> strList = new List<string>();
for (int i = spList.Count - ; i >= ; i--)
{
string[] clist = spList[i];
for (int j = clist.Length - ; j >= ; j--)
{
if (j == clist.Length - && i > )//对于第二个元素增加 L或者C的标识
{
var pointWord = tmpList[i - ].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.687898
if (clist.Length == && i > )//说明只有一个元素 ex L44.679973,69.679973
{
strList.Add(tmpList[i - ].Item2);
}
}
}
}
string reverseData = "M" + string.Join(" ", strList);
#endregion return reverseData; }

如果大家在使用过程中还有发现算法bug,请在下方评论并把data贴出来。粘贴格式如下:

<Path x:Name="path0" Data="M 96 288 C 576 0, 0 0, 480 288"
Stretch="None" Stroke="#FF61E70A" StrokeThickness="" />

源代码下载

WPF路径动画(动态逆向动画)的更多相关文章

  1. WPF学习之绘图和动画

    如今的软件市场,竞争已经进入白热化阶段,功能强.运算快.界面友好.Bug少.价格低都已经成为了必备条件.这还不算完,随着计算机的多媒体功能越来越强,软件的界面是否色彩亮丽.是否能通过动画.3D等效果是 ...

  2. WPF学习之绘图和动画--DarrenF

    Blend作为专门的设计工具让WPF如虎添翼,即能够帮助不了解编程的设计师快速上手,又能够帮助资深开发者快速建立图形或者动画的原型. 1.1   WPF绘图 与传统的.net开发使用GDI+进行绘图不 ...

  3. WPF学习(12)动画

    本篇来学习WPF的动画.什么是动画?动画就是一系列帧.在WPF中,动画就是在一段时间内修改依赖属性值的行为,它是基于时间线Timeline的.有人会说,要动画干嘛,华而不实,而且添加了额外的资源消耗而 ...

  4. 《深入浅出WPF》笔记——绘画与动画

    <深入浅出WPF>笔记——绘画与动画   本篇将记录一下如何在WPF中绘画和设计动画,这方面一直都不是VS的强项,然而它有一套利器Blend:这方面也不是我的优势,幸好我有博客园,能记录一 ...

  5. WPF:完美自定义MeaagseBox 动画 反弹 背景模糊 扁平化

    不知道为什么,WPF的MeaageBox的风格还停留在Win 2000的风格... 很久前就想自己封装一个MessageBox出来,但是都只是简单的封装,不怎么具有通用性.这次终于搞完了. 使用方法和 ...

  6. WPF圆形环绕的Loading动画

    原文:WPF圆形环绕的Loading动画 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/yangyisen0713/article/details/ ...

  7. WPF编游戏系列 之七 动画效果(2)

    原文:WPF编游戏系列 之七 动画效果(2)        上一篇已经对关闭窗口图标进行了动画效果处理,本篇将对窗口界面的显示和关闭效果进行处理.由于所有的动画效果都是针对窗口界面的Canvas,所以 ...

  8. WPF编游戏系列 之六 动画效果(1)

    原文:WPF编游戏系列 之六 动画效果(1)        本篇主要针对界面进行动画效果处理.首先在打开或关闭界面时,使其产生动态效果而不是生硬的显示或消失(如下图).其次在鼠标放到关闭窗口图标上时, ...

  9. [WPF] 玩玩彩虹文字及动画

    1. 前言 兴致来了玩玩 WPF 的彩虹文字.不是用 LinearGradientBrush 制作渐变色那种,是指每个文字独立颜色那种彩虹文字.虽然没什么实用价值,但希望这篇文章里用 ItemsCon ...

随机推荐

  1. mysql源码解读之事务提交过程(一)

    mysql是一种关系型数据库,关系型数据库一个重要的特性就是支持事务,这是区别于no-sql产品的一个核心特性.当然了,no-sql产品支持键值查询,不能支持sql语句,这也是一个区别.今天主要讨论下 ...

  2. Java api 入门教程 之 JAVA的StringBuffer类

    StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存 ...

  3. iOS 懒加载不起作用的原因

    在.m类中定义了一共strong属性,用懒加载getter方式去处理,发现用的时候无论如何属性都是null,调试后,发现根本没进getter方法. (ps:懒加载,又称为延迟加载.说的通俗一点,就是在 ...

  4. shell脚本切割tomcat的日志文件

    鉴于在调试logback和log4j的文件切割一直无法成功,随性用shell写个脚本用来切割tomcat下的日志文件(大家如果有在logback或log4j使用文件切割成功的话,可以留下使用方式,先谢 ...

  5. 10、WGET

    这个我看过比较好的  http://www.cnblogs.com/peida/archive/2013/03/18/2965369.html WGET 支持HTTP和FTP协议,断点续传功能,自动递 ...

  6. Windows Azure 虚拟机的IP地址操作

    Windows Azure上的一个虚拟机对应两个IP地址,VIP和DIP. VIP,公网IPv4地址,动态分配.虚拟机停止(deallocate,在管理控制台上关机或者使用PowerShell关机)后 ...

  7. C#基础----Linq之List<T>篇

    最近有用到List处理排序以及分页的问题.想想还是写一个博客记录一下.以下围绕Person类实现,Person类只有Name和Age两个属性   一.List<T>排序 1.1 List& ...

  8. C#基础---委托的使用

    一:什么是委托     委托是一种定义方法签名的类型当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法.委托是一个引用类型,所以它具有引用类型所具有的通性.它保存 ...

  9. 遇到一位ITer,一位出租车司机,必看。

    百木-ITer职业交流 群-北京 :141588103 今天去用户那,一个政府的事业单位.       遇到一位ITer,B同学,一个行业的,和他们公司既是合作关系,又是竞争关系.最近我们接了该单位的 ...

  10. Caffe CNN特征可视化

    转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/ 以下部分代码是根据caffe的python接口,从一次forwo ...