WPF 自定义图片视频混播控件

水平一般,采用很简单(菜)的方式实现了图片与视频混合轮播的效果

主要通过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);
            }
        }
    }

目前来说只是实现了功能,对于性能这块没做什么优化,相信还有更优雅的实现方式。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值