- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
效果图 。
。
。
。
。
好久没有写wpf了.
最近看到飞书的点赞动画非常有意思,决定试试,虽然不及飞书那样的绚丽,但是练手还是可以的,希望自己的手艺还在! 。
那么如何写一个这样的动画呢?
首先需要刨析这个动画的构成:
外圈圆 。
大拇指-1竖着 。
大拇指-2握着 。
颤动动画 。
中心旋转动画 。
展开中心旋转动画 。
当我们分析这些东西剩下的就好办了.
首先我们先办了这个最难的东西大拇指.
。
。
这个东西的构成,我们使用Path 直接去写。显然我们就会得到这样的代码 。
< Geometry x:Key ="t1" > M 20 40 v 0 40 h 0 7 v 0 -40 z M 30 42 v 0 38 h 40 0 l 15 -35 l -10 -5 h -25 0 l 2 -20 <!-- 小褶皱 --> q -10 -10, -20 22 z </ Geometry >
当我们在path 100*100的大小的时候使用脑补进行绘制就就可以了.
至于这个小褶皱我曾经不想要,但是看到了自己的猪爪...还是决定加上了.
这代码的原理非常简单,基本都是基本的直线绘制,最难的就是用了个贝塞尔来制造大拇指背部的弧度. 。
不管咋样还是弄出来个简单的赞.
剩下就是握着的状态了 。
那么我们只需要修改部分代码就可以达到了~ 。
也就是 。
< Geometry x:Key ="t2" > M 20 40 v 0 40 h 0 7 v 0 -40 z M 30 42 v 0 38 h 40 0 l 15 -35 l -10 -5 h -25 0 l 2 0 <!-- 小褶皱 --> q -10 -10, -20 0 z </ Geometry >
我们修改了最后两行代码的 l 的y参数和q最后的end point参数的y的值都是降到0了 这样会形成一个简单的弧度 。
。
。
哈 这样子 我们就是得到了两个手掌的不同状态了.
剩下的事情就是来组装吧~~~~ 。
首先是大拇指张开和大拇指握住的状态转换.
做到这事情最简单的动画就是使用eventtigger来做,我们使用简单的鼠标按下事件作为启动,当然了 想要丰富过程也是可以使用鼠标浮动事件作为启动事件之一.
< Path.Triggers > < EventTrigger RoutedEvent ="MouseLeftButtonDown" > < BeginStoryboard x:Name ="Bs1" > < Storyboard > < ObjectAnimationUsingKeyFrames BeginTime ="0:0:0" Storyboard.TargetProperty ="Data" > < DiscreteObjectKeyFrame KeyTime ="0:0:0.01" > < DiscreteObjectKeyFrame.Value > < StaticResource ResourceKey ="t2" /> </ DiscreteObjectKeyFrame.Value > </ DiscreteObjectKeyFrame > </ ObjectAnimationUsingKeyFrames > </ Storyboard > </ BeginStoryboard > </ EventTrigger > </ Path.Triggers >
为了做件事 ,我们把geometry作为window的资源 所以子啊写动画的时候 用离弦值就非常方便了.
观察代码,我们仅仅只是在点下的时候让path转换为握住的data,因为我们需要在松开左键的时候才让拇指竖起来.
所以还需要补上一个MouseLeftButtonUp的动画 。
这最终的代码就是 。
< Path.Triggers > < EventTrigger RoutedEvent ="MouseLeftButtonDown" > < BeginStoryboard x:Name ="Bs1" > < Storyboard > < ObjectAnimationUsingKeyFrames BeginTime ="0:0:0" Storyboard.TargetProperty ="Data" > < DiscreteObjectKeyFrame KeyTime ="0:0:0.01" > < DiscreteObjectKeyFrame.Value > < StaticResource ResourceKey ="t2" /> </ DiscreteObjectKeyFrame.Value > </ DiscreteObjectKeyFrame > </ ObjectAnimationUsingKeyFrames > </ Storyboard > </ BeginStoryboard > </ EventTrigger > < EventTrigger RoutedEvent ="MouseLeftButtonUp" > < RemoveStoryboard BeginStoryboardName ="Bs1" /> </ EventTrigger > </ Path.Triggers >
效果图 。
。
。
莫名的搞笑.... 。
基础的东西我们构建好了,剩下就是补全了.
不全颤抖啊,补全中心旋转动画,也就是手指握住后有一个向下的动画.
首先这个颤动 我们可以简单的理解为位移,一个快速的上下左右的位移 。
正好WPF有这种动画 所以我们就可以得到如下的代码 。
< ThicknessAnimationUsingKeyFrames RepeatBehavior ="Forever" Duration ="0:0:0.4" Storyboard.TargetProperty ="Margin" > < SplineThicknessKeyFrame KeyTime ="0:0:0.0" Value ="4,3,0,0" /> < SplineThicknessKeyFrame KeyTime ="0:0:0.2" Value ="3,4,0,0" /> < SplineThicknessKeyFrame KeyTime ="0:0:0.3" Value ="0,0,4,0" /> < SplineThicknessKeyFrame KeyTime ="0:0:0.35" Value ="0,0,4,3" /> < SplineThicknessKeyFrame KeyTime ="0:0:0.4" Value ="4,3,0,0" /> </ ThicknessAnimationUsingKeyFrames >
我们可以直代码放到path的eventtriger中 。
看得出来 离散动画的值就是简单的marigin的位移,代码非常简单.
。
。
就是在这里颤抖... 。
虽然看上去不是很好看,但是我们结合下一个动画,也就是手掌向下就会好很多了 。
这个动画很明显是一个旋转动画,所以我们需要提前准备一个roteate的transofrom 。
代码如下 。
< Path.RenderTransform > < RotateTransform x:Name ="rote" Angle ="0" /> </ Path.RenderTransform >
动画代码如下 。
< DoubleAnimation Duration ="0:0:0.1" To ="30" Storyboard.TargetName ="rote" Storyboard.TargetProperty ="Angle" > < DoubleAnimation.EasingFunction > < CubicEase /> </ DoubleAnimation.EasingFunction > </ DoubleAnimation >
我们简单的使用了一个函数,提升一下效果的动感... 。
但是感觉没啥用 。
效果图就是这样的了 。
。
。
。
虽然看上去已经非常不错了,但是还有些不做,想想 我们的手都朝下了 松开之后为啥没有一个向上的弹簧动作呢?
也就是 。
。
。
我们需要在抬起时加上一个角度的旋转.
也就是 。
< EventTrigger RoutedEvent ="MouseLeftButtonUp" > < BeginStoryboard x:Name ="Bs2" > < Storyboard > < DoubleAnimation FillBehavior ="Stop" Duration ="0:0:0.5" To ="-30" Storyboard.TargetName ="rote" Storyboard.TargetProperty ="Angle" > < DoubleAnimation.EasingFunction > < CubicEase EasingMode ="EaseOut" /> </ DoubleAnimation.EasingFunction > </ DoubleAnimation > </ Storyboard > </ BeginStoryboard > < RemoveStoryboard BeginStoryboardName ="Bs1" /> </ EventTrigger >
代码可以说手掌向下的反向操作.
顺便播放完把bs1动画解除掉.
剩下的就是圈的构造和动画.
圆圈呢,我们可以是直接的圆圈,也可以是broder,看个人喜欢了.
我就不罗嗦直接上代码 。
< Border BorderThickness ="2" Background ="Transparent" BorderBrush ="Transparent" CornerRadius ="100" Width ="200" Height =" {Binding RelativeSource={RelativeSource Mode=Self}, Path=Width} " Grid.Column ="1" Grid.Row ="1" > < Border x:Name ="sor" Visibility ="Hidden" BorderThickness ="2" Background ="Transparent" BorderBrush ="Transparent" CornerRadius ="100" Width ="200" Height =" {Binding RelativeSource={RelativeSource Mode=Self}, Path=Width} " Grid.Column ="1" Grid.Row ="1" /> </ Border >
构造了两个嵌套的borderr,宽度其实可以随意,只是演示的时候放大的大小而已.
动画则是放到了path的启动动画之中 。
也就是 。
< DoubleAnimation RepeatBehavior ="Forever" SpeedRatio ="1.2" Duration ="0:0:1.5" To ="0" Storyboard.TargetName ="sor" Storyboard.TargetProperty ="Width" > < DoubleAnimation.EasingFunction > < CubicEase /> </ DoubleAnimation.EasingFunction > </ DoubleAnimation > < ObjectAnimationUsingKeyFrames BeginTime ="0:0:0" Storyboard.TargetName ="sor" Storyboard.TargetProperty ="Visibility" > < DiscreteObjectKeyFrame KeyTime ="0:0:0.1" > < DiscreteObjectKeyFrame.Value > < Visibility > Visible </ Visibility > </ DiscreteObjectKeyFrame.Value > </ DiscreteObjectKeyFrame > </ ObjectAnimationUsingKeyFrames >
代码非常简单,控制下内圈的大小,还有是否隐藏而已.
这样子我们就最终得到了头图的效果了 。
。
。
总的过程还是比较简单的.
下面是全部的代码 。
< Window.Resources > < Geometry x:Key ="t1" > M 20 40 v 0 40 h 0 7 v 0 -40 z M 30 42 v 0 38 h 40 0 l 15 -35 l -10 -5 h -25 0 l 2 -20 <!-- 小褶皱 --> q -10 -10, -20 22 z </ Geometry > < Geometry x:Key ="t2" > M 20 40 v 0 40 h 0 7 v 0 -40 z M 30 42 v 0 38 h 40 0 l 15 -35 l -10 -5 h -25 0 l 2 0 <!-- 小褶皱 --> q -10 -10, -20 0 z </ Geometry > < PathGeometry Figures =" M 20 40 l 2 -5 v 0 5 h -2 0 z" x:Key ="roue" /> </ Window.Resources > < Grid > < Border BorderThickness ="2" Background ="Transparent" BorderBrush ="BlueViolet" CornerRadius ="100" Width ="200" Height =" {Binding RelativeSource={RelativeSource Mode=Self}, Path=Width} " Grid.Column ="1" Grid.Row ="1" > < Border x:Name ="sor" Visibility ="Hidden" BorderThickness ="2" Background ="Transparent" BorderBrush ="Salmon" CornerRadius ="100" Width ="200" Height =" {Binding RelativeSource={RelativeSource Mode=Self}, Path=Width} " Grid.Column ="1" Grid.Row ="1" /> </ Border > < Grid Width ="300" Height ="300" ShowGridLines ="False" > < Grid.RowDefinitions > < RowDefinition /> < RowDefinition /> < RowDefinition /> </ Grid.RowDefinitions > < Grid.ColumnDefinitions > < ColumnDefinition /> < ColumnDefinition /> < ColumnDefinition /> </ Grid.ColumnDefinitions > < Path StrokeThickness ="2" Grid.Column ="1" Grid.Row ="1" VerticalAlignment ="Bottom" Stretch ="Uniform" Fill ="Pink" Width ="80" Height ="80" Stroke ="Blue" Data =" {StaticResource t1} " RenderTransformOrigin ="0.5,0.5" > < Path.RenderTransform > < RotateTransform x:Name ="rote" Angle ="0" /> </ Path.RenderTransform > < Path.Triggers > < EventTrigger RoutedEvent ="MouseLeftButtonDown" > < BeginStoryboard x:Name ="Bs1" > < Storyboard > < ObjectAnimationUsingKeyFrames BeginTime ="0:0:0" Storyboard.TargetProperty ="Data" > < DiscreteObjectKeyFrame KeyTime ="0:0:0.01" > < DiscreteObjectKeyFrame.Value > < StaticResource ResourceKey ="t2" /> </ DiscreteObjectKeyFrame.Value > </ DiscreteObjectKeyFrame > </ ObjectAnimationUsingKeyFrames > < ThicknessAnimationUsingKeyFrames RepeatBehavior ="Forever" Duration ="0:0:0.4" Storyboard.TargetProperty ="Margin" > < SplineThicknessKeyFrame KeyTime ="0:0:0.0" Value ="4,3,0,0" /> < SplineThicknessKeyFrame KeyTime ="0:0:0.2" Value ="3,4,0,0" /> < SplineThicknessKeyFrame KeyTime ="0:0:0.3" Value ="0,0,4,0" /> < SplineThicknessKeyFrame KeyTime ="0:0:0.35" Value ="0,0,4,3" /> < SplineThicknessKeyFrame KeyTime ="0:0:0.4" Value ="4,3,0,0" /> </ ThicknessAnimationUsingKeyFrames > < DoubleAnimation Duration ="0:0:0.1" To ="30" Storyboard.TargetName ="rote" Storyboard.TargetProperty ="Angle" > < DoubleAnimation.EasingFunction > < CubicEase /> </ DoubleAnimation.EasingFunction > </ DoubleAnimation > < DoubleAnimation RepeatBehavior ="Forever" SpeedRatio ="1.2" Duration ="0:0:1.5" To ="0" Storyboard.TargetName ="sor" Storyboard.TargetProperty ="Width" > < DoubleAnimation.EasingFunction > < CubicEase /> </ DoubleAnimation.EasingFunction > </ DoubleAnimation > < ObjectAnimationUsingKeyFrames BeginTime ="0:0:0" Storyboard.TargetName ="sor" Storyboard.TargetProperty ="Visibility" > < DiscreteObjectKeyFrame KeyTime ="0:0:0.1" > < DiscreteObjectKeyFrame.Value > < Visibility > Visible </ Visibility > </ DiscreteObjectKeyFrame.Value > </ DiscreteObjectKeyFrame > </ ObjectAnimationUsingKeyFrames > </ Storyboard > </ BeginStoryboard > </ EventTrigger > < EventTrigger RoutedEvent ="MouseLeftButtonUp" > < BeginStoryboard x:Name ="Bs2" > < Storyboard > < DoubleAnimation FillBehavior ="Stop" Duration ="0:0:0.5" To ="-30" Storyboard.TargetName ="rote" Storyboard.TargetProperty ="Angle" > < DoubleAnimation.EasingFunction > < CubicEase EasingMode ="EaseOut" /> </ DoubleAnimation.EasingFunction > </ DoubleAnimation > </ Storyboard > </ BeginStoryboard > < RemoveStoryboard BeginStoryboardName ="Bs1" /> </ EventTrigger > </ Path.Triggers > </ Path > </ Grid >
。
最后此篇关于WPF使用动画绘制一个点赞大拇指的文章就讲到这里了,如果你想了解更多关于WPF使用动画绘制一个点赞大拇指的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
有没有办法在另一个 WPF 窗口内托管 WPF 窗口。我有几个有点复杂的表格。但现在为了简化事情,我试图将其中一些合并为一个“仪表板”表单中的标签页。 请注意,我不是要托管 Windows 窗体,而是
WPF 特有的哪些方面和实践在非 WPF GUI 编程中最有用(并且并非难以实现)? 最佳答案 通过学习 WPF 命令,我了解了命令模式。它构成了 UI - 代码分离的基础,我认为应该在其他应用程序中
WinRT/Metro 正在获得一个新的 SemanticZoom控制,但我很难为 WPF 找到任何东西。 我不想为我的特定项目切换到 Metro,因为它不允许我制作窗口应用程序或跨多个显示器的多个实
我很难解决我的问题,我快要疯了。 想法是这样的:我有两个 ListView 元素,当一个元素从第一个列表掉落到第二个列表时,我需要打开一个对话,但我需要被掉落的元素的信息以及被添加以填充对话的元素。
如果我遵循TabControl,并且一切正常,当我切换到第二个Tabitem时,它显示就没有问题。 //datagrid //datagrid2 但是如果我有这个xaml,当我
在 Windows 窗体应用程序中,我们的数据 GridView 有很多事件,如行鼠标双击或行单击以及额外的...... 但是在 WPF 中我找不到这些事件。我如何将行鼠标双击添加到其中包含数据网格的
在这个项目中,代码 正确编译和执行 ;但是,我需要帮助解决两个问题: VS2012 WPF 设计器不适用于此 XAML 文件。它显示消息设计 View 对于 x64 和 ARM 目标平台不可用。 我收
目前我正在设计 WPF ScrollViewer,我发现了这个 Content="M 0 0 L 4 4 L 0 8 Z" 阅读 MSDN examples .现在我真的很想知道这意味着什么,但我无法
在 WPF 中,元素的可见性可以为“可见”,但实际上在屏幕上不可见,因为它的父元素(或父元素的父元素)具有折叠的可见性。 我希望能够知道一个元素是否实际呈现在屏幕上,而不必遍历可视化树检查父元素。 有
我应该使用 ApplicationCommands.Close用于关闭模式对话框还是该命令被认为是为关闭应用程序保留的?如果是后者,请大家创建Close每个命令 Dialog盒子或只是一个 Close
WPF 是否有任何可用的 piemenu 控件? 最佳答案 我在我的最爱中找到了这个,你可以看看: This 祝你今天过得愉快。 关于wpf - WPF 的菜单,我们在Stack Overflow上找
我正在尝试使用 WrapPanel 和两个 TextBlock 将星号 (*) 附加到某些文本的左侧,允许文本换行,并强制文本右对齐。通过创建一个 FlowDirection 设置为 RightToL
这里是场景(简化):我在Window上有一个控件(比如说一个Rectangle)。我迷上了MouseMove事件,以使其启动拖放操作。然后在MouseDown事件中进行动画处理,向右移动50个像素。但
我有一个 ListView ,它的项目来源是一个列表。我希望用户只选择一项。当我将 listview 的 SelectionMode 设置为 single 时,用户仍然可以选择多个项目,并且似乎 li
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
INotifyPropertyChanged 的目的是什么。我知道每当更改属性时都会触发此事件,但是 View /用户界面如何知道触发了此事件: 这是实现 INotifyPropertyChang
我正在查看工具箱中的 WPF 组件,但找不到 2005/2008 中存在的错误提供程序。 被移除了吗? 最佳答案 ErrorProvider是一个 Winforms 控件。 WPF 中没有等效项。但是
我试图在单击和双击 wpf Image 控件时有不同的行为。不幸的是,单击首先被触发,因此双击被忽略。 最佳答案 如果您改用 MouseDown 事件,则它在 EventArgs 中为 ClickCo
这可能吗? 我使用了一个框架控件并且:显示(例如:showwindow.xaml) 但是我得到这个错误: root element is not valid for navigation 最佳答案 确
我在蓝色背景的窗口上放置了一个扩展器,我想让扩展器的按钮与默认颜色不同(蓝色,它是从窗口接收的)。当我修改扩展器的背景属性时,它会将整个扩展器、标题和全部更改为新颜色。但是,我只想更改按钮本身。谁能指
我是一名优秀的程序员,十分优秀!