private static void PrepareAnimations(FrameworkElement element, bool useSecondaryAnimation = false) { if (element == null) { return; } // Make sure to not start an animation when an element is not visible if (element.Visibility != Visibility.Visible) { return; } // Make sure to stop any running animations if (_actives.IsElementAnimating(GetElementGuid(element))) { foreach (var active in _actives.GetAllNonIteratingActiveTimelines(GetElementGuid(element))) { active.Timeline.Stop(); } } var animationSettings = element.GetSettings( useSecondaryAnimation ? SettingsTarget.Secondary : SettingsTarget.Primary, getPrimaryFunc: GetPrimary, getSecondaryFunc: GetSecondary); // Settings can be null if a Trigger is set before the associated element is loaded if (animationSettings == null) { return; } var settingsList = animationSettings.ToSettingsList(); var startFirst = true; var iterationBehavior = GetIterationBehavior(element); var iterationCount = GetIterationCount(element); var sequenceCounter = 0; foreach (var settings in settingsList) { var isSequence = settingsList.Count > 1; // The "first" animation must always run immediately if (startFirst) { RunAnimation(element, settings, isSequence); startFirst = false; } else { _actives.Add(null, settings, element, AnimationState.Idle, iterationBehavior, iterationCount, isSequence, sequenceOrder: sequenceCounter); } sequenceCounter++; } }
// This can be called from the three main entry-points (Primary, Secondary, and StartWith) private static void InitializeElement(FrameworkElement element) { if (GetIsInitialized(element)) { return; } // Set IsInitialized to true to only run this code once per element SetIsInitialized(element, true); #if __UWP__ // The new way of handling translate animations (see Translation property section): // https://blogs.windows.com/buildingapps/2017/06/22/sweet-ui-made-possible-easy-windows-ui-windows-10-creators-update/ ElementCompositionPreview.SetIsTranslationEnabled(element, true); #endif element .Events() .LoadedUntilUnloaded .Take(1) .Subscribe( args => { // Perform validations on element's attached properties Validate(element); var startSettings = element.GetSettings(SettingsTarget.StartWith, getStartWithFunc: GetStartWith); // If any StartWith settings were specified, apply them if (startSettings != null) { element.ApplyInitialSettings((AnimationSettings)startSettings); } }, ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.Loaded)} event of {nameof(FrameworkElement)}", ex) ); element .Observe(UIElement.VisibilityProperty) .TakeUntil(element.Events().UnloadedMaterialized) .Subscribe( _ => { var isVisible = element.Visibility == Visibility.Visible; var elementGuid = GetElementGuid(element); if (isVisible && _actives.GetNextIdleActiveTimeline(elementGuid)?.Timeline is Timeline idle) { RunNextAnimation(idle, element); } }, ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.Visibility)} changes of {nameof(FrameworkElement)}", ex) ); #if __UWP__ element .Events() .SizeChanged .TakeUntil(element.Events().UnloadedMaterialized) .Subscribe( args => { // If the element child is a SpriteVisual, maintain its size so update any effects applied if (args.Sender is FrameworkElement elem && ElementCompositionPreview.GetElementChildVisual(elem) is SpriteVisual sprite) { sprite.Size = new Vector2((float)elem.ActualWidth, (float)elem.ActualHeight); } }, ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.SizeChanged)} event of {nameof(FrameworkElement)}", ex) ); #endif }