您的位置:首页 > 其它

详解WPF Blend工具中的复合路径功能 ( 含路径标记语法 )

2013-11-14 01:31 232 查看
写此文章的目的是为了简单分析一下Blend工具中提供的"复合路径"功能.有人在我的博文中留言问我复合路径的问题.



稍微琢磨一下,觉得应该是对的.因此贴出来和大家分享.有不对的说错的欢迎指正.

在此之前我们先了解一下WPF的"路径标记语法"

M:表示绘制起点//M0,0

L:表示绘制直线(H:横线V:竖线)//L100,0

C:三次方贝塞尔曲线//C100,200200,400300,200

Q:二次曲线

z:闭合

......

要注意的是每一次的绘制都是基于上一次的终点(或者原点M)

例如M0,0L100,0L200,50表示移动绘制原点到(0,0)然后绘制直线到(100,0)紧接着从(100,0)开始再绘制直线到(200,50),也就是说每一次绘制命令都是接着上一次开始的.

*手写语法命令的时候注意空格的使用,以及逗号的使用.

等等MSDN有详细介绍不了解的可以去看看.

大致了解路径标记语法后我们来探讨一下"复合路径"功能.

首先我们绘制两条线

(一)

<Canvas>
<PathData="M0,0L50,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>
<PathData="M100,0L250,120"Stretch="Fill"Stroke="green"StrokeThickness="5"/>
</Canvas>


看下效果



我们在看Blend->复合路径后的代码



<PathData="M2.5,2.5L52.5,122.5M2.5,2.5L152.5,122.5"Stretch="Fill"Stroke="red"StrokeThickness="5"/>


我们仔细观察复合前的2个Path.Data的语法和复合后的Path.Data的差别.

看看看看看看....嗯...IQ处理中......................

我们把前两个拼起来看看!

//拼前:
<PathData="M0,0L50,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>
<PathData="M100,0L250,120"Stretch="Fill"Stroke="green"StrokeThickness="5"/>

//拼后:

<PathData="M0,0L50,120M100,0L250,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>

//Blend复合的:

<PathData="M2.5,2.5L52.5,122.5M2.5,2.5L152.5,122.5"Stretch="Fill"Stroke="red"StrokeThickness="5"/>


看看后两个Path有什么一样的地方吗?!

是的Blend好像也是给拼接起来的?可是为什么有2.5的误差呢?为什么每个数都是2.5怎么不是0.1不是其他呢?奥秘就在这里:StrokeThickness="5"

2.5正好是5的一半嘛,是的,这个2.5只是算了粗细而已.我们可以去掉它也不会影响整体的形状的.

当我们把5改为1后(什么你说改成0??0像素好粗啊会闪下我氪金狗眼的!别闹~~~)

再使用复合路径得到的数据是M0.5,0.5L50.5,120.5M0.5,0.5L150.5,120.5,看看"误差"变为0.5了吧.如果你手动去掉所有的小数,那么你会看到形状不变的.这里我就不去演示了.

那么我们初步得到结论:复合路径=路径1+路径2+路径3+.....(拼接所有的路径部分).

(二)

下面我们再来看一组数据:

<PathData="M0,0L50,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>
<PathData="M100,0L300,120"Canvas.Left="50"Stretch="Fill"Stroke="red"StrokeThickness="5"/>


效果:



在看Blend复合后的代码:

<PathData="M2.5,2.5L52.5,122.5M52.5,2.5L252.5,122.5"Stretch="Fill"Stroke="red"StrokeThickness="5"/>


首先我们基于(一)的结论忽略掉粗细误差2.5(顺便验证一下这个结论)得到结果

<PathData="M0,0L50,120M50,0L250,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>


Blend中我们看到形状位置都没变.

接下来我们尝试手动拼接上面(二)的2个Path得到

<PathData="M0,0L50,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>
<PathData="M100,0L300,120"Canvas.Left="50"Stretch="Fill"Stroke="green"StrokeThickness="5"/>

手动拼接:

<PathData="M0,0L50,120M100,0L300,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>




这是为什么?怎么分离的这么远?

我们来解密一下:

看看第二条Path他有这个附加属性Canvas.Left="50"居然给右移了50!!!!那么我们给他挪回去试试?

得到

<PathData="M0,0L50,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>
<PathData="M100,0L300,120"Canvas.Left="50"Stretch="Fill"Stroke="green"StrokeThickness="5"/>

手动拼接:

<PathData="M0,0L50,120M100,0L300,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>


把第二个Path的Left50左移回去得到:<PathData="M0,0L50,120M50,0L250,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>


左移后<PathData="M0,0L50,120M50,0L250,120"Stretch="Fill"Stroke="red"StrokeThickness="5"/>效果:



是不是一样了!左移第二条线是移动原点M和L的横坐标所以得到M50,0L250,120"
(被左移-X需要减掉相应值.被右移-X需要加上相应值)
上下移同理,上移(Top负数)需加,下移(Top正数)需减
这个过程我们暂且称为"复位"
因此我们又得到一个结论Canvas.Left同样会影响复合路径!当然这里也包括Canvas.Top/Right/Bottom,
值得提醒的是当Left/Top等的值为负数时直接简单拼接和"复位"是不对的.因为你可能复不到位.不信你试试看.

这里稍微解释一下标记语法一个特别的地方(我猜的!没有去MSDN考证.)
<PathData="M100,0L300,120"Stretch="Fill"Stroke="green"StrokeThickness="5"/>
<PathData="M0,0L200,120"Stretch="Fill"Stroke="green"StrokeThickness="5"/>
<PathData="M-100,0L100,120"Stretch="Fill"Stroke="green"StrokeThickness="5"/>
这3个Path是一样的!
当Path中只有一段图形时(这里是只有一段Line),Line整体平移(指的是原点从0,0平移到100,0且端点从200,120平移到300,120)是不会影响Path形状和位置的.
因此在只有一段图形的Path中我们可以约掉这个平移我们暂且称为"约分"(参考数学分数的约分哈,不严谨好记而已~~)

所以上面我说当Canvas.Left为负数时不能简单直接拼接和复位.怎么办呢?我们需要先约分!先把所有能约分的线段的原点约分到不能再约分的实际原点,
例如上面的三个Path的实际原点其实都是M0,0.约分处理完所有图形片段后再进行拼接和复位.最后就能得到复合路径的结果了.

另外,凡是所有能影响Path位置的属性改变都会影响复合路径的结果,比如RenderTransform和Margin等.

如果想手动去算复合路径可能是非常繁琐的一个过程~~~您可能需要为所有影响Path位置变化的属性改变都写一个复位的方法.在执行复合路径之前需要先调用所有的复位/约分方法来恢复Path的Data到实际值.再进行拼接计算.

以上是我粗略分析后的一些看法和结论.我之前也不知道这些的,只不过是在我的一片自定义MessageBox的文章中有人问我这个问题,我就试着猜猜.
这位童鞋@距离永远您可请俺喝酒啊!!嘻嘻~~

如果哪位童鞋有在code中动态计算路径的需求,不妨参考一下此文.
在下拙见,若有达人,不吝赐教!

/*******************************************************/

欢迎转载!欢迎拍砖!

版权所有©Vito野子

E-mail:vito2015@live.com

转载请注明出处/article/7001340.html

/*******************************************************/


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: