在 WPF 中显示 GIF 动画图像的最佳方式是什么?

发布于 2024-11-28 05:02:26 字数 108 浏览 5 评论 0原文

我想在程序进行过程中在 XAML 中显示动画 gif,例如“loading...”。我发现这在 WPF 中不容易完成,因为我加载了 Gif 并且它只显示了第一帧。在 WPF 中显示动画的最佳方式是什么?

I would like to display an animation gif such as loading... in my XAML as my procedure is progressing. I found out that this cannot be easily done in WPF as I loaded my Gif and it just shows the first frame. What are the best ways to display an animation in WPF.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏尔 2024-12-05 05:02:26

您可以使用以下代码在 WPF 应用程序中加载 GIFImage

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Media.Imaging;

    /// <summary>
    /// Class to host nornmal and Gif images and plays the animation.
    /// To make it work, instead of setting ImageSource, set the AnimationSourcePath property.
    /// </summary>
    public class GifImage : Image
    {
        /// <summary>
        /// Dependency property to hold value for AnimationSourcePath.
        /// </summary>
        public static readonly DependencyProperty AnimationSourcePathProperty =
            DependencyProperty.Register(
            "AnimationSourcePath",
            typeof(string),
            typeof(GifImage),
            new UIPropertyMetadata(String.Empty, AnimationSourcePathPropertyChanged));

        /// <summary>
        /// Dependency property to hold value of integer animation timeline values for FrameIndex.
        /// </summary>
        private static readonly DependencyProperty FrameIndexProperty =
            DependencyProperty.Register(
            "FrameIndex",
            typeof(int),
            typeof(GifImage),
            new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));

        /// <summary>
        /// Dependency property to hold value of integer animation rate which slows down animation speed if value is more than 1.
        /// </summary>
        private static readonly DependencyProperty FrameRefreshRateProperty =
            DependencyProperty.Register(
            "FrameRefreshRate",
            typeof(int),
            typeof(GifImage),
            new UIPropertyMetadata(1, AnimationSourcePathPropertyChanged));

        /// <summary>
        /// Member to hold animation timeline for integer values.
        /// </summary>
        private Int32Animation anim;

        /// <summary>
        /// Member to hold flag to indicate if animation is working.
        /// </summary>
        private bool animationIsWorking = false;

        /// <summary>
        /// Member to hold Gif Bitmap Decoder.
        /// </summary>
        private GifBitmapDecoder gf;

        /// <summary>
        /// Initializes a new instance of the GifImage class.
        /// </summary>
        public GifImage()
        {
        }

        /// <summary>
        /// Initializes a new instance of the GifImage class based on the uri.
        /// </summary>
        /// <param name="uri">Uri of the image source.</param>
        public GifImage(Uri uri)
        {
            GifImage.SetupAnimationSource(this, uri);
        }

        /// <summary>
        /// Gets or sets a value indicating AnimationSourcePath.
        /// </summary>
        public string AnimationSourcePath
        {
            get { return (string)GetValue(AnimationSourcePathProperty); }
            set { SetValue(AnimationSourcePathProperty, value); }
        }

        /// <summary>
        /// Gets or sets a value indicating FrameIndex.
        /// </summary>
        public int FrameIndex
        {
            get { return (int)GetValue(FrameIndexProperty); }
            set { SetValue(FrameIndexProperty, value); }
        }

        /// <summary>
        /// Gets or sets a value for frame refresh rate. A value more than 1 would slow the animation down.
        /// </summary>
        public int FrameRefreshRate
        {
            get { return (int)GetValue(FrameRefreshRateProperty); }
            set { SetValue(FrameRefreshRateProperty, value); }
        }

        /// <summary>
        /// Method to handle property changed event of AnimationSourcePath property.
        /// </summary>
        /// <param name="obj">Source image.</param>
        /// <param name="ev">Event arguments.</param>
        protected static void AnimationSourcePathPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
        {
            GifImage ob = obj as GifImage;
            ob.BeginAnimation(GifImage.FrameIndexProperty, null);
            ob.anim = null;
            ob.gf = null;
            ob.Source = null;

            if (!String.IsNullOrEmpty(ob.AnimationSourcePath) &&
                Uri.IsWellFormedUriString(ob.AnimationSourcePath, UriKind.RelativeOrAbsolute))
            {
                if (((string)ob.AnimationSourcePath).ToLower().EndsWith(".gif"))
                {
                    Uri uri = new Uri(ob.AnimationSourcePath);
                    GifImage.SetupAnimationSource(ob, uri);
                    ob.BeginAnimation(GifImage.FrameIndexProperty, ob.anim);
                }
                else
                {
                    ob.Source = (new ImageSourceConverter()).ConvertFromString(ob.AnimationSourcePath) as ImageSource;
                    ob.InvalidateVisual();
                }

                ob.animationIsWorking = true;
            }
        }

        /// <summary>
        /// Method to handle property changed event of FrameIndex property.
        /// </summary>
        /// <param name="obj">Source image.</param>
        /// <param name="ev">Event arguments.</param>
        protected static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
        {
            GifImage ob = obj as GifImage;
            ob.Source = ob.gf.Frames[ob.FrameIndex];
            ob.InvalidateVisual();
        }

        /// <summary>
        /// Method to setup animation source against a Gif Image.
        /// </summary>
        /// <param name="ob">Gif image.</param>
        /// <param name="uri">Uri of the gif image source.</param>
        protected static void SetupAnimationSource(GifImage ob, Uri uri)
        {
            ob.gf = new GifBitmapDecoder(uri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            double val = (ob.gf.Frames.Count / 15.0) - (ob.gf.Frames.Count / 15);
            TimeSpan tmpSpn = new TimeSpan(0, 0, 0, ob.gf.Frames.Count / 15, (int)(val * 1000));
            Duration durtn = new Duration(new TimeSpan(tmpSpn.Ticks * ob.FrameRefreshRate));
            ob.anim = new Int32Animation(0, ob.gf.Frames.Count - 1, durtn);
            ob.anim.RepeatBehavior = RepeatBehavior.Forever;
            ob.Source = ob.gf.Frames[0];
        }

        /// <summary>
        /// Method to override the OnRender event of the image.
        /// </summary>
        /// <param name="dc">Drawing Context of the image.</param>
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

            if (!this.animationIsWorking)
            {
                BeginAnimation(GifImage.FrameIndexProperty, this.anim);
                this.animationIsWorking = true;
            }
        }
    }

