How to make frosted glass effect in Windows 10 Universal App?

So, how to make such an effect using C # and XAML?

http://i.stack.imgur.com/L2Zhc.gif

+4
source share
2 answers

I have been trying to create something like this since iOS 7 introduced frosted glass. Now thanks to Win2D it is much easier to create similar effects in WinRT.

First you need to get the Win2D.uwp package from NuGet.

The idea is to create a GaussianBlurEffect based on the image source and place it on top of another white color mask to simulate the appearance of frosted glass.

To get the GaussianBlurEffect ready, you will need to create the CanvasControl from the Win2D library. Thus, the user interface structure looks something like this:

 <Grid x:Name="ImagePanel2" Width="356" Height="200" Margin="0,0,0,40" VerticalAlignment="Bottom"> <Image x:Name="Image2" Source="Assets/Food.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> <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Frosted Glass" VerticalAlignment="Top" Foreground="#FF595959" Margin="12,12,0,0" FontWeight="Light" FontSize="26.667" FontStyle="Italic" TextLineBounds="Tight" /> </Grid> 

Note. I created the Clip element for the Overlay element because I need to reduce the third Rect parameter (i.e. width) while I pan it to the left to create the illusion that Overlay slides along with my finger.

The code behind is pretty simple -

 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 instead await Task.Delay(200); using (var stream = new InMemoryRandomAccessStream()) { // get the stream from the background image var 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 value Source = _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) { // reset the inital with of the Rect _x = (float)this.ImagePanel2.ActualWidth; } void Overlay_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) { // get the movement on X axis _x += (float)e.Delta.Translation.X; // keep the pan within the bountry if (_x > this.ImagePanel2.ActualWidth || _x < 0) return; // we clip the overlay to reveal the actual image underneath this.Clip.Rect = new Rect(0, 0, _x, this.ImagePanel2.ActualHeight); } void Overlay_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) { // reset the clip to show the full overlay this.Clip.Rect = new Rect(0, 0, this.ImagePanel2.ActualWidth, this.ImagePanel2.ActualHeight); } 

You can also set the BlurAmount property as well as the opacity indicator ( 0.9f ) to get the exact effect you want.

It should also be noted that in the future there may be another (better?) Way to do this. If the new API supports GaussianBlurEffect in a future version, I will update the answer.

You can find the current working sample from this GitHub repository . And I added an image here to demonstrate how it looks. :)

enter image description here

+9
source

You should look into Win2D classes and where there are Canvas effects, there are GaussianBlurEffect that can be useful. Here's the link: http://microsoft.imtqy.com/Win2D/html/N_Microsoft_Graphics_Canvas_Effects.htm and for GaussianBlurEffect: http://microsoft.imtqy.com/Win2D/html/T_Microsoft_Graphics_Canvas_Effects_Gaect.txt Code examples.

Addition: if you want to know how to use win2D, I just found a convenient tutorial (which I myself am watching right now :)) http://blogs.msdn.com/b/uk_faculty_connection/archive/2014/09/05/ win2d.aspx

+2
source

All Articles