您的位置:首页 > 其它

【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挺好玩的!前台就能解决一些基本的动画效果,加上后台简直爽。最后,感谢单位的老司机们!

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: