Z 深度和陰影

A gif showing four gray rectangles that are stacked diagonally, one on top of the other. The gif is animated so that shadows appear and disappear.

在 UI 中建立元素的視覺階層,可讓 UI 輕鬆掃描並傳達應該聚焦的重要事項。 系統往往會運用立體高度 (強調 UI 的重要元素) 在軟體中達到階層效果。 本文探討如何使用 z 深度和陰影在 Windows 應用程式中建立立體高度。

Z 深度是在 3D 應用程式製作者之間通用的詞彙,用來表示沿著 Z 軸的兩個表面之間的距離, 展現了物件與檢視者之間有多近。 可以將其視為類似於 x/y 座標的概念,但為 z 的方向。

Windows 應用程式會使用陰影來表達深度並新增視覺階層。 為了實現這一點,z 軸提供了一個簡單的編碼路徑。 然而,陰影是模擬的; 它們並不是以真正的 3D 方式顯示。 這樣我們就可以在不犧牲應用程式 UI 效能的情況下獲得深度感。

為何使用 z 深度?

在現實世界中,人類傾向於對焦於離自己較近的物件。 這種空間直覺也可以套用至數位 UI。 例如,如果將元素靠近使用者,則使用者會直覺地將焦點放在該元素上。 藉由在 z 軸上移近 UI 元素,您可以在物件之間建立視覺層級,讓使用者在應用程式中自然且有效率地完成任務。

什麼是陰影?

陰影是使用者感知立體高度圖的一種方式。 高架物件上方的光線會在下方的表面上產生陰影。 物件越高,陰影面積變得越大且越柔和。 UI 中的高架物件不需要陰影,但是陰影有助於展現立體高度的外觀。

在 Windows 應用程式中,應該基於明確的目的使用陰影,而非出於美觀。 使用太多陰影會降低或消除使用者透過陰影聚焦的能力。

如果您使用標準控制項,則陰影已合併到您的 UI 中。 不過,您可以使用 ThemeShadowDropShadow API,在 UI 中手動加入陰影。

ThemeShadow

ThemeShadow 類型可套用至任何 XAML 元素,以根據 x、y、z 座標適當繪製陰影。

  • 它會根據 z 深度值將陰影套用至元素,模擬深度。
  • 由於內建的陰影美學,它可以在整個應用程式中保持陰影一致。

以下會介紹在 MenuFlyout 上實作 ThemeShadow 的方式。 MenuFlyout 具有一個內建陰影,深度為 32px,其為套用至主功能表和所有巢狀功能表。

A screen shot of ThemeShadow applied to a MenuFlyout with three open, nested menus.

通用控制項中的 ThemeShadow

除非另有指定,否則以下通用控制項將自動使用 ThemeShadow 投射 32px 深度的陰影:

注意

ThemeShadow 於 Windows 10 版本 1903 (SDK 18362) 中引入。 它在 Windows 11 中更新為使用 ninegrid 陰影,而不是投影陰影,以獲得更好的效能。

快顯中的 ThemeShadow

通常,在需要使用者注意並快速採取動作的情況下,應用程式的 UI 會使用快顯。 這些是使用陰影以在應用程式 UI 中建立階層的優良範例。

當套用至快顯中的任何 XAML 元素時,ThemeShadow 會自動投射陰影。 它會在後方的應用程式背景內容以及下方其他任何開啟的快顯上,投射陰影。

若要將 ThemeShadow 與快顯搭配使用,請使用 Shadow 屬性,以將 ThemeShadow 套用至 XAML 元素。 再從其背後的其他元素提高元素,例如使用 Translation 屬性的 z 元件。 對於大多數的快顯 UI,與應用程式背景內容相對的建議預設立體高度為 32 有效像素。

此範例的快顯中的矩形,會將陰影投射到應用程序背景內容及其後面的任何其他快顯上:

<Popup>
    <Rectangle x:Name="PopupRectangle" Fill="Lavender" Height="48" Width="96">
        <Rectangle.Shadow>
            <ThemeShadow />
        </Rectangle.Shadow>
    </Rectangle>
</Popup>
// Elevate the rectangle by 32px
PopupRectangle.Translation += new Vector3(0, 0, 32);

A single rectangular popup with a shadow.

停用自訂飛出視窗控制項的預設 ThemeShadow

FlyoutDatePickerFlyoutMenuFlyoutTimePickerFlyout 為基礎的控制項,會自動使用 ThemeShadow 以投射陰影。

如果預設陰影在控制項的內容上看起來不正確,您可以在相關的 FlyoutPresenter 上,將 IsDefaultShadowEnabled 屬性設為 false,將其停用:

<Flyout>
    <Flyout.FlyoutPresenterStyle>
        <Style TargetType="FlyoutPresenter">
            <Setter Property="IsDefaultShadowEnabled" Value="False" />
        </Style>
    </Flyout.FlyoutPresenterStyle>
</Flyout>

其他元素中的 ThemeShadow

注意

從 Windows 11 開始,如果應用程式針對 Windows SDK 版本 22000 或更新版本,則將忽略 Receivers 集合。 但這不會造成任何錯誤,且陰影會繼續運作。

在一般情況下,建議您仔細考慮陰影的使用方式,用途僅限於展現有意義的視覺階層。 不過如果您有進階案例需要此功能,確實有方式可從任何 UI 元素投射陰影。

如果要從並非位在快顯中的 XAML 元素投射陰影,必須明確指定可以在 ThemeShadow.Receivers 集合中接收陰影的其他元素。 接收者不可以是視覺化樹狀結構中投射者的上階。

此範例顯示兩個矩形,會將陰影投射到它們後面的網格:

<Grid>
    <Grid.Resources>
        <ThemeShadow x:Name="SharedShadow" />
    </Grid.Resources>

    <Grid x:Name="BackgroundGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" />

    <Rectangle x:Name="Rectangle1" Height="100" Width="100" Fill="Turquoise" Shadow="{StaticResource SharedShadow}" />

    <Rectangle x:Name="Rectangle2" Height="100" Width="100" Fill="Turquoise" Shadow="{StaticResource SharedShadow}" />
</Grid>
/// Add BackgroundGrid as a shadow receiver and elevate the casting buttons above it
SharedShadow.Receivers.Add(BackgroundGrid);

Rectangle1.Translation += new Vector3(0, 0, 16);
Rectangle2.Translation += new Vector3(120, 0, 32);

Two turquoise rectangles next to each other, both with shadows.

投影

DropShadow 不提供內建陰影值,您需要自行指定它們。 如需實作範例,請參閱 DropShadow

提示

從 Windows 11 開始,如果應用程式是針對 Windows SDK 版本 22000 或更新版本,ThemeShadow 將表現得像投影一樣。 如果您使用的是 DropShadow,可以考慮使用 ThemeShadow。

我應該使用哪一種陰影?

屬性 ThemeShadow DropShadow
SDK 最低版本 SDK 18362 SDK 14393
適應性 No
自訂 Yes
光源
在 3D 環境中支援 是 (雖然它在 3D 環境中運作,但會模擬陰影。 No
  • 請記住,陰影的用途是展現有意義的階層,而非簡單的視覺處理。
  • 一般來說,建議使用 ThemeShadow,其能提供一致的陰影值。
  • 如有效能方面的考量,請限制陰影數目,使用其他視覺處理,或使用 DropShadow。
  • 如果您有更多進階案例要實作視覺階層,請考慮使用其他視覺處理 (例如顏色)。 如果需要陰影,請使用 DropShadow。