首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

WPF 實作漸變淡入淡出登入視窗:OpacityMask 動畫完整教學

     編輯:ASP.NET 基礎

前言

WPF 強大的繪圖與動畫系統,讓我們能輕易實作出極具視覺衝擊力的視窗轉場效果。本文示範如何利用 `OpacityMask` 搭配 `LinearGradientBrush` 與 `Storyboard` 動畫,打造漸變淡入(載入時)與淡出(關閉時)的登入視窗。

核心原理

  1. OpacityMask:使用畫筆定義元素各區域的不透明度,黑色為完全不透明,透明色為完全透明
  2. LinearGradientBrush:線性漸變畫筆,透過調整 `GradientStop` 的 `Offset` 與 `Color` 產生漸變遮罩
  3. Storyboard 動畫:對 `GradientStop.Offset` 與 `Color` 進行動畫,產生「由上而下」或「由下而上」的漸變顯示/隱藏效果

一、XAML 完整實作(淡入動畫)

主視窗 XAML

<Window x:Class="WpfFadeWindow.MainWindow"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        Title="登入系統" Height="350" Width="500"
        WindowStyle="None" AllowsTransparency="True" Background="Transparent"
        Loaded="Window_Loaded">
    
    <Window.Resources>
        <!-- 淡出動畫資源(關閉時使用) -->
        <Storyboard x:Key="CloseStoryboard" x:Name="closeStoryboard">
            <DoubleAnimation Storyboard.TargetName="LoginGrid"
                             Storyboard.TargetProperty="OpacityMask.(GradientBrush.GradientStops)[1].Offset"
                             From="1" To="0" Duration="0:0:2" />
            <DoubleAnimation Storyboard.TargetName="LoginGrid"
                             Storyboard.TargetProperty="OpacityMask.(GradientBrush.GradientStops)[2].Offset"
                             From="1" To="0" Duration="0:0:1.5" BeginTime="0:0:0.5" />
            <ColorAnimation Storyboard.TargetName="LoginGrid"
                            Storyboard.TargetProperty="OpacityMask.(GradientBrush.GradientStops)[2].Color"
                            To="#00000000" Duration="0" />
        </Storyboard>
        
        <!-- 淡出用漸變畫筆(初始全不透明) -->
        <LinearGradientBrush x:Key="CloseBrush" StartPoint="0.5,0" EndPoint="0.5,1">
            <GradientStop Color="#FF000000" Offset="0" />
            <GradientStop Color="#FF000000" Offset="1" />
            <GradientStop Color="#FF000000" Offset="1" />
        </LinearGradientBrush>
    </Window.Resources>

    <Grid x:Name="LoginGrid" Background="White">
        <!-- 淡入用漸變遮罩(初始全透明) -->
        <Grid.OpacityMask>
            <LinearGradientBrush StartPoint="0.5,1" EndPoint="0.5,0">
                <GradientStop Color="#00000000" Offset="0" />
                <GradientStop Color="#00000000" Offset="1" />
                <GradientStop Color="#00000000" Offset="1" />
            </LinearGradientBrush>
        </Grid.OpacityMask>

        <!-- 淡入觸發器:視窗載入時自動播放 -->
        <Grid.Triggers>
            <EventTrigger RoutedEvent="Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <!-- 第 2 個 GradientStop:從 Offset=1 移至 0 -->
                        <DoubleAnimation Storyboard.TargetProperty="OpacityMask.(GradientBrush.GradientStops)[1].Offset"
                                         From="1" To="0" Duration="0:0:1.5" />
                        <!-- 第 3 個 GradientStop:延遲 0.5s 開始 -->
                        <DoubleAnimation Storyboard.TargetProperty="OpacityMask.(GradientBrush.GradientStops)[2].Offset"
                                         From="1" To="0" Duration="0:0:1" BeginTime="0:0:0.5" />
                        <!-- 第 3 個 GradientStop:顏色從透明變黑 -->
                        <ColorAnimation Storyboard.TargetProperty="OpacityMask.(GradientBrush.GradientStops)[2].Color"
                                        To="#FF000000" Duration="0" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Grid.Triggers>

        <!-- 登入表單內容 -->
        <StackPanel VerticalAlignment="Center" Margin="40">
            <TextBlock Text="系統登入" FontSize="24" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,0,0,20"/>
            <TextBlock Text="帳號:" Margin="0,5"/>
            <TextBox x:Name="txtAccount" Height="30" Margin="0,0,0,10"/>
            <TextBlock Text="密碼:" Margin="0,5"/>
            <PasswordBox x:Name="txtPassword" Height="30" Margin="0,0,0,20"/>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Button x:Name="btnLogin" Content="登入" Width="80" Height="30" Margin="0,0,10,0" Click="btnLogin_Click"/>
                <Button x:Name="btnCancel" Content="取消" Width="80" Height="30" Click="btnCancel_Click"/>
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

