部分内容参考博文WPF 如何显示gif

一、使用Storyboard

效果:

(1)页面xaml:

<Window x:Class="PlayGifDemo.StoryboardWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PlayGifDemo"
mc:Ignorable="d"
Title="StoryboardWindow" Height="400" Width="400" WindowStartupLocation="CenterScreen">
<Grid>
<Image x:Name="imgGifShow" Stretch="Fill" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</Window>
(2)后台代码:

/// <summary>
/// StoryboardWindow.xaml 的交互逻辑
/// </summary>
public partial class StoryboardWindow : Window
{
private Storyboard board = null;

public StoryboardWindow()
{
InitializeComponent();
ShowGifByAnimate(@"pack://application:,,,/Resource/loading.gif");
}

/// <summary>
/// 显示GIF动图
/// </summary>
private void ShowGifByAnimate(string filePath)
{
this.Dispatcher.Invoke(() =>
{
List<BitmapFrame> frameList = new List<BitmapFrame>();
GifBitmapDecoder decoder = new GifBitmapDecoder(
new Uri(filePath, UriKind.RelativeOrAbsolute),
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
if (decoder != null && decoder.Frames != null)
{
frameList.AddRange(decoder.Frames);
ObjectAnimationUsingKeyFrames objKeyAnimate = new ObjectAnimationUsingKeyFrames();
objKeyAnimate.Duration = new Duration(TimeSpan.FromSeconds(1));
foreach (var item in frameList)
{
DiscreteObjectKeyFrame k1_img1 = new DiscreteObjectKeyFrame(item);
objKeyAnimate.KeyFrames.Add(k1_img1);
}
imgGifShow.Source = frameList[0];

board = new Storyboard();
board.RepeatBehavior = RepeatBehavior.Forever;
board.FillBehavior = FillBehavior.HoldEnd;
board.Children.Add(objKeyAnimate);
Storyboard.SetTarget(objKeyAnimate, imgGifShow);
Storyboard.SetTargetProperty(objKeyAnimate, new PropertyPath("(Image.Source)"));
board.Begin();
}
});
}
}
二、使用WpfAnimatedGif

效果:

(1)NuGet包管理器安装WpfAnimatedGif

(2)页面xaml:

<Window x:Class="PlayGifDemo.WpfAnimatedGifWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PlayGifDemo"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
mc:Ignorable="d"
Title="WpfAnimatedGifWindow" Height="400" Width="400" WindowStartupLocation="CenterScreen">
<Grid>
<Image gif:ImageBehavior.AnimatedSource="Resource/loading.gif" />
</Grid>
</Window>
三、使用ImageAnimator

效果:

(1)页面xaml:

<Window x:Class="PlayGifDemo.ImageAnimatorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PlayGifDemo"
mc:Ignorable="d"
Closing="Window_Closing"
Title="ImageAnimatorWindow" Height="400" Width="400" WindowStartupLocation="CenterScreen">
<Grid>
<Image x:Name="imgGifShow" Stretch="Fill" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</Window>
(2)后台代码:

/// <summary>
/// ImageAnimatorWindow.xaml 的交互逻辑
/// </summary>
public partial class ImageAnimatorWindow : Window
{
private Bitmap gifBitmap;// gif动画的System.Drawing.Bitmap
private BitmapSource bitmapSource;// 用于显示每一帧的BitmapSource

public ImageAnimatorWindow()
{
InitializeComponent();
GetGifImage(AppDomain.CurrentDomain.BaseDirectory + @"/Resource/loading.gif");
}

private void GetGifImage(string path)
{
this.gifBitmap = new Bitmap(path);
this.bitmapSource = this.GetBitmapSource();
this.imgGifShow.Source = this.bitmapSource;
StartAnimate();
}

/// <summary>
/// 从System.Drawing.Bitmap中获得用于显示的那一帧图像的BitmapSource
/// </summary>
/// <returns></returns>
private BitmapSource GetBitmapSource()
{
IntPtr handle = IntPtr.Zero;
try
{
handle = this.gifBitmap.GetHbitmap();
this.bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
finally
{
if (handle != IntPtr.Zero)
{
DeleteObject(handle);
}
}
return this.bitmapSource;
}

/// <summary>
/// Start
/// </summary>
public void StartAnimate()
{
ImageAnimator.Animate(this.gifBitmap, this.OnFrameChanged);
}

/// <summary>
/// Stop
/// </summary>
public void StopAnimate()
{
ImageAnimator.StopAnimate(this.gifBitmap, this.OnFrameChanged);
}

/// <summary>
/// 帧处理
/// </summary>
private void OnFrameChanged(object sender, EventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
ImageAnimator.UpdateFrames(); // 更新到下一帧
if (this.bitmapSource != null)
{
this.bitmapSource.Freeze();
}

this.bitmapSource = this.GetBitmapSource();
this.imgGifShow.Source = this.bitmapSource;
this.InvalidateVisual();
}));
}

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
StopAnimate();
}

