Toolkit.UI.Controls.Avalonia
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.SceneGraph;
|
||||
using Avalonia.Skia;
|
||||
using Avalonia.Styling;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Toolkit.UI.Controls.Avalonia;
|
||||
|
||||
public class BlurBehind :
|
||||
Control
|
||||
{
|
||||
public static readonly StyledProperty<ExperimentalAcrylicMaterial> MaterialProperty =
|
||||
AvaloniaProperty.Register<BlurBehind, ExperimentalAcrylicMaterial>("Material");
|
||||
|
||||
public static readonly ImmutableExperimentalAcrylicMaterial DefaultAcrylicMaterialDark =
|
||||
(ImmutableExperimentalAcrylicMaterial)new ExperimentalAcrylicMaterial()
|
||||
{
|
||||
MaterialOpacity = 0.25,
|
||||
TintColor = Colors.Black,
|
||||
TintOpacity = 0.7,
|
||||
PlatformTransparencyCompensationLevel = 0
|
||||
}.ToImmutable();
|
||||
|
||||
public static readonly ImmutableExperimentalAcrylicMaterial DefaultAcrylicMaterialLight =
|
||||
(ImmutableExperimentalAcrylicMaterial)new ExperimentalAcrylicMaterial()
|
||||
{
|
||||
MaterialOpacity = 0.0,
|
||||
TintColor = Colors.White,
|
||||
TintOpacity = 0.3,
|
||||
PlatformTransparencyCompensationLevel = 0
|
||||
}.ToImmutable();
|
||||
|
||||
static BlurBehind()
|
||||
{
|
||||
AffectsRender<BlurBehind>(MaterialProperty);
|
||||
}
|
||||
|
||||
public ExperimentalAcrylicMaterial Material
|
||||
{
|
||||
get => GetValue(MaterialProperty);
|
||||
set => SetValue(MaterialProperty, value);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
ImmutableExperimentalAcrylicMaterial material = Material is not null
|
||||
? (ImmutableExperimentalAcrylicMaterial)Material.ToImmutable()
|
||||
: Application.Current?.ActualThemeVariant == ThemeVariant.Dark ? DefaultAcrylicMaterialDark : DefaultAcrylicMaterialLight;
|
||||
|
||||
context.Custom(new BlurBehindRenderOperation(material, new Rect(default, Bounds.Size)));
|
||||
}
|
||||
|
||||
private class BlurBehindRenderOperation(ImmutableExperimentalAcrylicMaterial material,
|
||||
Rect bounds) : ICustomDrawOperation
|
||||
{
|
||||
private readonly Rect bounds = bounds;
|
||||
private readonly ImmutableExperimentalAcrylicMaterial material = material;
|
||||
|
||||
public Rect Bounds => bounds.Inflate(4);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool Equals(ICustomDrawOperation? other) =>
|
||||
other is BlurBehindRenderOperation behindRenderOperation &&
|
||||
behindRenderOperation.bounds == bounds && behindRenderOperation.material.Equals(material);
|
||||
|
||||
public bool HitTest(Point point) => bounds.Contains(point);
|
||||
|
||||
public void Render(ImmediateDrawingContext context)
|
||||
{
|
||||
if (context.TryGetFeature<ISkiaSharpApiLeaseFeature>() is ISkiaSharpApiLeaseFeature leaseFeature)
|
||||
{
|
||||
using ISkiaSharpApiLease? lease = leaseFeature.Lease();
|
||||
if (lease.SkCanvas is SKCanvas canvas)
|
||||
{
|
||||
if (canvas.TotalMatrix.TryInvert(out SKMatrix currentInvertedTransform))
|
||||
{
|
||||
if (lease.SkSurface is SKSurface surface)
|
||||
{
|
||||
using SKImage backgroundSnapshot = surface.Snapshot();
|
||||
using SKShader backdropShader = SKShader.CreateImage(backgroundSnapshot, SKShaderTileMode.Clamp,
|
||||
SKShaderTileMode.Clamp, currentInvertedTransform);
|
||||
|
||||
using SKSurface blurred = SKSurface.Create(lease.GrContext, false,
|
||||
new SKImageInfo((int)Math.Ceiling(bounds.Width), (int)Math.Ceiling(bounds.Height),
|
||||
SKImageInfo.PlatformColorType, SKAlphaType.Premul));
|
||||
|
||||
using (SKImageFilter filter = SKImageFilter.CreateBlur(8, 8, SKShaderTileMode.Clamp))
|
||||
using (SKPaint blurPaint = new() { Shader = backdropShader, ImageFilter = filter })
|
||||
blurred.Canvas.DrawRect(5, 5, (float)bounds.Width - 20, (float)bounds.Height - 20, blurPaint);
|
||||
|
||||
using SKImage blurSnap = blurred.Snapshot();
|
||||
using SKShader blurSnapShader = SKShader.CreateImage(blurSnap);
|
||||
using SKPaint blurSnapPaint = new()
|
||||
{
|
||||
Shader = blurSnapShader,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
canvas.DrawRect(0, 0, (float)bounds.Width, (float)bounds.Height, blurSnapPaint);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user