二、後端程式碼(淡出關閉邏輯)

using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace WpfFadeWindow
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // 淡入動畫完全由 XAML EventTrigger 處理,這裡可為空
        }

        private void btnLogin_Click(object sender, RoutedEventArgs e)
        {
            // 驗證邏輯...
            bool success = true; // 假設驗證通過
            
            if (success)
            {
                // 開啟主視窗並關閉登入視窗
                var main = new MainAppWindow();
                main.Show();
                this.Close(); // 直接關閉,無淡出效果(或依需求加淡出)
            }
            else
            {
                MessageBox.Show("帳號或密碼錯誤");
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            // 1. 禁用介面防止重複點擊
            this.IsEnabled = false;

            // 2. 套用淡出用畫筆(全不透明狀態開始淡出)
            LoginGrid.OpacityMask = this.Resources["CloseBrush"] as LinearGradientBrush;

            // 3. 取得並啟動淡出動畫
            var storyboard = this.Resources["CloseStoryboard"] as Storyboard;
            
            // 4. 動畫完成後真正關閉視窗
            storyboard.Completed += (s, args) => this.Close();
            
            storyboard.Begin();
        }
    }
}

三、關鍵技術細節解析

GradientStop 索引對應

<LinearGradientBrush>
    <GradientStop x:Name="stop0" Color="#00000000" Offset="0" />  <!-- 索引 0:起始端 -->
    <GradientStop x:Name="stop1" Color="#00000000" Offset="1" />  <!-- 索引 1:中間控制點 -->
    <GradientStop x:Name="stop2" Color="#00000000" Offset="1" />  <!-- 索引 2:結束端 -->
</LinearGradientBrush>

動畫針對 `stop1` 與 `stop2` 的 `Offset` 從 1→0 移動,配合 `stop2` 的 `Color` 從透明→黑,產生「由下往上」或「由上往下」的漸變揭露效果。

StartPoint / EndPoint 方向控制

  • 淡入:`StartPoint="0.5,1" EndPoint="0.5,0"`(從下往上)
  • 淡出:`StartPoint="0.5,0" EndPoint="0.5,1"`(從上往下)

AllowsTransparency="True" 必要條件

視窗必須設定:

WindowStyle="None" 
AllowsTransparency="True" 
Background="Transparent"

否則 `OpacityMask` 只會在視窗客戶區內生效,無法實現整個視窗的漸變。

四、效果展示

WPF 漸變淡入淡出登入視窗效果展示

五、擴充應用建議

  1. 通用化基底類別:建立 `FadeWindowBase` 繼承 `Window`,封裝淡入/淡出邏輯,所有視窗繼承即可使用
  2. 多種漸變方向:支援左→右、右→左、放射狀等效果
  3. 搭配 EasingFunction:加入 `CubicEase`、`BounceEase` 等緩動函數豐富動畫手感
  4. MVVM 友善:使用 Attached Property 或 Behavior 將動畫觸發綁定至 ViewModel 指令

總結

WPF 的 `OpacityMask` + `GradientBrush` + `Storyboard` 組合,提供了極具彈性的視窗轉場實作方式。完全宣告式的 XAML 淡入動畫與程式碼觸發的淡出動畫相輔相成,無需第三方函式庫即可打造專業級的使用者體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved