WPF 循环切换图片达到动画效果

  最近刚接触WPF,  一边学着一边用着,知识点还没有系统化的进行学习整理.

  现在手上有一些美术做好的图片,需要连起来观看形成动画的效果,由于需求比较急,一时半会也静不下心来看WPF关于动画的知识.

  潜意识里一个Image控件,循环设定Source属性,一看效果总是显示集合的最后一项.难道是循环速度太快?基于此思路下折腾了好久也无结果。开始不得不借着可以找到的资源进行尝试。试想我们一张张的图片进行播放形成的动画,是不是类似帧的这种概念.顺这个便找到了CompositionTarget.Rendering事件创建基于帧的动画.

  第一种尝试:

namespace ImgAniDemo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ObservableCollection<BitmapImage> bmList;

        public MainWindow()
        {
            InitializeComponent();

            InitList();

            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }

        public void InitList()
        {
            bmList = new ObservableCollection<BitmapImage>();
            for (int i = 1; i < 4; i++)
            {
                BitmapImage bmImg = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\" + i.ToString() + ".jpg"));
                bmList.Add(bmImg);
            }
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            for (int i = 0; i < bmList.Count; i++)
            {
                this.imgViewer.Source = bmList[i];
                this.imgViewer.Width = this.imgViewer.Source.Width;
                this.imgViewer.Height = this.imgViewer.Source.Height;
            }
        }
    }
}

 运行程序ImgAniDemo.exe结果还是只显示了最后一幅图片.

  回头认真思考一下,可以做一个这样的猜测,WPF是不是做了优化,如果循环去设置Image的Source属性,用户看到的效果只会是最后一张图片呢?

  Render是什么意思?不错,Rendering事件被处理的时候,我们是用了一个循环,按着上面的猜测,只会显示最后一张图片便在情理之中了.

  聪明的你一定是想到了方法,我们在Rendering事件的时候不去循环了,只指定某一个图片给Source属性不就ok了吗?

  修改后的代码:

namespace ImgAniDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<BitmapImage> bmList;

int index = 0; //记录索引

public MainWindow()
{
InitializeComponent();

InitList();

CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
}

public void InitList()
{
bmList = new ObservableCollection<BitmapImage>();
for (int i = 1; i < 4; i++)
{
BitmapImage bmImg = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\" + i.ToString() + ".jpg"));
bmList.Add(bmImg);
}
}

void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (index < bmList.Count)
{
this.imgViewer.Source = bmList[index];
this.imgViewer.Width = this.imgViewer.Source.Width;
this.imgViewer.Height = this.imgViewer.Source.Height;

index++;
}
else
{
index = 0;
}
}
}
}

这时候我们已经可以看到图片在自动切换了.会不会感觉速度太快了,我想按着一定的速度来控件切换怎么办?

直接上代码了

namespace ImgAniDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<BitmapImage> bmList;

int index = 0; //记录索引
bool isRendering = false;

public MainWindow()
{
InitializeComponent();

InitList();

CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync();
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
isRendering = true;
System.Threading.Thread.Sleep(1000); //停1秒
}
}

public void InitList()
{
bmList = new ObservableCollection<BitmapImage>();
for (int i = 1; i < 4; i++)
{
BitmapImage bmImg = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\" + i.ToString() + ".jpg"));
bmList.Add(bmImg);
}
}

void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (isRendering)
{
if (index < bmList.Count)
{
this.imgViewer.Source = bmList[index];
this.imgViewer.Width = this.imgViewer.Source.Width;
this.imgViewer.Height = this.imgViewer.Source.Height;

index++;
}
else
{
index = 0;
}
isRendering = false;
}
}
}
}

在运行看下效果呢?

呵呵,图片是不是在自动播放呢?

注:以上代码中用到的图片名称分别为1.jpg,2.jpg,3.jpg,且图片放在exe程序一起即可

以上仅是个人想到的一种方法,若有不正确的地方,还请多多指点...

原文地址:https://www.cnblogs.com/dreamzgj/p/2373850.html