圖1
1.介紹
從我開始使用vista的時候,我就非常喜歡它的圓形玻璃按鈕。WPF最好的一個方面就是允許自定義任何控件的樣式。用了一段時間的Microsoft Expression Blend后。我做出了這個樣式。我覺得做的還行。因為。我決定分享。如我所說。我使用Microsoft Expression Blend來做。但是。我也是用XAML編輯器--Kaxaml。
2.概述
玻璃按鈕樣式包含了三層。組織了玻璃效果(Glass Effect)和一個ContentPresenter
來存儲按鈕的內容。所有的這些層都在一個最外層的Grid里。當鼠標放到按鈕上,按下去的時候也定義了一些觸發器(Triggers),來增加一些交互。
我把這個樣式做成了資源文件。但是這個Key可以刪除,來使得所有的按鈕都是這個效果。
好我們來看一下這些層次。這些被廣泛應用在微軟產品中的按鈕。
3.按鈕層次
3.1背景層
第一層是一個橢圓。其實是一個canvas,一會在上面畫反射和折射層,填充的顏色和按鈕的背景(Background)關聯。
下面是Blend中的截圖
圖2
<!-- Background Layer --> <Ellipse Fill="{TemplateBinding Background}"/>
3.1.1折射層
第二層模擬了光從上到下的折射。被放在反射層之前是因為,要達到反光玻璃的效果,反射層必須在按鈕的中間某處有一個硬邊緣。這一層實際上是另一個橢圓。但是這次。我們使用一個徑向漸變(白色-透明)的填充。來模擬光的折射。漸變開始於第一層底部的中央。結束於上面的中間。然而。為了降低折射光的強度。漸變還是開始於橢圓的底部再下一點為好。可以從圖上和代碼里清晰的看到。
<!-- Refraction Layer --> <Ellipse x:Name="RefractionLayer"> <Ellipse.Fill> <RadialGradientBrush GradientOrigin="0.496,1.052"> <RadialGradientBrush.RelativeTransform> <TransformGroup> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1.5" ScaleY="1.5"/> <TranslateTransform X="0.02" Y="0.3"/> </TransformGroup> </RadialGradientBrush.RelativeTransform> <GradientStop Offset="1" Color="#00000000"/> <GradientStop Offset="0.4" Color="#FFFFFFFF"/> </RadialGradientBrush> </Ellipse.Fill> </Ellipse>
3.1.2反射層
第三層是光的反射層。是最難的部分。問題是反射效果不能使用任何標准的形狀來畫。因此。使用路徑(Path)來畫反射區域。當時。手工畫也是可以的。但老實說。手工畫圖實在沒什么可享受的(除非你是一個藝術家,或者有一個數位板),無論如何。我現在MS Blend中華好一個橢圓並轉換成一個路徑,然后我使用貝塞爾曲線點調整得到平滑的路徑,你可以添加漸變到一個復雜的Path對象上。就像你對其他與定義的圖形,比如橢圓,矩形所做的一樣。為了得到光澤反射。我額每年需要一個透明-白色的徑向漸變填充,從路徑的底部開始(也就是按鈕的中間某處),結束在頂部。我想如果我是一個藝術家。我會讓漸變更准一點。可是我不是。因此。就這樣。因為我們要把我們的按鈕放在一個Grid里。所有我們設置VerticalAlignment="Top" 這樣反射區域在按鈕的中間的結束了。
圖三
<!-- Reflection Layer --> <Path x:Name="ReflectionLayer" VerticalAlignment="Top" Stretch="Fill"> <Path.RenderTransform> <ScaleTransform ScaleY="0.5" /> </Path.RenderTransform> <Path.Data> <PathGeometry> <PathFigure IsClosed="True" StartPoint="98.999,45.499"> <BezierSegment Point1="98.999,54.170" Point2="89.046,52.258" Point3="85.502,51.029"/> <BezierSegment IsSmoothJoin="True" Point1="75.860,47.685" Point2="69.111,45.196" Point3="50.167,45.196"/> <BezierSegment Point1="30.805,45.196" Point2="20.173,47.741" Point3="10.665,51.363"/> <BezierSegment IsSmoothJoin="True" Point1="7.469,52.580" Point2="1.000,53.252" Point3="1.000,44.999"/> <BezierSegment Point1="1.000,39.510" Point2="0.884,39.227" Point3="2.519,34.286"/> <BezierSegment IsSmoothJoin="True" Point1="9.106,14.370" Point2="27.875,0" Point3="50,0"/> <BezierSegment Point1="72.198,0" Point2="91.018,14.466" Point3="97.546,34.485"/> <BezierSegment IsSmoothJoin="True" Point1="99.139,39.369" Point2="98.999,40.084" Point3="98.999,45.499"/> </PathFigure> </PathGeometry> </Path.Data> <Path.Fill> <RadialGradientBrush GradientOrigin="0.498,0.526"> <RadialGradientBrush.RelativeTransform> <TransformGroup> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1" ScaleY="1.997"/> <TranslateTransform X="0" Y="0.5"/> </TransformGroup> </RadialGradientBrush.RelativeTransform> <GradientStop Offset="1" Color="#FFFFFFFF"/> <GradientStop Offset="0.85" Color="#92FFFFFF"/> <GradientStop Offset="0" Color="#00000000"/> </RadialGradientBrush> </Path.Fill> </Path>
最后。我添加一個ContentPresenter
到按鈕中間。經驗告訴我,內容區域再向下一個像素會使得按鈕看起來更漂亮。因此,在這里我用了margin屬性(注意。因為內容區域在Grid的中間(Center)。所以2個像素的top實際上是向下移動了一個像素 )
好了。最后在Blend中看起來大概是這樣
圖4
4.添加一些交互性
4.1鼠標懸停效果
為了有鼠標懸停效果,我們需要增加光源的亮度。因此。我們為IsMouseOver 事件定義一個觸發器,復制並且粘貼反射和折射層的漸變設置代碼。對於折射層。我僅僅移動了漸變的起點向上了一點。在反射層中。我改變了漸變停止點。使不透明的白色多一點。
<Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="RefractionLayer" Property="Fill"> <Setter.Value> <RadialGradientBrush GradientOrigin="0.496,1.052"> <RadialGradientBrush.RelativeTransform> <TransformGroup> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1.5" ScaleY="1.5"/> <TranslateTransform X="0.02" Y="0.3"/> </TransformGroup> </RadialGradientBrush.RelativeTransform> <GradientStop Offset="1" Color="#00000000"/> <GradientStop Offset="0.45" Color="#FFFFFFFF"/> </RadialGradientBrush> </Setter.Value> </Setter> <Setter TargetName="ReflectionLayer" Property="Fill"> <Setter.Value> <RadialGradientBrush GradientOrigin="0.498,0.526"> <RadialGradientBrush.RelativeTransform> <TransformGroup> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1" ScaleY="1.997"/> <TranslateTransform X="0" Y="0.5"/> </TransformGroup> </RadialGradientBrush.RelativeTransform> <GradientStop Offset="1" Color="#FFFFFFFF"/> <GradientStop Offset="0.85" Color="#BBFFFFFF"/> <GradientStop Offset="0" Color="#00000000"/> </RadialGradientBrush> </Setter.Value> </Setter> </Trigger>
4.2鼠標點擊效果
對於IsPressed
事件,需要降低光。因此。反向操作即可。折射層中光源下一點。反射層中漸變停止點更加透明一些。
<Trigger Property="IsPressed" Value="True"> <Setter TargetName="RefractionLayer" Property="Fill"> <Setter.Value> <RadialGradientBrush GradientOrigin="0.496,1.052"> <RadialGradientBrush.RelativeTransform> <TransformGroup> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1.5" ScaleY="1.5"/> <TranslateTransform X="0.02" Y="0.3"/> </TransformGroup> </RadialGradientBrush.RelativeTransform> <GradientStop Offset="1" Color="#00000000"/> <GradientStop Offset="0.3" Color="#FFFFFFFF"/> </RadialGradientBrush> </Setter.Value> </Setter> <Setter TargetName="ReflectionLayer" Property="Fill"> <Setter.Value> <RadialGradientBrush GradientOrigin="0.498,0.526"> <RadialGradientBrush.RelativeTransform> <TransformGroup> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1" ScaleY="1.997"/> <TranslateTransform X="0" Y="0.5"/> </TransformGroup> </RadialGradientBrush.RelativeTransform> <GradientStop Offset="1" Color="#CCFFFFFF"/> <GradientStop Offset="0.85" Color="#66FFFFFF"/> <GradientStop Offset="0" Color="#00000000"/> </RadialGradientBrush> </Setter.Value> </Setter> </Trigger>
再說一次。漸變停止點的值靠經驗選的。我也不能給出精確的值。
5.使用代碼
為了使用這個樣式。把定義在GlassButton.xaml 里的樣式資源文件並不到你的窗體/頁里。然后設置按鈕的樣式為{StaticResource GlassButton}
. 為了設置按鈕的顏色。使用Background屬性即可。
<Window x:Class="GlassButton.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Glass Buttons" Height="228" Width="272"> <Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Resources\GlassButton.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> <Grid> <Button Style="{StaticResource GlassButton}" Width="50" Height="50" Background="#FF660707" Margin="10"/> </Grid> </Window>
6.Demo下載
7.許可
本文包括源代碼和文件在CPOL下授權。