基于WPF繪制一個點贊大拇指動畫
效果圖

好久沒有寫wpf了。
最近看到飛書的點贊動畫非常有意思,決定試試,雖然不及飛書那樣的絢麗,但是練手還是可以的,希望自己的手藝還在!
實現(xiàn)思路
那么如何寫一個這樣的動畫呢?
首先需要刨析這個動畫的構(gòu)成:
- 外圈圓
- 大拇指-1豎著
- 大拇指-2握著
- 顫動動畫
- 中心旋轉(zhuǎn)動畫
- 展開中心旋轉(zhuǎn)動畫
當(dāng)我們分析這些東西剩下的就好辦了。
首先我們先辦了這個最難的東西大拇指。

這個東西的構(gòu)成,我們使用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>當(dāng)我們在path 100*100的大小的時候使用腦補進(jìn)行繪制就就可以了。
至于這個小褶皺我曾經(jīng)不想要,但是看到了自己的豬爪...還是決定加上了。
這代碼的原理非常簡單,基本都是基本的直線繪制,最難的就是用了個貝塞爾來制造大拇指背部的弧度.
不管咋樣還是弄出來個簡單的贊。
剩下就是握著的狀態(tài)了
那么我們只需要修改部分代碼就可以達(dá)到了~
也就是
<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參數(shù)和q最后的end point參數(shù)的y的值都是降到0了 這樣會形成一個簡單的弧度

哈 這樣子 我們就是得到了兩個手掌的不同狀態(tài)了。
剩下的事情就是來組裝吧~~~~
首先是大拇指張開和大拇指握住的狀態(tài)轉(zhuǎn)換。
做到這事情最簡單的動畫就是使用eventtigger來做,我們使用簡單的鼠標(biāo)按下事件作為啟動,當(dāng)然了 想要豐富過程也是可以使用鼠標(biāo)浮動事件作為啟動事件之一。
<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轉(zhuǎn)換為握住的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>效果圖

莫名的搞笑....
基礎(chǔ)的東西我們構(gòu)建好了,剩下就是補全了。
不全顫抖啊,補全中心旋轉(zhuǎn)動畫,也就是手指握住后有一個向下的動畫。
首先這個顫動 我們可以簡單的理解為位移,一個快速的上下左右的位移
正好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的位移,代碼非常簡單。

就是在這里顫抖...
雖然看上去不是很好看,但是我們結(jié)合下一個動畫,也就是手掌向下就會好很多了
這個動畫很明顯是一個旋轉(zhuǎn)動畫,所以我們需要提前準(zhǔn)備一個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>我們簡單的使用了一個函數(shù),提升一下效果的動感...
但是感覺沒啥用
效果圖就是這樣的了

雖然看上去已經(jīng)非常不錯了,但是還有些不做,想想 我們的手都朝下了 松開之后為啥沒有一個向上的彈簧動作呢?

也就是我們需要在抬起時加上一個角度的旋轉(zhuǎn)。
<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動畫解除掉。
剩下的就是圈的構(gòu)造和動畫。
圓圈呢,我們可以是直接的圓圈,也可以是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>構(gòu)造了兩個嵌套的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>代碼非常簡單,控制下內(nèi)圈的大小,還有是否隱藏而已。
這樣子我們就最終得到了頭圖的效果了

總的過程還是比較簡單的。
完整代碼
下面是全部的代碼
<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繪制一個點贊大拇指動畫的詳細(xì)內(nèi)容,更多關(guān)于WPF繪制點贊動畫的資料請關(guān)注腳本之家其它相關(guān)文章!

