win10 uwp 毛玻璃
版權聲明:博客已遷移到 http://lindexi.gitee.io 歡迎訪問。如果當前博客圖片看不到,請到 http://lindexi.gitee.io 訪問博客。本文地址 https://blog.csdn.net/lindexi_gd/article/details/73456809
毛玻璃在UWP很簡單,不會和WPF那樣傷性能。
本文告訴大家,如何在 UWP 使用 win2d 做毛玻璃。
毛玻璃可以使用 win2D 方法,也可以使用 Compositor 。
使用 win2d 得到軟件內控件毛玻璃,而使用 Compositor 可以獲得窗口毛玻璃。
先來說下如何使用 Compositor 做窗口毛玻璃,感覺小伙伴感興趣的是窗口毛玻璃。
Compositor 創建毛玻璃
先寫最簡單的頁面,只有一個 Grid, 給他名稱 GlassHost,這個控件用于顯示毛玻璃
<Grid x:Name="GlassHost"></Grid>然后在構造函數使用InitializeFrostedGlass,這個函數用于在一個控件顯示毛玻璃
public MainPage(){InitializeComponent();InitializeFrostedGlass(GlassHost);}private void InitializeFrostedGlass(UIElement glassHost){Visual hostVisual = ElementCompositionPreview.GetElementVisual(glassHost);Compositor compositor = hostVisual.Compositor;var backdropBrush = compositor.CreateHostBackdropBrush();var glassVisual = compositor.CreateSpriteVisual();glassVisual.Brush = backdropBrush;ElementCompositionPreview.SetElementChildVisual(glassHost, glassVisual);var bindSizeAnimation = compositor.CreateExpressionAnimation("hostVisual.Size");bindSizeAnimation.SetReferenceParameter("hostVisual", hostVisual);glassVisual.StartAnimation("Size", bindSizeAnimation);}這樣就可以看到毛玻璃效果
這個代碼是從 http://www.jianshu.com/p/3b49fd3d7edb 復制的
大概解釋一下, compositor.CreateHostBackdropBrush() 獲得 創建之前繪制窗口后面視覺效果的區域,然后把他添加到Grid就可以了。
但是模糊的玻璃可以看不到里面控件,于是就把控件放在一個Grid 的最前,這樣看起來背景就是毛玻璃
<Grid > 最外層的 Grid 不要設置 BackGround <Grid x:Name="GlassHost"></Grid> 把他放在最前<ListView ItemsSource="{x:Bind AvaloniaCol}" IsItemClickEnabled="True" ItemClick="ListViewBase_OnItemClick" ><ListView.ItemTemplate><DataTemplate><Grid Background="#FFFFFF" PointerPressed="UIElement_OnPointerPressed"><TextBlock Text="{Binding}"></TextBlock></Grid></DataTemplate></ListView.ItemTemplate></ListView><Button Content="添加" Click="ButtonBase_OnClick"></Button> 可以看到按鈕,是清晰的</Grid>如何去掉標題欄,上面的博客也有說,于是我就不多說啦。
win2D
下面介紹使用 win2d 做毛玻璃
使用 win2D 方法,需要使用 Nuget 安裝,如果速度太慢,推薦使用博客園的鏡像
這個方法可以獲得控件的毛玻璃,但是不可以獲得窗口毛玻璃
接下來告訴大家如何做上圖的效果。
但是可以看到,上面的圖做了其他的,如拖動時顯示后面的圖片。為了顯示最短的代碼,讓大家知道毛玻璃是如何做的,下面先來做效果。
第一步,獲得顯示的圖片
參見:win10 uwp 截圖 獲取屏幕顯示界面保存圖片
于是在界面顯示一個圖片,界面的左邊就是圖片,右邊就是毛玻璃。之所以需要獲得圖片的截圖是因為毛玻璃需要輸入源,于是界面代碼如下
<Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><Grid Margin="10 10 10 10">必須把圖片的路徑修改為自己工程的路徑,需要在工程存在圖片<Image x:Name="Image" Source="Assets/2017年5月31日 210702.jpg" Stretch="UniformToFill" /></Grid><Grid Grid.Column="1" Margin="10 10 10 10"><xaml:CanvasControl x:Name="Canvas" CreateResources="Canvas_CreateResources" Draw="Canvas_Draw" /></Grid>毛玻璃效果寫在 CanvasControl ,
需要對顯示截圖,把圖片做效果。然后把得到的效果顯示
但是在什么時候截圖?也就是什么時候才是截圖最好的時候?
我認為可以在 CreateResources 事件進行截圖,請看代碼
void Canvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args){args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction());}async Task CreateResourcesAsync(CanvasControl sender){// give it a little bit delay to ensure the image is load, ideally you want to Image.ImageOpened event insteadawait Task.Delay(200); 這是等待圖片加載,因他發生在控件初始之后,而圖片加載發生在圖片控件初始的時候,但是圖片加載需要時間,所以這里等待一下。我覺得這是比較差的方法using (var stream = new InMemoryRandomAccessStream()){// get the stream from the background imagevar target = new RenderTargetBitmap(); 這就是截圖await target.RenderAsync(Image);var pixelBuffer = await target.GetPixelsAsync();var pixels = pixelBuffer.ToArray();var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint) target.PixelWidth, (uint) target.PixelHeight, 96 如果 dpi 不是96 那么這里需要寫實際的,為了簡單,我就不寫如何獲得dpi, 96, pixels);await encoder.FlushAsync();stream.Seek(0);// load the stream into our bitmap_bitmap = await CanvasBitmap.LoadAsync(sender, stream);}}第二步就是把圖片進行效果,代碼很少
void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args){using (var session = args.DrawingSession){var blur = new GaussianBlurEffect{BlurAmount = 50.0f, // increase this to make it more blurry or vise versa.//Optimization = EffectOptimization.Balanced, // default value//BorderMode = EffectBorderMode.Soft // default valueSource = _bitmap};session.DrawImage(blur, new Rect(0, 0, sender.ActualWidth, sender.ActualHeight),new Rect(0, 0, _bitmap.SizeInPixels.Width, _bitmap.SizeInPixels.Height), 0.9f);}}現在看起來就是
如果需要修改模糊,請把 BlurAmount 修改為你想要的
上面的代碼就是主要的,接下來就是做上圖的效果
首先xaml代碼:
<Grid x:Name="ImagePanel2" Width="356" Height="200" Margin="0,0,0,40" VerticalAlignment="Bottom"><Image x:Name="Image2" Source="Assets/2017年5月31日 210702.jpg" Stretch="UniformToFill" /><Grid x:Name="Overlay" ManipulationMode="TranslateX" ManipulationStarted="Overlay_ManipulationStarted" ManipulationDelta="Overlay_ManipulationDelta" ManipulationCompleted="Overlay_ManipulationCompleted" RenderTransformOrigin="0.5,0.5"><Grid.Clip><RectangleGeometry x:Name="Clip" Rect="0, 0, 356, 200" /></Grid.Clip><Rectangle x:Name="WhiteMask" Fill="White" /><xaml:CanvasControl x:Name="Canvas" CreateResources="Canvas_CreateResources" Draw="Canvas_Draw" /></Grid></Grid>可以看到,這里引用 CanvasControl ,還有很多代碼需要寫在后面
void Canvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args){args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction());}async Task CreateResourcesAsync(CanvasControl sender){// give it a little bit delay to ensure the image is load, ideally you want to Image.ImageOpened event insteadawait Task.Delay(200);using (var stream = new InMemoryRandomAccessStream()){// get the stream from the background imagevar target = new RenderTargetBitmap();await target.RenderAsync(this.Image2);var pixelBuffer = await target.GetPixelsAsync();var pixels = pixelBuffer.ToArray();var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint) target.PixelWidth, (uint) target.PixelHeight, 96, 96, pixels);await encoder.FlushAsync();stream.Seek(0);// load the stream into our bitmap_bitmap = await CanvasBitmap.LoadAsync(sender, stream);}}void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args){using (var session = args.DrawingSession){var blur = new GaussianBlurEffect{BlurAmount = 50.0f, // increase this to make it more blurry or vise versa.//Optimization = EffectOptimization.Balanced, // default value//BorderMode = EffectBorderMode.Soft // default valueSource = _bitmap};session.DrawImage(blur, new Rect(0, 0, sender.ActualWidth, sender.ActualHeight),new Rect(0, 0, _bitmap.SizeInPixels.Width, _bitmap.SizeInPixels.Height), 0.9f);}}void Overlay_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e){// 重新設置 _x_x = (float) this.ImagePanel2.ActualWidth;}void Overlay_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e){//獲得當前的x,用于下面計算_x += (float) e.Delta.Translation.X;//如果當前的x超過了,或者已經最小if (_x > ImagePanel2.ActualWidth || _x < 0)return;//我們剪輯覆蓋,用于顯示下面的圖片Clip.Rect = new Rect(0, 0, _x, this.ImagePanel2.ActualHeight);}void Overlay_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e){// 重置剪輯顯示完整的覆蓋Clip.Rect = new Rect(0, 0, this.ImagePanel2.ActualWidth, this.ImagePanel2.ActualHeight);}上面的代碼就是獲得圖片,把圖片使用 GaussianBlurEffect 得到毛玻璃
實際代碼做的就是 如下面顯示,做出毛玻璃效果,其他代碼都是為了做剛才的圖
void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args){using (var session = args.DrawingSession){var blur = new GaussianBlurEffect{BlurAmount = 50.0f, // increase this to make it more blurry or vise versa.//Optimization = EffectOptimization.Balanced, // default value//BorderMode = EffectBorderMode.Soft // default valueSource = _bitmap};session.DrawImage(blur, new Rect(0, 0, sender.ActualWidth, sender.ActualHeight),new Rect(0, 0, _bitmap.SizeInPixels.Width, _bitmap.SizeInPixels.Height), 0.9f);}}關于拖動使用裁剪顯示后面的圖,我就不多說了,實際代碼看起來很多,但是不是很難,我就不說拉。
請看下面的效果,這就是不停修改 BlurAmount 得到。
代碼很簡單,所以我就不說。
最簡單方法
當然,還有最簡單的代碼,只需要一句話,請看文檔
Acrylic material
因為不知道微軟是否還更改,所以我就不寫了。
為了說明代碼的簡單,我需要給個例子,上面那么長的代碼,現在只需要一行
<Grid Background="{ThemeResource SystemControlAcrylicElementBrush}">參見:https://stackoverflow.com/questions/31987817/how-to-make-frosted-glass-effect-in-windows-10-universal-app
http://microsoft.github.io/Win2D/html/N_Microsoft_Graphics_Canvas_Effects.htm
(UWP)應用窗口實現毛玻璃效果 - 簡書
本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名林德熙(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用于商業目的,基于本文修改后的作品務必以相同的許可發布。如有任何疑問,請與我聯系。
總結
以上是生活随笔為你收集整理的win10 uwp 毛玻璃的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网易云轻舟微服务深度解读:基于开源,强于
- 下一篇: nosql介绍、memrcached介绍