Skip to content

[Feature] Composition Brush #20150

@zxbmmmmmmmmm

Description

@zxbmmmmmmmmm

Abstract

Currently, we can't create composition animations on Brush, and brush transitions is based on classic animation that runs on UI thread.

This can cause input lag and decreases in frame rate , which significantly reduces the user experience, especially on mobile devices.

Describe the solution you'd like

  • Introduce a CompositionBrush family (solid color, linear gradient, radial gradient, conic gradient) that runs animations on the composition thread.
  • Support explicit or implicit expression animations consistent with existing composition APIs .
  • [Future] Provide a simpler way to declare CompositionBrush and its animations in XAML.(previously discussed in [Draft] Add Xaml Composition Implicit Animations #19747)

We can create composition brushes and animate it like this:

var visual = ElementComposition.GetElementVisual(SolidBrushHost)!;
var compositor = visual.Compositor;
var brush = compositor.CreateSolidColorBrush(Colors.Red);
var animation = compositor.CreateColorKeyFrameAnimation();
animation.InsertKeyFrame(0f, Colors.Red);
animation.InsertKeyFrame(0.5f, Colors.Green);
animation.InsertKeyFrame(1f, Colors.Blue);
animation.Duration = TimeSpan.FromSeconds(5);
brush.StartAnimation("Color", animation);

APIs

+ public class CompositionBrush : CompositionObject, IBrush
+ public class CompositionSolidColorBrush : CompositionBrush, ISolidColorBrush
+ {
+     public Avalonia.Media.Color Color { get; set; }
+ }
+ public class CompositionGradientBrush : CompositionBrush, IGradientBrush
+ {
+     public List<IGradientStop> GradientStops { get; set; } 
+     IReadOnlyList<IGradientStop> IGradientBrush.GradientStops => GradientStops;
+     public GradientSpreadMethod SpreadMethod { get; set; }
+ }
+ public class CompositionLinearGradientBrush : CompositionGradientBrush, ILinearGradientBrush
+ {
+     public RelativePoint StartPoint { get; set; } 
+     public RelativePoint EndPoint { get; set; } 
+ }
+ public class CompositionRadialGradientBrush : CompositionGradientBrush, IRadialGradientBrush
+ {
+     public RelativePoint Center { get; set; } 
+     public RelativePoint GradientOrigin { get; set; } 
+     public RelativeScalar RadiusX { get; set; } = RelativeScalar.Middle;
+     public RelativeScalar RadiusY { get; set; } = RelativeScalar.Middle;
+ }
+ public class CompositionConicGradientBrush : CompositionGradientBrush, IConicGradientBrush
+ {
+     public double Angle { get; set; } 
+     public RelativePoint Center { get; set; } 
+ }
+ public class CompositionGradientStop : CompositionObject, IGradientStop
+ {
+     public Color Color { get; set; }
+     public double Offset { get; set; }
+ }
public class Compositor
{
+     public CompositionSolidColorBrush CreateSolidColorBrush()
+     public CompositionSolidColorBrush CreateSolidColorBrush(Color color)
+     public CompositionLinearGradientBrush CreateLinearGradientBrush()
+     public CompositionConicGradientBrush CreateConicGradientBrush()
+     public CompositionRadialGradientBrush CreateRadialGradientBrush()
+     public CompositionGradientStop CreateCompositionGradientStop(double offset, Color color)
}

Additional context

To verify feasibility, I edited composition-schema.xml to make the generator generate CompositionBrush on both server and client with animatable composition properties and made some changes to allow using it as Brush.

Here is the demo video:

20251127-0502-21.5374281.mp4

I can submit a PR in the future if accepted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions