WPF界面设计技巧(3)—实现不规则动画按钮
?
?
發布了定義WPF按鈕的教程后,有朋友問能否實現不規則形狀的按鈕,今天我們就來講一下不規則按鈕的制作。
?
不規則按鈕的做法實際上和先前我們做不規則窗體的方法差不多,只是為按鈕弄個不是那么方方正正的背景而已。
?
我們這次沿用自定義窗體時的設計圖形,設計一個動態的不規則按鈕,在這個示例中我們要將先前設計的整個圖形作為按鈕,并讓外圍的圓環始終圍繞中心圓形旋轉,在鼠標移入時,還要產生顏色變化及發光效果。
?
首先用 Microsoft Expression Design 2 打開上次的設計文件,將圖層名稱由“back”改為“sphericity”。
?
然后選中圓環部分,按 Ctrl + X 將其剪切,新建一個圖層,命名為“ring”,將圓環粘貼進該層,并把該層移動到“sphericity”層下面。
?
再選中圓環部分,如圖所示地移動它,將其內環貼近圓形的邊緣。
?
?
然后在“ring”層新創建一個圓形,填充色設為深紅色,無描邊。
?
?
在圖層面板上展開“ring”層,將新創建的圓形挪到圓環下方。
?
?
?
參考“sphericity”層的圓形中心點坐標值,將新創建的這個圓形中心點與之重合。
?
你可以先選中“sphericity”層的圓形,然后復制其X坐標值,再選中新創建的圓形,選中其X坐標值,按 Ctrl + V 粘貼以覆蓋其先前值,然后再以同樣的方法處理Y坐標值。
?
?
當中心點重合后,隱藏“sphericity”層,等比例放大這個圓形使之邊緣蓋過圓環。
?
?
然后將該圓形的不透明度修改為0。
?
?
同時選中圓環與這個看不見的圓形,點擊右鍵,在彈出菜單中選擇“組合”。
?
?
這樣這個看不見的圓形就成為了圓環的旋轉參照物,重新顯示出“sphericity”層,你可以現在就嘗試旋轉一下圓環,你會看到圓環始終都會貼緊并圍繞中間的圓形旋轉。
?
?
設計部分做完了,現在導出資源字典。
?
?
打開 Microsoft Visual Studio 2008 新建一個WPF應用程序,將導出的資源字典導入解決方案。
?
?
在App.xaml中添加對資源字典的引用。
?
?
調整窗體尺寸為400×400,在代碼視圖中 <Grid> … </Grid> 標記內貼入如下代碼:
?
Code????????<Button?Height="300"?Width="300"?Margin="-59,-57,-18,-94"?Name="button1"?Cursor="Hand">
????????????<Button.Template>
????????????????<ControlTemplate>
????????????????????<!--容器-->
????????????????????<Canvas?Height="300"?Width="300">
????????????????????????<!--圓環-->
????????????????????????<Rectangle?x:Name="ring"?Canvas.Top="0"?Canvas.Left="0"?Fill="{StaticResource?ring}"??Height="300"?Width="300"?>
????????????????????????????<Rectangle.RenderTransform>
????????????????????????????????<RotateTransform?Angle="135"?CenterX="150"?CenterY="150"/>
????????????????????????????</Rectangle.RenderTransform>
????????????????????????</Rectangle>
????????????????????????<!--圓形及文字-->
????????????????????????<Rectangle?x:Name="sphericity"?Canvas.Top="33"?Canvas.Left="33"?Fill="{StaticResource?sphericity}"?Height="234"?Width="234">
????????????????????????????<Rectangle.BitmapEffect>
????????????????????????????????<OuterGlowBitmapEffect?GlowColor="Orange"??GlowSize="0"/>
????????????????????????????</Rectangle.BitmapEffect>
????????????????????????</Rectangle>
????????????????????</Canvas>
????????????????????<!--觸發器-->
????????????????????<ControlTemplate.Triggers>
????????????????????????<!--載入事件觸發器-->
????????????????????????<EventTrigger?RoutedEvent="FrameworkElement.Loaded">
????????????????????????????<BeginStoryboard>
????????????????????????????????<Storyboard>
????????????????????????????????????<DoubleAnimationUsingKeyFrames?Duration="0:0:0.6"?RepeatBehavior="Forever"?Storyboard.TargetName="ring"?Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)">
????????????????????????????????????????<DoubleAnimationUsingKeyFrames.KeyFrames>
????????????????????????????????????????????<SplineDoubleKeyFrame?KeyTime="0:0:0"?Value="135"?KeySpline="0.5,0,0,0.5"/>
????????????????????????????????????????????<SplineDoubleKeyFrame?KeyTime="0:0:0.6"?Value="495"?KeySpline="0,0.5,0.5,0"/>
????????????????????????????????????????</DoubleAnimationUsingKeyFrames.KeyFrames>
????????????????????????????????????</DoubleAnimationUsingKeyFrames>
????????????????????????????????</Storyboard>
????????????????????????????</BeginStoryboard>
????????????????????????</EventTrigger>
????????????????????????<!--鼠標移入觸發器-->
????????????????????????<Trigger?Property="IsMouseOver"?Value="True">
????????????????????????????<Trigger.EnterActions>
????????????????????????????????<BeginStoryboard>
????????????????????????????????????<Storyboard>
????????????????????????????????????????<DoubleAnimation?To="12"?Duration="0:0:0.1"?Storyboard.TargetName="sphericity"?Storyboard.TargetProperty="(Rectangle.BitmapEffect).(OuterGlowBitmapEffect.GlowSize)"/>
????????????????????????????????????????<ColorAnimation?To="#FFEB55"?Duration="0:0:0.1"?Storyboard.TargetName="sphericity"?Storyboard.TargetProperty="(Rectangle.Fill).(DrawingBrush.Drawing).(DrawingGroup.Children)[0].(GeometryDrawing.Brush).(RadialGradientBrush.GradientStops)[0].(GradientStop.Color)"/>
????????????????????????????????????????<ColorAnimation?To="#FFC955"?Duration="0:0:0.1"?Storyboard.TargetName="sphericity"?Storyboard.TargetProperty="(Rectangle.Fill).(DrawingBrush.Drawing).(DrawingGroup.Children)[0].(GeometryDrawing.Brush).(RadialGradientBrush.GradientStops)[1].(GradientStop.Color)"/>
????????????????????????????????????????<ColorAnimation?To="#D79248"?Duration="0:0:0.1"?Storyboard.TargetName="sphericity"?Storyboard.TargetProperty="(Rectangle.Fill).(DrawingBrush.Drawing).(DrawingGroup.Children)[0].(GeometryDrawing.Brush).(RadialGradientBrush.GradientStops)[2].(GradientStop.Color)"/>
????????????????????????????????????</Storyboard>
????????????????????????????????</BeginStoryboard>
????????????????????????????</Trigger.EnterActions>
????????????????????????????<Trigger.ExitActions>
????????????????????????????????<BeginStoryboard>
????????????????????????????????????<Storyboard>
????????????????????????????????????????<DoubleAnimation?Duration="0:0:0.1"?Storyboard.TargetName="sphericity"?Storyboard.TargetProperty="(Rectangle.BitmapEffect).(OuterGlowBitmapEffect.GlowSize)"/>
????????????????????????????????????????<ColorAnimation?Duration="0:0:0.1"?Storyboard.TargetName="sphericity"?Storyboard.TargetProperty="(Rectangle.Fill).(DrawingBrush.Drawing).(DrawingGroup.Children)[0].(GeometryDrawing.Brush).(RadialGradientBrush.GradientStops)[0].(GradientStop.Color)"/>
????????????????????????????????????????<ColorAnimation?Duration="0:0:0.1"?Storyboard.TargetName="sphericity"?Storyboard.TargetProperty="(Rectangle.Fill).(DrawingBrush.Drawing).(DrawingGroup.Children)[0].(GeometryDrawing.Brush).(RadialGradientBrush.GradientStops)[1].(GradientStop.Color)"/>
????????????????????????????????????????<ColorAnimation?Duration="0:0:0.1"?Storyboard.TargetName="sphericity"?Storyboard.TargetProperty="(Rectangle.Fill).(DrawingBrush.Drawing).(DrawingGroup.Children)[0].(GeometryDrawing.Brush).(RadialGradientBrush.GradientStops)[2].(GradientStop.Color)"/>
????????????????????????????????????</Storyboard>
????????????????????????????????</BeginStoryboard>
????????????????????????????</Trigger.ExitActions>
????????????????????????</Trigger>
????????????????????</ControlTemplate.Triggers>
????????????????</ControlTemplate>
????????????</Button.Template>
????????</Button>
?
還是回過頭在研究代碼,先編譯并運行,可以看到下圖這樣的界面,其中的圓環在不停的轉動。
?
?
鼠標移入時圓形會變色,并且外發光:
?
好了,下面只講解一下代碼中需要注意的地方,重復的知識不再累述,大家可以參考先前的兩篇文章。
?
?
Canvas 是一個簡單的容器元素,它內部的元素以簡單的坐標位置來描述。
?
其內部放置了兩個矩形元素 Rectangle ,我們用 Rectangle 分別裝載圓環和圓形及文字的圖像。
?
?
通過 Rectangle.RenderTransform? 屬性可以對 Rectangle 的外形進行轉換調整,其功能類似 Photoshop 中的“自由變換”,在這里使用 RotateTransform 來改變角度。
?
“CenterX="150" CenterY="150"”設置了旋轉中心的坐標值,我們之前曾做過一個隱形的旋轉參照,所以可以肯定我們的圖形中心就是旋轉的中心,現在我們的圖片被設置為300×300大小了,所以中心坐標就是150,150。
?
Angle 屬性指定了旋轉的角度,這里我設置為135是為了讓它正好旋轉到下面這樣的角度。
?
?
因為我們后面將會做動畫使其順時針旋轉,受地心引力的影響,順時針旋轉時這個角度會是旋轉力度的一個分水嶺,越過這個角度將會使運動較為吃力,而超過180度以后將會加速運動,我們可以通過動畫的緩動值設定來粗略模擬這一物理現象。
?
?
順帶提一下兩個圖形的尺寸設定,上面一組是圓環的,下面的是圓形及文字的,圓環的300×300是我任意設置的,我覺得這個大小當個按鈕還算說的過去,下面的234×234是依據原圖中的尺寸,這里的按比例縮小后,又進行了一些微調后確立的,設定好它的尺寸后,為了使它位于圓環圖形中心,需要調整它在Canvas 中的頂部和左部坐標值均為33,即 (300-234)/2。
?
?
接下來是觸發器部分,首先啟用了一個事件觸發器,觸發 FrameworkElement.Loaded 事件,我們要在程序載入完畢時就啟動圓環的旋轉動畫,并使之一直運轉。
?
為什么要使用 FrameworkElement.Loaded 事件?我不知道,我一直認為應該使用按鈕的 Loaded 事件,可是總會看到一些BT的錯誤信息,導致無法正常運轉,后來從Blend里學來的 FrameworkElement.Loaded ,那就用它吧,好用就得了。
?
這次與以往不同,我們采用了關鍵幀動畫 DoubleAnimationUsingKeyFrames ,主要是為了達成動畫的緩動和加速效果,如前所述,在這里我們要讓圓環旋轉起來。
?
“RepeatBehavior="Forever"”屬性指定動畫永遠執行。
?
“SplineDoubleKeyFrame”是關鍵幀,這里只有兩個關鍵幀,通過這兩個關鍵幀,讓圓環從之前設定好的135度轉到495(135 + 360)度,其 KeySpline 是指示緩動曲線的貝塞爾控制點坐標值,具體設置方法得參考MSDN,我自己也暈暈乎乎的,我大體上認為這4個double數值是2組數據,即為“X1,Y1,X2,Y2”,分別代表開始時和結束時的速度,其中每組的X值越大代表速度越慢,Y值越大代表速度越快,這個理解可能不是很準確,僅供參考。
?
?
鼠標移入事件的觸發器大家應該很熟悉了,不過大家看到這里那幾個動畫行的后面一大段,可能都要痙攣了:
?
(Rectangle.Fill).(DrawingBrush.Drawing).(DrawingGroup.Children)[0].(GeometryDrawing.Brush).(RadialGradientBrush.GradientStops)[0].(GradientStop.Color)
?
諸如這樣長的路徑聲明是非常惡心人的,沒辦法,因為我們繪制的圖形比較復雜,所以只能使用復雜的路徑語句來描述了,可以參考如下選取路徑的方式:
?
?
好了,別的就沒什么了,我繼續干活去啦。
源代碼和設計文件
轉載于:https://www.cnblogs.com/lonelyxmas/p/3579494.html
總結
以上是生活随笔為你收集整理的WPF界面设计技巧(3)—实现不规则动画按钮的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1.网页学习-开始学习第一步:
- 下一篇: login控件“您的登录尝试不成功。请重