WPF水珠效果按钮组的实现教程

这部分基本就是废话,网上都能找到,我只不过是整理了以下.建议先不看,用到的时候可以回来看看

贝塞尔曲线

先来看两组图,有助于理解什么是贝塞尔曲线(图片取自维基百科,参考链接1)

二次贝塞尔曲线:

WPF水珠效果按钮组的实现教程

WPF水珠效果按钮组的实现教程

P0是起点,P2是终点,P1是控制点

三次贝塞尔曲线:

WPF水珠效果按钮组的实现教程

WPF水珠效果按钮组的实现教程

P0是起点,P2是终点,P1是控制点1,P2是控制点2

依次连接所有点,组成线段

t是比例,在0-1之间,就是每条线段的长度都是1

贝塞尔曲线就是最里层的线段在t位置的点所组成的路径

三次贝塞尔曲线公式:B(t)=(1-t)^3*P0+3(1-t)^2*t*P1+3(1-t)*t^2*P2+t^3*P3,0<=t<=1

B(t)代表曲线上任意点,P0,1,2,3分别代表决定曲线的4个点,t代表曲线长度为1的任意取值

其他知识

没接触过贝塞尔曲线的话,可能得花些时间整理下,其他的知识就比较简单了

WPF水珠效果按钮组的实现教程

直角三角形,角A的对边a,临边b,斜边c

三角函数:

sinA=a/c

cosA=b/c

勾股定理:

c^2=a^2+b^2

概括介绍

这个效果难点就两部分:一是水球分离和融合时候的连接,二是主体圆的抖动

然而其实网上都有解决方案了

第一部分是在两个圆之间加个用贝塞尔曲线组成的path,用一样的颜色,其实是障眼法.见参考链接4

第二部分是用4段三次贝塞尔曲线组成的path代替Ellipse,因为Ellipse是抖动不起来的,这样就可以控制贝塞尔曲线的点来让圆抖动.见参考链接3

主体的大圆

Path画法

主体的大圆是个ToggleButton,替换模版,背景换成贝塞尔曲线组成的圆.

每个贝塞尔曲线的起点和终点就不说了,非常简单,这里主要说说控制点.

WPF水珠效果按钮组的实现教程

计算出1/4圆弧的中间位置的点,此时t=0.5, 三角型边长h=sin45*r

让控制点P1,P2分别在起点和终点的切线上,P1到X轴的距离等于P2到Y轴的距离L

B(0.5)=h=sin45*r=(1-0.5)^3*0+3*(1-0.5)^2*0.5*L+3*(1-0.5)*0.5^2*r+0.5^3*r

sin45*r=0+0.375*L+0.375*r+0.125*r

L=(sin45*r-0.5*r)/0.375

于是两个控制点(r,L)和(L,r)可以确定

求出来的两个点是数学的坐标,要转换成程序的坐标,对应成4个象限,无非就是加减半径,加减L,不细说了

完整的path,取半径是50,见代码

<Path> <Path.Data> <PathGeometry> <PathFigure StartPoint="50,0"> <BezierSegment Point1="77.614237491541,0" Point2="100,22.385762508459" Point3="100,50"></BezierSegment> <BezierSegment Point1="100,77.614237491541" Point2="77.614237491541,100" Point3="50,100"></BezierSegment> <BezierSegment Point1="22.385762508459,100" Point2="0,77.614237491541" Point3="0,50"></BezierSegment> <BezierSegment Point1="0,22.385762508459" Point2="22.385762508459,0" Point3="50,0"></BezierSegment> </PathFigure> </PathGeometry> </Path.Data> </Path>

抖动动画

由于圆是被12个点控制的,让圆抖动,也就是对12个点做点动画

可以用关键帧动画,这样控制的比较细致,要注意的是,衔接的地方要平滑.我这里做的比较简陋,就找了一个变换后的图形,重复了5次.如果你有兴趣,可以多做些,做的越多,动画看起来表现力越强

这里我并没有去研究什么算法,就是简单的在blend里,找了一些点

见代码:

<EventTrigger RoutedEvent="Click"> <BeginStoryboard> <Storyboard> <PointAnimationUsingKeyFrames Storyboard.TargetName="pf_main" Storyboard.TargetProperty="StartPoint" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="40,0" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main0" Storyboard.TargetProperty="Point1" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="68,-10" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main0" Storyboard.TargetProperty="Point2" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="115,14" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main0" Storyboard.TargetProperty="Point3" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="100,66" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main1" Storyboard.TargetProperty="Point1" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="100,67" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main1" Storyboard.TargetProperty="Point2" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="85,111" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main1" Storyboard.TargetProperty="Point3" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="33,103" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main2" Storyboard.TargetProperty="Point1" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="22,103" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main2" Storyboard.TargetProperty="Point2" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="-15,85" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main2" Storyboard.TargetProperty="Point3" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="-6,50" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main3" Storyboard.TargetProperty="Point1" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="4,9" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main3" Storyboard.TargetProperty="Point2" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="41,-1" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main3" Storyboard.TargetProperty="Point3" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop"> <EasingPointKeyFrame Value="42,0" KeyTime="0:0:0.2"></EasingPointKeyFrame> </PointAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger>

item

按钮的位置

不管是奇数个,还是偶数个,我们都想让它以Y轴对称

首先把圆分成8等份,每一份都是45度,也就是最多只能放下8个item,

WPF水珠效果按钮组的实现教程

从上图可以看出来,其实就是奇数个在线上,偶数个在两线之间

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdspfx.html