部分内容参考博文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. 可视化学习:使用WebGL绘制圆形,实现色盘

    前言 在Canvas2D中实现圆形的绘制比较简单,只要调用arc指令就能在Canvas画布上绘制出一个圆形,类似的,在SVG中我们也只需要一个<circle>标签就能在页面上绘制一个圆形. ...

  2. go语言结构体使用小结

    转载请注明出处: 在Go语言中,结构体(struct)是一种复合数据类型,它允许你将多个不同类型的字段组合成一个单一的类型.结构体为数据的封装和抽象提供了便利,使得数据组织更加清晰和易于管理. 结构体 ...

  3. mysql 必知必会整理—事务[十六]

    前言 简单整理一下事务. 正文 并非所有引擎都支持事务处理 正如第21章所述,MySQL支持几种基本的数据库引擎. 正如本章所述,并非所有引擎都支持明确的事务处理管理. MyISAM和InnoDB是两 ...

  4. 力扣202(java&python)-快乐数(简单)

    题目: 编写一个算法来判断一个数 n 是不是快乐数. 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和.然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终 ...

  5. CF1913C Game with Multiset 题解

    [题目描述] 你有一个空的多重集,你需要处理若干下列询问: ADD $ x $:加入一个数值为 $ 2^x $ 的元素到该多重集. GET $ w $:判断是否存在一个该多重集的子集,使得这个子集的所 ...

  6. 浅谈DDD中的聚合

    简介: 在我看来并不是MVC的基础上增加领域层,使用充血模型,解耦基础服务,我的代码就符合DDD了. 作者 | 李宇飞(菜尊)来源 | 阿里开发者公众号 在我看来并不是MVC的基础上增加领域层,使用充 ...

  7. 【Serverless实战】B站每日自动签到&&传统单节点网站的Serverless上云

    简介: Serverless好哇!这里将针对个人与生产两个应用方向的测评 使用Serverless实现自动获取每日B站的经验值,让你更快冲到LV6! 你的业务站点还是一台服务器All in One吗? ...

  8. Apache Flink 在汽车之家的应用与实践

    ​简介: 汽车之家如何基于 Flink 上线了 AutoStream 平台并持续打磨. 本文整理自汽车之家实时计算平台负责人邸星星在 Flink Forward Asia 2020 分享的议题< ...

  9. [FAQ] VsCode 同时多行编辑

      [多光标自定义编辑] 按住 alt 键,鼠标左键点击,出现多个光标. [批量选中匹配编辑] 鼠标选中字符,按快捷键 ctrl + shift + L,字符的右侧都出现光标,可同时编辑. Tool: ...

  10. [FAQ] web3js, Error: Please pass numbers as strings or BN objects to avoid precision errors.

    我们在调用合约方法时,都可以传一些参数的,比如转账金额 value. value 的单位是 wei,这是一个很小的单位,所以一般数值很大. 注意,把 ether 转 wei 需要先把 ether 的值 ...