-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] New/Updated XAML/C# Animations Package #3638
Comments
Just... WOW!!! 👏👏👏 |
Spec Change Note: Added |
Hi @JustinXinLiu, was thinking we could go all-in with default parameters both on the C# side and in XAML to allow developers to write less code when just dealing with simple animations, while still getting some nice default values that could work in a good number of cases, like you suggested. Would these be default values that could work, as a baseline?
Of course, we can tweak the duration or easing if you had something else in mind for the default values. AnimationBuilder.New()
.Opacity(to: 0)
.Translation(Axis.X, to: 20)
.Start(MyButton); Another option would be to make the AnimationBuilder.New()
.Opacity(0)
.Translation(Axis.X, 20)
.Start(MyButton); This one would make simpler animations with just a target value particularly simple to define. <Button x:Name="MyButton">
<animations:Explicit.Animations>
<xaml:AnimationCollection x:Name="MyAnimation">
<xaml:OpacityAnimation To="0"/>
<xaml:TranslationAnimation To="20,0,0" />
</xaml:AnimationCollection>
</animations:Explicit.Animations>
</Button> And of course, more complex animations would be possible too, with additional parameters and methods (work in progress): AnimationBuilder.New()
.Opacity(from: 0, to: 1, duration: 600)
.Scale(from: 1.4, to: 1)
.NormalizedKeyFrames<double>(nameof(Visual.Rotation), b => b
.KeyFrame(0.0, 0)
.KeyFrame(0.4, 90, EasingType.Cubic)
.KeyFrame(0.8, -45)
.KeyFrame(1.0, 0, EasingType.Circle, EasingMode.EaseIn))
.TimedKeyFrames<Vector3>(nameof(Visual.Offset), b => b
.KeyFrame(200, Vector3.Zero)
.KeyFrame(600, new(40, 0, 0))
.KeyFrame(2000, new(20, 20, 0))
.Start(this); Any feedbacks are welcome! 😊 EDIT: fluent APIs to create custom animations with normalized keyframes now working 🚀 Custom keyframe composition animation (click to expand):SdJrglmlR1.mp4Custom keyframe XAML color animation (click to expand):Q4d0Ed1v0b.mp4Combining XAML + composition, both relative and timed keyframes (click to expand):hMFUNA88vr.mp4 |
I really hope WinUI itself starts taking some of the great ideas from the toolkit like this one. I've been astounded more than once by the things you come up with here. Having this level of advanced feature development in the framework itself is sorely missed. The whole animation system in WinUI XAML should be revised and this is a great start. I hope you can voice this internally once it all comes together. Using Lottie animations instead of expanding what XAML can do was one of my concerns: microsoft/microsoft-ui-xaml#1858 (comment) |
@Sergio0694 looking good! For the easing, is the Toolkit default the same as the Composition default? Because Composition explicit animation already has a default easing that follows the Fluent design guideline, and let's just make sure they are the same. 😉 Also, I wonder if it's worth creating an enum to store all the animation properties so we don't need to write them like |
@JustinXinLiu Awesome, glad to hear that! 😄
So far I mostly focused on the backend work for the package, so I just reused the same beizer curve control points that were in the Toolkit before. We'll double check to ensure the default ones match those that are used in the default animations, absolutely! 🙂
I definitely agree that having to pass the property name as a string when doing animations with custom keyframes is not ideal, so I ended up reworking those APIs and exposing some additional overload that offer a fully type safe way to set those animations up, so that it won't be possible to get the property name wrong nor to accidentally try to use a keyframe type that's not supported or that doesn't match the target property. Here's a before/after comparison, with the code I previously shared: // BEFORE
AnimationBuilder.Create()
.Opacity(from: 0, to: 1)
.NormalizedKeyFrames<double>(nameof(Visual.RotationAngleInDegrees), b => b
.KeyFrame(0.0, 0)
.KeyFrame(0.4, 90, EasingType.Cubic)
.KeyFrame(0.8, -45))
.NormalizedKeyFrames<Vector3>(nameof(Visual.Offset), b => b
.KeyFrame(0.4, Vector3.Zero)
.KeyFrame(0.8, new(40, 0, 0))
.KeyFrame(1, new(20, 20, 0)))
.NormalizedKeyFrames<Vector3>(nameof(Visual.Scale), b => b
.KeyFrame(0.5, new(1.2f))
.KeyFrame(1, new(1)))
.Start(this);
//AFTER
AnimationBuilder.Create()
.Opacity(from: 0, to: 1)
.RotationInDegrees().NormalizedKeyFrames(b => b
.KeyFrame(0.0, 0)
.KeyFrame(0.4, 90, EasingType.Cubic)
.KeyFrame(0.8, -45))
.Offset().NormalizedKeyFrames(b => b
.KeyFrame(0.4, Vector3.Zero)
.KeyFrame(0.8, new(40, 0, 0))
.KeyFrame(1, new(20, 20, 0)))
.Scale().NormalizedKeyFrames(b => b
.KeyFrame(0.5, new(1.2f))
.KeyFrame(1, new(1)))
.Start(this); Each supported animation type now has a dedicated method that allows you to add a keyframe animation to the schedule (still with the option to choose to use either normalized keyframes, or timed ones too), and the builder will take care of selecting the right animaiton type automatically, so the whole API is much more robust and way less error prone to use too. Let us know what you think! 😊 EDIT: updated the default easing types in d963d11 as requested, we're now using the same default easing values as mentioned in the official docs page (here). The ones that were being used before were probably outdated now, so this should address that 😄 |
Awesome! I will also double check the easing when I get to play with this new lib. 😉 I love the change you made. Now the expression looks even clearer! One small question is, let's take properties (e.g. Scale and Offset) that support |
Really happy to hear you like the new changes, awesome! 😊
Absolutely! I've specifically added overloads for all animation properties that support multiple axes/dimensions to make it easy to only target one, which as you said is handy both to make the code more compact, but also to avoid overwriting values on other axes. Here's a few examples, but the same APIs are available for all APIs for eg. offset/translation/scale/etc.: // Explicit, single-keyframe APIs
AnimationBuilder.Create()
.Offset(Axis.X, 100)
.Translation(Axis.Y, 200)
.Scale(Axis.Z, 1.4)
.AnchorPoint(Axis.X, 20)
.CenterPoint(Axis.Y, 10)
.Size(Axis.Y, 200)
.Start(this);
// Works for clipping too!
AnimationBuilder.Create()
.Clip(Side.Right, from: 240, to: 0)
.Start(this);
// Explicit, multi-keyframe APIs
AnimationBuilder.Create()
.Offset(Axis.X).NormalizedKeyFrames(b => b
.KeyFrame(0.5, 100)
.KeyFrame(1.0, 80))
.Scale(Axis.Y).NormalizedKeyFrames(b => b
.KeyFrame(0.5, 1.4)
.KeyFrame(1.0, 1))
// And more...
.Start(this); I've also added some special convenience overloads for 2D animations that can automatically target the AnimationBuilder.Create()
.Translation(new Vector2(100, 200))
.Scale(new Vector2(1.2f))
.Start(this); The same pattern applies to all these overloads - they have the default values we mentioned earlier but it's possible to specify the starting/final value for each of them, as well as the delay, duration, easing type and easing mode. I also applied the Let me know what you think, and if there's anything else you'd like me to tweak or to investigate! 😄 EDIT: I'm making some tests comparing the default easings for composition animations and it actually looks like the default easing used by them doesn't match the one reported in the docs (as in, this one), and it's quite different. Investigating... EDIT 2: fixed in 7262c7c, the easing should now be identical and the APIs are also a bit more efficient with this change! 🎉 |
FYI @Sergio0694 updated some of the spec to use the new names for things. Think we've got a lot of things covered, just need to do some more testing probably with implicit animations and that works for effects and things? (And add samples for each individual thing.) Outside of that, I think the only thing we haven't done yet is have |
Those options are available through the extensions in the |
@Sergio0694 yeah, think having those properties exposed would be powerful and help anyone migrating from Storyboards as well. Mind taking a quick look? |
Alright, so this is the current plan regarding those missing APIs (posting here after conversation on Discord). There are three main aspects of an animation that don't yet have a mapping in our XAML types:
In general, the options in
Will start working on these new features, will update again when all the new changes are available 🙂 |
See Technical Background below for more details.
Background (Summary)
As part of our refactoring work there are some Win2D based behaviors which don't fit in well in any particular package, see technical background below for more details. It's unclear if we would want to create a temporary home vs. utilizing existing work already in the toolkit and from the goal of #3108 to bootstrap a revitalization of our animations in general to support all the original scenarios.
This work item it to detail the new animation system and how everything can work together with these more independent package setups.
Describe the problem this feature would solve
The new animation system is focused primarily on extending the success we've seen with exposing the Implicit Composition Animation APIs to XAML as well as the flexibility we've seen from our Pipeline Brushes to leverage similar API surfaces with code-behind and XAML that are smaller in scope, but powerful to compose.
We have built this proposal with a variety of scenarios in mind to fill in gaps in our existing APIs, streamline the usage of other API dependencies like Behaviors and Win2D effects, and address new opportunities. We've done this as well with a focus on ease-of-use and composability to present this as a complete alternative to animations that are either composition or XAML based.
Describe the solution
Firstly, existing XAML Composition based Animation Support in the Toolkit should still be supported (with hopefully with no to minimal breaking changes). References:
This section is collapsed by scenario with embedded examples of a proposed XAML based syntax. Please expand each scenario to explore and see how it would be handled with the new system. Each example may build on previously defined examples, so it is best to review in order from top to bottom. This order does not necessarily imply any particular priority for each feature.
This section will be updated inline based on feedback.
Scenarios
Explicitly Defined Animations in XAML
This would expand upon our Implicit animation XAML API to create an independent animation that can be triggered or run in different cases outside of the normal show/hide cases of the composition API.
Key framed animations are still supported (existing+)
Existing complex crafted key frame animations should still be supported.
Multiple copies of the same animation type can be used
As an alternative to key frames for a single animation, multiple animations can be used within the same collection without overlapping time windows:
Expression animations can still be used (existing+)
Expression animations allow for animations to interact with dynamic values within the context of it's parent control.
Existing example with Implicit Animation:
AnimationSets can be nested to share properties
This makes it easier to group similar timed and transitioned animations to build more complex timelines. These properties are shared with children and multiple collections can be nested together. The named parent collection can also define these properties.
Ability to choose whether an Animation collection starts concurrently or sequentially
By default all animations start concurrently at the same time (this would remain the default). However, being able to create a timeline of animations that occur sequentially instead can make it easier to manage and visualize a sequence of complex animations.
Complex example:
Can re-use the same animation in a resource with multiple elements
In some scenarios there may be a common animation that will want to be played on different elements. They should be able to be added to a resource dictionary and used where appropriate. For an example (with the Behaviors, see more in section below):
Ability to trigger other animations within an animation
Sometimes an animation may be composed of multiple elements. These may want to occur together or one after another, in combination with different delays (or using sequential mode defined above), this ability would allow complex compositing of animations with ease.
If we had a general animation in a resource we could use a
TargetObject="{x:Bind OurImage}"
instead to play that generalized animation on that particular object:Multiple animations can be triggered from within a single animation collection
To allow for complex chaining, triggered animations should be allowed in any number (with reason) to either daisy-chain animations across different elements or to set-off a coordinated animation across multiple elements.
Support `RepeatBehaviors` on Collections and Animations
Animations alone are powerful, but there are times when you want them to repeat or loop for various reasons. We should support adding a
RepeatBehavior
element on both collections and animations. This would provide a greater amount of flexibility for animation definitions. P2: A stretch goal in the future would be to support aRepeatDirection
enum for eitherForward
,Backward
,ForwardThenBackward
, orBackwardThenForward
modes of controlling how an animation repeats itself.More complex future example:
TODO: Choose which framework the animation is running on (Composition vs. XAML)
TODO: Have C# API for Animations in General that's easy to use and exposes duration, delays, easings, enableDependentAnimations, layer (composition or XAML), calling action after animation.
Integration with
Microsoft.Toolkit.Uwp.UI.Behaviors
(new package)Can trigger animations with Behaviors
This would allow the new Explicit animations to be triggered from a variety of scenarios within XAML, for instance events caused by user interaction, data loading, progress completion, etc...
Ability to trigger Behavior Actions
By including the behaviors package, we'd also have the ability to trigger other actions within this ecosystem.
Integration with
Microsoft.Toolkit.Uwp.UI.Media
(Win2D based Effects)Expose Pipeline Effects to General Framework Effects
This is base work outside of animations specifically to expose the work done in the Pipeline Brush API effects to be usable on any general framework element to provide similar effects..
Can specify to add animations to an effect with `IsAnimatable`
By including the behaviors package, we'd also have the ability to trigger other actions within this ecosystem.
Visual effect animations work with implicit animations as well
This is base work outside of animations specifically to expose the work done in the Pipeline Brush API effects to be usable on any general framework element to provide similar effects..
Currently Lower-Priority Scenarios/Goals
TODO: Expose our Implicit Animation API via C# (or do we do this already?)
TODO: Existing Implicit Animation Toolkit users can re-use the same code without any modification... (it's important to note that the base scenarios of attaching to implicit/show/hide animations are still a requirement as you can do today with the current animations package, this spec is more about detailing all the additions to the base system we had here and changing some of the underlying infrastructure.)
Describe alternatives you've considered
We know from experience that there are many scenarios that are difficult to accomplish with Storyboards, as we've seen the great power and flexibility that comes with our Implicit animation work. We also know that there are some scenarios more easily handled in code, but that exposing XAML helps better define workflow patterns between view and function. We want this to build upon the work we've already seen within the Toolkit and the community to move the platform forward in this space.
Additional context & Screenshots
Quick test example of an explicitly defined mixed animation triggered from code-behind:
(see above examples for proposed syntax)
Animating an Effect using a Behavior on a Button Click (all in XAML!):
Custom XAML animation combining new types (eg. clip) with also Win2D effect animations:
Example of the declarative C# APIs to create complex animations, combining composition and XAML:
hMFUNA88vr.mp4
Technical Background (Detailed)
This is a follow-on from work being done in #3594 and PR #3634 which is trying to sort out the dependencies of the toolkit and clean-up their complexities. Currently the Animations package pulls in both Win2D and the XAML Behaviors package, which then get also included in the Controls package.
The goal here is to have a more light-weight animations package which doesn't pull in these dependencies directly. Instead, both our Win2D based Media package and the new Behaviors package (in #3634) would add the animations library for supporting those scenarios if desired by the end developer.
Migrations:
This will streamline the ability for developers to consume the toolkit and focus the purpose of each individual package.
The text was updated successfully, but these errors were encountered: