原文: WPF水珠效果按钮组

效果图

相关知识

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

贝塞尔曲线

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

二次贝塞尔曲线:

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

三次贝塞尔曲线:

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的任意取值

其他知识

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

直角三角形,角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,替换模版,背景换成贝塞尔曲线组成的圆.

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

计算出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,见代码

 1 <Path>
 2     <Path.Data>
 3         <PathGeometry>
 4             <PathFigure StartPoint="50,0">
 5                 <BezierSegment Point1="77.614237491541,0" Point2="100,22.385762508459" Point3="100,50"></BezierSegment>
 6                 <BezierSegment Point1="100,77.614237491541" Point2="77.614237491541,100" Point3="50,100"></BezierSegment>
 7                 <BezierSegment Point1="22.385762508459,100" Point2="0,77.614237491541" Point3="0,50"></BezierSegment>
 8                 <BezierSegment Point1="0,22.385762508459" Point2="22.385762508459,0" Point3="50,0"></BezierSegment>
 9             </PathFigure>
10         </PathGeometry>
11     </Path.Data>
12 </Path>

View Code

抖动动画

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

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

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

见代码:

 1 <EventTrigger RoutedEvent="Click">
 2     <BeginStoryboard>
 3         <Storyboard>
 4             <PointAnimationUsingKeyFrames Storyboard.TargetName="pf_main" Storyboard.TargetProperty="StartPoint" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
 5                 <EasingPointKeyFrame Value="40,0" KeyTime="0:0:0.2"></EasingPointKeyFrame>
 6             </PointAnimationUsingKeyFrames>
 7             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main0" Storyboard.TargetProperty="Point1" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
 8                 <EasingPointKeyFrame Value="68,-10" KeyTime="0:0:0.2"></EasingPointKeyFrame>
 9             </PointAnimationUsingKeyFrames>
10             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main0" Storyboard.TargetProperty="Point2" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
11                 <EasingPointKeyFrame Value="115,14" KeyTime="0:0:0.2"></EasingPointKeyFrame>
12             </PointAnimationUsingKeyFrames>
13             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main0" Storyboard.TargetProperty="Point3" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
14                 <EasingPointKeyFrame Value="100,66" KeyTime="0:0:0.2"></EasingPointKeyFrame>
15             </PointAnimationUsingKeyFrames>
16             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main1" Storyboard.TargetProperty="Point1" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
17                 <EasingPointKeyFrame Value="100,67" KeyTime="0:0:0.2"></EasingPointKeyFrame>
18             </PointAnimationUsingKeyFrames>
19             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main1" Storyboard.TargetProperty="Point2" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
20                 <EasingPointKeyFrame Value="85,111" KeyTime="0:0:0.2"></EasingPointKeyFrame>
21             </PointAnimationUsingKeyFrames>
22             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main1" Storyboard.TargetProperty="Point3" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
23                 <EasingPointKeyFrame Value="33,103" KeyTime="0:0:0.2"></EasingPointKeyFrame>
24             </PointAnimationUsingKeyFrames>
25             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main2" Storyboard.TargetProperty="Point1" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
26                 <EasingPointKeyFrame Value="22,103" KeyTime="0:0:0.2"></EasingPointKeyFrame>
27             </PointAnimationUsingKeyFrames>
28             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main2" Storyboard.TargetProperty="Point2" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
29                 <EasingPointKeyFrame Value="-15,85" KeyTime="0:0:0.2"></EasingPointKeyFrame>
30             </PointAnimationUsingKeyFrames>
31             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main2" Storyboard.TargetProperty="Point3" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
32                 <EasingPointKeyFrame Value="-6,50" KeyTime="0:0:0.2"></EasingPointKeyFrame>
33             </PointAnimationUsingKeyFrames>
34             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main3" Storyboard.TargetProperty="Point1" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
35                 <EasingPointKeyFrame Value="4,9" KeyTime="0:0:0.2"></EasingPointKeyFrame>
36             </PointAnimationUsingKeyFrames>
37             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main3" Storyboard.TargetProperty="Point2" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
38                 <EasingPointKeyFrame Value="41,-1" KeyTime="0:0:0.2"></EasingPointKeyFrame>
39             </PointAnimationUsingKeyFrames>
40             <PointAnimationUsingKeyFrames Storyboard.TargetName="bs_main3" Storyboard.TargetProperty="Point3" BeginTime="0:0:0.7" AutoReverse="True" RepeatBehavior="5x" FillBehavior="Stop">
41                 <EasingPointKeyFrame Value="42,0" KeyTime="0:0:0.2"></EasingPointKeyFrame>
42             </PointAnimationUsingKeyFrames>
43         </Storyboard>
44     </BeginStoryboard>
45 </EventTrigger>

View Code

item

按钮的位置

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

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

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

有个简单的办法,就是先在顶点依次顺时针排列,每个item间隔45度,然后再逆时针旋转,每多一个item就多转45/2度(两条分割线是45度,中间也就是45/2度),如下图:

上图是item终点的位置,起点的位置是在圆心.

动画用DoubleAnimation控制item按钮的位移,从圆心移动到计算后的位置

计算位置的代码:

1 //函数是弧度制 2PI是360度
2 1 a = c * Math.Sin(2 * Math.PI / 8 * i - (itemsSource.Count - 1) * 2 * Math.PI / 8 / 2);
3 2 b = c * Math.Cos(2 * Math.PI / 8 * i - (itemsSource.Count - 1) * 2 * Math.PI / 8 / 2);

水球连接的部分

连接的部分是用两个二次贝塞尔和一条直线做一个path

开始的时候,两条贝塞尔曲线的高度是0,控制点在path所在矩形的边上,然后对而塞尔曲线上面的点和控制点做动画,分别向上和内移动,最终形成上图右边的图形,然后把这个动画和item按钮向外部移动的动画结合起来,就伪装成了水球分离的效果.

