一个silverlight播放器的DEMO(Expression Encoder 2)
在写完"Silverlight中鼠标事件的js开发"一文之后,我就想写一篇真正应用这种事件处理方式的进行实际开发的例子。
后来在网上看到了这篇文章(实际应用链接:http://www.thejamesbondmovies.com/),发现里面的DEMO正好是
我想演示的。如下:
因为这个DEMO的演示用到了Expression Encoder, 而相关下载链接, 请点击这里。
原文中的老外因为不满足于Expression Encoder所提供的模板代码,他认为在媒体列表中应该实现点播的效果。而
不仅仅是“一味”的顺序播放。因此他在Expression Encoder代码生成的基础上,对Xaml和js文件都做了相应改动。下面
我们来看一下他所开发的主要流程。
首先使用Expression Encoder来创建一个项目,并将其模板设置为"Expression" (因为本人不喜欢这个模板,所以
在DEMO中使用了"Executive"模板),然后单击Import按钮来选择要播放的视频文件。如下图所示。最后单击“Encode”
进行编码转换(当转换成功后会启动一个测试页面进行演示,“Preview In Brower”需勾选)。
这样我们就可以在“Directory”设置项中下找到我们所生成的所有项目文件了。
因为模板文件生成的XAML中不带播放列表,所以要修改XAML文件中 Canvas的高度,并将下面的XAML代码(播入列表代码)
放在该文件的结尾处:
下面就要改一下相应的js文件了,找到StartPlayer.js文件,新的播入列表方法放在页面的最上面:
将原码中的原有播放文件列表变量和相关内容注释:
将下列代码放在该注释下方来解决对相应媒体播放按钮进行事件绑定:
而下面就是其相应的事件处理代码了:
因为使用了新的播放列表变量,所以原来生成的如下方法内容会被改写如下:
到这里我们可以在本地运行一下default.htm来看一下效果。
然后为了演示方便,我将这个Application上传到了Silverlight Streaming上,经常了n遍的上传之后,终于测试
成功,所以才在本文开头做了相应的演示。
好了,今天的内容就先到这里了.
源码下载,请点击这里:)
注:因为老外所写的文章是在silverlight 1.0下运行的,所以本文的JS与原文中有所变动,但不会影响对代码的理解。
后来在网上看到了这篇文章(实际应用链接:http://www.thejamesbondmovies.com/),发现里面的DEMO正好是
我想演示的。如下:
因为这个DEMO的演示用到了Expression Encoder, 而相关下载链接, 请点击这里。
原文中的老外因为不满足于Expression Encoder所提供的模板代码,他认为在媒体列表中应该实现点播的效果。而
不仅仅是“一味”的顺序播放。因此他在Expression Encoder代码生成的基础上,对Xaml和js文件都做了相应改动。下面
我们来看一下他所开发的主要流程。
首先使用Expression Encoder来创建一个项目,并将其模板设置为"Expression" (因为本人不喜欢这个模板,所以
在DEMO中使用了"Executive"模板),然后单击Import按钮来选择要播放的视频文件。如下图所示。最后单击“Encode”
进行编码转换(当转换成功后会启动一个测试页面进行演示,“Preview In Brower”需勾选)。
这样我们就可以在“Directory”设置项中下找到我们所生成的所有项目文件了。
因为模板文件生成的XAML中不带播放列表,所以要修改XAML文件中 Canvas的高度,并将下面的XAML代码(播入列表代码)
放在该文件的结尾处:
<!-- Playlist region starts here -->
<!-- Navigation Arrows -->
<Path x:Name="LeftArrow" Opacity="0.74" Width="38" Height="38" Stretch="Fill" Stroke="#FF000000"
Canvas.Left="11" Canvas.Top="514" Data="M37.5,0.5 L37.5,37.5 0.5,37.5 z" Fill="#FFFFFFFF"
RenderTransformOrigin="0.5,0.5" Cursor="Hand">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="134.119"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<Path x:Name="RightArrow" Opacity="0.74" Width="38" Height="38" Stretch="Fill" Stroke="#FF000000"
Canvas.Left="588" Canvas.Top="514" Data="M37.5,0.5 L37.5,37.5 0.5,37.5 z" Fill="#FFFFFFFF"
RenderTransformOrigin="0.5,0.5" Cursor="Hand">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="314.365"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<!-- The outer canvas here is clipped: only the area defined by the rectangle geometry is visible -->
<!-- This is necessary as when we animate the 'Library' canvas inside it we do not want to see the
thumbnails slide under the navigation arrows and off the screen-->
<Canvas x:Name="ClippedCanvas" Canvas.Top="491" Canvas.Left="43" Width="550" Height="90"
Background="Silver">
<Canvas.Clip>
<RectangleGeometry Rect="0, 0, 550, 114"/>
</Canvas.Clip>
<!-- Animations to move the playlist left and right. They are numbered so that we can call them
logically from code -->
<Canvas.Resources>
<Storyboard x:Name="MoveLeft01">
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="Library"
From="13" To="-613" Duration="0:0:2" />
</Storyboard>
<Storyboard x:Name="MoveRight02">
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="Library"
From="-613" To="13" Duration="0:0:2" />
</Storyboard>
</Canvas.Resources>
<!-- The Library Canvas groups the playlist buttons into a single element that can be easily animated
left - right. -->
<Canvas Width="1157.275" Height="82.96" Canvas.Left="0" Canvas.Top="0" x:Name="Library">
<Canvas Width="550.275" Height="82.96" x:Name="playlist1">
<Image x:Name="play0" Opacity="0.74" Width="133.275" Height="82.96" Source="1.png"
Stretch="Fill" Cursor="Hand" />
<Image x:Name="play1" Opacity="0.74" Width="133.275" Height="82.96" Source="2.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="139"/>
<Image x:Name="play2" Opacity="0.74" Width="133.275" Height="82.96" Source="3.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="278"/>
<Image x:Name="play3" Opacity="0.74" Width="133.275" Height="82.96" Source="4.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="417"/>
</Canvas>
<Canvas Width="550.275" Height="82.96" x:Name="playlist2" Canvas.Left="607">
<Image x:Name="play4" Opacity="0.74" Width="133.275" Height="82.96" Source="5.png"
Stretch="Fill" Cursor="Hand" />
<Image x:Name="play5" Opacity="0.74" Width="133.275" Height="82.96" Source="6.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="139"/>
<Image x:Name="play6" Opacity="0.74" Width="133.275" Height="82.96" Source="7.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="278"/>
<Image x:Name="play7" Opacity="0.74" Width="133.275" Height="82.96" Source="8.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="417"/>
</Canvas>
</Canvas>
</Canvas>
<!-- Navigation Arrows -->
<Path x:Name="LeftArrow" Opacity="0.74" Width="38" Height="38" Stretch="Fill" Stroke="#FF000000"
Canvas.Left="11" Canvas.Top="514" Data="M37.5,0.5 L37.5,37.5 0.5,37.5 z" Fill="#FFFFFFFF"
RenderTransformOrigin="0.5,0.5" Cursor="Hand">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="134.119"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<Path x:Name="RightArrow" Opacity="0.74" Width="38" Height="38" Stretch="Fill" Stroke="#FF000000"
Canvas.Left="588" Canvas.Top="514" Data="M37.5,0.5 L37.5,37.5 0.5,37.5 z" Fill="#FFFFFFFF"
RenderTransformOrigin="0.5,0.5" Cursor="Hand">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="314.365"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<!-- The outer canvas here is clipped: only the area defined by the rectangle geometry is visible -->
<!-- This is necessary as when we animate the 'Library' canvas inside it we do not want to see the
thumbnails slide under the navigation arrows and off the screen-->
<Canvas x:Name="ClippedCanvas" Canvas.Top="491" Canvas.Left="43" Width="550" Height="90"
Background="Silver">
<Canvas.Clip>
<RectangleGeometry Rect="0, 0, 550, 114"/>
</Canvas.Clip>
<!-- Animations to move the playlist left and right. They are numbered so that we can call them
logically from code -->
<Canvas.Resources>
<Storyboard x:Name="MoveLeft01">
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="Library"
From="13" To="-613" Duration="0:0:2" />
</Storyboard>
<Storyboard x:Name="MoveRight02">
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="Library"
From="-613" To="13" Duration="0:0:2" />
</Storyboard>
</Canvas.Resources>
<!-- The Library Canvas groups the playlist buttons into a single element that can be easily animated
left - right. -->
<Canvas Width="1157.275" Height="82.96" Canvas.Left="0" Canvas.Top="0" x:Name="Library">
<Canvas Width="550.275" Height="82.96" x:Name="playlist1">
<Image x:Name="play0" Opacity="0.74" Width="133.275" Height="82.96" Source="1.png"
Stretch="Fill" Cursor="Hand" />
<Image x:Name="play1" Opacity="0.74" Width="133.275" Height="82.96" Source="2.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="139"/>
<Image x:Name="play2" Opacity="0.74" Width="133.275" Height="82.96" Source="3.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="278"/>
<Image x:Name="play3" Opacity="0.74" Width="133.275" Height="82.96" Source="4.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="417"/>
</Canvas>
<Canvas Width="550.275" Height="82.96" x:Name="playlist2" Canvas.Left="607">
<Image x:Name="play4" Opacity="0.74" Width="133.275" Height="82.96" Source="5.png"
Stretch="Fill" Cursor="Hand" />
<Image x:Name="play5" Opacity="0.74" Width="133.275" Height="82.96" Source="6.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="139"/>
<Image x:Name="play6" Opacity="0.74" Width="133.275" Height="82.96" Source="7.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="278"/>
<Image x:Name="play7" Opacity="0.74" Width="133.275" Height="82.96" Source="8.png"
Stretch="Fill" Cursor="Hand" Canvas.Left="417"/>
</Canvas>
</Canvas>
</Canvas>
下面就要改一下相应的js文件了,找到StartPlayer.js文件,新的播入列表方法放在页面的最上面:
//全局变量声明
var curPos = 1; //当前播入的媒体文件在列表中的位置
var maxPos = 2; //当前的分页数,因为是8个文件,每4个文件为1页,所以这里是两页
var cVideos = 8; //视频文件个数(本DEMO中有8个)
function get_mediainfo(mediainfoIndex) {
switch (mediainfoIndex) {
case 0:
return { "mediaSource": "Movie1.wmv",
"placeholderSource": "",
"chapters": [] };
case 1:
return { "mediaSource": "Movie2.wmv",
"placeholderSource": "",
"chapters": [] };
case 2:
return { "mediaSource": "Movie3.wmv",
"placeholderSource": "",
"chapters": [] };
case 3:
return { "mediaSource": "Movie4.wmv",
"placeholderSource": "",
"chapters": [] };
case 4:
return { "mediaSource": "Movie5.wmv",
"placeholderSource": "",
"chapters": [] };
case 5:
return { "mediaSource": "Movie6.wmv",
"placeholderSource": "",
"chapters": [] };
case 6:
return { "mediaSource": "Movie7.wmv",
"placeholderSource": "",
"chapters": [] };
case 7:
return { "mediaSource": "Movie8.wmv",
"placeholderSource": "",
"chapters": [] };
default:
throw Error.invalidOperation("No such mediainfo");
}
}
var curPos = 1; //当前播入的媒体文件在列表中的位置
var maxPos = 2; //当前的分页数,因为是8个文件,每4个文件为1页,所以这里是两页
var cVideos = 8; //视频文件个数(本DEMO中有8个)
function get_mediainfo(mediainfoIndex) {
switch (mediainfoIndex) {
case 0:
return { "mediaSource": "Movie1.wmv",
"placeholderSource": "",
"chapters": [] };
case 1:
return { "mediaSource": "Movie2.wmv",
"placeholderSource": "",
"chapters": [] };
case 2:
return { "mediaSource": "Movie3.wmv",
"placeholderSource": "",
"chapters": [] };
case 3:
return { "mediaSource": "Movie4.wmv",
"placeholderSource": "",
"chapters": [] };
case 4:
return { "mediaSource": "Movie5.wmv",
"placeholderSource": "",
"chapters": [] };
case 5:
return { "mediaSource": "Movie6.wmv",
"placeholderSource": "",
"chapters": [] };
case 6:
return { "mediaSource": "Movie7.wmv",
"placeholderSource": "",
"chapters": [] };
case 7:
return { "mediaSource": "Movie8.wmv",
"placeholderSource": "",
"chapters": [] };
default:
throw Error.invalidOperation("No such mediainfo");
}
}
将原码中的原有播放文件列表变量和相关内容注释:
// this._playlist=[];
// try {
// eval( 'this._playlist=['+
// '{"mediaSource":"15_mt_l2s_callingsqlfunctions.wmv",'+
// '"placeholderSource":"",'+
// '"chapters":'+
// '['+
// ']},'+
// '{"mediaSource":"18_mt_l2s_transactions.wmv",'+
// '"placeholderSource":"",'+
// '"chapters":'+
// '['+
// ']}'+
// '];' );
// }
// catch(e){}
// this._galleryItems=[];
// try {
// eval( 'this._galleryItems=['+
// 'new ExpressionPlayer.GalleryItem("15_mt_l2s_callingsqlfunctions.wmv",""),'+
// 'new ExpressionPlayer.GalleryItem("18_mt_l2s_transactions.wmv","")'+
// '];' );
// }
// catch(e){}
// this._player.set_galleryInfo( this._galleryItems, Function.createDelegate(this, this._onClickGalleryItem) );
// this._onPlayNextVideo(null,null);
// try {
// eval( 'this._playlist=['+
// '{"mediaSource":"15_mt_l2s_callingsqlfunctions.wmv",'+
// '"placeholderSource":"",'+
// '"chapters":'+
// '['+
// ']},'+
// '{"mediaSource":"18_mt_l2s_transactions.wmv",'+
// '"placeholderSource":"",'+
// '"chapters":'+
// '['+
// ']}'+
// '];' );
// }
// catch(e){}
// this._galleryItems=[];
// try {
// eval( 'this._galleryItems=['+
// 'new ExpressionPlayer.GalleryItem("15_mt_l2s_callingsqlfunctions.wmv",""),'+
// 'new ExpressionPlayer.GalleryItem("18_mt_l2s_transactions.wmv","")'+
// '];' );
// }
// catch(e){}
// this._player.set_galleryInfo( this._galleryItems, Function.createDelegate(this, this._onClickGalleryItem) );
// this._onPlayNextVideo(null,null);
将下列代码放在该注释下方来解决对相应媒体播放按钮进行事件绑定:
//wire up the rollover and click events for each of our play buttons
this.Plugin = document.getElementById(this._hostname);
for (var i = 0; i < cVideos; i++)
{
var element = this.Plugin.Content.findName('play' + i);
element.addEventListener("MouseEnter", Function.createDelegate(this,this._rollOver));
element.addEventListener("MouseLeave", Function.createDelegate(this,this._rollOut));
element.addEventListener("MouseLeftButtonUp", Function.createDelegate(this,this._playX));
}
this.Plugin.Content.findName('LeftArrow').addEventListener("MouseEnter",
Function.createDelegate(this,this._rollOver));
this.Plugin.Content.findName('LeftArrow').addEventListener("MouseLeave",
Function.createDelegate(this,this._rollOut));
this.Plugin.Content.findName('LeftArrow').addEventListener("MouseLeftButtonUp",
Function.createDelegate(this,this._slideLeft));
this.Plugin.Content.findName('RightArrow').addEventListener("MouseEnter",
Function.createDelegate(this,this._rollOver));
this.Plugin.Content.findName('RightArrow').addEventListener("MouseLeave",
Function.createDelegate(this,this._rollOut));
this.Plugin.Content.findName('RightArrow').addEventListener("MouseLeftButtonUp",
Function.createDelegate(this,this._slideRight));
this._onPlayNextVideo(null, null);
this.Plugin = document.getElementById(this._hostname);
for (var i = 0; i < cVideos; i++)
{
var element = this.Plugin.Content.findName('play' + i);
element.addEventListener("MouseEnter", Function.createDelegate(this,this._rollOver));
element.addEventListener("MouseLeave", Function.createDelegate(this,this._rollOut));
element.addEventListener("MouseLeftButtonUp", Function.createDelegate(this,this._playX));
}
this.Plugin.Content.findName('LeftArrow').addEventListener("MouseEnter",
Function.createDelegate(this,this._rollOver));
this.Plugin.Content.findName('LeftArrow').addEventListener("MouseLeave",
Function.createDelegate(this,this._rollOut));
this.Plugin.Content.findName('LeftArrow').addEventListener("MouseLeftButtonUp",
Function.createDelegate(this,this._slideLeft));
this.Plugin.Content.findName('RightArrow').addEventListener("MouseEnter",
Function.createDelegate(this,this._rollOver));
this.Plugin.Content.findName('RightArrow').addEventListener("MouseLeave",
Function.createDelegate(this,this._rollOut));
this.Plugin.Content.findName('RightArrow').addEventListener("MouseLeftButtonUp",
Function.createDelegate(this,this._slideRight));
this._onPlayNextVideo(null, null);
而下面就是其相应的事件处理代码了:
_rollOver: function(sender, eventArgs) {
sender.opacity=1;
},
_rollOut: function(sender, eventArgs) {
sender.opacity=0.74;
},
_playX: function(sender, eventArgs) {
var X = Number(sender.Name.substring(4));
this._currentMediainfo = X;
this._player.set_mediainfo( get_mediainfo( X ));
sender.opacity=1;
},
_slideLeft: function(sender, eventArgs) {
switch(curPos)
{
case 1:
sender.findName("LeftArrow").opacity = 0.85;
break;
default:
sender.findName("MoveRight0" + curPos).Begin();
curPos--;
}
},
_slideRight: function(sender, eventArgs) {
switch(curPos)
{
case maxPos:
sender.findName("RightArrow").opacity = 0.85;
break;
default:
sender.findName("MoveLeft0" + curPos).Begin();
curPos++;
sender.findName("LeftArrow").opacity = 1;
}
}
sender.opacity=1;
},
_rollOut: function(sender, eventArgs) {
sender.opacity=0.74;
},
_playX: function(sender, eventArgs) {
var X = Number(sender.Name.substring(4));
this._currentMediainfo = X;
this._player.set_mediainfo( get_mediainfo( X ));
sender.opacity=1;
},
_slideLeft: function(sender, eventArgs) {
switch(curPos)
{
case 1:
sender.findName("LeftArrow").opacity = 0.85;
break;
default:
sender.findName("MoveRight0" + curPos).Begin();
curPos--;
}
},
_slideRight: function(sender, eventArgs) {
switch(curPos)
{
case maxPos:
sender.findName("RightArrow").opacity = 0.85;
break;
default:
sender.findName("MoveLeft0" + curPos).Begin();
curPos++;
sender.findName("LeftArrow").opacity = 1;
}
}
因为使用了新的播放列表变量,所以原来生成的如下方法内容会被改写如下:
_onPlayPreviousVideo: function(sender, eventArgs) {
if (this._currentMediainfo>0)
{
this._player.set_mediainfo(get_mediainfo(--this._currentMediainfo ));
}
},
_onPlayNextVideo: function(sender, eventArgs) {
if (this._currentMediainfo<cVideos)
{
this._player.set_mediainfo(get_mediainfo(++this._currentMediainfo ));
}
},
if (this._currentMediainfo>0)
{
this._player.set_mediainfo(get_mediainfo(--this._currentMediainfo ));
}
},
_onPlayNextVideo: function(sender, eventArgs) {
if (this._currentMediainfo<cVideos)
{
this._player.set_mediainfo(get_mediainfo(++this._currentMediainfo ));
}
},
到这里我们可以在本地运行一下default.htm来看一下效果。
然后为了演示方便,我将这个Application上传到了Silverlight Streaming上,经常了n遍的上传之后,终于测试
成功,所以才在本文开头做了相应的演示。
好了,今天的内容就先到这里了.
源码下载,请点击这里:)
注:因为老外所写的文章是在silverlight 1.0下运行的,所以本文的JS与原文中有所变动,但不会影响对代码的理解。