/// <summary>
/// 删除本地 bitmap resource
/// </summary>
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteObject(IntPtr hObject);
}
四、使用Winform控件PictureBox

效果:

(1)添加对System.Windows.Forms.dll、WindowsFormsIntegration.dll、System.Drawing.dll的引用

(2)页面xaml:

<Window x:Class="PlayGifDemo.PictureBoxWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PlayGifDemo"
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d"
Loaded="Window_Loaded"
Title="PictureBoxWindow" Height="400" Width="400" WindowStartupLocation="CenterScreen">
<Grid>
<wfi:WindowsFormsHost>
<winForms:PictureBox x:Name="pictureGifShow"></winForms:PictureBox>
</wfi:WindowsFormsHost>
</Grid>
</Window>
(3)后台代码:

/// <summary>
/// PictureBoxWindow.xaml 的交互逻辑
/// </summary>
public partial class PictureBoxWindow : Window
{
public PictureBoxWindow()
{
InitializeComponent();
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.pictureGifShow.Image = System.Drawing.Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + @"/Resource/loading.gif");
this.pictureGifShow.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
}
}
五、使用MediaElement

效果(采用MediaElement控件这种方式播放背景底色默认是黑色):

(1)页面xaml:

<Window x:Class="PlayGifDemo.MediaElementWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PlayGifDemo"
mc:Ignorable="d"
Loaded="Window_Loaded"
Title="MediaElementWindow" Height="400" Width="400" WindowStartupLocation="CenterScreen">
<Grid>
<MediaElement Name="mediaGifShow" MediaEnded="MediaElement_MediaEnded" Stretch="Fill"/>
</Grid>
</Window>
(2)后台代码:

/// <summary>
/// MediaElementWindow.xaml 的交互逻辑
/// </summary>
public partial class MediaElementWindow : Window
{
public MediaElementWindow()
{
InitializeComponent();
}

private void MediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
((MediaElement)sender).Position = ((MediaElement)sender).Position.Add(TimeSpan.FromMilliseconds(1));
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.mediaGifShow.Source = new Uri(AppDomain.CurrentDomain.BaseDirectory + @"/Resource/loading.gif");
}
}

————————————————
版权声明:本文为CSDN博主「RunnerDNA」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dnazhd/article/details/105736989

