Inheritance: ObjectKeyFrame, IDiscreteObjectKeyFrame
Example #1
0
        /// <summary>
        /// Starts new animation from given images. 
        /// </summary>
        /// <param name="imageNames">Names of images in assets folder</param>
        /// <param name="interval">Interval between animation frames</param>
        public void StartAnimation(IEnumerable<string> imageNames, TimeSpan interval)
        {
            Storyboard storyboard = new Storyboard();
            ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames();

            // We're going to animate image inside our control.
            Storyboard.SetTarget(animation, image);
            // Animation relies on changing value of property source
            Storyboard.SetTargetProperty(animation, nameof(image.Source));

            TimeSpan currentInterval = TimeSpan.FromMilliseconds(0);
            foreach (string imageName in imageNames)
            {
                // We're creating individual frames from given images
                ObjectKeyFrame keyFrame = new DiscreteObjectKeyFrame();
                keyFrame.Value = CreateImageFromAssets(imageName);
                keyFrame.KeyTime = currentInterval;
                animation.KeyFrames.Add(keyFrame);
                currentInterval = currentInterval.Add(interval);
            }

            // We're configuring our storyboard which will play animations
            storyboard.RepeatBehavior = RepeatBehavior.Forever;
            storyboard.AutoReverse = true;
            storyboard.Children.Add(animation);
            storyboard.Begin();
        }
        public static void AnimatePath(Windows.UI.Xaml.Shapes.Path progressPath, double radius, Point initialPoint, double finalAngle = 180, double timeStep = 0.01)
        {
            var storyboard = new Storyboard();

            var progressAnimation = new ObjectAnimationUsingKeyFrames();
            Storyboard.SetTarget(progressAnimation, progressPath);
            Storyboard.SetTargetProperty(progressAnimation, "(Path.Data)");

            // for a smoother animation
            double multiplier = 3;

            Point center = new Point(radius, radius);
            for (int i = 0; i <= finalAngle * multiplier; i++)
            {
                var discreteObjectKeyFrame = new DiscreteObjectKeyFrame();
                discreteObjectKeyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(i * timeStep));

                // create points for each ArcSegment
                Point firstArcPoint = new Point(radius, 0);
                Point secondArcPoint = new Point(radius, 0);
                Point calculatedPoint = new Point()
                {
                    X = Math.Cos(Math.PI * (270 - i / multiplier) / 180.0) * radius + center.X,
                    Y = Math.Sin(Math.PI * (270 - i / multiplier) / 180.0) * radius + center.Y
                };

                if (i < 180 * multiplier)
                {
                    // use the calculated point for the first and second arc segments
                    firstArcPoint = calculatedPoint;
                    secondArcPoint = calculatedPoint;
                }
                else
                {
                    // leave the first arc segment static and use the calculated point for the second
                    firstArcPoint = new Point() { X = radius, Y = radius * 2 };
                    secondArcPoint = calculatedPoint;
                }

                // for instance, a complete circle with a radius of 150: "m 150,0 A 150,150 0 0 0 150,300 A 150,150 0 0 0 150,0"
                string dataValue = "m {0},{1} A {2},{2} 0 0 0 {3},{4} A {2},{2} 0 0 0 {5},{6}";
                discreteObjectKeyFrame.Value = string.Format(dataValue, initialPoint.X, initialPoint.Y, radius, firstArcPoint.X, firstArcPoint.Y, secondArcPoint.X, secondArcPoint.Y);
                progressAnimation.KeyFrames.Add(discreteObjectKeyFrame);
            }

            storyboard.Children.Add(progressAnimation);
            storyboard.Begin();
        }
        public void StartAnimation(IEnumerable<string> imageNames, TimeSpan interval)
        {
            Storyboard storyboard = new Storyboard();
            ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames();
            Storyboard.SetTarget(animation, image);
            Storyboard.SetTargetProperty(animation, "Source");

            TimeSpan currentInterval = TimeSpan.FromMilliseconds(0);
            foreach (string imageName in imageNames)
            {
                ObjectKeyFrame keyFrame = new DiscreteObjectKeyFrame();
                keyFrame.Value = CreateImageFromAssets(imageName);
                keyFrame.KeyTime = currentInterval;
                animation.KeyFrames.Add(keyFrame);
                currentInterval = currentInterval.Add(interval);
            }
            storyboard.RepeatBehavior = RepeatBehavior.Forever;
            storyboard.AutoReverse = true;
            storyboard.Children.Add(animation);
            storyboard.Begin();
        }
        private static Storyboard CreateStoryboard(
            FrameworkElement target,
            DependencyProperty animatingDependencyProperty,
            string propertyPath,
            ref object toValue,
            TimeSpan durationTimeSpan,
            EasingFunctionBase easingFunction)
        {
            object fromValue = target.GetValue(animatingDependencyProperty);

            double fromDoubleValue;
            double toDoubleValue;

            DateTime fromDateTime;
            DateTime toDateTime;

            Storyboard storyBoard = new Storyboard();
            Storyboard.SetTarget(storyBoard, target);
          
            Storyboard.SetTargetProperty(storyBoard, propertyPath);

            if ((fromValue != null && toValue != null))
            {
                if (ValueHelper.TryConvert(fromValue, out fromDoubleValue) && ValueHelper.TryConvert(toValue, out toDoubleValue))
                {
                    DoubleAnimation doubleAnimation = new DoubleAnimation();
                    doubleAnimation.EnableDependentAnimation = true;
#if !NO_EASING_FUNCTIONS
                    doubleAnimation.EasingFunction = easingFunction;
#endif
                    doubleAnimation.Duration = durationTimeSpan;
                    doubleAnimation.To = ValueHelper.ToDouble(toValue);
                    toValue = doubleAnimation.To;

                    storyBoard.Children.Add(doubleAnimation);
                }
                else if (ValueHelper.TryConvert(fromValue, out fromDateTime) && ValueHelper.TryConvert(toValue, out toDateTime))
                {
                    ObjectAnimationUsingKeyFrames keyFrameAnimation = new ObjectAnimationUsingKeyFrames();
                    keyFrameAnimation.EnableDependentAnimation = true;
                    keyFrameAnimation.Duration = durationTimeSpan;

                    long intervals = (long)(durationTimeSpan.TotalSeconds * KeyFramesPerSecond);
                    if (intervals < 2L)
                    {
                        intervals = 2L;
                    }

                    IEnumerable<TimeSpan> timeSpanIntervals =
                        ValueHelper.GetTimeSpanIntervalsInclusive(durationTimeSpan, intervals);

                    IEnumerable<DateTime> dateTimeIntervals =
                        ValueHelper.GetDateTimesBetweenInclusive(fromDateTime, toDateTime, intervals);

                    IEnumerable<DiscreteObjectKeyFrame> keyFrames =
                        EnumerableFunctions.Zip(
                            dateTimeIntervals,
                            timeSpanIntervals,
                            (dateTime, timeSpan) => new DiscreteObjectKeyFrame() { Value = dateTime, KeyTime = timeSpan });

                    foreach (DiscreteObjectKeyFrame keyFrame in keyFrames)
                    {
                        keyFrameAnimation.KeyFrames.Add(keyFrame);
                        toValue = keyFrame.Value;
                    }

                    storyBoard.Children.Add(keyFrameAnimation);
                }
            }

            if (storyBoard.Children.Count == 0)
            {
                ObjectAnimationUsingKeyFrames keyFrameAnimation = new ObjectAnimationUsingKeyFrames();
                keyFrameAnimation.EnableDependentAnimation = true;
                DiscreteObjectKeyFrame endFrame = new DiscreteObjectKeyFrame() { Value = toValue, KeyTime = new TimeSpan(0, 0, 0) };
                keyFrameAnimation.KeyFrames.Add(endFrame);

                storyBoard.Children.Add(keyFrameAnimation);
            }

           return storyBoard;
        }
        /// <summary>
        /// Reveals data points using a storyboard.
        /// </summary>
        /// <param name="dataPoints">The data points to change the state of.
        /// </param>
        /// <param name="dataPointCount">The number of data points in the sequence.</param>
        /// <param name="newState">The state to change to.</param>
        private void StaggeredStateChange(IEnumerable<DataPoint> dataPoints, int dataPointCount, DataPointState newState)
        {
            if (PlotArea == null || dataPointCount == 0)
            {
                return;
            }

            Storyboard stateChangeStoryBoard = new Storyboard();

            dataPoints.ForEachWithIndex((dataPoint, count) =>
            {
                // Create an Animation
                ObjectAnimationUsingKeyFrames objectAnimationUsingKeyFrames = new ObjectAnimationUsingKeyFrames();
                objectAnimationUsingKeyFrames.EnableDependentAnimation = true;
                Storyboard.SetTarget(objectAnimationUsingKeyFrames, dataPoint);
                Storyboard.SetTargetProperty(objectAnimationUsingKeyFrames, "State");

                // Create a key frame
                DiscreteObjectKeyFrame discreteObjectKeyFrame = new DiscreteObjectKeyFrame();
                discreteObjectKeyFrame.Value = (object)((int)newState);

                // Create the specified animation type
                switch (AnimationSequence)
                {
                    case AnimationSequence.Simultaneous:
                        discreteObjectKeyFrame.KeyTime = TimeSpan.Zero;
                        break;
                    case AnimationSequence.FirstToLast:
                        discreteObjectKeyFrame.KeyTime = TimeSpan.FromMilliseconds(1000 * ((double)count / dataPointCount));
                        break;
                    case AnimationSequence.LastToFirst:
                        discreteObjectKeyFrame.KeyTime = TimeSpan.FromMilliseconds(1000 * ((double)(dataPointCount - count - 1) / dataPointCount));
                        break;
                }

                // Add the Animation to the Storyboard
                objectAnimationUsingKeyFrames.KeyFrames.Add(discreteObjectKeyFrame);
                stateChangeStoryBoard.Children.Add(objectAnimationUsingKeyFrames);
            });
            //stateChangeStoryBoard.Duration = new Duration(AnimationSequence.Simultaneous == AnimationSequence ?
            //    TimeSpan.FromTicks(1) :
            //    TimeSpan.FromMilliseconds(1001));

            _storyBoardQueue.Enqueue(
                stateChangeStoryBoard,
                (sender, args) =>
                {
                    stateChangeStoryBoard.Stop();
                });
        }
 /// <summary>
 /// Create the actual storyboard that will be used to animate the transition. Use all previously calculated results.
 /// </summary>
 /// <param name="duration">The duration of the animation</param>
 /// <param name="ease">The easing function to be used in the animation</param>
 /// <param name="movingElements">The set of elements that will be moving</param>
 /// <param name="oldOpacities">The old opacities of the elements whose viisibility is changing</param>
 /// <returns>The storyboard</returns>
 private static Storyboard CreateLayoutTransitionStoryboard(VisualTransition transition, List<FrameworkElement> movingElements, Dictionary<FrameworkElement, double> oldOpacities)
 {
     Duration duration = (transition != null) ? transition.GeneratedDuration : new Duration(TimeSpan.Zero);
     EasingFunctionBase function = (transition != null) ? transition.GeneratedEasingFunction : null;
     Storyboard storyboard = new Storyboard
     {
         Duration = duration
     };
     foreach (FrameworkElement element in movingElements)
     {
         WrapperCanvas parent = element.Parent as WrapperCanvas;
         if (parent != null)
         {
             DoubleAnimation timeline = new DoubleAnimation
             {
                 From = 1.0,
                 To = 0.0,
                 Duration = duration,
                 EasingFunction = function
             };
             Storyboard.SetTarget(timeline, parent);
             Storyboard.SetTargetProperty(timeline, "SimulationProgress" /*WrapperCanvas.SimulationProgressProperty*/);
             storyboard.Children.Add(timeline);
             parent.SimulationProgress = 1.0;
             Rect newRect = parent.NewRect;
             if (!IsClose(parent.Width, newRect.Width))
             {
                 DoubleAnimation animation3 = new DoubleAnimation
                 {
                     From = new double?(newRect.Width),
                     To = new double?(newRect.Width),
                     Duration = duration
                 };
                 Storyboard.SetTarget(animation3, parent);
                 Storyboard.SetTargetProperty(animation3, "Width" /*FrameworkElement.WidthProperty*/);
                 storyboard.Children.Add(animation3);
             }
             if (!IsClose(parent.Height, newRect.Height))
             {
                 DoubleAnimation animation5 = new DoubleAnimation
                 {
                     From = new double?(newRect.Height),
                     To = new double?(newRect.Height),
                     Duration = duration
                 };
                 Storyboard.SetTarget(animation5, parent);
                 Storyboard.SetTargetProperty(animation5, "Height" /*FrameworkElement.HeightProperty*/);
                 storyboard.Children.Add(animation5);
             }
             if (parent.DestinationVisibilityCache == Visibility.Collapsed)
             {
                 Thickness margin = parent.Margin;
                 if ((!IsClose(margin.Left, 0.0) || !IsClose(margin.Top, 0.0)) || (!IsClose(margin.Right, 0.0) || !IsClose(margin.Bottom, 0.0)))
                 {
                     ObjectAnimationUsingKeyFrames frames = new ObjectAnimationUsingKeyFrames
                     {
                         Duration = duration
                     };
                     DiscreteObjectKeyFrame frame2 = new DiscreteObjectKeyFrame
                     {
                         KeyTime = TimeSpan.Zero
                     };
                     Thickness thickness2 = new Thickness();
                     frame2.Value = thickness2;
                     DiscreteObjectKeyFrame frame = frame2;
                     frames.KeyFrames.Add(frame);
                     Storyboard.SetTarget(frames, parent);
                     Storyboard.SetTargetProperty(frames, "Margin" /*FrameworkElement.MarginProperty*/);
                     storyboard.Children.Add(frames);
                 }
                 if (!IsClose(parent.MinWidth, 0.0))
                 {
                     DoubleAnimation animation7 = new DoubleAnimation
                     {
                         From = 0.0,
                         To = 0.0,
                         Duration = duration
                     };
                     Storyboard.SetTarget(animation7, parent);
                     Storyboard.SetTargetProperty(animation7, "MinWidth" /*FrameworkElement.MinWidthProperty*/);
                     storyboard.Children.Add(animation7);
                 }
                 if (!IsClose(parent.MinHeight, 0.0))
                 {
                     DoubleAnimation animation9 = new DoubleAnimation
                     {
                         From = 0.0,
                         To = 0.0,
                         Duration = duration
                     };
                     Storyboard.SetTarget(animation9, parent);
                     Storyboard.SetTargetProperty(animation9, "MinHeight" /*FrameworkElement.MinHeightProperty*/);
                     storyboard.Children.Add(animation9);
                 }
             }
         }
     }
     foreach (FrameworkElement element2 in oldOpacities.Keys)
     {
         WrapperCanvas target = element2.Parent as WrapperCanvas;
         if (target != null)
         {
             double a = oldOpacities[element2];
             double num2 = (target.DestinationVisibilityCache == Visibility.Visible) ? 1.0 : 0.0;
             if (!IsClose(a, 1.0) || !IsClose(num2, 1.0))
             {
                 DoubleAnimation animation11 = new DoubleAnimation
                 {
                     From = new double?(a),
                     To = new double?(num2),
                     Duration = duration,
                     EasingFunction = function
                 };
                 Storyboard.SetTarget(animation11, target);
                 Storyboard.SetTargetProperty(animation11, "Opacity" /*UIElement.OpacityProperty*/);
                 storyboard.Children.Add(animation11);
             }
         }
     }
     return storyboard;
 }
        private void BuildStoryBoard(List<TimeSpan> speeds)
        {
            //  Clear the story board, if it has previously been filled
            if (storyboard.Children.Count > 0)
            {
                storyboard.Children.Clear();
            }

            //  Now create the animation as a set of ObjectAnimationUsingKeyFrames (I love this name!)
            var anim = new ObjectAnimationUsingKeyFrames();
            anim.BeginTime = TimeSpan.FromSeconds(0);

            var ts = new TimeSpan();

            // Create each DiscreteObjectKeyFrame and advance the KeyTime by 100 ms (=10 fps) and add it to 
            // the storyboard.
            for (int frameIndex = 0; frameIndex < this.bitmapFrames.Count; frameIndex++)
            {
                var keyFrame = new DiscreteObjectKeyFrame();

                keyFrame.KeyTime = KeyTime.FromTimeSpan(ts);
                keyFrame.Value = this.bitmapFrames[frameIndex];

                ts = ts.Add(speeds[frameIndex]);
                anim.KeyFrames.Add(keyFrame);
            }

            //  Connect the image control with the story board

            Storyboard.SetTarget(anim, image);
            Storyboard.SetTargetProperty(anim, "Source");

            //  And finally add the animation-set to the storyboard
            storyboard.Children.Add(anim);
        }
