水平一般,采用很简单(菜)的方式实现了图片与视频混合轮播的效果
主要通过3个 Storyboard动画 和一个Timer来控制图片和视频控件左右轮播
已满足一下情况:
1、只有一张图片
这种情况最简单 直接显示,啥也不做
2、只有一个视频
这个的话也是直接播放,在播放结束时接着播放
3、N张图片+M个视频
这种情况就用到三个Storyboard,一个是图片和图片轮播,一个是图片轮播到视频,一个是视频轮播到图片,在合适的时候启动Storyboard就可以了
原理图
控制Banner控件父布局中的大小
效果图:
代码:
BBanner.cs实体类
/// <summary>
/// banner类 视频、图片
/// </summary>
public class BBanner
{
/// <summary>
/// 类型 1 视频 ,0 图片
/// </summary>
public int Type { get; set; }
/// <summary>
/// 链接 本地链接
/// </summary>
public string Url { get; set; }
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; }
}
Banner.xmal 布局文件
<Grid x:Name="gRoot" >
<Image x:Name="image1" Stretch="Fill" />
<Image x:Name="image2" Stretch="Fill" />
<MediaElement x:Name="meVideo" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" LoadedBehavior="Manual" Visibility="Collapsed" />
<Label x:Name="cover" Background="Transparent" MouseDown="cover_MouseDown" />
</Grid>
Banner.xmal.cs
/// <summary>
/// Banner.xaml 的交互逻辑
/// </summary>
public partial class Banner : UserControl
{
/// <summary>
/// 滚动时间
/// </summary>
public int ScrollTime = INIUtilBase.Instance.MediaScrollTime;
/// <summary>
/// 轮播间隔
/// </summary>
public int IntervalTime = INIUtilBase.Instance.MediaIntervalTime;
/// <summary>
/// 轮播timer
/// </summary>
DispatcherTimer mScrollTimer; //
/// <summary>
/// 0 n>1图片+m个视频; 1 一张图片+1个视频; 2 一张图片或一个视频
/// </summary>
int Type = 0;
/// <summary>
/// 下一个媒体是否是视频
/// </summary>
bool nextVideo = false;
/// <summary>
/// 是否开始滚动
/// </summary>
public bool isBegin = false;
/// <summary>
/// 集合图片数量
/// </summary>
public int ImageCount { get; set; }
/// <summary>
/// 集合视频数量
/// </summary>
public int VideoCount { get; set; }
/// <summary>
/// 滚动图片组
/// </summary>
public List<BBanner> Banners { get; set; }
/// <summary>
/// 滚动宽度
/// </summary>
public double width
{
get { return this.Width; }
}
/// <summary>
/// 滚动高度
/// </summary>
public double height
{
get { return this.Height; }
}
/// <summary>
/// 滚动索引
/// </summary>
private int Index = 0;
/// <summary>
/// 媒体目录
/// </summary>
public string PathMedia { get; set; }
public Banner()
{
InitializeComponent();
gRoot.Width = this.Width;
gRoot.Height = this.Height;
image1.Width = this.Width;
image1.Height = this.Height;
image2.Width = this.Width;
image2.Height = this.Height;
meVideo.Width = this.Width;
meVideo.Height = this.Height;
cover.Width = this.Width;
cover.Height = this.Height;
if (ScrollTime >= IntervalTime)
{
IntervalTime = ScrollTime + 2;
}
mScrollTimer = new DispatcherTimer();
mScrollTimer.Tick += MScrollTimer_Tick;
mScrollTimer.Interval = new TimeSpan(0, 0, (IntervalTime + ScrollTime));
meVideo.MediaEnded += MeVideo_MediaEnded;
}
private void MScrollTimer_Tick(object sender, EventArgs e)
{
// 继续下轮动画
if (Type == 1)
{
ImageVideoAnim.Begin();
}
else
{
ImageAnim.Begin();
if (nextVideo)
{
//下一个是视频,开始 图片到视频 的滚动
meVideo.Margin = new Thickness(width, 0, -(width), 0);
meVideo.Visibility = Visibility.Visible;
ImageVideoAnim.Begin();
}
}
}
/// <summary>
/// 开始播放视频
/// </summary>
/// <param name="url"></param>
void StartVideo(string url)
{
try
{
StopTimer();
meVideo.Margin = new Thickness(0, 0, 0, 0);
meVideo.Visibility = Visibility.Visible;
meVideo.Source = new Uri(url);
meVideo.Play();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private void MeVideo_MediaEnded(object sender, RoutedEventArgs e)
{
//播放结束 判断下一个banner
BBanner banner = Banners[this.Index % this.Banners.Count];
if (banner.Type == 1)
{
//如果是视频 继续播放
StartVideo(banner.Url);
Index++;
}
else
{
//展示图片
image1.Visibility = Visibility.Visible;
image1.Margin = new Thickness(width, 0, -(width), 0);
image1.Source = LoadImageFreeze(banner.Url);
VideoImageAnim.Begin();
}
}
/// <summary>
/// 开始滚动
/// </summary>
private void StartTimer()
{
image1.Visibility = Visibility.Visible;
image2.Visibility = Visibility.Visible;
mScrollTimer.Start();
}
private void StopTimer()
{
image1.Visibility = Visibility.Hidden;
image2.Visibility = Visibility.Hidden;
if (mScrollTimer != null && mScrollTimer.IsEnabled)
{
mScrollTimer.Stop();
}
}
private Storyboard _imgAnim;
/// <summary>
/// 图片-->图片 滚动
/// </summary>
public Storyboard ImageAnim
{
get
{
if (_imgAnim == null)
{
_imgAnim = new Storyboard();
ThicknessAnimation marginAnimation1 = new ThicknessAnimation();
marginAnimation1.From = new Thickness(0, 0, 0, 0);
marginAnimation1.To = new Thickness(-(width), 0, (width), 0);
marginAnimation1.Duration = TimeSpan.FromSeconds(ScrollTime);
_imgAnim.Children.Add(marginAnimation1);
Storyboard.SetTarget(marginAnimation1, image1);
Storyboard.SetTargetProperty(marginAnimation1, new PropertyPath(Grid.MarginProperty));
ThicknessAnimation marginAnimation2 = new ThicknessAnimation();
marginAnimation2.From = new Thickness(width, 0, -(width), 0);
marginAnimation2.To = new Thickness(0, 0, -(0), 0);
marginAnimation2.Duration = TimeSpan.FromSeconds(ScrollTime);
_imgAnim.Children.Add(marginAnimation2);
Storyboard.SetTarget(marginAnimation2, image2);
Storyboard.SetTargetProperty(marginAnimation2, new PropertyPath(Grid.MarginProperty));
_imgAnim.FillBehavior = FillBehavior.Stop;
_imgAnim.Completed += _imgAnim_Completed;
}
return _imgAnim;
}
}
private Storyboard _imgVideoAnim;
/// <summary>
/// 图片 --> 视频 滚动
/// </summary>
public Storyboard ImageVideoAnim
{
get
{
if (_imgVideoAnim == null)
{
_imgVideoAnim = new Storyboard();
ThicknessAnimation marginAnimation1 = new ThicknessAnimation();
marginAnimation1.From = new Thickness(0, 0, 0, 0);
marginAnimation1.To = new Thickness(-(width), 0, (width), 0);
marginAnimation1.Duration = TimeSpan.FromSeconds(ScrollTime);
_imgVideoAnim.Children.Add(marginAnimation1);
Storyboard.SetTarget(marginAnimation1, image1);
Storyboard.SetTargetProperty(marginAnimation1, new PropertyPath(Grid.MarginProperty));
ThicknessAnimation marginAnimation2 = new ThicknessAnimation();
marginAnimation2.From = new Thickness(width, 0, -(width), 0);
marginAnimation2.To = new Thickness(0, 0, -(0), 0);
marginAnimation2.Duration = TimeSpan.FromSeconds(ScrollTime);
_imgVideoAnim.Children.Add(marginAnimation2);
Storyboard.SetTarget(marginAnimation2, meVideo);
Storyboard.SetTargetProperty(marginAnimation2, new PropertyPath(Grid.MarginProperty));
_imgVideoAnim.FillBehavior = FillBehavior.HoldEnd;
_imgVideoAnim.Completed += _imgVideoAnim_Completed;
}
return _imgVideoAnim;
}
}
private void _imgVideoAnim_Completed(object sender, EventArgs e)
{
BBanner banner = Banners[this.Index % this.Banners.Count];
if (banner.Type == 1)
{
//如果是视频 继续播放
StartVideo(banner.Url);
Index++;
}
}
void OneImageVideo()
{
this.image1.Margin = new Thickness(0, 0, 0, 0);
this.meVideo.Margin = new Thickness(this.width, 0, -(this.width), 0);
try
{
//接下来第一个为图片 还是视频
BBanner banner = Banners[Index % Banners.Count];
if (banner.Type == 0)
{
//展示图片
image1.Margin = new Thickness(0, 0, 0, 0);
image1.Source = LoadImageFreeze(Banners[Index % Banners.Count].Url);
Index += 1;
}
else
{
meVideo.Source = new Uri(Banners[Index % Banners.Count].Url);
}
}
catch (Exception ex)
{
Console.WriteLine("OneImageVideo " + ex.ToString());
}
}
private Storyboard _videoImgAnim;
/// <summary>
/// 视频 -->图片 滚动
/// </summary>
public Storyboard VideoImageAnim
{
get
{
if (_videoImgAnim == null)
{
_videoImgAnim = new Storyboard();
ThicknessAnimation marginAnimation1 = new ThicknessAnimation();
marginAnimation1.From = new Thickness(0, 0, 0, 0);
marginAnimation1.To = new Thickness(-(width), 0, (width), 0);
marginAnimation1.Duration = TimeSpan.FromSeconds(ScrollTime);
_videoImgAnim.Children.Add(marginAnimation1);
Storyboard.SetTarget(marginAnimation1, meVideo);
Storyboard.SetTargetProperty(marginAnimation1, new PropertyPath(Grid.MarginProperty));
ThicknessAnimation marginAnimation2 = new ThicknessAnimation();
marginAnimation2.From = new Thickness(width, 0, -(width), 0);
marginAnimation2.To = new Thickness(0, 0, -(0), 0);
marginAnimation2.Duration = TimeSpan.FromSeconds(ScrollTime);
_videoImgAnim.Children.Add(marginAnimation2);
Storyboard.SetTarget(marginAnimation2, image1);
Storyboard.SetTargetProperty(marginAnimation2, new PropertyPath(Grid.MarginProperty));
_videoImgAnim.FillBehavior = FillBehavior.Stop;
_videoImgAnim.Completed += _videoAnim_Completed;
}
return _videoImgAnim;
}
}
private void _videoAnim_Completed(object sender, EventArgs e)
{
meVideo.Margin = new Thickness(width, 0, -(width), 0);
ResetControl();
StartTimer();
}
private void _imgAnim_Completed(object sender, EventArgs e)
{
//动画结束后 判断当前显示的是图片还是视频
// 显示图片
ResetControl();
}
/// <summary>
/// 加载数据
/// </summary>
/// <param name="path"></param>
public void LoadResources(string path)
{
if (!Directory.Exists(path))
return;
string[] fileNames = Directory.GetFiles(path);
List<BBanner> medias = new List<BBanner>();
int imgCount = 0;
int videoCount = 0;
foreach (string file in fileNames)
{
FileInfo fi = new FileInfo(file);
BBanner banner = null;
Console.WriteLine(fi.Extension.ToLower());
if (fi.Extension.ToLower() == ".jpg" || fi.Extension.ToLower() == ".png")
{
banner = new BBanner { Url = file, Type = 0, Title = fi.Name };
imgCount++;
}
if (fi.Extension.ToLower().Equals(".mp4") || fi.Extension.ToLower().Equals(".avi"))
{
banner = new BBanner { Url = file, Type = 1, Title = fi.Name };
videoCount++;
}
if (banner != null)
medias.Add(banner);
}
ImageCount = imgCount;
VideoCount = videoCount;
Banners = medias;
}
/// <summary>
/// 开始滚动动画
/// </summary>
public void Begin()
{
if (!isBegin)
{
LoadResources(PathMedia);
if (Banners == null || Banners.Count == 0)
return;
isBegin = true;
//只有一个媒体数据 判断是图片还是视频
if (Banners.Count == 1)
{
if (Banners[0].Type == 0)
{
//只有一张图片
image1.Margin = new Thickness(0, 0, 0, 0);
image1.Source = LoadImageFreeze(Banners[0].Url);
Type = 2;
}
else
{
Type = 2;
//只有一个视频
StartVideo(Banners[0].Url);
}
}
else if (ImageCount == 1)//一个图片一个视频
{
Type = 1;
// 显示图片
OneImageVideo();
// 开始动画
StartTimer();
}
else
{
Type = 0;
// 重置界面
ResetControl();
// 开始动画
StartTimer();
}
}
}
/// <summary>
/// 初始化动画版,显示动画中的图片 重置控件界面
/// </summary>
void ResetControl()
{
nextVideo = false;
// 复位
// 显示图片
try
{
//接下来第一个为图片 还是视频
BBanner banner = Banners[Index % Banners.Count];
if (banner.Type == 0)
{
//展示图片
image1.Margin = new Thickness(0, 0, 0, 0);
image1.Source = LoadImageFreeze(Banners[Index % Banners.Count].Url);
}
else
{
meVideo.Margin = new Thickness(0, 0, 0, 0);
image1.Visibility = Visibility.Collapsed;
StartVideo(banner.Url);
}
Index += 1;
//判断第二个
banner = Banners[Index % Banners.Count];
if (banner.Type == 0)
{
image2.Margin = new Thickness(width, 0, -(width), 0);
image2.Source = LoadImageFreeze(Banners[Index % Banners.Count].Url);
}
else
{
nextVideo = true;
image2.Visibility = Visibility.Collapsed;
}
}
catch (Exception ex)
{
Console.WriteLine("ResetControl " + ex.ToString());
}
}
public static BitmapImage LoadImageFreeze(string imagePath)
{
try
{
BitmapImage bitmap = new BitmapImage();
if (File.Exists(imagePath))
{
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
using (Stream ms = new MemoryStream(File.ReadAllBytes(imagePath)))
{
bitmap.StreamSource = ms;
bitmap.EndInit();
bitmap.Freeze();
}
}
return bitmap;
}
catch (Exception ex)
{
Console.WriteLine("LoadImageFreeze " + ex.ToString());
return null;
}
}
private void cover_MouseDown(object sender, MouseButtonEventArgs e)
{
}
}
简单使用 Window
<Window x:Class="信息展示.MainWindow"
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" Loaded="Window_Loaded"
xmlns:local="clr-namespace:信息展示" WindowState="Maximized" WindowStyle="None" AllowsTransparency="True"
Title="信息展示" >
<Grid>
<local:Banner x:Name="banner" />
<TextBlock Width="100" HorizontalAlignment="Left" VerticalAlignment="Top" MouseDown="TextBlock_MouseDown" Height="100"/>
</Grid>
</Window>
Window.cs
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Width = SystemParameters.PrimaryScreenWidth;
this.Height = SystemParameters.PrimaryScreenHeight;
banner.Width = SystemParameters.PrimaryScreenWidth;
banner.Height = SystemParameters.PrimaryScreenHeight;
//ShowUtil.init(this, SynchronizationContext.Current);
// SettingModel s = INIUtil.Instance;
}
string path = AppDomain.CurrentDomain.BaseDirectory + "/media";
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string[] files = Directory.GetFiles(path);
if (files != null && files.Length > 0)
{
banner.PathMedia = path;
banner.Begin();
}
else
{
// ShowUtil.showTips(false, "请将图片资源拷贝到目录:" + path);
}
}
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
App.Current.Shutdown(0);
}
}
}
目前来说只是实现了功能,对于性能这块没做什么优化,相信还有更优雅的实现方式。