WPF加载GIF的五种方式(Storyboard / WpfAnimatedGif / ImageAnimator / PictureBox / MediaElement)的更多相关文章

  1. JavaScript判断图片是否加载完成的三种方式

    JavaScript判断图片是否加载完成的三种方式 有时需要获取图片的尺寸,这需要在图片加载完成以后才可以.有三种方式实现,下面一一介绍. 一.load事件 1 2 3 4 5 6 7 8 9 10 ...

  2. jsp页面加载readyState的五种状态根据我们状态添加进度条

    这段代码放在页面最下面 原文如下: document.onreadystatechange = subSomething;//当页面加载状态改变的时候执行这个方法. function subSomet ...

  3. WebView加载页面的两种方式——网络页面和本地页面

    WebView加载页面的两种方式 一.加载网络页面 加载网络页面,是最简单的一种方式,只需要传入http的URL就可以,实现WebView加载网络页面 代码如下图: 二.加载本地页面 1.加载asse ...

  4. [Android] Android ViewPager 中加载 Fragment的两种方式 方式(二)

    接上文: https://www.cnblogs.com/wukong1688/p/10693338.html Android ViewPager 中加载 Fragmenet的两种方式 方式(一) 二 ...

  5. [Android] Android ViewPager 中加载 Fragment的两种方式 方式(一)

    Android ViewPager 中加载 Fragmenet的两种方式 一.当fragment里面的内容较少时,直接 使用fragment xml布局文件填充 文件总数 布局文件:view_one. ...

  6. Vue加载组件、动态加载组件的几种方式

    https://cn.vuejs.org/v2/guide/components.html https://cn.vuejs.org/v2/guide/components-dynamic-async ...

  7. VUE 动态加载组件的四种方式

    动态加载组件的四种方式: 1.使用import导入组件,可以获取到组件 var name = 'system'; var myComponent =() => import('../compon ...

  8. 加载映射文件几种方式和mapper接口注解执行sql语句

    一.加载映射文件几种方式 二.mapper接口注解执行sql语句 就将xml中的sql语句放到注解的括号中就可以,一般只用于简单的sql语句合适:

  9. 让浏览器非阻塞加载javascript的几种方式

    通常大多数浏览器是并行下载资源的,但由于外部脚本的特殊性例如通过脚本改变文档的DOM结构.脚本之间的存在依赖关系.使用document.write 向页面输出HTML等.浏览器为了确保正确执行脚本和呈 ...

  10. 从Xib文件加载UIView的5种方式

    在不同的Xib文件中最容易维护的是定义的视图,因此对于从Xib文件中加载UIView来说一个方便的流程是非常重要. 在过去的几年里我发现唯一易于管理创建和维护视图(或者任何界面元素,通常会更多)方式就 ...

随机推荐

  1. ContOS7搭建RAID-5磁盘阵列

    RAID5:分布式奇偶校验的独立磁盘结构 RAID5就是raid0和RAID1的一种折中,既提升了磁盘读写能力,又有一定的容错能力,成本也低: 实验开始: 1.挂载四块5G硬盘 2.进行分区:fdis ...

  2. sql 语句系列(字符串之裂开)[八百章之第十三章]

    创建分割列表 一张表: 先查询出来的效果是这样的: mysql: select emp_copy.deptno,GROUP_CONCAT(emp_copy.emps SEPARATOR ',') fr ...

  3. python3中os.renames()和os.rename()区别

    renames源码:def renames(old, new): head, tail = path.split(new) # 作用是分割为两部分,head为路径,tail为文件名: if head ...

  4. 关于伺服刹车/急停/前后设备信号对接/PLC输入输出模块的公共端介绍

    一.伺服刹车 关键词:急停,急停中间继电器.刹车中间继电器,刹车使能 正文: 通常情况不用硬件为主导而用程序来主导控制,多场景应用方便修改且安全可靠. 伺服刹车硬件,一般是24v电源给进去,就会释放刹 ...

  5. 使用Quorum Journal Manager(QJM)的HDFS NameNode高可用配置

    前面的一篇文章写到了hadoop hdfs 3.2集群的部署,其中是部署的单个namenode的hdfs集群,一旦其中namenode出现故障会导致整个hdfs存储不可用,如果是要求比较高的集群,有必 ...

  6. 转载(localStorage设置过期时间)

    转载地址:https://blog.csdn.net/zhaoxiang66/article/details/86703438 class Storage{ constructor(name){ th ...

  7. 字节面试:如何解决MQ消息积压问题?

    MQ(Message Queue)消息积压问题指的是在消息队列中累积了大量未处理的消息,导致消息队列中的消息积压严重,超出系统处理能力,影响系统性能和稳定性的现象. 1.消息积压是哪个环节的问题? M ...

  8. 力扣594(java&python)-最长和谐子序列(简单)

    题目: 和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 . 现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度. 数组的子序列是一个由数组派生出来 ...

  9. 力扣479(java)-最大回文数乘积(困难)

    题目: 给定一个整数 n ,返回 可表示为两个 n 位整数乘积的 最大回文整数 .因为答案可能非常大,所以返回它对 1337 取余 . 示例 1: 输入:n = 2输出:987解释:99 x 91 = ...

  10. 千万商家的智能决策引擎--AnalyticDB如何助力生意参谋双十一

    作者:算法&健兮,阿里巴巴数据技术及产品部技术专家 生意参谋介绍 生意参谋是阿里官方打造的全渠道.全链路.一站式数据平台,致力于为用户提供经营分析.市场洞察.客群洞察等多样化数据服务,帮助用户 ...