【MediaElement】WPF视频播放器【2】
2016-07-01 23:27
411 查看
一、前言
上回说到需要做放视频的使用向导,这两天公司里的老司机一直帮我答疑解惑,让这个任务变得挺顺的,真心感谢他们!
这次与【1】中的不同之处在于:
(1)播放和暂停按钮集成在<MediaElement>的点击事件之中,点一下是播放,再点一下是暂停
(2)加入了微软官方改写的粒子特效
(3)加上了自己琢磨的按钮旋转效果,以及按钮弹出popup效果
(4)进度条改善美观
二、代码
前台:
<Window 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:WPF_Nav" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" xmlns:dxwui="http://schemas.devexpress.com/winfx/2008/xaml/windowsui" x:Class="WPF_Nav.MainWindow" mc:Ignorable="d" Title="MainWindow" Height="600" Width="800" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation ="CenterScreen" Loaded="Window_Loaded"> <Window.Resources> <LinearGradientBrush x:Key="SliderBackground" StartPoint="0,0" EndPoint="0,1"> <GradientStop Offset="0.5" Color="#00b3fe"/> </LinearGradientBrush> <LinearGradientBrush x:Key="SliderThumb" StartPoint="0,0" EndPoint="0,1"> <GradientStop Offset="0" Color="#FFD9D3E8"/> </LinearGradientBrush> <Style x:Key="Slider_RepeatButton" TargetType="RepeatButton"> <Setter Property="Focusable" Value="false" /> <Setter Property="Height" Value="5"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="RepeatButton"> <Border Background="{StaticResource SliderBackground}" /> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="Slider_RepeatButton1" TargetType="RepeatButton"> <Setter Property="Focusable" Value="false" /> <Setter Property="Height" Value="5"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="RepeatButton"> <Border Background="Silver" /> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="Slider_Thumb" TargetType="Thumb"> <Setter Property="Focusable" Value="false" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Thumb"> <Ellipse Name="e" Width="15" Height="15" Fill="White" Stroke="Gray"/> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="Slider"> <Setter Property="Focusable" Value="false" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Slider"> <Grid> <Border BorderBrush="Red" BorderThickness="0" CornerRadius="0,0,0,0"> <Track Name="PART_Track"> <Track.DecreaseRepeatButton> <RepeatButton Style="{StaticResource Slider_RepeatButton}" Command="Slider.DecreaseLarge"/> </Track.DecreaseRepeatButton> <Track.IncreaseRepeatButton> <RepeatButton Style="{StaticResource Slider_RepeatButton1}" Command="Slider.IncreaseLarge"/> </Track.IncreaseRepeatButton> <Track.Thumb> <Thumb Style="{StaticResource Slider_Thumb}"/> </Track.Thumb> </Track> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="Button_Close" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Image x:Name="IMG" Source="E:\Test\WPFTest\Sources\Close.jpg"></Image> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="Button_Forbidden" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Image x:Name="IMG" Source="E:\Test\WPFTest\Sources\Forbidden.jpg"></Image> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="Button_Left" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Image x:Name="IMG" Source="E:\Test\WPFTest\Sources\Left.png" Stretch="Fill"></Image> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="Button_Right" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Image x:Name="IMG" Source="E:\Test\WPFTest\Sources\Right.png" Stretch="Fill"></Image> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> <Grid Name="Main_Grid"> <Grid.RowDefinitions> <RowDefinition Height="50"></RowDefinition> <RowDefinition Height="500"></RowDefinition> <RowDefinition Height="50"></RowDefinition> </Grid.RowDefinitions> <Border Name="title_Border" BorderBrush="#FBD3D0CD" BorderThickness="3" Grid.Row="0"> <Grid Name="Title"> <Grid.ColumnDefinitions> <ColumnDefinition Width="200"></ColumnDefinition> <ColumnDefinition Width="400"></ColumnDefinition> <ColumnDefinition Width="120"></ColumnDefinition> <ColumnDefinition Width="80"></ColumnDefinition> </Grid.ColumnDefinitions> <Grid Grid.Column="1"> <Canvas x:Name="ParticleHost" Width="400" > <TextBlock Name="txtB_Step" Grid.Column="1" Width="200" Height="30" TextAlignment="Center" FontSize="20" FontFamily="Microsoft YaHei" Text="asss" Margin="100,7,0,0"/> </Canvas> </Grid> <Grid Name="grid_Cofig" Grid.Column="3"> <Button Name="btn_Forbidden" Width="30" Click="Config_Click" Margin="2,10,48,12" HorizontalAlignment="Center" Focusable="False" Style="{StaticResource Button_Forbidden}" RenderTransformOrigin="0.5,0.5" ToolTipService.ToolTip="播放设置" ToolTipService.InitialShowDelay="1" ToolTipService.Placement="Bottom"> <Button.RenderTransform> <RotateTransform x:Name="trans_forbidden" Angle="0"/> </Button.RenderTransform> <Button.Triggers> <EventTrigger RoutedEvent="Button.MouseEnter"> <BeginStoryboard > <Storyboard> <DoubleAnimation From="0" To="90" Duration="0:0:0.4" Storyboard.TargetName="trans_forbidden" Storyboard.TargetProperty="Angle"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> </Grid> <Popup x:Name="Pop" PopupAnimation="Slide" Placement="Bottom" Width="93" Height="58" PlacementTarget="{Binding ElementName=grid_Cofig}" AllowsTransparency="True" StaysOpen="False" IsOpen="False" > <Border Background="White" BorderBrush="#FFC4C9CD" BorderThickness="2" Width="93"> <StackPanel Margin="1"> <StackPanel Name="sp_play" Orientation="Horizontal" Width="83" Height="22" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="2" MouseEnter="sp_play_enter" MouseLeave="sp_play_leave" > <CheckBox x:Name="ch_play" VerticalAlignment="Center" Margin="3,4" /> <TextBlock x:Name="txb_play" Text="不再播放" Margin="5,0" VerticalAlignment="Center"/> </StackPanel> <StackPanel Name="sp_doc" Width="83" Height="22" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="2" MouseEnter="sp_doc_enter" MouseLeave="sp_doc_leave"> <TextBlock Name="txb_Doc" Text="官方帮助文档" Margin="4,0,5,0" VerticalAlignment="Center"> </TextBlock> </StackPanel> </StackPanel> </Border> </Popup> <Button Name="btn_Close" Grid.Column="3" Width="30" Click="Close_Click" Margin="37,10,13,12" HorizontalAlignment="Center" Focusable="False" Style="{StaticResource Button_Close}" RenderTransformOrigin="0.5,0.5" ToolTipService.ToolTip="关闭视频" ToolTipService.InitialShowDelay="1" ToolTipService.Placement="Bottom"> <Button.RenderTransform> <RotateTransform x:Name="trans" Angle="0"/> </Button.RenderTransform> <Button.Triggers> <EventTrigger RoutedEvent="Button.MouseEnter"> <BeginStoryboard > <Storyboard> <DoubleAnimation From="0" To="90" Duration="0:0:0.4" Storyboard.TargetName="trans" Storyboard.TargetProperty="Angle"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> </Grid> </Border> <Grid Name="Movie" Grid.Row="1"> <MediaElement Stretch="Fill" LoadedBehavior="Manual" Name="QS_Movie" MediaOpened="Element_MediaOpened" Loaded="QS_Movie_Loaded" MouseLeftButtonDown="QS_Movie_MouseLeftButtonDown" /> <Button Name="btn_pre" Width="30" Height="40" HorizontalAlignment="Left" VerticalAlignment="Center" Click="Left_Click" Focusable="False" Style="{StaticResource Button_Left}"/> <Button Name="btn_next" Width="30" Height="40" HorizontalAlignment="Right" VerticalAlignment="Center" Click="Right_Click" Focusable="False" Style="{StaticResource Button_Right}"/> </Grid> <Border Name="Progress_Border" BorderBrush="#FBD3D0CD" BorderThickness="3" Grid.Row="2"> <Grid Name="Control_Progress" > <Slider Grid.Column="0" Width="700" Name="timelineSlider" VerticalAlignment="Center" PreviewMouseLeftButtonDown="timelineMDown" PreviewMouseLeftButtonUp="timelineMUp" BorderThickness="0,6,0,0" /> </Grid> </Border> </Grid> </Window>
后台:
using System.Windows.Media; using System.Windows.Media.Effects; using System.Windows.Shapes; namespace WPF_Nav { public class Particle { public Point3D Position { get; set; } public Point3D Velocity { get; set; } public double Size { get; set; } public Ellipse Ellipse { get; set; } public BlurEffect Blur { get; set; } public Brush Brush { get; set; } } }
namespace WPF_Nav { public class Point3D { public double X { get; set; } public double Y { get; set; } public double Z { get; set; } public Point3D(double X, double Y, double Z) { this.X = X; this.Y = Y; this.Z = Z; } } }
主体:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using System.Windows.Media.Effects; namespace WPF_Nav { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer(); // 定义一个DT bool play_flag = true; //判断播放状态 int play_now = 0; //判断当前视频索引 int play_target; List<string> Play_Video = new List<string>(); List<string> Title_Video = new List<string>(); public MainWindow() { InitializeComponent(); Play_Video = LoadMovies(); Title_Video = LoadTitles(); } private List<string> LoadTitles() { List<string> list_title = new List<string>(); list_title.Add("Step1"); list_title.Add("Step2"); list_title.Add("Step3"); return list_title; } private List<string> LoadMovies() { List<string> Movie_Uri = new List<string>(); Movie_Uri.Add(@"E:\Test\WPFTest\Sources\preview.mp4"); Movie_Uri.Add(@"E:\Test\WPFTest\Sources\preview1.mp4"); Movie_Uri.Add(@"E:\Test\WPFTest\Sources\preview2.mp4"); return Movie_Uri; } private void Play_Click(object sender, RoutedEventArgs e) { QS_Movie.Play(); } private void Pause_Click(object sender, RoutedEventArgs e) { QS_Movie.Pause(); } private void Element_MediaOpened(object sender, EventArgs e) { timelineSlider.Maximum = QS_Movie.NaturalDuration.TimeSpan.TotalMilliseconds; //设置slider最大值 dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); //超过计时间隔时发生 dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 200); //DT间隔 dispatcherTimer.Start(); //DT启动 } private void dispatcherTimer_Tick(object sender, EventArgs e) { int time = (int)QS_Movie.Position.TotalSeconds; timelineSlider.ToolTip = SecToTime(time); timelineSlider.Value = QS_Movie.Position.TotalMilliseconds; //slider滑动值随播放内容位置变化 } private string SecToTime(int sec) { int min = sec / 60; sec = sec - min * 60; int hour = min / 60; min = min - hour * 60; string h = hour.ToString(); string mm = ((min < 10) ? "0" : "") + min.ToString(); string ss = ((sec < 10) ? "0" : "") + sec.ToString(); string time = h + ":" + mm + ":" + ss; return time; } private void timelineMDown(object sender, EventArgs e) { dispatcherTimer.Stop(); } private void timelineMUp(object sender, EventArgs e) { QS_Movie.Position = new TimeSpan(0, 0, 0, 0, (int)timelineSlider.Value); dispatcherTimer.Start(); QS_Movie.Play(); } private void QS_Movie_Loaded(object sender, RoutedEventArgs e) { PreLoad(400,play_now); } private void Left_Click(object sender, RoutedEventArgs e) { play_target = (play_now + Play_Video.Count-1) % Play_Video.Count; PreLoad(200, play_target); play_now = play_target; } private void Right_Click(object sender, RoutedEventArgs e) { play_target = (play_now + 1) % Play_Video.Count; PreLoad(200, play_target); play_now = play_target; } private void PreLoad(int interval, int index) { QS_Movie.Source = new Uri(Play_Video[index]); QS_Movie.Play(); System.Threading.Thread.Sleep(interval); QS_Movie.Pause(); txtB_Step.Text = Title_Video[index]; } private void QS_Movie_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if(play_flag==true) { QS_Movie.Play(); btn_pre.Visibility = System.Windows.Visibility.Hidden; btn_next.Visibility = btn_pre.Visibility = System.Windows.Visibility.Hidden; } if(play_flag==false) { QS_Movie.Pause(); btn_pre.Visibility = System.Windows.Visibility.Visible; btn_next.Visibility = System.Windows.Visibility.Visible; } play_flag = !play_flag; } private void Close_Click(object sender, RoutedEventArgs e) { this.Close(); } private void Config_Click(object sender, RoutedEventArgs e) { this.Pop.IsOpen = true; } private void sp_play_enter(object sender, MouseEventArgs e) { Brush br_bg = new SolidColorBrush(Color.FromRgb(0, 162, 232)); Brush br_white = new SolidColorBrush(Color.FromRgb(255, 255, 255)); txb_play.Foreground = br_white; sp_play.Background = br_bg; } private void sp_play_leave(object sender, MouseEventArgs e) { Brush br_white = new SolidColorBrush(Color.FromRgb(255, 255, 255)); Brush br_black = new SolidColorBrush(Color.FromRgb(0, 0, 0)); txb_play.Foreground = br_black; sp_play.Background = br_white; } private void sp_doc_enter(object sender, MouseEventArgs e) { Brush br_bg = new SolidColorBrush(Color.FromRgb(0, 162, 232)); Brush br_white = new SolidColorBrush(Color.FromRgb(255, 255, 255)); txb_Doc.Foreground = br_white; sp_doc.Background = br_bg; } private void sp_doc_leave(object sender, MouseEventArgs e) { Brush br_white = new SolidColorBrush(Color.FromRgb(255, 255, 255)); Brush br_black = new SolidColorBrush(Color.FromRgb(0, 0, 0)); txb_Doc.Foreground = br_black; sp_doc.Background = br_white; } /// <summary> /// 特效部分 /// </summary> List<Particle> particles = new List<Particle>(); List<Particle> deadList = new List<Particle>(); Random random = new Random(); private void Window_Loaded(object sender, RoutedEventArgs e) { timer.Interval = TimeSpan.FromMilliseconds(10); timer.Tick += new EventHandler(timer_Tick); timer.Start(); } void timer_Tick(object sender, EventArgs e) { UpdateParticules(); } DispatcherTimer timer = new DispatcherTimer(); double elapsed = 0.1; private void UpdateParticules() { //更新粒子信息 deadList.Clear(); foreach (Particle p in this.particles) { if (p.Position.Y < -p.Size || p.Position.X < -p.Size || p.Position.X > Width + p.Size) { deadList.Add(p); } else { //更新位置 p.Position.X += p.Velocity.X * elapsed; p.Position.Y += p.Velocity.Y * elapsed; p.Position.Z += p.Velocity.Z * elapsed; TranslateTransform t = (p.Ellipse.RenderTransform as TranslateTransform); t.X = p.Position.X; t.Y = p.Position.Y; //更新颜色信息 p.Ellipse.Fill = p.Brush; p.Ellipse.Effect = p.Blur; } } //创建新的粒子 for (int i = 0; i < 10 && this.particles.Count < 40; i++) { //尝试循环使用已有例子 if (deadList.Count - 1 >= i) { SpawnParticle(deadList[i].Ellipse); deadList[i].Ellipse = null; } else { SpawnParticle(null); } } foreach (Particle p in deadList) { if (p.Ellipse != null) ParticleHost.Children.Remove(p.Ellipse); this.particles.Remove(p); } } private void SpawnParticle(Ellipse e) { double x = RandomWithVariance(Width / 2, Width / 2); double y = Height; double z = 10 * (random.NextDouble() * 100); double speed = RandomWithVariance(10, 10); double size = RandomWithVariance(10,10); Particle p = new Particle(); p.Position = new Point3D(x, y, z); p.Size = size; //模糊 var blur = new BlurEffect(); blur.RenderingBias = RenderingBias.Performance; blur.Radius = RandomWithVariance(5, 5); p.Blur = blur; //颜色 var brush = (Brush)Brushes.Lime.Clone(); brush.Opacity = RandomWithVariance(0.6, 0.5); p.Brush = brush; TranslateTransform t; if (e != null) { e.Fill = null; e.Width = e.Height = size; p.Ellipse = e; t = e.RenderTransform as TranslateTransform; } else { p.Ellipse = new Ellipse(); p.Ellipse.Width = p.Ellipse.Height = size; this.ParticleHost.Children.Add(p.Ellipse); t = new TranslateTransform(); p.Ellipse.RenderTransform = t; p.Ellipse.RenderTransformOrigin = new Point(0.5, 0.5); } t.X = p.Position.X; t.Y = p.Position.Y; double velocityMultiplier = (random.NextDouble() + 0.25) * speed; double vX = (1.0 - (random.NextDouble() * 2.0)) * velocityMultiplier; double vY = -Math.Abs((1.0 - (random.NextDouble() * 2.0)) * velocityMultiplier); p.Velocity = new Point3D(vX, vY, 0); this.particles.Add(p); } private double RandomWithVariance(double midvalue, double variance) { double min = Math.Max(midvalue - (variance / 2), 0); double max = midvalue + (variance / 2); double value = min + ((max - min) * random.NextDouble()); return value; } } }
三、效果
四、小结
WPF挺好玩的!前台就能解决一些基本的动画效果,加上后台简直爽。最后,感谢单位的老司机们!
相关文章推荐
- Unity3d界面优化方法
- Activiti Designer申请请假流程
- 迁移到MSYS2 与 Qt 工具链注意的几个事情(注意链接顺序,并且人造mingw工具链所没有的局部midl.exe命令)
- 李洪强iOS开发之OC[006] - 类和对象
- 2016传智WEB前端开发01期系列视频教程
- Import DS JOB issue
- 2016传智WEB前端开发01期系列视频教程
- flume入门
- .NET Core & ASP.NET Core 1.0
- 总结Ant
- Android ENV Setup Errors
- 给定一个任意长度的java数组,求数组内的数能组合出来的最大整数
- http://www.tuicool.com/articles/EjMJNz
- 文章标题android之listview异步加载图片时显示加载进度ProgressBar
- 关于在页面输入特殊符号保存到数据库后,页面查询,特殊字符可以展示到页面的问题
- http://jingyan.baidu.com/article/7f41ecec1b7a2e593d095ce6.html
- 做个自己用的英语词典
- maven nexus私服搭建
- Codeforces Gym 100340A Cookies
- 短信提醒 BroadcastReceiver