/// <summary>Creates a new animated property.</summary> /// <param name="animation">The animation that this property is a part of.</param> /// <param name="property">The property being animated.</param> /// <param name="targetValue">The value that this property will be when the animation is over.</param> /// <param name="constantSpeedTime">How long the animation will change the value at a constant speed for.</param> /// <param name="timeToAccelerateFor">How long the animation will accelerate for. This produces a smoother animation.</param> /// <param name="timeToDecelerateFor">How long the animation will decelerate for. This produces a smoother animation.</param> /// <param name="updateCss">True if this particular property should flush its changes to css/the screen.</param> public AnimatedProperty(UIAnimation animation, CssProperty property, int innerIndex, Css.Value targetValue, float constantSpeedTime, float timeToAccelerateFor, float timeToDecelerateFor, bool updateCss) { Animation = animation; PropertyInfo = property; InnerIndex = innerIndex; Css.ValueType type = targetValue.Type; if (!Animation.ElementStyle.Properties.TryGetValue(property, out ValueObject)) { ComputedStyle computed = Animation.ElementStyle.Computed; if (computed != null && computed.Properties.TryGetValue(property, out ValueObject)) { // Let's derive from the computed form. ValueObject = ValueObject.Copy(); } else { ValueObject = new Css.Value(); if (innerIndex != -1 || type == Css.ValueType.Null) { type = Css.ValueType.Rectangle; } property.SetDefault(ValueObject, type); } Animation.ElementStyle.Properties[property] = ValueObject; } if (ValueObject.Type == Css.ValueType.Inherit) { // Special case - we need to duplicate it. Animation.ElementStyle.Properties[property] = ValueObject = ValueObject.Copy(); ValueObject.Type = type; } PropertyValueObject = ValueObject; if (innerIndex != -1) { Css.Value innerValue = ValueObject[innerIndex]; if (innerValue == null) { ValueObject[innerIndex] = innerValue = new Css.Value(); } ValueObject = innerValue; } // Set our starting value: ActiveValue = ValueObject.ToFloat(); Animate(Animation, targetValue, constantSpeedTime, timeToAccelerateFor, timeToDecelerateFor, updateCss); }
/// <summary>Creates a new UIAnimation for animating CSS and immediately animates it. /// See <see cref="PowerUI.Element.animate"/>.</summary> /// <param name="animating">The element being animated.</param> /// <param name="properties">The CSS property string. Each property should define the value it will be when the animation is done.</param> /// <param name="constantSpeedTime">How long this animation lasts for at a constant speed.</param> /// <param name="timeToAccelerateFor">How long this animation accelerates for. Creates smooth animations when used.</param> /// <param name="timeToDecelerateFor">How long this animation decelerates for. Creates smooth animations when used.</param> public UIAnimation(Element animating, string properties, float constantSpeedTime, float timeToAccelerateFor, float timeToDecelerateFor) { Animating = animating; ElementStyle = Animating.Style; if (string.IsNullOrEmpty(properties)) { Wrench.Log.Add("No properties given to animate!"); return; } if (constantSpeedTime < 0f) { constantSpeedTime = 0f; } if (timeToAccelerateFor < 0f) { timeToAccelerateFor = 0f; } if (timeToDecelerateFor < 0f) { timeToDecelerateFor = 0f; } TotalTime = (timeToDecelerateFor + timeToAccelerateFor + constantSpeedTime); ConstantSpeedTime = constantSpeedTime; TimeToAccelerateFor = timeToAccelerateFor; TimeToDecelerateFor = timeToDecelerateFor; if (TotalTime == 0f) { // Instant - probably a fault somewhere in the users request, so we won't do anything. Wrench.Log.Add("Instant css animation request ignored. Told to take no time to transition."); return; } if (timeToDecelerateFor == 0f) { Decelerate = false; } else { Decelerate = true; DecelerateAt = timeToAccelerateFor + constantSpeedTime; } if (properties.StartsWith(".") || properties.StartsWith("#")) { // Targeting a selector, e.g. #fadedBox // First, get the selector style: Css.SelectorStyle selector = animating.Document.getStyleBySelector(properties); if (selector == null) { return; } // Animate each property: foreach (KeyValuePair <CssProperty, Css.Value> kvp in selector.Properties) { // Is it a composite property? Css.Value value = kvp.Value; // Grab the type: Css.ValueType type = value.Type; if (type == Css.ValueType.Null || type == Css.ValueType.Text) { // Can't deal with either of these. continue; } if (type == Css.ValueType.Rectangle || type == Css.ValueType.Point || type == Css.ValueType.Color) { // Animate it (note that we don't need to copy it): AnimateComposite(kvp.Key, value); } else { // Animate it (note that we don't need to copy it): Animate(kvp.Key, -1, value, true); } } return; } string[] propertySet = properties.Split(';'); foreach (string currentProperty in propertySet) { if (currentProperty == "") { continue; } string[] keyValue = currentProperty.Split(Css.Style.Delimiter, 2); if (keyValue.Length != 2) { continue; } string key = keyValue[0].Trim(); if (key == "opacity") { key = "color-overlay-a"; } // Grab the inner index: int innerIndex = Css.Value.GetInnerIndex(ref key); // Get the property: CssProperty property = CssProperties.Get(key); if (property == null) { Wrench.Log.Add("Warning: CSS property '" + keyValue[0] + "' not found during animate."); continue; } // Trim shouldn't be applied to inner-text's value, but we can't animate that anyway! This is all we need to do: string value = keyValue[1].Trim(); // Key could be a composite property - for example padding, which needs to be broken down into it's individual inner elements (e.g. padding-left) Css.ValueType type; if (innerIndex == -1) { type = Css.Value.TypeOf(property, ref value); } else { type = Css.Value.TypeOf(value); } if (type == Css.ValueType.Null || type == Css.ValueType.Text) { // Can't deal with either of these. continue; } else if (type == Css.ValueType.Rectangle || type == Css.ValueType.Point || type == Css.ValueType.Color) { // We have a composite property (and we're animating the whole thing). Css.Value tempValue = new Css.Value(); tempValue.Set(value, type); // Animate it: AnimateComposite(property, tempValue); } else { Animate(property, innerIndex, new Css.Value(value, type), true); } } }