[原譯]一步步教你制作WPF圓形玻璃按鈕


圖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下載

Demo與源代碼下載

 

7.許可

本文包括源代碼和文件在CPOL下授權。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM