自从iOS 7引入了毛玻璃效果以来,我一直在尝试创建类似的东西。现在有了Win2D,使用WinRT创建类似的效果就变得简单多了。
首先,您需要从NuGet获取Win2D.uwp包。
我们的想法是基于图像源创建一个GaussianBlurEffect,并将其放在另一个白色掩模上方,以模仿毛玻璃的外观。
要准备好GaussianBlurEffect,您需要从Win2D库创建一个xaml控件CanvasControl。因此,UI结构如下:
<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>
注意,我已经为“Overlay”元素创建了一个“Clip”,因为我需要在将其向左滑动时减少“Rect”的第三个参数(即“宽度”),以制造“Overlay”似乎随着手指滑动的错觉。
后面的代码非常简单-
void Canvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args)
{
args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction());
}
async Task CreateResourcesAsync(CanvasControl sender)
{
await Task.Delay(200);
using (var stream = new InMemoryRandomAccessStream())
{
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);
_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,
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)
{
_x = (float)this.ImagePanel2.ActualWidth;
}
void Overlay_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
_x += (float)e.Delta.Translation.X;
if (_x > this.ImagePanel2.ActualWidth || _x < 0) return;
this.Clip.Rect = new Rect(0, 0, _x, this.ImagePanel2.ActualHeight);
}
void Overlay_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
this.Clip.Rect = new Rect(0, 0, this.ImagePanel2.ActualWidth, this.ImagePanel2.ActualHeight);
}
你可以进一步调整
BlurAmount
属性以及不透明度数值(
0.9f
),以获得你想要的确切效果。
另外需要注意的是,未来可能会有另一种(更好的?)方法来实现这一点。如果
new Composition API在将来的版本中支持
GaussianBlurEffect
,我会更新答案。
你可以从这个GitHub
repo中找到当前的工作样例。我在这里附上了一张图片以展示它的样子。 :)
![enter image description here](https://istack.dev59.com/eWJbG.gif)