简体   繁体   中英

Dropshadow with image blur UWP

I would like to get the result of the Windows video app blur. I did an image with a dropshadow, but giving the dropshadow only one color. Is it possible with win2d or other to get this result ,then use the image for the DropShadow?

在此输入图像描述

My MainPage.xaml:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Grid x:Name="grid"/>
        <Image x:Name="image" Source="Assets/image.jpg"/>
    </Grid>
</Grid>

My MainPage.xaml.cs:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    var compositor = ElementCompositionPreview.GetElementVisual(grid).Compositor;
    var spriteVisual = compositor.CreateSpriteVisual();
    spriteVisual.Size = new Vector2(200, 200);
    var dropShadow = compositor.CreateDropShadow();
    dropShadow.Offset = new Vector3(10, 10, 0);
    dropShadow.BlurRadius = 10;
    dropShadow.Color = Colors.Orange;
    spriteVisual.Shadow = dropShadow;
    ElementCompositionPreview.SetElementChildVisual(grid, spriteVisual);
}

Thanks for help.

This should get you started in creating the effect you're looking for. You'll need the UWP Community Toolkit library which is sponsored by Microsoft. It has this amazing animation syntax you'll see below, and it uses the Composition API under the hood. Tweak the blur, scale and fade as you see fit.

XAML

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center" PointerEntered="Grid_PointerEntered" PointerExited="Grid_PointerExited">
        <Image x:Name="imageBackdrop" Source="Assets/image.jpg" Opacity="0"/>
        <Image x:Name="image" Source="Assets/image.jpg"/>
    </Grid>
</Grid>

C#

using Microsoft.Toolkit.Uwp.UI.Animations;

private void Grid_PointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{    
  imageBackdrop.Fade(0.5f, 50).Scale(1.1f, 1.1f,0,0,0).Blur(75, 0).Offset(0, 20, 0).Start();
}

private void Grid_PointerExited(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{    
  imageBackdrop.Opacity = 0;
}

EDIT: Easier to just scale in XAML using a container. Also adding an opacity effect to the same element as a blur effect seems to make the blur effect cap out at a very low BlurAmount. Use something like this in combination with an opacity mask or something to darken it and feather the edges:

private void Grid_PointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
    var element = imageBackdrop;
    var visual = ElementCompositionPreview.GetElementVisual(element);
    var compositor = visual.Compositor;

    var effect = new GaussianBlurEffect()
    {
        Name = "Blur",
        Source = new CompositionEffectSourceParameter("EffectSource"),
        BlurAmount = 50f,
        BorderMode = EffectBorderMode.Soft,
    };

    var blurEffectFactory = compositor.CreateEffectFactory(effect, new[] { effect.Name + "." + nameof(effect.BlurAmount) });
    var brush = blurEffectFactory.CreateBrush();
    var destinationBrush = compositor.CreateBackdropBrush();
    brush.SetSourceParameter("EffectSource", destinationBrush);

    var sprite = compositor.CreateSpriteVisual();
    sprite.Size = new Vector2((float)(element.RenderSize.Width), (float)(element.RenderSize.Height));
    sprite.Brush = brush;
    ElementCompositionPreview.SetElementChildVisual(element, sprite);
    imageBackdropContainer.Opacity = 1;
}

private void Grid_PointerExited(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
    imageBackdropContainer.Opacity = 0;
}

在此输入图像描述

You can try to offset the same image with a lower Opacity to implement the similar effect using the CompositionSurfaceBrush .

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    var compositor = ElementCompositionPreview.GetElementVisual(grid).Compositor;
    var spriteVisual = compositor.CreateSpriteVisual();
    spriteVisual.Size = new Vector2(215, 215);

    var brush = compositor.CreateSurfaceBrush();
    LoadedImageSurface _loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/image.jpg"));
    brush.Surface = _loadedSurface;

    spriteVisual.Opacity = 0.1f;
    spriteVisual.Brush = brush;

    ElementCompositionPreview.SetElementChildVisual(grid, spriteVisual);
}

And this is the effect:

在此输入图像描述

DropShadowPanel from Windows Community Toolkit should achieve what you want. At least I used this to implement that. Then use VisualStateManager to set it's visibility to True when PointerOver.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM