/// <summary> /// Perform animation effects on the set of children. /// </summary> /// <param name="animateId">Identifier of the animate to be used.</param> /// <param name="metaPanel">Reference to owning panel instance.</param> /// <param name="stateDict">Dictionary of per-element state.</param> /// <param name="elements">Collection of elements to be animated.</param> /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param> /// <param name="startOpacity">Opacity for start of animation.</param> /// <param name="endOpacity">Opacity for end of animation.</param> public void ApplyAnimation(string animateId, MetaPanelBase metaPanel, MetaElementStateDict stateDict, ICollection elements, double elapsedMilliseconds, double startOpacity, double endOpacity) { // Only apply if we match the incoming animate identifier if (string.IsNullOrEmpty(Id) || Id.Equals(animateId)) { // Only grab the dependancy properties once, for improved perf double duration = Duration; foreach (UIElement element in elements) { // Only apply animation to element of required target state MetaElementState elementState = stateDict[element]; if (elementState.Status == Target) { // If the element is the correct target and correct status for starting animation if ((!elementState.RemoveCalculated && (Target == MetaElementStatus.Removing)) || (elementState.NewCalculating && (Target == MetaElementStatus.New))) { // Use the starting opacity element.Opacity = startOpacity; elementState.ElapsedOpacityTime = 0; } else { // Only perform animation if some time has actually ellapsed and not already at target if ((elapsedMilliseconds > 0) && (element.Opacity != (double)endOpacity)) { // Add new elapsed time to the animation running time elementState.ElapsedOpacityTime += elapsedMilliseconds; // Does elapsed time indicate animation should have completed? if (elementState.ElapsedOpacityTime >= duration) { element.Opacity = endOpacity; } else { element.Opacity = EasingCalculation.Calculate(elementState.ElapsedOpacityTime, startOpacity, endOpacity - startOpacity, duration); } } } // If not yet at target opacity then not finished with animating elementState.AnimateComplete &= (element.Opacity == (double)endOpacity); } } } }
/// <summary> /// Perform animation effects on the set of children. /// </summary> /// <param name="animateId">Identifier of the animate to be used.</param> /// <param name="metaPanel">Reference to owning panel instance.</param> /// <param name="stateDict">Dictionary of per-element state.</param> /// <param name="elements">Collection of elements to be animated.</param> /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param> public override void ApplyAnimation(string animateId, MetaPanelBase metaPanel, MetaElementStateDict stateDict, ICollection elements, double elapsedMilliseconds) { // Only apply if we match the incoming animate identifier if (string.IsNullOrEmpty(Id) || Id.Equals(animateId)) { // Update the easing equation with latest value EasingCalculation.Easing = Easing; // Cache dependancy properties for faster perf double duration = Math.Max((double)1, Duration); foreach (UIElement element in elements) { // Only apply animation to element of required target state MetaElementState elementState = stateDict[element]; if (elementState.Status == Target) { Rect targetRect = elementState.TargetRect; Rect currentRect = (elementState.CurrentRect.IsEmpty ? targetRect : elementState.CurrentRect); // If start of animation.... if (elementState.TargetChanged) { // Cache starting information elementState.StartRect = currentRect; elementState.ElapsedBoundsTime = 0; } else { // Only perform animation if some time has actually ellapsed and not already at target if ((elapsedMilliseconds > 0) && !currentRect.Equals(targetRect)) { // Add new elapsed time to the animation running time elementState.ElapsedBoundsTime += elapsedMilliseconds; // Does elapsed time indicate animation should have completed? if (elementState.ElapsedBoundsTime >= duration) { currentRect = targetRect; } else { Rect startRect = elementState.StartRect; double elapsedTime = elementState.ElapsedBoundsTime; // Using animation easing to discover new target rectangle corners double left = EasingCalculation.Calculate(elapsedTime, startRect.X, targetRect.X - startRect.X, duration); double top = EasingCalculation.Calculate(elapsedTime, startRect.Y, targetRect.Y - startRect.Y, duration); double bottom = EasingCalculation.Calculate(elapsedTime, startRect.Bottom, targetRect.Bottom - startRect.Bottom, duration); double right = EasingCalculation.Calculate(elapsedTime, startRect.Right, targetRect.Right - startRect.Right, duration); // Normalize edges left/right edges if (left > right) { elapsedTime = left; left = right; right = elapsedTime; } // Normalize edges top/bottom edges if (top > bottom) { elapsedTime = top; top = bottom; bottom = elapsedTime; } currentRect = new Rect(left, top, right - left, bottom - top); } } } // Put back the updated rectangle and decide if more animation is needed elementState.CurrentRect = currentRect; elementState.AnimateComplete &= (currentRect.Equals(targetRect)); } } } }
/// <summary> /// Initialize a new instance of the MovePositionAnimate class. /// </summary> /// <param name="target">State of elements to animate.</param> protected EasingAnimate(MetaElementStatus target) { _target = target; _easing = new EasingCalculation(DEFAULT_EASING); }