概述 UWP Community Toolkit 中有一個為 Frmework Element 提供投影效果的控制項 - DropShadowPanel,本篇我們結合代碼詳細講解 DropShadowPanel 的實現。 DropShadowPanel 提供的陰影效果有很多應用場景,比如給文本提供陰影 ...
概述
UWP Community Toolkit 中有一個為 Frmework Element 提供投影效果的控制項 - DropShadowPanel,本篇我們結合代碼詳細講解 DropShadowPanel 的實現。
DropShadowPanel 提供的陰影效果有很多應用場景,比如給文本提供陰影,可以讓文本在背景變化時可以明顯顯示,比如地圖上的標尺文本;應用在圖形或圖片時,可以設置陰影效果,另外它有很多參數可以調整,如陰影偏移,顏色,透明度和陰影模糊半徑等,14393 開始支持,下麵看看官方示例的截圖:
Doc: https://docs.microsoft.com/zh-cn/windows/uwpcommunitytoolkit/controls/dropshadowpanel
Namespace: Microsoft.Toolkit.Uwp.UI.Controls; Nuget: Microsoft.Toolkit.Uwp.UI.Controls;
開發過程
代碼分析
我們先來看看 DropShadowPanel 控制項的類構成:
- DropShadowPanel.Properties.cs - DropShadowPanel 控制項部分類的依賴屬性類
- DropShadowPanel.cs - DropShadowPanel 控制項部分類的定義和處理方法
- DropShadowPanel.xaml - DropShadowPanel 控制項的樣式文件
1. DropShadowPanel.Properties.cs
DropShadowPanel 控制項部分類的依賴屬性類,定義了以下依賴屬性:
- Color - drop shadow 的顏色,變化時會觸發 OnColorChanged(d, e)
- BlurRadius - drop shadow 的模糊半徑,變化時會觸發 OnBlurRadiusChanged(d, e)
- OffsetX - drop shadow 的 x 軸方向偏移,變化時觸發 OnOffsetXChanged(d, e)
- OffsetY - drop shadow 的 y 軸方向偏移,變化時觸發 OnOffsetYChanged(d, e)
- OffsetZ - drop shadow 的 z 軸方向偏移,變化時觸發 OnOffsetZChanged(d, e)
- ShadowOpacity - drop shadow 的陰影透明度,變化時觸發 OnShadowOpacityChanged(d, e)
2. DropShadowPanel.cs
DropShadowPanel 控制項的定義和處理邏輯,類繼承自 ContentControl;先來看看構造方法:
確定系統版本支持滿足條件後,創建一個 Compositor 和 dropShadow,創建 shadowVisual,並用 dropShadow 給它賦值;
public DropShadowPanel() { this.DefaultStyleKey = typeof(DropShadowPanel); if (IsSupported) { Compositor compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; _shadowVisual = compositor.CreateSpriteVisual(); _dropShadow = compositor.CreateDropShadow(); _shadowVisual.Shadow = _dropShadow; } }
接著來看一下上面 DropShadowPanel.Properties.cs 中屬性的變化觸發事件,實際的處理方法都在 DropShadowPanel.cs 類中,處理過程就是把 newValue 賦值給 dropShadow;
而在 OnSizeChanged(s, e) 事件觸發時,以及初始化時,主要處理邏輯是 UpdateShadowSize() 方法:
方法處理中,獲取需要設置投影的 Content,得到實際顯示寬度和高度,賦值給 shadowVisual;作為 dropShadow 的顯示宿主;
private void UpdateShadowSize() { if (_shadowVisual != null) { Vector2 newSize = new Vector2(0, 0); if (Content is FrameworkElement contentFE) { newSize = new Vector2((float)contentFE.ActualWidth, (float)contentFE.ActualHeight); } _shadowVisual.Size = newSize; } }
更一個主要的處理方法是 UpdateShadowMask(),負責更新投影的 mask:
根據需要設置投影的 Content 類型,Image,Shape,TextBlock 或 ImageExBase,使用 GetAlphaMask() 來得到 alphaMask,賦值給 dropShadow 的 mask 屬性,作為投影效果的顯示效果;配合上面的 UpdateShadowSize() 方法,以及 Opacity,Offset 等屬性,正確顯示投影效果;
private void UpdateShadowMask() { if (!IsSupported) { return; } if (Content != null) { CompositionBrush mask = null; if (Content is Image) { mask = ((Image)Content).GetAlphaMask(); } else if (Content is Shape) { mask = ((Shape)Content).GetAlphaMask(); } else if (Content is TextBlock) { mask = ((TextBlock)Content).GetAlphaMask(); } else if (Content is ImageExBase imageExBase) { imageExBase.ImageExInitialized += ImageExInitialized; if (imageExBase.IsInitialized) { imageExBase.ImageExInitialized -= ImageExInitialized; mask = ((ImageExBase)Content).GetAlphaMask(); } } _dropShadow.Mask = mask; } else { _dropShadow.Mask = null; } }
3. DropShadowPanel.xaml
DropShadowPanel 控制項的樣式文件,我們來看 Template 部分:投影效果的實現,是使用一個 Border 放置在實際內容控制項的後面,通過 Border 中對內容的顯示和位置調整來實現投影。
<Style TargetType="controls:DropShadowPanel"> <Setter Property="IsTabStop" Value="False" /> <Setter Property="HorizontalAlignment" Value="Stretch"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="VerticalAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="controls:DropShadowPanel"> <Grid Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"> <Border x:Name="ShadowElement" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
調用示例
下麵的示例中,我們定義了兩個相同的 TextBlock,其中一個應用了 DropShadow,一個未應用,可以看出,應用了 DropShadow 的一個,文本明顯會有模糊的黑色陰影;
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Orientation="Vertical" VerticalAlignment="Center"> <controls:DropShadowPanel BlurRadius="10" ShadowOpacity="0.8" OffsetX="0" OffsetY="0" Color="Black" VerticalAlignment="Center" HorizontalAlignment="Center"> <TextBlock FontSize="20" TextWrapping="Wrap"> The DropShadowPanel Control allows the creation of a drop shadow effect for any Xaml FrameworkElement in the markup. You can control the following property of the drop shadow effect : Offset, Color, Opactity and Blur Radius. NOTE: Windows Anniversary Update (10.0.14393.0) is needed to support correctly this effect. </TextBlock> </controls:DropShadowPanel> <TextBlock TextWrapping="Wrap" FontSize="20" Margin="0,10,0,0"> The DropShadowPanel Control allows the creation of a drop shadow effect for any Xaml FrameworkElement in the markup. You can control the following property of the drop shadow effect : Offset, Color, Opactity and Blur Radius. NOTE: Windows Anniversary Update (10.0.14393.0) is needed to support correctly this effect. </TextBlock> </StackPanel> </Grid>
總結
到這裡我們就把 UWP Community Toolkit 中的 DropShadowPanel 控制項的源代碼實現過程和簡單的調用示例講解完成了,希望能對大家更好的理解和使用這個控制項有所幫助。歡迎大家多多交流,謝謝!
最後,再跟大家安利一下 UWPCommunityToolkit 的官方微博:https://weibo.com/u/6506046490, 大家可以通過微博關註最新動態。
衷心感謝 UWPCommunityToolkit 的作者們傑出的工作,Thank you so much, UWPCommunityToolkit authors!!!