Jus*_* XL 9

自iOS 7推出磨砂玻璃以来,我一直在努力创造这样的东西.现在感谢Win2D,在WinRT中创建类似的效果要简单得多.

首先,您需要从NuGet 获取Win2D.uwp包.

我们的想法是创建一个GaussianBlurEffect基于图像源,并将其放在另一个白色面具的顶部,以模仿磨砂玻璃外观.

GaussianBlurEffect准备好,您需要CanvasControl从Win2D库创建一个xaml控件.所以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>
Run Code Online (Sandbox Code Playgroud)

注意我已经ClipOverlay元素创建了一个'因为我需要减少Rect第三个参数(即宽度),而我向左平移它以产生一个幻觉,即Overlay我的手指在滑动.

背后的代码非常简单 -

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);
}
Run Code Online (Sandbox Code Playgroud)

您可以进一步调整BlurAmount属性以及不透明度图(0.9f)以获得您想要的确切效果.

还要注意,未来可能会有另一种(更好的?)方法.如果新的Composition API确实支持GaussianBlurEffect将来的版本,我将更新答案.

您可以从此GitHub 仓库中找到当前的工作样本.我在这里附上一张图片来展示它的样子.:)

在此输入图像描述