上图红色矩形就是连接部分的path.动画的过程就是Item按钮的直径和大圆相交的时候开始和item按钮一起做动画,最后移动到Item按钮直径所在的位置,整个距离就是Item的半径+item到主体的距离+蓝色的d,而蓝色的d可以通过公式求出

开始的时候也是让连接部分path在圆心的位置.定位方法和定位Item按钮的方法是完全一样的.这里就不在重复了.只说一下c边的距离是:大圆和小圆圆心的距离-连接path高度的一半

源码下载:WaterDropsButtonGroup.zip

参考连接:

  1. https://en.wikipedia.org/wiki/B%C3%A9zier_curve
  2. https://baike.baidu.com/item/%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF/1091769?fr=aladdin
  3. https://www.cnblogs.com/ArthurQQ/articles/1730214.html
  4. http://blog.csdn.net/chouglas/article/details/50967566

WPF水珠效果按钮组相关推荐

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

    扣扣技术交流群:460189483 效果图 相关知识 这部分基本就是废话,网上都能找到,我只不过是整理了以下.建议先不看,用到的时候可以回来看看 贝塞尔曲线 先来看两组图,有助于理解什么是贝塞尔曲线( ...

  2. WPF 实现水珠效果按钮组

    本文经原作者授权以原创方式二次分享,欢迎转载.分享. 原文作者:普通的地球人 原文地址:https://www.cnblogs.com/tsliwei/p/8041928.html 相关知识 这部分基 ...

  3. 1.2文字排版、颜色、表格、图像形状、Jumbotron、信息提示框、按钮、按钮组、徽章、加载效果、分页、列表组、卡片、下拉菜单、折叠

    Bootstrap 5 默认设置 Bootstrap 5 默认的 font-size 为 16px, line-height 为 1.5. 此外,所有的 <p> 元素 margin-top ...

  4. Bootstrap3 按钮组插件

    按钮组 将按钮组放在特定的容器中,不必编写JavaScript代码,就可以让按钮组具有HTML的复选框(checkbox)或单选框(radio)的效果. 1)复选按钮组 复选按钮组是类似于复选框的一组 ...

  5. Bootstrap两端对齐的按钮组

    两端对齐的按钮组 Bootstrap3两端对齐的按钮组可以将一组按钮拉长为相同的尺寸,并让整个按钮组填满父元素的宽度.对于按钮组中的按钮式下拉菜单也同样适用. 如果按钮组中的按钮是 <a> ...

  6. Bootstrap禁用某个按钮组

    禁用某个按钮组 某些特殊情况下,可能需要垂直分组的按钮效果.这也很简单,只需把 .btn-group类换成.btn-group-vertical类,就可以让按钮组中的按钮堆叠排列.堆叠排列的按钮组中, ...

  7. Bootstrap按钮组嵌套

    按钮组嵌套 按钮组允许嵌套,即可以在一个.btn-group中嵌套另一个.btn-group.比如,当你想给按钮组中的某一个按钮添加下拉菜单时,就会用到这种嵌套结构.如: <div class= ...

  8. Bootstrap按钮组中按钮的尺寸

    按钮的尺寸 在按钮组中,你可以为每个按钮应用按钮的尺寸类,如 .btn-lg..btn-sm或.btn-xs ,来调整按钮的大小. 考虑到这种方式比较麻烦,Bootstrap专门为按钮组提供了额外的尺 ...

  9. Bootstrap创建按钮组

    按钮组 在实际应用中,单个按钮有时候并不能满足我们的业务需求,常常需要将多个按钮组合在一起使用,形成一个页面组件,比如富文本编辑器中的一组小图标按钮等. 创建按钮组 要创建按钮组,只需把相关的链接或按 ...

最新文章

  1. k8s四种port解析:nodePort、port、targetPort、containerPort
  2. java中字符串的操作_java中字符串的操作
  3. Qt 【遍历文件夹文件,为listwidgetItem设置图标】
  4. linux之expect
  5. 常见批处理作业调度算法
  6. 创新不是突然而至——它是慢慢成长的
  7. Careercup - Microsoft面试题 - 5680049562845184
  8. 下载ue5和古代山谷
  9. 三天搞定射频识别技术(一)1.3
  10. 自然人股东分红必须要缴纳20%个税吗?有三种真不用
  11. 如何在Dynamic CRM 2011中使用自定义Workflow
  12. 【烧录问题】flymcu下载出现从08000000开始运行失败
  13. 计算机如何计算指数函数
  14. RINEX 采用的格式说明
  15. access百科 pc_access
  16. 使用cubeide调试发现变量查看为<optimized out>
  17. R720 ESXi6.5 raid5磁盘阵列扩容
  18. UE 材质一 : 材质通道
  19. sources和binaries文件区别
  20. vb.net 教程 3-2 窗体编程之窗体 3

热门文章

  1. 称霸全球云服务的他怎么了
  2. poj 1873The Fortified Forest (凸包 二进制枚举)
  3. C++模拟蚁群算法解决作业车间调度问题(Job-Shop Scheduling Problem,JSP)
  4. python类的析构方法是什么_python类的析构方法是什么_python类析构
  5. 果园机器人是什么文体_果园机器人本课是一篇能体现什么的文章
  6. IAR下载报错 “Fatal error: Failed to connect to CPU Session aborted!”
  7. 3D插画玩起来,如何简单快速地创作可交互的3D内容? | Mixlab设计工具
  8. [PSQL] 自连接的用法
  9. Robot Framework 自动化测试框架核心指南-初识Robot Framework(学习笔记2)
  10. JAVA调用SAP ODATA服务