您使用它的方式如下......

    <ns:GifImage AnimationSourcePath="../MyGifImage.gif" />

让我知道这是否对您有帮助。

You can use the following code for loading GIFImage in a WPF app

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Media.Imaging;

    /// <summary>
    /// Class to host nornmal and Gif images and plays the animation.
    /// To make it work, instead of setting ImageSource, set the AnimationSourcePath property.
    /// </summary>
    public class GifImage : Image
    {
        /// <summary>
        /// Dependency property to hold value for AnimationSourcePath.
        /// </summary>
        public static readonly DependencyProperty AnimationSourcePathProperty =
            DependencyProperty.Register(
            "AnimationSourcePath",
            typeof(string),
            typeof(GifImage),
            new UIPropertyMetadata(String.Empty, AnimationSourcePathPropertyChanged));

        /// <summary>
        /// Dependency property to hold value of integer animation timeline values for FrameIndex.
        /// </summary>
        private static readonly DependencyProperty FrameIndexProperty =
            DependencyProperty.Register(
            "FrameIndex",
            typeof(int),
            typeof(GifImage),
            new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));

        /// <summary>
        /// Dependency property to hold value of integer animation rate which slows down animation speed if value is more than 1.
        /// </summary>
        private static readonly DependencyProperty FrameRefreshRateProperty =
            DependencyProperty.Register(
            "FrameRefreshRate",
            typeof(int),
            typeof(GifImage),
            new UIPropertyMetadata(1, AnimationSourcePathPropertyChanged));

        /// <summary>
        /// Member to hold animation timeline for integer values.
        /// </summary>
        private Int32Animation anim;

        /// <summary>
        /// Member to hold flag to indicate if animation is working.
        /// </summary>
        private bool animationIsWorking = false;

        /// <summary>
        /// Member to hold Gif Bitmap Decoder.
        /// </summary>
        private GifBitmapDecoder gf;

        /// <summary>
        /// Initializes a new instance of the GifImage class.
        /// </summary>
        public GifImage()
        {
        }

        /// <summary>
        /// Initializes a new instance of the GifImage class based on the uri.
        /// </summary>
        /// <param name="uri">Uri of the image source.</param>
        public GifImage(Uri uri)
        {
            GifImage.SetupAnimationSource(this, uri);
        }

        /// <summary>
        /// Gets or sets a value indicating AnimationSourcePath.
        /// </summary>
        public string AnimationSourcePath
        {
            get { return (string)GetValue(AnimationSourcePathProperty); }
            set { SetValue(AnimationSourcePathProperty, value); }
        }

        /// <summary>
        /// Gets or sets a value indicating FrameIndex.
        /// </summary>
        public int FrameIndex
        {
            get { return (int)GetValue(FrameIndexProperty); }
            set { SetValue(FrameIndexProperty, value); }
        }

        /// <summary>
        /// Gets or sets a value for frame refresh rate. A value more than 1 would slow the animation down.
        /// </summary>
        public int FrameRefreshRate
        {
            get { return (int)GetValue(FrameRefreshRateProperty); }
            set { SetValue(FrameRefreshRateProperty, value); }
        }

        /// <summary>
        /// Method to handle property changed event of AnimationSourcePath property.
        /// </summary>
        /// <param name="obj">Source image.</param>
        /// <param name="ev">Event arguments.</param>
        protected static void AnimationSourcePathPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
        {
            GifImage ob = obj as GifImage;
            ob.BeginAnimation(GifImage.FrameIndexProperty, null);
            ob.anim = null;
            ob.gf = null;
            ob.Source = null;

            if (!String.IsNullOrEmpty(ob.AnimationSourcePath) &&
                Uri.IsWellFormedUriString(ob.AnimationSourcePath, UriKind.RelativeOrAbsolute))
            {
                if (((string)ob.AnimationSourcePath).ToLower().EndsWith(".gif"))
                {
                    Uri uri = new Uri(ob.AnimationSourcePath);
                    GifImage.SetupAnimationSource(ob, uri);
                    ob.BeginAnimation(GifImage.FrameIndexProperty, ob.anim);
                }
                else
                {
                    ob.Source = (new ImageSourceConverter()).ConvertFromString(ob.AnimationSourcePath) as ImageSource;
                    ob.InvalidateVisual();
                }

                ob.animationIsWorking = true;
            }
        }

        /// <summary>
        /// Method to handle property changed event of FrameIndex property.
        /// </summary>
        /// <param name="obj">Source image.</param>
        /// <param name="ev">Event arguments.</param>
        protected static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
        {
            GifImage ob = obj as GifImage;
            ob.Source = ob.gf.Frames[ob.FrameIndex];
            ob.InvalidateVisual();
        }

        /// <summary>
        /// Method to setup animation source against a Gif Image.
        /// </summary>
        /// <param name="ob">Gif image.</param>
        /// <param name="uri">Uri of the gif image source.</param>
        protected static void SetupAnimationSource(GifImage ob, Uri uri)
        {
            ob.gf = new GifBitmapDecoder(uri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            double val = (ob.gf.Frames.Count / 15.0) - (ob.gf.Frames.Count / 15);
            TimeSpan tmpSpn = new TimeSpan(0, 0, 0, ob.gf.Frames.Count / 15, (int)(val * 1000));
            Duration durtn = new Duration(new TimeSpan(tmpSpn.Ticks * ob.FrameRefreshRate));
            ob.anim = new Int32Animation(0, ob.gf.Frames.Count - 1, durtn);
            ob.anim.RepeatBehavior = RepeatBehavior.Forever;
            ob.Source = ob.gf.Frames[0];
        }

        /// <summary>
        /// Method to override the OnRender event of the image.
        /// </summary>
        /// <param name="dc">Drawing Context of the image.</param>
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

            if (!this.animationIsWorking)
            {
                BeginAnimation(GifImage.FrameIndexProperty, this.anim);
                this.animationIsWorking = true;
            }
        }
    }

The way you use it as follows....

    <ns:GifImage AnimationSourcePath="../MyGifImage.gif" />

Let me know if this helps you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文