如何将Mask应用于CompositionBrush

时间:2017-01-24 12:10:31

标签: c# uwp win2d xaml-composition

<Grid>
    <Image x:Name="BackgroundImage" Source="/Assets/background.png" />
    <Rectangle x:Name="ClippingRect" Margin="50" Fill="#30f0" />
</Grid>

如何应用alpha蒙版或剪贴蒙版,以便除矩形之外的所有内容都会模糊?

我照常做的事:GraphicsEffect-&gt; EffectFactory-&gt; Brush-&gt;设置为SpriteVisual

 var graphicsEffect = new BlendEffect
 {
     Mode = BlendEffectMode.Multiply,
     Background = new ColorSourceEffect
     {
         Name = "Tint",
         Color = Windows.UI.Color.FromArgb(50,0,255,0),
     },

     Foreground = new GaussianBlurEffect()
     {
         Name = "Blur",
         Source =  new CompositionEffectSourceParameter("Backdrop"),
         BlurAmount = (float)20,
         BorderMode = EffectBorderMode.Hard,
     }
 };

 var blurEffectFactory = _compositor.CreateEffectFactory(graphicsEffect,
     new[] { "Blur.BlurAmount", "Tint.Color" });

 var _brush = blurEffectFactory.CreateBrush();
 _brush.SetSourceParameter("Backdrop", _compositor.CreateBackdropBrush());

 var blurSprite = _compositor.CreateSpriteVisual();
 blurSprite.Size = new Vector2((float)BackgroundImage.ActualWidth, (float)BackgroundImage.ActualHeight);
 blurSprite.Brush = _brush;
 ElementCompositionPreview.SetElementChildVisual(BackgroundImage, blurSprite);

enter image description here

2 个答案:

答案 0 :(得分:2)

您可以使用以下使用两次相同图像的解决方案。 我使用一个用于模糊背景,一个用于剪切前景。

我们的想法是使用前景视觉的Clip属性绘制全尺寸背景,并在其上仅绘制所需的剪裁区域。

页面/控件的XAML:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Image x:Name="BackgroundImage" Source="/Assets/Purple Tentacle.png" />
    <Image x:Name="ClippedImage" Source="/Assets/Purple Tentacle.png" />
</Grid>

背后的代码:

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
        _backgroundImageVisual  = ElementCompositionPreview.GetElementVisual(BackgroundImage);

        var graphicEffect   = new BlendEffect
        {
            Mode    = BlendEffectMode.Multiply,
            Background  = new ColorSourceEffect
            {
                Color= Color.FromArgb(50, 0, 255, 0)
            },

            Foreground = new GaussianBlurEffect
            {
                Source = new CompositionEffectSourceParameter("Backdrop"),
                BlurAmount  = 20.0f,
                BorderMode = EffectBorderMode.Hard
            }
        };


        var backdropBrush       = _compositor.CreateBackdropBrush();

        var blurEffectFactory   = _compositor.CreateEffectFactory(graphicEffect);
        _brush                  = blurEffectFactory.CreateBrush();
        _brush.SetSourceParameter("Backdrop", backdropBrush);

        _blurSprite          = _compositor.CreateSpriteVisual();
        _blurSprite.Brush    = _brush;

        ElementCompositionPreview.SetElementChildVisual(BackgroundImage, _blurSprite);

        _foregroundImageVisual  = ElementCompositionPreview.GetElementVisual(ClippedImage);
        _foregroundImageVisual.Clip = _compositor.CreateInsetClip(100, 100, 100, 100);

        SizeChanged += MainPage_SizeChanged;
        MainPage_SizeChanged(this, null);
    }

    private void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        _blurSprite.Size    = new Vector2((float) BackgroundImage.ActualWidth, (float) BackgroundImage.ActualHeight);

        // change the clip values here to change the non-blurred region
        _foregroundImageVisual.Clip = _compositor.CreateInsetClip(100, 100, 100, 100);
    }

enter image description here

答案 1 :(得分:0)

在Creators更新中,我可以创建派生自<Grid> <Image x:Name="BackgroundImage" Source="/Assets/background.png" /> <Path> <Path.Fill> <local:BlurTintBrush BlurRadius="5" TintColor="Black" TintOpacity="0.7" /> </Path.Fill> <Path.Data> <GeometryGroup> <RectangleGeometry x:Name="ImageGeometry" Rect="0,0,1027,768" / <RectangleGeometry x:Name="CropGeometry" Rect="50,50,25,25" /> </GeometryGroup> </Path.Data> </Path> </Grid> 的类并将其应用于xaml元素,因此它会模糊:

extension UIViewController {
    static func instanceWithDefaultNib() -> Self {
        let className = NSStringFromClass(self).components(separatedBy: ".").last
        return self.init(nibName: className, bundle: nil)
    }
}