随笔-127  评论-2647  文章-26  trackbacks-67
     在写完"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代码(播入列表代码)
放在该文件的结尾处:

<!-- 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>

   
    下面就要改一下相应的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");
     }
}

   将原码中的原有播放文件列表变量和相关内容注释:

//    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);  

      将下列代码放在该注释下方来解决对相应媒体播放按钮进行事件绑定:

//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(nullnull);   


    而下面就是其相应的事件处理代码了:

 

 _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;     
      }
 }


     因为使用了新的播放列表变量,所以原来生成的如下方法内容会被改写如下:
 

_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 ));   
    }
},
 

     到这里我们可以在本地运行一下default.htm来看一下效果。

     然后为了演示方便,我将这个Application上传到了Silverlight Streaming
上,经常了n遍的上传之后,终于测试
成功,所以才在本文开头做了相应的演示。

    好了,今天的内容就先到这里了.

    源码下载,请点击这里:)

    注:因为老外所写的文章是在silverlight 1.0下运行的,所以本文的JS与原文中有所变动,但不会影响对代码的理解


posted on 2008-07-09 18:00 代震军 阅读(1978) 评论(36)  编辑 收藏 所属分类: silverlight

评论:
#1楼  2008-07-09 21:26 | 浪剑仙客 [未注册用户]
支持一下。^_^
  回复  引用    
#2楼 [楼主] 2008-07-10 09:45 | 代震军      
@浪剑仙客
谢谢关注:)

  回复  引用  查看    
#3楼  2008-07-10 11:11 | mat1 [未注册用户]
还可以``一直没用过这工具`都是在BLEND里自己画``之后在手写JS``没想到这工具是做这个的最佳利器```
  回复  引用    
#4楼 [楼主] 2008-07-10 11:34 | 代震军      
@mat1
是呀,能剩不少事,而且界面也不错,功能也差不多够用了:)
  回复  引用  查看    
#5楼  2008-07-10 15:07 | PerfectDesign      
不过现在似乎有资质做视频的网站已经不多了啊...................
  回复  引用  查看    
#6楼  2008-07-10 18:20 | mat1 [未注册用户]
哎``看看能不能给我找点资料我想写个动态``silverlight做一个动态网站首页导航栏用XLINQ动态加载```想了想```思路还不完整``
我发现了一个SIL2BT1的折叠导航栏跟你分享一下```
http://www.mdong.org/?p=136
不过不是我想要的效果````这个有点像折叠菜单```很像AJAXTOOK的风格``
  回复  引用    
#7楼  2008-07-10 19:58 | airwolf2026      
学习成本...新东西太多了...
  回复  引用  查看    
#8楼 [楼主] 2008-07-11 09:01 | 代震军      
@PerfectDesign
国家对这类网站目前是管的比较严
  回复  引用  查看    
#9楼 [楼主] 2008-07-11 09:02 | 代震军      
@airwolf2026
其实工具(expression encoder 2)还是非常好用的:)
  回复  引用  查看    
#10楼 [楼主] 2008-07-11 09:02 | 代震军      
@airwolf2026
谢谢分享,这种精神正是我所希望的,呵呵:)
  回复  引用  查看    
#11楼  2008-07-11 10:51 | mat1 [未注册用户]
谢谢分享,这种精神正是我所希望的,呵呵:)

是不是应该是对我说的??
  回复  引用    
#12楼  2008-07-11 11:46 | langmuir [未注册用户]
很明显是对你说的.

哈哈
  回复  引用    
#13楼 [楼主] 2008-07-11 15:05 | 代震军      
@mat1
正是SHARE的思想,才会让大家的学习效率不断提升,知识面也变得越来越宽:)
  回复  引用  查看    
#14楼  2008-07-11 15:57 | mat1 [未注册用户]
把他们改成BETA2的了吗?
  回复  引用    
#15楼  2008-07-11 15:58 | mat1 [未注册用户]
恩`那可不是吗``一个人在牛```也不可能什么都知道``人的时间是有限的``
  回复  引用    
#16楼 [楼主] 2008-07-11 16:57 | 代震军      
@mat1
没错,呵呵:)
  回复  引用  查看    
#17楼  2008-07-11 17:10 | mat1 [未注册用户]
我改了一下····就卡在了百分之百就不动了··看来给反编译内个DLL··看看用不用改了···这个肯定是BATE1做的···没有对作者不敬的意思···
  回复  引用    
#18楼 [楼主] 2008-07-11 17:48 | 代震军      
@mat1
我下载的Expression Encoder 2是最新的,不知道你所说的beta1做的是什么意思?并且这个DEMO是没有DLL的,莫非您说的DLL是那个老外写的DLL?
  回复  引用  查看    
