├── Properties ├── Microsoft.Windows.Toolkit.UI.Animations.rd.xml └── AssemblyInfo.cs ├── project.json ├── Microsoft.Toolkit.Uwp.UI.Animations.csproj.DotSettings ├── AnimationSetCompletedEventArgs.cs ├── Behaviors ├── CompositionBehaviorBase.nongeneric.cs ├── Blur.cs ├── CompositionBehaviorBase.cs └── BehaviorBase.cs ├── AnimationSetState.cs ├── EffectAnimationDefinition.cs ├── EffectDirectPropertyChangeDefinition.cs ├── AnimationTask.cs ├── Extensions ├── AnimationTools.cs ├── AnimationExtensions.Blur.cs └── AnimationExtensions.cs ├── .gitattributes ├── Effects ├── Blur.cs └── AnimationEffect.cs ├── EasingType.cs ├── README.md ├── Microsoft.Toolkit.Uwp.UI.Animations.ruleset ├── .gitignore ├── SurfaceLoader.cs ├── Mika.Toolkit.Uwp.UI.Animations.csproj └── AnimationSet.cs /Properties/Microsoft.Windows.Toolkit.UI.Animations.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.3.2", 4 | "Microsoft.Xaml.Behaviors.Uwp.Managed": "2.0.0", 5 | "Win2D.uwp": "1.20.0" 6 | }, 7 | "frameworks": { 8 | "uap10.0": {} 9 | }, 10 | "runtimes": { 11 | "win10-arm": {}, 12 | "win10-arm-aot": {}, 13 | "win10-x86": {}, 14 | "win10-x86-aot": {}, 15 | "win10-x64": {}, 16 | "win10-x64-aot": {} 17 | } 18 | } -------------------------------------------------------------------------------- /Microsoft.Toolkit.Uwp.UI.Animations.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True -------------------------------------------------------------------------------- /AnimationSetCompletedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using System; 14 | 15 | namespace Microsoft.Toolkit.Uwp.UI.Animations 16 | { 17 | /// 18 | /// AnimationSet Completed EventArgs. 19 | /// 20 | public class AnimationSetCompletedEventArgs : EventArgs 21 | { 22 | /// 23 | /// Gets a value indicating whether the animation completed 24 | /// 25 | public bool Completed { get; internal set; } 26 | } 27 | } -------------------------------------------------------------------------------- /Behaviors/CompositionBehaviorBase.nongeneric.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Windows.UI.Xaml; 14 | 15 | namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors 16 | { 17 | /// 18 | /// Non-generic convenience implementation to provide backwards compatibility. 19 | /// 20 | /// 21 | public abstract class CompositionBehaviorBase : CompositionBehaviorBase 22 | { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /AnimationSetState.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | namespace Microsoft.Toolkit.Uwp.UI.Animations 14 | { 15 | /// 16 | /// States of AnimationSet. 17 | /// 18 | public enum AnimationSetState 19 | { 20 | /// 21 | /// The animation has not been started 22 | /// 23 | NotStarted, 24 | 25 | /// 26 | /// The animation has been started and is in progress 27 | /// 28 | Running, 29 | 30 | /// 31 | /// The animation has been started and is stopped 32 | /// 33 | Stopped, 34 | 35 | /// 36 | /// The animation had completed 37 | /// 38 | Completed 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /EffectAnimationDefinition.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Windows.UI.Composition; 14 | 15 | namespace Microsoft.Toolkit.Uwp.UI.Animations 16 | { 17 | /// 18 | /// Defines an which is used by 19 | /// to link effect animations to Visuals 20 | /// 21 | internal class EffectAnimationDefinition 22 | { 23 | /// 24 | /// Gets or sets that will be animated 25 | /// 26 | public CompositionObject EffectBrush { get; set; } 27 | 28 | /// 29 | /// Gets or sets the 30 | /// 31 | public CompositionAnimation Animation { get; set; } 32 | 33 | /// 34 | /// Gets or sets the property name that will be animated on the 35 | /// 36 | public string PropertyName { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EffectDirectPropertyChangeDefinition.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Windows.UI.Composition; 14 | 15 | namespace Microsoft.Toolkit.Uwp.UI.Animations 16 | { 17 | /// 18 | /// Defines an which is used by 19 | /// to link effect property Changes to Visuals 20 | /// 21 | internal class EffectDirectPropertyChangeDefinition 22 | { 23 | /// 24 | /// Gets or sets that will be animated 25 | /// 26 | public CompositionObject EffectBrush { get; set; } 27 | 28 | /// 29 | /// Gets or sets the value for the property 30 | /// 31 | public float Value { get; set; } 32 | 33 | /// 34 | /// Gets or sets the property name that will be animated on the 35 | /// 36 | public string PropertyName { get; set; } 37 | } 38 | } -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using System.Reflection; 14 | using System.Runtime.InteropServices; 15 | 16 | // General Information about an assembly is controlled through the following 17 | // set of attributes. Change these attribute values to modify the information 18 | // associated with an assembly. 19 | [assembly: AssemblyTitle("Mika.Toolkit.Uwp.UI.Animations")] 20 | [assembly: AssemblyDescription("")] 21 | [assembly: AssemblyConfiguration("")] 22 | [assembly: AssemblyCompany("")] 23 | [assembly: AssemblyProduct("Mika.Toolkit.Uwp.UI.Animations")] 24 | [assembly: AssemblyCopyright("Copyright © 2017")] 25 | [assembly: AssemblyTrademark("")] 26 | [assembly: AssemblyCulture("")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // You can specify all the values or you can default the Build and Revision Numbers 34 | // by using the '*' as shown below: 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion("0.5.0.0")] 37 | [assembly: AssemblyFileVersion("0.5.0.0")] 38 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /AnimationTask.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using System; 14 | using System.Threading.Tasks; 15 | 16 | namespace Microsoft.Toolkit.Uwp.UI.Animations 17 | { 18 | /// 19 | /// Defines which is used by 20 | /// to run animations that require 21 | /// asyncronous initialization 22 | /// 23 | internal class AnimationTask 24 | { 25 | /// 26 | /// Gets or sets that will run before any animation 27 | /// and it will add the animation to the AnimationSet once complete 28 | /// 29 | public Task Task { get; set; } 30 | 31 | /// 32 | /// Gets or sets that will run the animation 33 | /// 34 | public AnimationSet AnimationSet { get; set; } 35 | 36 | /// 37 | /// Gets or sets Duration to be applied to the animation once the task is completed 38 | /// Used when Duration is changed before Task completes 39 | /// 40 | public TimeSpan? Duration { get; set; } 41 | 42 | /// 43 | /// Gets or sets Delay to be applied to the animation once the task is completed 44 | /// Used when Duration is changed before Task completes 45 | /// 46 | public TimeSpan? Delay { get; set; } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Extensions/AnimationTools.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Windows.UI.Xaml; 14 | 15 | namespace Microsoft.Toolkit.Uwp.UI.Animations 16 | { 17 | /// 18 | /// Internal tool to link composite transforms to elements 19 | /// 20 | internal class AnimationTools : DependencyObject 21 | { 22 | /// 23 | /// Attached property used to link composite transform with UIElement 24 | /// 25 | public static readonly DependencyProperty AnimationCompositeTransformIndexProperty = DependencyProperty.RegisterAttached( 26 | "AnimationCompositeTransformIndex", 27 | typeof(int), 28 | typeof(AnimationTools), 29 | new PropertyMetadata(-2)); 30 | 31 | /// 32 | /// Attach a composite transform index to an UIElement. 33 | /// 34 | /// UIElement to use 35 | /// Composite transform index 36 | public static void SetAnimationCompositeTransformIndex(UIElement element, int value) 37 | { 38 | element.SetValue(AnimationCompositeTransformIndexProperty, value); 39 | } 40 | 41 | /// 42 | /// Get the composite transform index attached to an UIElement. 43 | /// 44 | /// UIElement to use 45 | /// Composite transform index. 46 | public static int GetAnimationCompositeTransformIndex(UIElement element) 47 | { 48 | return (int)element.GetValue(AnimationCompositeTransformIndexProperty); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Behaviors/Blur.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Windows.UI.Xaml; 14 | 15 | namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors 16 | { 17 | /// 18 | /// Performs an blur behind the window animation using composition. 19 | /// 20 | /// 21 | /// 22 | /// Blurs are only supported on Build 1703 and up. Assigning the blur behavior on an older 23 | /// version of Windows will not add any effect. You can use the 24 | /// property to check for whether blurs are supported on the device at runtime. 25 | /// 26 | /// 27 | /// 28 | /// Microsoft.Xaml.Interactivity.Behavior{Windows.UI.Xaml.UIElement} 29 | /// 30 | /// 31 | public class Blur : CompositionBehaviorBase 32 | { 33 | /// 34 | /// The Blur value of the associated object 35 | /// 36 | public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(double), typeof(Blur), new PropertyMetadata(0d, PropertyChangedCallback)); 37 | 38 | /// 39 | /// Gets or sets the Blur. 40 | /// 41 | /// 42 | /// The Blur. 43 | /// 44 | public double Value 45 | { 46 | get { return (double)GetValue(ValueProperty); } 47 | set { SetValue(ValueProperty, value); } 48 | } 49 | 50 | /// 51 | /// Starts the animation. 52 | /// 53 | public override void StartAnimation() 54 | { 55 | if (AnimationExtensions.BlurEffect.IsSupported) 56 | { 57 | AssociatedObject?.Blur(duration: Duration, delay: Delay, value: (float)Value)?.Start(); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Effects/Blur.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Microsoft.Graphics.Canvas.Effects; 14 | using Windows.Foundation.Metadata; 15 | using Windows.UI.Composition; 16 | 17 | namespace Microsoft.Toolkit.Uwp.UI.Animations.Effects 18 | { 19 | /// 20 | /// An animation effect that applies blur. 21 | /// 22 | /// 23 | public class Blur : AnimationEffect 24 | { 25 | /// 26 | /// Gets a value indicating whether blur is supported. 27 | /// 28 | /// 29 | /// true if this instance is supported; otherwise, false. 30 | /// 31 | public override bool IsSupported 32 | => ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3); 33 | 34 | /// 35 | /// Gets the name of the effect. 36 | /// 37 | /// 38 | /// The name of the effect. 39 | /// 40 | public override string EffectName { get; } = "Blur"; 41 | 42 | /// 43 | /// Applies the effect. 44 | /// 45 | /// 46 | /// An array of strings of the effect properties to change. 47 | /// 48 | public override string[] ApplyEffect() 49 | { 50 | var gaussianBlur = new GaussianBlurEffect 51 | { 52 | Name = EffectName, 53 | BlurAmount = 0f, 54 | Optimization = EffectOptimization.Balanced, 55 | BorderMode = EffectBorderMode.Hard, 56 | Source = new CompositionEffectSourceParameter("source") 57 | }; 58 | 59 | var propertyToChange = $"{EffectName}.BlurAmount"; 60 | var propertiesToAnimate = new[] { propertyToChange }; 61 | 62 | EffectBrush = Compositor.CreateEffectFactory(gaussianBlur, propertiesToAnimate).CreateBrush(); 63 | EffectBrush.SetSourceParameter("source", Compositor.CreateHostBackdropBrush()); 64 | 65 | return propertiesToAnimate; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /EasingType.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | namespace Microsoft.Toolkit.Uwp.UI.Animations 14 | { 15 | /// 16 | /// EasingType is used to describe how the animation interpolates between keyframes. 17 | /// 18 | public enum EasingType 19 | { 20 | /// 21 | /// Creates an animation that accelerates with the default EasingType which is specified in AnimationExtensions.DefaultEasingType which is by default Cubic. 22 | /// 23 | Default, 24 | 25 | /// 26 | /// Creates an animation that accelerates or decelerates linear. 27 | /// 28 | Linear, 29 | 30 | /// 31 | /// Creates an animation that accelerates or decelerates using the formula f(t) = t3. 32 | /// 33 | Cubic, 34 | 35 | /// 36 | /// Retracts the motion of an animation slightly before it begins to animate in the path indicated. 37 | /// 38 | Back, 39 | 40 | /// 41 | /// Creates a bouncing effect. 42 | /// 43 | Bounce, 44 | 45 | /// 46 | /// Creates an animation that resembles a spring oscillating back and forth until it comes to rest. 47 | /// 48 | Elastic, 49 | 50 | /// 51 | /// Creates an animation that accelerates or decelerates using a circular function. 52 | /// 53 | Circle, 54 | 55 | /// 56 | /// Creates an animation that accelerates or decelerates using the formula f(t) = t2. 57 | /// 58 | Quadratic, 59 | 60 | /// 61 | /// Creates an animation that accelerates or decelerates using the formula f(t) = t4. 62 | /// 63 | Quartic, 64 | 65 | /// 66 | /// Create an animation that accelerates or decelerates using the formula f(t) = t5. 67 | /// 68 | Quintic, 69 | 70 | /// 71 | /// Creates an animation that accelerates or decelerates using a sine formula. 72 | /// 73 | Sine 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Acrylic Toolkit Blur for UWP 2 | Add HostBackdrop with this library to your UWP app. HostBackdrop adds blur and transparency through the window (by the specified element on XAML). If you want give a Neon look for you app, so this is the lib! This is based on the open-source UWP Community Toolkit. 3 | 4 | # How to use? 5 | The very first thing you need to do, is to add as a [nuget package to your project](https://www.nuget.org/packages/Mika.Toolkit.Uwp.UI.Animations/), or clone this project and add to your solution and reference it. 6 | 7 | After that, you need to add to your XAML these 3 lines first: 8 | ``` 9 | xmlns:acrylic="using:Microsoft.Toolkit.Uwp.UI.Animations.Behaviors" 10 | xmlns:interactivity="using:Microsoft.Xaml.Interactivity" 11 | ``` 12 | 13 | And the app body, you will call Acrylic Blur like this: 14 | ``` 15 | 16 | 17 | 19 | 20 | 21 | ``` 22 | 23 | You don't need to put it just on Grid's. You can put on almost every XAML element, like SlackPanel, pictures and more. 24 | If you are familiar with XAML and Behaviors, this will be extremally easy for you. 25 | Here is the full "code" on a sample app: 26 | 27 | ``` XAML 28 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | ``` 49 | 50 | # Requirements 51 | You can install on Mobile and other devices, but for now, the API used on the library (CreateHostBackdrop) just works on Desktop and it needs Windows 10 version 1703 (build 15063) at least. On devices that is not Desktop, it will show a black background, as the Windows compositor doesn't support yet. 52 | 53 | # Issues and Pull Request 54 | If you have any problems, you can open issues and if you want improvements, you can open Pull Requests any time. 55 | 56 | # Contact 57 | If you want to talk with me and other stuff, https://t.me/vitorgrs on Telegram or https://twitter.com/vitorgrs 58 | -------------------------------------------------------------------------------- /Extensions/AnimationExtensions.Blur.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Microsoft.Toolkit.Uwp.UI.Animations.Effects; 14 | using Windows.Foundation.Metadata; 15 | using Windows.UI.Xaml; 16 | 17 | namespace Microsoft.Toolkit.Uwp.UI.Animations 18 | { 19 | /// 20 | /// These extension methods perform animation on UIElements 21 | /// 22 | public static partial class AnimationExtensions 23 | { 24 | /// 25 | /// Gets the blur effect. 26 | /// 27 | /// 28 | /// The blur effect. 29 | /// 30 | public static Blur BlurEffect { get; } = new Blur(); 31 | 32 | /// 33 | /// Gets a value indicating whether the platform supports blur. 34 | /// 35 | /// 36 | /// A check should always be made to IsBlurSupported prior to calling Blur, 37 | /// since older operating systems will not support blurs. 38 | /// 39 | /// 40 | public static bool IsBlurSupported => 41 | ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3); // SDK >= 15063 42 | 43 | /// 44 | /// Animates the gaussian blur of the the UIElement. 45 | /// 46 | /// The associated object. 47 | /// The blur amount. 48 | /// The duration in milliseconds. 49 | /// The delay. (ignored if duration == 0) 50 | /// 51 | /// An Animation Set. 52 | /// 53 | /// 54 | public static AnimationSet Blur( 55 | this FrameworkElement associatedObject, 56 | double value = 0d, 57 | double duration = 500d, 58 | double delay = 0d) 59 | { 60 | if (associatedObject == null) 61 | { 62 | return null; 63 | } 64 | 65 | var animationSet = new AnimationSet(associatedObject); 66 | return animationSet.Blur(value, duration, delay); 67 | } 68 | 69 | /// 70 | /// Animates the gaussian blur of the the UIElement. 71 | /// 72 | /// The animation set. 73 | /// The blur amount. 74 | /// The duration in milliseconds. 75 | /// The delay. (ignored if duration == 0) 76 | /// 77 | /// An Animation Set. 78 | /// 79 | /// 80 | public static AnimationSet Blur( 81 | this AnimationSet animationSet, 82 | double value = 0d, 83 | double duration = 500d, 84 | double delay = 0d) 85 | { 86 | return BlurEffect.EffectAnimation(animationSet, value, duration, delay); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Microsoft.Toolkit.Uwp.UI.Animations.ruleset: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Behaviors/CompositionBehaviorBase.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Windows.UI.Xaml; 14 | 15 | namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors 16 | { 17 | /// 18 | /// A base class for all behaviors using composition.It contains some of the common propeties to set on a visual. 19 | /// 20 | /// The type of the associated object. 21 | /// 22 | public abstract class CompositionBehaviorBase : BehaviorBase 23 | where T : UIElement 24 | { 25 | /// 26 | /// Called when the associated object has been loaded. 27 | /// 28 | protected override void OnAssociatedObjectLoaded() 29 | { 30 | base.OnAssociatedObjectLoaded(); 31 | 32 | if (AutomaticallyStart) 33 | { 34 | StartAnimation(); 35 | } 36 | } 37 | 38 | /// 39 | /// The duration of the animation. 40 | /// 41 | public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(nameof(Duration), typeof(double), typeof(CompositionBehaviorBase), new PropertyMetadata(1d, PropertyChangedCallback)); 42 | 43 | /// 44 | /// The delay of the animation. 45 | /// 46 | public static readonly DependencyProperty DelayProperty = DependencyProperty.Register(nameof(Delay), typeof(double), typeof(CompositionBehaviorBase), new PropertyMetadata(0d, PropertyChangedCallback)); 47 | 48 | /// 49 | /// The property sets if the animation should automatically start. 50 | /// 51 | public static readonly DependencyProperty AutomaticallyStartProperty = DependencyProperty.Register(nameof(AutomaticallyStart), typeof(bool), typeof(CompositionBehaviorBase), new PropertyMetadata(true, PropertyChangedCallback)); 52 | 53 | /// 54 | /// Gets or sets a value indicating whether [automatically start] on the animation is set. 55 | /// 56 | /// 57 | /// true if [automatically start]; otherwise, false. 58 | /// 59 | public bool AutomaticallyStart 60 | { 61 | get { return (bool)GetValue(AutomaticallyStartProperty); } 62 | set { SetValue(AutomaticallyStartProperty, value); } 63 | } 64 | 65 | /// 66 | /// Gets or sets the delay. 67 | /// 68 | /// 69 | /// The delay. 70 | /// 71 | public double Delay 72 | { 73 | get { return (double)GetValue(DelayProperty); } 74 | set { SetValue(DelayProperty, value); } 75 | } 76 | 77 | /// 78 | /// Gets or sets the duration. 79 | /// 80 | /// 81 | /// The duration. 82 | /// 83 | public double Duration 84 | { 85 | get { return (double)GetValue(DurationProperty); } 86 | set { SetValue(DurationProperty, value); } 87 | } 88 | 89 | /// 90 | /// Starts the animation. 91 | /// 92 | public abstract void StartAnimation(); 93 | 94 | /// 95 | /// If any of the properties are changed then the animation is automatically started depending on the AutomaticallyStart property. 96 | /// 97 | /// The dependency object. 98 | /// The instance containing the event data. 99 | protected static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 100 | { 101 | var behavior = dependencyObject as CompositionBehaviorBase; 102 | if (behavior == null) 103 | { 104 | return; 105 | } 106 | 107 | if (behavior.AutomaticallyStart) 108 | { 109 | behavior.StartAnimation(); 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /Behaviors/BehaviorBase.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using Microsoft.Xaml.Interactivity; 14 | using Windows.UI.Xaml; 15 | 16 | namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors 17 | { 18 | /// 19 | /// Base class for behaviors that solves 2 problems: 20 | /// 1. Prevent duplicate initialization that can happen (prevent multiple OnAttached calls); 21 | /// 2. Whenever initially fails, this method will subscribe to to allow lazy initialization. 22 | /// 23 | /// The type of the associated object. 24 | /// 25 | /// 26 | /// For more info, see https://github.com/Microsoft/UWPCommunityToolkit/issues/1008. 27 | /// 28 | public abstract class BehaviorBase : Behavior 29 | where T : UIElement 30 | { 31 | private bool _isAttaching; 32 | private bool _isAttached; 33 | 34 | /// 35 | /// Gets a value indicating whether this behavior is attached. 36 | /// 37 | /// 38 | /// true if this behavior is attached; otherwise, false. 39 | /// 40 | protected bool IsAttached 41 | { 42 | get { return _isAttached; } 43 | } 44 | 45 | /// 46 | /// Called after the behavior is attached to the . 47 | /// 48 | /// 49 | /// Override this to hook up functionality to the 50 | /// 51 | protected override void OnAttached() 52 | { 53 | base.OnAttached(); 54 | 55 | HandleAttach(); 56 | 57 | var frameworkElement = AssociatedObject as FrameworkElement; 58 | if (frameworkElement != null) 59 | { 60 | frameworkElement.Loaded += OnAssociatedObjectLoaded; 61 | frameworkElement.Unloaded += OnAssociatedObjectUnloaded; 62 | frameworkElement.SizeChanged += OnAssociatedObjectSizeChanged; 63 | } 64 | } 65 | 66 | /// 67 | /// Called when the behavior is being detached from its . 68 | /// 69 | /// 70 | /// Override this to unhook functionality from the 71 | /// 72 | protected override void OnDetaching() 73 | { 74 | base.OnDetaching(); 75 | 76 | var frameworkElement = AssociatedObject as FrameworkElement; 77 | if (frameworkElement != null) 78 | { 79 | frameworkElement.Loaded -= OnAssociatedObjectLoaded; 80 | frameworkElement.Unloaded -= OnAssociatedObjectUnloaded; 81 | frameworkElement.SizeChanged -= OnAssociatedObjectSizeChanged; 82 | } 83 | 84 | HandleDetach(); 85 | } 86 | 87 | /// 88 | /// Called when the associated object has been loaded. 89 | /// 90 | protected virtual void OnAssociatedObjectLoaded() 91 | { 92 | } 93 | 94 | /// 95 | /// Called when the associated object has been unloaded. 96 | /// 97 | protected virtual void OnAssociatedObjectUnloaded() 98 | { 99 | } 100 | 101 | /// 102 | /// Initializes the behavior to the associated object. 103 | /// 104 | /// true if the initialization succeeded; otherwise false. 105 | protected virtual bool Initialize() 106 | { 107 | return true; 108 | } 109 | 110 | /// 111 | /// Uninitializes the behavior from the associated object. 112 | /// 113 | /// true if uninitialization succeeded; otherwise false. 114 | protected virtual bool Uninitialize() 115 | { 116 | return true; 117 | } 118 | 119 | private void OnAssociatedObjectLoaded(object sender, RoutedEventArgs e) 120 | { 121 | if (!_isAttached) 122 | { 123 | HandleAttach(); 124 | } 125 | 126 | OnAssociatedObjectLoaded(); 127 | } 128 | 129 | private void OnAssociatedObjectUnloaded(object sender, RoutedEventArgs e) 130 | { 131 | OnAssociatedObjectUnloaded(); 132 | 133 | // Note: don't detach here, we'll let the behavior implementation take care of that 134 | } 135 | 136 | private void OnAssociatedObjectSizeChanged(object sender, SizeChangedEventArgs e) 137 | { 138 | if (!_isAttached) 139 | { 140 | HandleAttach(); 141 | } 142 | } 143 | 144 | private void HandleAttach() 145 | { 146 | if (_isAttaching || _isAttached) 147 | { 148 | return; 149 | } 150 | 151 | _isAttaching = true; 152 | 153 | var attached = Initialize(); 154 | if (attached) 155 | { 156 | _isAttached = true; 157 | } 158 | 159 | _isAttaching = false; 160 | } 161 | 162 | private void HandleDetach() 163 | { 164 | if (!_isAttached) 165 | { 166 | return; 167 | } 168 | 169 | var detached = Uninitialize(); 170 | if (detached) 171 | { 172 | _isAttached = false; 173 | } 174 | } 175 | } 176 | } -------------------------------------------------------------------------------- /Extensions/AnimationExtensions.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using System; 14 | using System.Threading.Tasks; 15 | using Windows.UI.Xaml; 16 | using Windows.UI.Xaml.Media; 17 | using Windows.UI.Xaml.Media.Animation; 18 | 19 | namespace Microsoft.Toolkit.Uwp.UI.Animations 20 | { 21 | /// 22 | /// These extension methods perform animation on UIElements 23 | /// 24 | public static partial class AnimationExtensions 25 | { 26 | /// 27 | /// Gets or sets the default EasingType used for storyboard animations 28 | /// 29 | public static EasingType DefaultEasingType { get; set; } = EasingType.Cubic; 30 | 31 | /// 32 | /// Begins a Storyboard animation and returns a task that completes when the 33 | /// animaton is complete 34 | /// 35 | /// The storyoard to be started 36 | /// Task that completes when the animation is complete 37 | public static Task BeginAsync(this Storyboard storyboard) 38 | { 39 | var taskSource = new TaskCompletionSource(); 40 | EventHandler completed = null; 41 | completed += (s, e) => 42 | { 43 | storyboard.Completed -= completed; 44 | taskSource.SetResult(null); 45 | }; 46 | 47 | storyboard.Completed += completed; 48 | storyboard.Begin(); 49 | 50 | return taskSource.Task; 51 | } 52 | 53 | /// 54 | /// Gets the EasingFunction from EasingType 55 | /// 56 | /// The EasingType used to determine the EasingFunction 57 | /// Return the appropriate EasingFuntion or null if the EasingType is Linear 58 | public static EasingFunctionBase GetEasingFunction(EasingType easingType) 59 | { 60 | if (easingType == EasingType.Default) 61 | { 62 | easingType = DefaultEasingType; 63 | } 64 | 65 | switch (easingType) 66 | { 67 | case EasingType.Linear: 68 | return null; 69 | case EasingType.Cubic: 70 | return new CubicEase(); 71 | case EasingType.Back: 72 | return new BackEase(); 73 | case EasingType.Bounce: 74 | return new BounceEase(); 75 | case EasingType.Elastic: 76 | return new ElasticEase(); 77 | case EasingType.Circle: 78 | return new CircleEase(); 79 | case EasingType.Quadratic: 80 | return new QuadraticEase(); 81 | case EasingType.Quartic: 82 | return new QuarticEase(); 83 | case EasingType.Quintic: 84 | return new QuinticEase(); 85 | case EasingType.Sine: 86 | return new SineEase(); 87 | default: 88 | throw new ArgumentOutOfRangeException(nameof(easingType), easingType, null); 89 | } 90 | } 91 | 92 | private static string GetAnimationPath(CompositeTransform transform, UIElement element, string property) 93 | { 94 | if (element.RenderTransform == transform) 95 | { 96 | return "(UIElement.RenderTransform).(CompositeTransform.Rotation)"; 97 | } 98 | 99 | var group = element.RenderTransform as TransformGroup; 100 | 101 | if (group == null) 102 | { 103 | return string.Empty; 104 | } 105 | 106 | for (var index = 0; index < group.Children.Count; index++) 107 | { 108 | if (group.Children[index] == transform) 109 | { 110 | return $"(UIElement.RenderTransform).(TransformGroup.Children)[{index}].(CompositeTransform.{property})"; 111 | } 112 | } 113 | 114 | return string.Empty; 115 | } 116 | 117 | private static CompositeTransform GetAttachedCompositeTransform(UIElement element) 118 | { 119 | // We need to use an index to keep track of our CompositeTransform as animation engine 120 | // recreates new transform objects when animating properties 121 | 122 | // Already attached? 123 | var compositeTransformIndex = AnimationTools.GetAnimationCompositeTransformIndex(element); 124 | 125 | if (compositeTransformIndex > -2) 126 | { 127 | if (compositeTransformIndex == -1 && element.RenderTransform is CompositeTransform) 128 | { 129 | return (CompositeTransform)element.RenderTransform; 130 | } 131 | 132 | var group = element.RenderTransform as TransformGroup; 133 | 134 | if (group?.Children.Count > compositeTransformIndex && group.Children[compositeTransformIndex] is CompositeTransform) 135 | { 136 | return (CompositeTransform)group.Children[compositeTransformIndex]; 137 | } 138 | } 139 | 140 | // Let's create a new CompositeTransform 141 | var result = new CompositeTransform(); 142 | 143 | var currentTransform = element.RenderTransform; 144 | 145 | if (currentTransform != null) 146 | { 147 | // We found a RenderTransform 148 | 149 | // Is it a TransformGroup? 150 | var currentTransformGroup = currentTransform as TransformGroup; 151 | 152 | if (currentTransformGroup != null) 153 | { 154 | currentTransformGroup.Children.Add(result); 155 | 156 | AnimationTools.SetAnimationCompositeTransformIndex(element, currentTransformGroup.Children.Count - 1); 157 | } 158 | else 159 | { 160 | // Let's create our own TransformGroup 161 | var group = new TransformGroup(); 162 | group.Children.Add(currentTransform); 163 | group.Children.Add(result); 164 | element.RenderTransform = group; 165 | 166 | AnimationTools.SetAnimationCompositeTransformIndex(element, 1); 167 | } 168 | } 169 | else 170 | { 171 | element.RenderTransform = result; 172 | 173 | AnimationTools.SetAnimationCompositeTransformIndex(element, -1); 174 | } 175 | 176 | return result; 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /Effects/AnimationEffect.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using System; 14 | using System.Numerics; 15 | using Windows.UI.Composition; 16 | using Windows.UI.Xaml; 17 | using Windows.UI.Xaml.Hosting; 18 | 19 | namespace Microsoft.Toolkit.Uwp.UI.Animations.Effects 20 | { 21 | /// 22 | /// An abstract class that provides the mechanism to create 23 | /// an effect using composition. 24 | /// 25 | public abstract class AnimationEffect 26 | { 27 | private static string[] _effectProperties; 28 | 29 | /// 30 | /// Gets a value indicating whether this instance is supported. 31 | /// 32 | /// 33 | /// true if this instance is supported; otherwise, false. 34 | /// 35 | public abstract bool IsSupported { get; } 36 | 37 | /// 38 | /// Gets the name of the effect. 39 | /// 40 | /// 41 | /// The name of the effect. 42 | /// 43 | public abstract string EffectName { get; } 44 | 45 | /// 46 | /// Gets or sets the compositor. 47 | /// 48 | /// 49 | /// The compositor. 50 | /// 51 | public Compositor Compositor { get; set; } 52 | 53 | /// 54 | /// Gets or sets the effect brush. 55 | /// 56 | /// 57 | /// The effect brush. 58 | /// 59 | public CompositionEffectBrush EffectBrush { get; set; } 60 | 61 | /// 62 | /// Applies the effect. 63 | /// 64 | /// An array of strings of the effect properties to change. 65 | public abstract string[] ApplyEffect(); 66 | 67 | /// 68 | /// An animation which will apply the derived effect. 69 | /// 70 | /// The animation set. 71 | /// The value. 72 | /// The duration in milliseconds. 73 | /// The delay in milliseconds. 74 | /// An animation set with the effect added to it. 75 | public AnimationSet EffectAnimation( 76 | AnimationSet animationSet, 77 | double value = 0d, 78 | double duration = 500d, 79 | double delay = 0d) 80 | { 81 | if (animationSet == null) 82 | { 83 | return null; 84 | } 85 | 86 | if (!IsSupported) 87 | { 88 | return null; 89 | } 90 | 91 | var visual = animationSet.Visual; 92 | var associatedObject = animationSet.Element as FrameworkElement; 93 | 94 | if (associatedObject == null) 95 | { 96 | return animationSet; 97 | } 98 | 99 | Compositor = visual?.Compositor; 100 | 101 | if (Compositor == null) 102 | { 103 | return null; 104 | } 105 | 106 | // check to see if the visual already has an effect applied. 107 | var spriteVisual = ElementCompositionPreview.GetElementChildVisual(associatedObject) as SpriteVisual; 108 | EffectBrush = spriteVisual?.Brush as CompositionEffectBrush; 109 | 110 | if (EffectBrush == null || EffectBrush?.Comment != EffectName) 111 | { 112 | _effectProperties = ApplyEffect(); 113 | EffectBrush.Comment = EffectName; 114 | 115 | var sprite = Compositor.CreateSpriteVisual(); 116 | sprite.Brush = EffectBrush; 117 | ElementCompositionPreview.SetElementChildVisual(associatedObject, sprite); 118 | 119 | sprite.Size = new Vector2((float)associatedObject.ActualWidth, (float)associatedObject.ActualHeight); 120 | 121 | associatedObject.SizeChanged += 122 | (s, e) => 123 | { 124 | sprite.Size = new Vector2( 125 | (float)associatedObject.ActualWidth, 126 | (float)associatedObject.ActualHeight); 127 | }; 128 | } 129 | 130 | if (duration <= 0) 131 | { 132 | foreach (var effectProperty in _effectProperties) 133 | { 134 | animationSet.AddEffectDirectPropertyChange(EffectBrush, (float)value, effectProperty); 135 | } 136 | } 137 | else 138 | { 139 | foreach (var effectProperty in _effectProperties) 140 | { 141 | var animation = Compositor.CreateScalarKeyFrameAnimation(); 142 | animation.InsertKeyFrame(1f, (float)value); 143 | animation.Duration = TimeSpan.FromMilliseconds(duration); 144 | animation.DelayTime = TimeSpan.FromMilliseconds(delay); 145 | 146 | animationSet.AddCompositionEffectAnimation(EffectBrush, animation, effectProperty); 147 | } 148 | } 149 | 150 | // Saturation starts from 1 to 0, instead of 0 to 1 so this makes sure the 151 | // the brush isn't removed from the UI element incorrectly. 152 | if (EffectName == "Saturation" && value >= 1) 153 | { 154 | animationSet.Completed += AnimationSet_Completed; 155 | } 156 | else if (EffectName != "Saturation" && value == 0) 157 | { 158 | animationSet.Completed += AnimationSet_Completed; 159 | } 160 | 161 | return animationSet; 162 | } 163 | 164 | /// 165 | /// Handles the Completed event of the AnimationSet control. 166 | /// When an animation is completed the brush is removed from the sprite. 167 | /// 168 | /// The source of the event. 169 | /// The instance containing the event data. 170 | private void AnimationSet_Completed(object sender, EventArgs e) 171 | { 172 | var animationSet = sender as AnimationSet; 173 | 174 | if (animationSet != null) 175 | { 176 | animationSet.Completed -= AnimationSet_Completed; 177 | 178 | var spriteVisual = ElementCompositionPreview.GetElementChildVisual(animationSet.Element) as SpriteVisual; 179 | var brush = spriteVisual?.Brush as CompositionEffectBrush; 180 | 181 | if (brush != null && brush.Comment == EffectName) 182 | { 183 | spriteVisual.Brush = null; 184 | } 185 | } 186 | } 187 | } 188 | } -------------------------------------------------------------------------------- /SurfaceLoader.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using System; 14 | using System.Threading.Tasks; 15 | using Microsoft.Graphics.Canvas; 16 | using Microsoft.Graphics.Canvas.Text; 17 | using Microsoft.Graphics.Canvas.UI.Composition; 18 | using Windows.Foundation; 19 | using Windows.Graphics.DirectX; 20 | using Windows.UI; 21 | using Windows.UI.Composition; 22 | 23 | namespace Microsoft.Toolkit.Uwp.UI.Animations 24 | { 25 | /// 26 | /// A delegate for load time effects. 27 | /// 28 | /// The bitmap. 29 | /// The device. 30 | /// The size target. 31 | /// A CompositeDrawingSurface 32 | public delegate CompositionDrawingSurface LoadTimeEffectHandler(CanvasBitmap bitmap, CompositionGraphicsDevice device, Size sizeTarget); 33 | 34 | /// 35 | /// The SurfaceLoader is responsible to loading images into Composition Objects. 36 | /// 37 | public class SurfaceLoader 38 | { 39 | /// 40 | /// A flag to store the intialized state. 41 | /// 42 | private static bool _intialized; 43 | 44 | /// 45 | /// The compositor 46 | /// 47 | private static Compositor _compositor; 48 | 49 | /// 50 | /// The canvas device 51 | /// 52 | private static CanvasDevice _canvasDevice; 53 | 54 | /// 55 | /// The composition graphic device to determinde which GPU is handling the request. 56 | /// 57 | private static CompositionGraphicsDevice _compositionDevice; 58 | 59 | /// 60 | /// Initializes the specified compositor. 61 | /// 62 | /// The compositor. 63 | public static void Initialize(Compositor compositor) 64 | { 65 | if (!_intialized) 66 | { 67 | _compositor = compositor; 68 | _canvasDevice = new CanvasDevice(); 69 | _compositionDevice = CanvasComposition.CreateCompositionGraphicsDevice(_compositor, _canvasDevice); 70 | 71 | _intialized = true; 72 | } 73 | } 74 | 75 | /// 76 | /// Uninitializes this instance. 77 | /// 78 | public static void Uninitialize() 79 | { 80 | _compositor = null; 81 | 82 | if (_compositionDevice != null) 83 | { 84 | _compositionDevice.Dispose(); 85 | _compositionDevice = null; 86 | } 87 | 88 | if (_canvasDevice != null) 89 | { 90 | _canvasDevice.Dispose(); 91 | _canvasDevice = null; 92 | } 93 | 94 | _intialized = false; 95 | } 96 | 97 | /// 98 | /// Gets a value indicating whether this instance is initialized. 99 | /// 100 | /// 101 | /// true if this instance is initialized; otherwise, false. 102 | /// 103 | public static bool IsInitialized 104 | { 105 | get 106 | { 107 | return _intialized; 108 | } 109 | } 110 | 111 | /// 112 | /// Loads an image from the URI. 113 | /// 114 | /// The URI. 115 | /// 116 | public static async Task LoadFromUri(Uri uri) 117 | { 118 | return await LoadFromUri(uri, Size.Empty); 119 | } 120 | 121 | /// 122 | /// Loads an image from URI with a specified size. 123 | /// 124 | /// The URI. 125 | /// The size target. 126 | /// 127 | public static async Task LoadFromUri(Uri uri, Size sizeTarget) 128 | { 129 | CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(_canvasDevice, uri); 130 | Size sizeSource = bitmap.Size; 131 | 132 | if (sizeTarget.IsEmpty) 133 | { 134 | sizeTarget = sizeSource; 135 | } 136 | 137 | CompositionDrawingSurface surface = _compositionDevice.CreateDrawingSurface( 138 | sizeTarget, 139 | DirectXPixelFormat.B8G8R8A8UIntNormalized, 140 | DirectXAlphaMode.Premultiplied); 141 | 142 | using (var ds = CanvasComposition.CreateDrawingSession(surface)) 143 | { 144 | ds.Clear(Color.FromArgb(0, 0, 0, 0)); 145 | ds.DrawImage(bitmap, new Rect(0, 0, sizeTarget.Width, sizeTarget.Height), new Rect(0, 0, sizeSource.Width, sizeSource.Height)); 146 | } 147 | 148 | return surface; 149 | } 150 | 151 | /// 152 | /// Loads the text on to a . 153 | /// 154 | /// The text. 155 | /// The size target. 156 | /// The text format. 157 | /// Color of the text. 158 | /// Color of the bg. 159 | /// 160 | public static CompositionDrawingSurface LoadText(string text, Size sizeTarget, CanvasTextFormat textFormat, Color textColor, Color bgColor) 161 | { 162 | CompositionDrawingSurface surface = _compositionDevice.CreateDrawingSurface( 163 | sizeTarget, 164 | DirectXPixelFormat.B8G8R8A8UIntNormalized, 165 | DirectXAlphaMode.Premultiplied); 166 | 167 | using (var ds = CanvasComposition.CreateDrawingSession(surface)) 168 | { 169 | ds.Clear(bgColor); 170 | ds.DrawText(text, new Rect(0, 0, sizeTarget.Width, sizeTarget.Height), textColor, textFormat); 171 | } 172 | 173 | return surface; 174 | } 175 | 176 | /// 177 | /// Loads an image from URI, with a specified size. 178 | /// 179 | /// The URI. 180 | /// The size target. 181 | /// The load effect handler callback. 182 | /// 183 | public static async Task LoadFromUri(Uri uri, Size sizeTarget, LoadTimeEffectHandler loadEffectHandler) 184 | { 185 | if (loadEffectHandler != null) 186 | { 187 | var bitmap = await CanvasBitmap.LoadAsync(_canvasDevice, uri); 188 | return loadEffectHandler(bitmap, _compositionDevice, sizeTarget); 189 | } 190 | else 191 | { 192 | return await LoadFromUri(uri, sizeTarget); 193 | } 194 | } 195 | } 196 | } -------------------------------------------------------------------------------- /Mika.Toolkit.Uwp.UI.Animations.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91} 8 | Library 9 | Properties 10 | Microsoft.Toolkit.Uwp.UI.Animations 11 | Microsoft.Toolkit.Uwp.UI.Animations 12 | en-US 13 | UAP 14 | 10.0.15063.0 15 | 10.0.15063.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | false 20 | 21 | 22 | AnyCPU 23 | true 24 | full 25 | false 26 | bin\Debug\ 27 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 28 | prompt 29 | 4 30 | bin\Debug\Microsoft.Toolkit.Uwp.UI.Animations.xml 31 | microsoft.toolkit.uwp.ui.animations.ruleset 32 | 33 | 34 | AnyCPU 35 | pdbonly 36 | true 37 | bin\Release\ 38 | TRACE;NETFX_CORE;WINDOWS_UWP 39 | prompt 40 | 4 41 | true 42 | bin\Release\Microsoft.Toolkit.Uwp.UI.Animations.xml 43 | microsoft.toolkit.uwp.ui.animations.ruleset 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 14.0 75 | 76 | 77 | 78 | 79 | 80 | true 81 | bin\Debug %28Version 1511%29\ 82 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 83 | bin\Debug\Microsoft.Windows.Toolkit.UI.Animations.XML 84 | true 85 | full 86 | AnyCPU 87 | false 88 | prompt 89 | microsoft.toolkit.uwp.ui.animations.ruleset 90 | 91 | 92 | true 93 | bin\Debug %28Anniversary Update%29\ 94 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 95 | bin\Debug\Microsoft.Windows.Toolkit.UI.Animations.XML 96 | true 97 | full 98 | AnyCPU 99 | false 100 | prompt 101 | microsoft.toolkit.uwp.ui.animations.ruleset 102 | 103 | 104 | bin\Release %28Version 1511%29\ 105 | CODE_ANALYSIS;TRACE;NETFX_CORE;WINDOWS_UWP 106 | bin\Release\Microsoft.Windows.Toolkit.UI.Animations.XML 107 | true 108 | true 109 | pdbonly 110 | AnyCPU 111 | true 112 | false 113 | prompt 114 | microsoft.toolkit.uwp.ui.animations.ruleset 115 | 116 | 117 | bin\Release %28Anniversary Update%29\ 118 | CODE_ANALYSIS;TRACE;NETFX_CORE;WINDOWS_UWP 119 | bin\Release\Microsoft.Windows.Toolkit.UI.Animations.XML 120 | true 121 | true 122 | pdbonly 123 | AnyCPU 124 | true 125 | false 126 | prompt 127 | microsoft.toolkit.uwp.ui.animations.ruleset 128 | 129 | 130 | bin\Publish\ 131 | CODE_ANALYSIS;TRACE;NETFX_CORE;WINDOWS_UWP 132 | bin\Release\Microsoft.Toolkit.Uwp.UI.Animations.xml 133 | true 134 | true 135 | pdbonly 136 | AnyCPU 137 | true 138 | false 139 | prompt 140 | microsoft.toolkit.uwp.ui.animations.ruleset 141 | 142 | 143 | 150 | 151 | 152 | $(OutputPath) 153 | $(TargetPath) 154 | $(OutDir) 155 | 156 | 157 | 158 | 159 | 160 | 161 | $(Saved_OutputPath) 162 | $(Saved_TargetPath) 163 | 164 | 165 | -------------------------------------------------------------------------------- /AnimationSet.cs: -------------------------------------------------------------------------------- 1 | // ****************************************************************** 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // This code is licensed under the MIT License (MIT). 4 | // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 5 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 7 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 8 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 9 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 10 | // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. 11 | // ****************************************************************** 12 | 13 | using System; 14 | using System.Collections.Generic; 15 | using System.Reflection; 16 | using System.Threading.Tasks; 17 | using Windows.UI.Composition; 18 | using Windows.UI.Xaml; 19 | using Windows.UI.Xaml.Hosting; 20 | using Windows.UI.Xaml.Media.Animation; 21 | 22 | namespace Microsoft.Toolkit.Uwp.UI.Animations 23 | { 24 | /// 25 | /// Defines an object for storing and managing CompositionAnimations for an element 26 | /// 27 | public class AnimationSet : IDisposable 28 | { 29 | private List _animationSets; 30 | 31 | private Compositor _compositor; 32 | private CompositionScopedBatch _batch; 33 | private Dictionary _compositionAnimations; 34 | private List _compositionEffectAnimations; 35 | private Dictionary _directCompositionPropertyChanges; 36 | private List _directCompositionEffectPropertyChanges; 37 | 38 | private Storyboard _storyboard; 39 | private Dictionary _storyboardAnimations; 40 | 41 | private List _animationTasks; 42 | 43 | private TaskCompletionSource _animationTCS; 44 | 45 | private bool _storyboardCompleted; 46 | private bool _compositionCompleted; 47 | 48 | /// 49 | /// Gets or sets a value indicating whether composition must be use even on SDK > 10586 50 | /// 51 | public static bool UseComposition { get; set; } 52 | 53 | /// 54 | /// Gets the object that backs the XAML element 55 | /// 56 | public Visual Visual { get; private set; } 57 | 58 | /// 59 | /// Gets the 60 | /// 61 | public UIElement Element { get; private set; } 62 | 63 | /// 64 | /// Gets the current state of the AnimationSet 65 | /// 66 | public AnimationSetState State { get; private set; } 67 | 68 | /// 69 | /// Initializes a new instance of the class. 70 | /// 71 | /// The associated element 72 | public AnimationSet(UIElement element) 73 | { 74 | if (element == null) 75 | { 76 | throw new NullReferenceException("Element must not be null"); 77 | } 78 | 79 | var visual = ElementCompositionPreview.GetElementVisual(element); 80 | 81 | if (visual == null) 82 | { 83 | throw new NullReferenceException("Visual must not be null"); 84 | } 85 | 86 | Visual = visual; 87 | if (Visual.Compositor == null) 88 | { 89 | throw new NullReferenceException("Visual must have a compositor"); 90 | } 91 | 92 | Element = element; 93 | State = AnimationSetState.NotStarted; 94 | _compositor = Visual.Compositor; 95 | 96 | _compositionAnimations = new Dictionary(); 97 | _compositionEffectAnimations = new List(); 98 | _directCompositionPropertyChanges = new Dictionary(); 99 | _directCompositionEffectPropertyChanges = new List(); 100 | _animationSets = new List(); 101 | _storyboard = new Storyboard(); 102 | _storyboardAnimations = new Dictionary(); 103 | _animationTasks = new List(); 104 | } 105 | 106 | /// 107 | /// Occurs when all animations have completed 108 | /// 109 | public event EventHandler Completed; 110 | 111 | /// 112 | /// Stats all animations. This method is not awaitable. 113 | /// 114 | public async void Start() 115 | { 116 | await StartAsync(); 117 | } 118 | 119 | /// 120 | /// Starts all animations and returns an awaitable task. 121 | /// 122 | /// A that can be awaited until all animations have completed 123 | public async Task StartAsync() 124 | { 125 | if (_animationTCS == null || _animationTCS.Task.IsCompleted) 126 | { 127 | if (_animationTCS != null && _animationTCS.Task.IsCompleted) 128 | { 129 | foreach (var set in _animationSets) 130 | { 131 | set.State = AnimationSetState.NotStarted; 132 | set._animationTCS = null; 133 | } 134 | } 135 | 136 | State = AnimationSetState.Running; 137 | _animationTCS = new TaskCompletionSource(); 138 | } 139 | else 140 | { 141 | return await _animationTCS.Task; 142 | } 143 | 144 | foreach (var set in _animationSets) 145 | { 146 | if (set.State != AnimationSetState.Completed) 147 | { 148 | var completed = await set.StartAsync(); 149 | 150 | if (!completed) 151 | { 152 | // the animation was stopped 153 | return await _animationTCS.Task; 154 | } 155 | } 156 | } 157 | 158 | foreach (var task in _animationTasks) 159 | { 160 | if (task.Task != null && !task.Task.IsCompleted) 161 | { 162 | await task.Task; 163 | } 164 | 165 | // if _animationSet is stopped while task was running 166 | if (State == AnimationSetState.Stopped) 167 | { 168 | return await _animationTCS.Task; 169 | } 170 | } 171 | 172 | _animationTasks.Clear(); 173 | 174 | foreach (var property in _directCompositionPropertyChanges) 175 | { 176 | typeof(Visual).GetProperty(property.Key).SetValue(Visual, property.Value); 177 | } 178 | 179 | foreach (var definition in _directCompositionEffectPropertyChanges) 180 | { 181 | definition.EffectBrush.Properties.InsertScalar(definition.PropertyName, definition.Value); 182 | } 183 | 184 | if (_compositionAnimations.Count > 0 || _compositionEffectAnimations.Count > 0) 185 | { 186 | if (_batch != null) 187 | { 188 | if (!_batch.IsEnded) 189 | { 190 | _batch.End(); 191 | } 192 | 193 | _batch.Completed -= Batch_Completed; 194 | } 195 | 196 | _batch = _compositor.CreateScopedBatch(CompositionBatchTypes.Animation); 197 | _batch.Completed += Batch_Completed; 198 | 199 | foreach (var anim in _compositionAnimations) 200 | { 201 | Visual.StartAnimation(anim.Key, anim.Value); 202 | } 203 | 204 | foreach (var effect in _compositionEffectAnimations) 205 | { 206 | effect.EffectBrush.StartAnimation(effect.PropertyName, effect.Animation); 207 | } 208 | 209 | _compositionCompleted = false; 210 | _batch.End(); 211 | } 212 | else 213 | { 214 | _compositionCompleted = true; 215 | } 216 | 217 | if (_storyboardAnimations.Count > 0) 218 | { 219 | _storyboardCompleted = false; 220 | 221 | _storyboard.Completed -= Storyboard_Completed; 222 | _storyboard.Completed += Storyboard_Completed; 223 | 224 | _storyboard.Begin(); 225 | } 226 | else 227 | { 228 | _storyboardCompleted = true; 229 | } 230 | 231 | HandleCompleted(); 232 | 233 | return await _animationTCS.Task; 234 | } 235 | 236 | /// 237 | /// Stops all animations. 238 | /// 239 | public void Stop() 240 | { 241 | foreach (var set in _animationSets) 242 | { 243 | if (set.State != AnimationSetState.Completed) 244 | { 245 | set.Stop(); 246 | } 247 | } 248 | 249 | if (_batch != null) 250 | { 251 | if (!_batch.IsEnded) 252 | { 253 | _batch.End(); 254 | } 255 | 256 | _batch.Completed -= Batch_Completed; 257 | } 258 | 259 | foreach (var anim in _compositionAnimations) 260 | { 261 | Visual.StopAnimation(anim.Key); 262 | } 263 | 264 | foreach (var effect in _compositionEffectAnimations) 265 | { 266 | effect.EffectBrush.StopAnimation(effect.PropertyName); 267 | } 268 | 269 | _storyboard.Pause(); 270 | 271 | HandleCompleted(true); 272 | _animationTCS = null; 273 | } 274 | 275 | /// 276 | /// Wait for existing animations to complete before running new animations 277 | /// 278 | /// AnimationSet to allow chaining 279 | public AnimationSet Then() 280 | { 281 | var savedAnimationSet = new AnimationSet(Element); 282 | savedAnimationSet._compositionAnimations = _compositionAnimations; 283 | savedAnimationSet._compositionEffectAnimations = _compositionEffectAnimations; 284 | savedAnimationSet._directCompositionPropertyChanges = _directCompositionPropertyChanges; 285 | savedAnimationSet._directCompositionEffectPropertyChanges = _directCompositionEffectPropertyChanges; 286 | savedAnimationSet._storyboard = _storyboard; 287 | savedAnimationSet._storyboardAnimations = _storyboardAnimations; 288 | 289 | _animationTasks.ForEach(t => t.AnimationSet = savedAnimationSet); 290 | savedAnimationSet._animationTasks = _animationTasks; 291 | 292 | _animationSets.Add(savedAnimationSet); 293 | 294 | _compositionAnimations = new Dictionary(); 295 | _compositionEffectAnimations = new List(); 296 | _directCompositionPropertyChanges = new Dictionary(); 297 | _directCompositionEffectPropertyChanges = new List(); 298 | _storyboard = new Storyboard(); 299 | _storyboardAnimations = new Dictionary(); 300 | _animationTasks = new List(); 301 | 302 | return this; 303 | } 304 | 305 | /// 306 | /// Ovewrites the duration on all animations after last Then() 307 | /// to the specified value 308 | /// 309 | /// The duration in milliseconds 310 | /// AnimationSet to allow chaining 311 | public AnimationSet SetDuration(double duration) 312 | { 313 | if (duration <= 0) 314 | { 315 | duration = 1; 316 | } 317 | 318 | return SetDuration(TimeSpan.FromMilliseconds(duration)); 319 | } 320 | 321 | /// 322 | /// Ovewrites the duration on all animations after last Then() 323 | /// to the specified value 324 | /// 325 | /// for the duration 326 | /// AnimationSet to allow chaining 327 | public AnimationSet SetDuration(TimeSpan duration) 328 | { 329 | foreach (var task in _animationTasks) 330 | { 331 | task.Duration = duration; 332 | } 333 | 334 | foreach (var anim in _compositionAnimations) 335 | { 336 | var animation = anim.Value as KeyFrameAnimation; 337 | if (animation != null) 338 | { 339 | animation.Duration = duration; 340 | } 341 | } 342 | 343 | foreach (var effect in _compositionEffectAnimations) 344 | { 345 | var animation = effect.Animation as KeyFrameAnimation; 346 | if (animation != null) 347 | { 348 | animation.Duration = duration; 349 | } 350 | } 351 | 352 | foreach (var timeline in _storyboardAnimations) 353 | { 354 | var animation = timeline.Value as DoubleAnimation; 355 | if (animation != null) 356 | { 357 | animation.Duration = duration; 358 | } 359 | } 360 | 361 | return this; 362 | } 363 | 364 | /// 365 | /// Ovewrites the duration on all animations to the specified value 366 | /// 367 | /// The duration in milliseconds 368 | /// AnimationSet to allow chaining 369 | public AnimationSet SetDurationForAll(double duration) 370 | { 371 | foreach (var set in _animationSets) 372 | { 373 | set.SetDuration(duration); 374 | } 375 | 376 | return SetDuration(duration); 377 | } 378 | 379 | /// 380 | /// Ovewrites the duration on all animations to the specified value 381 | /// 382 | /// for the duration 383 | /// AnimationSet to allow chaining 384 | public AnimationSet SetDurationForAll(TimeSpan duration) 385 | { 386 | foreach (var set in _animationSets) 387 | { 388 | set.SetDuration(duration); 389 | } 390 | 391 | return SetDuration(duration); 392 | } 393 | 394 | /// 395 | /// Ovewrites the delay time on all animations after last Then() 396 | /// to the specified value 397 | /// 398 | /// The delay time in milliseconds 399 | /// AnimationSet to allow chaining 400 | public AnimationSet SetDelay(double delayTime) 401 | { 402 | if (delayTime < 0) 403 | { 404 | delayTime = 0; 405 | } 406 | 407 | return SetDelay(TimeSpan.FromMilliseconds(delayTime)); 408 | } 409 | 410 | /// 411 | /// Ovewrites the delay time on all animations after last Then() 412 | /// to the specified value 413 | /// 414 | /// for how much to delay 415 | /// AnimationSet to allow chaining 416 | public AnimationSet SetDelay(TimeSpan delayTime) 417 | { 418 | foreach (var task in _animationTasks) 419 | { 420 | task.Delay = delayTime; 421 | } 422 | 423 | foreach (var anim in _compositionAnimations) 424 | { 425 | var animation = anim.Value as KeyFrameAnimation; 426 | if (animation != null) 427 | { 428 | animation.DelayTime = delayTime; 429 | } 430 | } 431 | 432 | foreach (var effect in _compositionEffectAnimations) 433 | { 434 | var animation = effect.Animation as KeyFrameAnimation; 435 | if (animation != null) 436 | { 437 | animation.DelayTime = delayTime; 438 | } 439 | } 440 | 441 | foreach (var timeline in _storyboardAnimations) 442 | { 443 | var animation = timeline.Value as DoubleAnimation; 444 | if (animation != null) 445 | { 446 | animation.BeginTime = delayTime; 447 | } 448 | } 449 | 450 | return this; 451 | } 452 | 453 | /// 454 | /// Ovewrites the delay time on all animations to the specified value 455 | /// 456 | /// The delay time in milliseconds 457 | /// AnimationSet to allow chaining 458 | public AnimationSet SetDelayForAll(double delayTime) 459 | { 460 | foreach (var set in _animationSets) 461 | { 462 | set.SetDelay(delayTime); 463 | } 464 | 465 | return SetDelay(delayTime); 466 | } 467 | 468 | /// 469 | /// Ovewrites the delay time on all animations to the specified value 470 | /// 471 | /// for how much to delay 472 | /// AnimationSet to allow chaining 473 | public AnimationSet SetDelayForAll(TimeSpan delayTime) 474 | { 475 | foreach (var set in _animationSets) 476 | { 477 | set.SetDelay(delayTime); 478 | } 479 | 480 | return SetDelay(delayTime); 481 | } 482 | 483 | /// 484 | /// Adds a composition animation to be run on 485 | /// 486 | /// The property to be animated on the backing Visual 487 | /// The to be applied 488 | public void AddCompositionAnimation(string propertyName, CompositionAnimation animation) 489 | { 490 | _compositionAnimations[propertyName] = animation; 491 | } 492 | 493 | /// 494 | /// Removes a composition animation from being run on property 495 | /// 496 | /// The property that no longer needs to be animated 497 | public void RemoveCompositionAnimation(string propertyName) 498 | { 499 | if (_compositionAnimations.ContainsKey(propertyName)) 500 | { 501 | _compositionAnimations.Remove(propertyName); 502 | } 503 | } 504 | 505 | /// 506 | /// Adds a composition effect animation to be run on backing 507 | /// 508 | /// The that will have a property animated 509 | /// The animation to be applied 510 | /// The property of the effect to be animated 511 | public void AddCompositionEffectAnimation(CompositionObject effectBrush, CompositionAnimation animation, string propertyName) 512 | { 513 | var effect = new EffectAnimationDefinition() 514 | { 515 | EffectBrush = effectBrush, 516 | Animation = animation, 517 | PropertyName = propertyName 518 | }; 519 | 520 | _compositionEffectAnimations.Add(effect); 521 | } 522 | 523 | /// 524 | /// Adds a composition property that will change instantaneously 525 | /// 526 | /// The property to be animated on the backing Visual 527 | /// The value to be applied 528 | public void AddCompositionDirectPropertyChange(string propertyName, object value) 529 | { 530 | _directCompositionPropertyChanges[propertyName] = value; 531 | } 532 | 533 | /// 534 | /// Removes a composition property change 535 | /// 536 | /// The property that no longer needs to be changed 537 | public void RemoveCompositionDirectPropertyChange(string propertyName) 538 | { 539 | if (_directCompositionPropertyChanges.ContainsKey(propertyName)) 540 | { 541 | _directCompositionPropertyChanges.Remove(propertyName); 542 | } 543 | } 544 | 545 | /// 546 | /// Adds a storyboard animation to be run 547 | /// 548 | /// The property to be animated with Storyboards 549 | /// The timeline object to be added to storyboard 550 | public void AddStoryboardAnimation(string propertyPath, Timeline timeline) 551 | { 552 | if (_storyboardAnimations.ContainsKey(propertyPath)) 553 | { 554 | var previousAnimation = _storyboardAnimations[propertyPath]; 555 | _storyboard.Children.Remove(previousAnimation); 556 | _storyboardAnimations.Remove(propertyPath); 557 | } 558 | 559 | _storyboardAnimations.Add(propertyPath, timeline); 560 | _storyboard.Children.Add(timeline); 561 | 562 | Storyboard.SetTarget(timeline, Element); 563 | Storyboard.SetTargetProperty(timeline, propertyPath); 564 | } 565 | 566 | /// 567 | /// Dispose resources. 568 | /// 569 | public void Dispose() 570 | { 571 | _animationTCS = null; 572 | } 573 | 574 | /// 575 | /// Adds a to the AnimationSet that 576 | /// will run add an animation once completed. Usefull when an animation 577 | /// needs to do asyncronous initialization before running 578 | /// 579 | /// The to be added 580 | internal void AddAnimationThroughTask(AnimationTask animationTask) 581 | { 582 | _animationTasks.Add(animationTask); 583 | } 584 | 585 | /// 586 | /// Adds an effect propety change to be run on 587 | /// 588 | /// The that will have a property changed 589 | /// The value to be applied 590 | /// The property of the effect to be animated 591 | internal void AddEffectDirectPropertyChange(CompositionObject effectBrush, float value, string propertyName) 592 | { 593 | var definition = new EffectDirectPropertyChangeDefinition() 594 | { 595 | EffectBrush = effectBrush, 596 | Value = value, 597 | PropertyName = propertyName 598 | }; 599 | 600 | _directCompositionEffectPropertyChanges.Add(definition); 601 | } 602 | 603 | private void Storyboard_Completed(object sender, object e) 604 | { 605 | _storyboardCompleted = true; 606 | _storyboard.Completed -= Storyboard_Completed; 607 | HandleCompleted(); 608 | } 609 | 610 | private void Batch_Completed(object sender, CompositionBatchCompletedEventArgs args) 611 | { 612 | _compositionCompleted = true; 613 | _batch.Completed -= Batch_Completed; 614 | HandleCompleted(); 615 | } 616 | 617 | private void HandleCompleted(bool stopped = false) 618 | { 619 | var completed = _storyboardCompleted && _compositionCompleted; 620 | 621 | if (!completed && !stopped) 622 | { 623 | return; 624 | } 625 | 626 | if (_storyboardCompleted && _compositionCompleted) 627 | { 628 | State = AnimationSetState.Completed; 629 | } 630 | else 631 | { 632 | State = AnimationSetState.Stopped; 633 | } 634 | 635 | if (_animationTCS != null && !_animationTCS.Task.IsCompleted) 636 | { 637 | Completed?.Invoke(this, new AnimationSetCompletedEventArgs() { Completed = _storyboardCompleted && _compositionCompleted }); 638 | _animationTCS.SetResult(State == AnimationSetState.Completed); 639 | } 640 | } 641 | } 642 | } 643 | --------------------------------------------------------------------------------