Example #8
0
        /// <summary>
        /// Creates storyboard which player ship flash animation.
        /// </summary>
        private void CreateFlashingAnimation()
        {
            _flashStoryboard = new Storyboard();
            ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames();
            Storyboard.SetTarget(animation, image);
            Storyboard.SetTargetProperty(animation, nameof(image.Visibility));

            ObjectKeyFrame visibleFrame = new DiscreteObjectKeyFrame()
            {
                Value = Windows.UI.Xaml.Visibility.Visible,
                KeyTime = TimeSpan.FromMilliseconds(0),
            };
            ObjectKeyFrame invisibleFrame = new DiscreteObjectKeyFrame()
            {
                Value = Windows.UI.Xaml.Visibility.Collapsed,
                KeyTime = TimeSpan.FromMilliseconds(500),
            };

            animation.KeyFrames.Add(visibleFrame);
            animation.KeyFrames.Add(invisibleFrame);

            _flashStoryboard.Children.Add(animation);
            _flashStoryboard.AutoReverse = true;
            _flashStoryboard.RepeatBehavior = RepeatBehavior.Forever;
        }
        /// <summary>
        /// Initiates a spritesheet animation
        /// </summary>
        /// <param name="shape">Shape to animate on (will create an ImageBrush)</param>
        /// <param name="spriteSheetColumns">Spritesheet columns</param>
        /// <param name="spriteSheetRows">Spritesheet rows</param>
        /// <param name="image">The spritesheet image</param>
        /// <param name="width">Width of the sprite on the spritesheet</param>
        /// <param name="height">Height of the sprite on the spritesheet</param>
        /// <param name="keyframeTime">Time that each keyframe should have</param>
        /// <returns>Storyboard created</returns>
        public static Storyboard BeginSpriteSheetStoryboard(Shape shape, int spriteSheetColumns, int spriteSheetRows, BitmapImage image,
            double width, double height, int keyframeTime)
        {
            ImageBrush ib = new ImageBrush() { Stretch = Stretch.None, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top };
            ib.Transform = new CompositeTransform();
            ib.ImageSource = image;

            shape.Fill = ib;

            Storyboard sb = new Storyboard();
            sb.RepeatBehavior = RepeatBehavior.Forever;

            ObjectAnimationUsingKeyFrames frm = new ObjectAnimationUsingKeyFrames();
            ObjectAnimationUsingKeyFrames frm2 = new ObjectAnimationUsingKeyFrames();
            frm.BeginTime = new TimeSpan(0, 0, 0);
            frm2.BeginTime = new TimeSpan(0, 0, 0);


            int time = 0;
            for (int j = 0; j < spriteSheetRows; j++)
            {
                for (int i = 0; i < spriteSheetColumns; i++)
                {
                    DiscreteObjectKeyFrame dokf = new DiscreteObjectKeyFrame();
                    dokf.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(time));
                    dokf.Value = -(i * width);
                    frm.KeyFrames.Add(dokf);


                    DiscreteObjectKeyFrame dokf2 = new DiscreteObjectKeyFrame();
                    dokf2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(time));
                    dokf2.Value = -(j * height);
                    frm2.KeyFrames.Add(dokf2);
                    time += keyframeTime;
                }
            }
            Storyboard.SetTarget(frm, shape.Fill);
            Storyboard.SetTarget(frm2, shape.Fill);
            Storyboard.SetTargetProperty(frm, "(ImageBrush.Transform).(CompositeTransform.TranslateX)");
            Storyboard.SetTargetProperty(frm2, "(ImageBrush.Transform).(CompositeTransform.TranslateY)");
            sb.Children.Add(frm);
            sb.Children.Add(frm2);
            sb.Begin();
            return sb;
        }
        private ObjectAnimationUsingKeyFrames initilizeSlideUpKeyFrames()
        {
            ObjectAnimationUsingKeyFrames slideUpAnimation = new ObjectAnimationUsingKeyFrames();
            for (int i = 1; i <= 20; i++)
            {
                DiscreteObjectKeyFrame frame = new DiscreteObjectKeyFrame();
                frame.KeyTime = new TimeSpan(0, 0, 0, 0, Convert.ToInt32(4.55 * i));
                frame.Value = new Thickness(0, 0, 0, Math.Pow(5, .16491060811 * i));

                slideUpAnimation.KeyFrames.Add(frame);
            }

            return slideUpAnimation;
        }
        async Task decodeGif(Uri source)
        {
            storyboard.Stop();
            animation.KeyFrames.Clear();

            TimeSpan cumulativeDelay;

            var file = await StorageFile.GetFileFromApplicationUriAsync(source);
            using (var stream = await file.OpenReadAsync())
            {
                var decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.GifDecoderId, stream);
                byte[] imageBuffer = new byte[decoder.PixelWidth * decoder.PixelHeight * 4];

                // fill with opaque black
                for (int i = 0; i < imageBuffer.Length; i += 4)
                {
                    imageBuffer[i + 0] = 0;
                    imageBuffer[i + 1] = 0;
                    imageBuffer[i + 2] = 0;
                    imageBuffer[i + 3] = 255;
                }

                for (uint i = 0; i < decoder.FrameCount; i++)
                {
                    // get pixel data for this frame
                    var frame = await decoder.GetFrameAsync(i);
                    var data = await frame.GetPixelDataAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, new BitmapTransform(), ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage);
                    var pixels = data.DetachPixelData();

                    // get frame properties
                    var properties = await frame.BitmapProperties.GetPropertiesAsync(EMPTY_ENUMERABLE_STRING);
                    var imgdesc = await ((BitmapPropertiesView)properties["/imgdesc"].Value).GetPropertiesAsync(EMPTY_ENUMERABLE_STRING);
                    var grctlext = await ((BitmapPropertiesView)properties["/grctlext"].Value).GetPropertiesAsync(EMPTY_ENUMERABLE_STRING);

                    var delay = (ushort)grctlext["/Delay"].Value;
                    var transparencyFlag = (bool)grctlext["/TransparencyFlag"].Value;
                    var disposal = (byte)grctlext["/Disposal"].Value;
                    var t = (ushort)imgdesc["/Top"].Value;
                    var l = (ushort)imgdesc["/Left"].Value;
                    var w = (ushort)imgdesc["/Width"].Value;
                    var h = (ushort)imgdesc["/Height"].Value;

                    // disposal values:
                    // 0: no disposal specified
                    // 1: do not dispose; graphic to be left in place
                    // 2: restore background color
                    // 3: restore to previous

                    if (disposal == 2)
                    {
                        // fill with background color
                        // TODO: figure out what the actual background color should be, but in the meantime
                        // we'll assume it's transparent
                        Array.Clear(imageBuffer, 0, imageBuffer.Length);
                    }

                    for (int y = 0; y < h; y++)
                    {
                        for (int x = 0; x < w; x++)
                        {
                            var sourceOffset = (y * w + x) * 4;
                            var destOffset = ((t + y) * decoder.PixelWidth + l + x) * 4;

                            if (pixels[sourceOffset + 3] == 255)
                            {
                                imageBuffer[destOffset + 0] = pixels[sourceOffset + 0];
                                imageBuffer[destOffset + 1] = pixels[sourceOffset + 1];
                                imageBuffer[destOffset + 2] = pixels[sourceOffset + 2];
                                imageBuffer[destOffset + 3] = 255;
                            }
                        }
                    }

                    // convert frame to WritableBitmap
                    var bmp = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
                    using (var bmpStream = bmp.PixelBuffer.AsStream())
                    {
                        bmpStream.Seek(0, SeekOrigin.Begin);
                        await bmpStream.WriteAsync(imageBuffer, 0, imageBuffer.Length);
                    }

                    // add animation frame
                    var keyFrame = new DiscreteObjectKeyFrame();
                    keyFrame.KeyTime = KeyTime.FromTimeSpan(cumulativeDelay);
                    keyFrame.Value = bmp;
                    animation.KeyFrames.Add(keyFrame);

                    // add frame delay
                    cumulativeDelay = cumulativeDelay.Add(TimeSpan.FromMilliseconds(delay * 10));
                }

                storyboard.RepeatBehavior = decoder.FrameCount == 1 ? new RepeatBehavior(1) : RepeatBehavior.Forever;
            }

            storyboard.Begin();
        }
 private ObjectAnimationUsingKeyFrames UpdateStoryBoardImpl(ObjectAnimationUsingKeyFrames anim, int i) // Broken out May 2015
 {
     // Make widths narrower for filled and half state:
     DiscreteObjectKeyFrame kf = new DiscreteObjectKeyFrame();
     kf.KeyTime = TimeSpan.FromSeconds(0);
     //kf.Value = 100;
     kf.SetValue(ZoneButton.ZoneButtonWidthProperty, 100);
     anim.KeyFrames.Add(kf);
     Storyboard.SetTargetName(anim, zb[i].Name);
     // fails with exception when filled mode invoked: Storyboard.SetTargetProperty(anim, "(ZoneButton.ZoneButtonWidthProperty)");
     Storyboard.SetTargetProperty(anim, "ZoneButtonWidth"); // doesn't throw exception but doesn't change width either.  Doesn't seem to call setter
     return anim;
 }