#19楼  2008-07-11 17:49 | mat1 [未注册用户]
我说的是我让你看的内个控件····您还没看呢吗·?
  回复  引用    
#20楼  2008-07-11 18:02 | mat1 [未注册用户]
Expression Encoder 2 下午玩了玩···可以把一个影片截出几个索引段落···还可以剪贴片头和片尾···如果好好弄一下的片头和片尾的话···在给您例子里每一个小影片一个8个··都做一个段落索引的话··也是一个好的思路··这样就可以不用写代码了····在选个有段落索引的皮肤···也可以搞定···嘿···效果是差不多了····我今天主要是看折叠导航栏来着···最近WPF的项目做完了···有些时间··可以看看别的····正好WPF的控件也做个十几个····想搞个网站首页的内种动态加载的导航条·····
  回复  引用    
#21楼 [楼主] 2008-07-14 09:31 | 代震军      
@mat1
看了,版本是老了一些,呵呵:)
  回复  引用  查看    
#22楼  2008-07-14 11:09 | mat1 [未注册用户]
嘿··我猜您就是今天给我回···我说今天抽空给改到BATE2能用的状态··如果您现在已经弄好了····我就不做无用功了····
  回复  引用    
#23楼  2008-07-14 14:40 | mat1 [未注册用户]
···
  回复  引用    
#24楼  2008-07-14 14:51 | mat1 [未注册用户]
不成··反编译不成啊···没有XAML··
  回复  引用    
#25楼 [楼主] 2008-07-14 15:00 | 代震军      
@mat1
我没太研究那个东西,主要是时间有限。看来你要孤军奋战了:()
  回复  引用  查看    
#26楼  2008-07-14 15:29 | mat1 [未注册用户]
看来借鉴不了了··给自己想想怎末实现写一个了···这叫独自长大·····
  回复  引用    
#27楼  2008-07-14 16:57 | mat1 [未注册用户]
我问一个愚笨的问题在BETA1中canvas.Resources.Add() add的方法需要一个参数是VALUE,而BETA2中``要两个参数KEY和VALUE```
我不知道在后台代码怎么给Storyboard 一个KEY```
XAML好说<Storyboard x:key="aa"> 但在C#中`怎么给KEY值呢``
  回复  引用    
#28楼 [楼主] 2008-07-14 17:32 | 代震军      
@mat1
http://technet.microsoft.com/zh-cn/sysinternals/ms521848.aspx
http://technet.microsoft.com/zh-cn/sysinternals/ms752326.aspx
从说明中感觉它应该是x:Name的名称,也就是HASHTABLE的KEY,以便进行引用和相应操作。

  回复  引用  查看    
#29楼  2008-07-14 18:06 | mat1 [未注册用户]
我想侃侃成不成我刚才看SDK呢```
  回复  引用    
#30楼  2008-07-14 18:29 | mat1 [未注册用户]
问题是KEy不能乱给··好像必须是你后面VALUE的 KEY··我canvas.Resources.Add(KEY,VALUE);
KEY是瞎给的 ··VALUE是实例的Storyboard对象···
就报An item with the same key has already been added错误··
所以我想在后台给 Storyboard对象一个KEY值··在这里面把KEY值填进去试试···SDK上没说···
  回复  引用    
#31楼 [楼主] 2008-07-15 09:37 | 代震军      
@mat1
An item with the same key has already been added
从字面上看是已添加过相同的key了:)
  回复  引用  查看    
#32楼  2008-07-15 10:56 | mat1 [未注册用户]
是啊···可是我真没加··所以我觉得必须给的是VALUE对应的KEY值··
  回复  引用    
#33楼  2008-07-15 11:10 | mat1 [未注册用户]
可能是我程序有问题···好像调了两次ADD方法·我再查查吧
  回复  引用    
#34楼  2008-07-30 15:31 | leanco      
能问个问题吗?上传的视频怎么样转换为silverlight可用的格式啊?谢谢啦!!!
  回复  引用  查看    
#35楼 [楼主] 2008-07-30 17:09 | 代震军      
@leanco
用一般的WMV文件就可以了,当前ENCODER软件也会转换这个视频,但没有太大问题:)
  回复  引用  查看    
#36楼  2008-08-02 14:20 | yoling [未注册用户]
由灵精美音频播放器v1.0 for sl2.0

看这个吧:http://slcenter.cn/show_33.aspx

惊暴SL界!好东东。。哈哈
  回复  引用