部分内容参考博文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. HarmonyOS振动效果开发指导

      Vibrator开发概述 振动器模块服务最大化开放硬工最新马达器件能力,通过拓展原生马达服务实现振动与交互融合设计,打造细腻精致的一体化振动体验和差异化体验,提升用户交互效率和易用性.提升用户体验 ...

  2. 【直播回顾】Hello HarmonyOS进阶课程第四课——ArkUI动画开发

    5 月 25 日晚上 19 点,由知名HarmonyOS开发领域的up主九弓子主讲的Hello HarmonyOS进阶系列应用篇第四课<ArkUI动画开发>,在众多HarmonyOS社群内 ...

  3. 动态规划(六)——树形dp

    树形dp,又称树状dp,即在树上进行的dp,在设计动态规划算法时,一般就以节点从深到浅(子树从小到大)的顺序作为dp的"阶段",dp的状态表示中,第一维通常是节点编号(代表以该节点 ...

  4. spark dstaframe 多字段统计

    val aggCols = List("Pclass","Age","Fare") .map(colName=>functions.a ...

  5. Next.js 实战

    0x1 CSR,SSR,SSG CSR 客户端渲染(Client-Side Rendering).常见 B 端 Web 应用开发模式,前后端分离,服务器压力相对更轻,渲染工作在客户端进行,服务器直接返 ...

  6. 高并发场景QPS等专业指标揭秘大全与调优实战

    高并发场景QPS等专业指标揭秘大全与调优实战 最近经常有小伙伴问及高并发场景下QPS的一些问题,特意结合项目经验和网上技术贴做了一些整理和归纳,供大家参考交流. 一.一直再说高并发,多少QPS才算高并 ...

  7. CentOS 7.9编译安装Python-3.10.13

    目录 查看CentOS版本.系统默认gcc版本.Python版本和pip版本 部署Python-3.10.13 测试 将yum中的Python版本修改为系统原来的2.7.5版本 查看CentOS版本. ...

  8. ClkLog自定义事件分析登场

     ClkLog的自定义事件分析功能在大家满满的期待下终于发布了. 这次更新我们添加了[用户关联].[事件采集].[事件分析]三大块功能点. 本次上线的自定义事件分析可以让用户根据自身业务场景创建不同维 ...

  9. 链栈的实现 C语言/C++

    堆栈的链式存储C/C++实现--链栈 与顺序栈相比,链栈的优点在于不存在栈满上溢的问题.链栈通常使用单链表实现,进栈.出栈操作就是在单链表表头的 插入.删除操作.用单链表实现链栈时,使用不带头结点的单 ...

  10. 一位 sealer maintainer 的心路历程

    简介: 本文作者将回顾个人参与 sealer 开源项目的机缘巧合,参与过程中的挑战,以及从中获取的所悟所感,写下一段文字进行分享,希望对开源新人有所帮助,能够激励想参与开源工作但还未踏出第一步的同学. ...