收藏本站腾讯微博新浪微博

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

蓝色理想 最新研发动态 网站开通淘帖功能 - 蓝色理想插件 论坛内容导读一页看论坛 - 给官方提建议

论坛活动及任务 地图和邮件任务 请多用悬赏提问 热夏来袭,选一款蓝色理想的个性T恤吧!

手机上论坛,使用APP获得更好体验 急需前端攻城狮,获得内部推荐机会 论坛开通淘帖功能,收藏终于可以分类了!

搜索
查看: 2362|回复: 1

[AS3] 跟kaka做播放器(二) ————歌词秀篇(核心篇)

[复制链接]
发表于 2008-9-22 16:37:45 | 显示全部楼层 |阅读模式
播放器演示地址:http://bbs.actionscript3.cn/thread-12211-1-1.html

kaka在写这篇教程的同时发了另一个贴kakaPlayer之歌词拖动猜想,在那里其实大家已经把kaka如果精确定位歌词的方法猜的八九不离十了,看来不管多奇妙的FLASH都是没有想不出,只有不敢想嘛..

不过为了让大家了解到更加详细、细致的制作过程以及需要注意的许多细节,同时也方便初学者学习,这篇教程还是有必要继续写下去的..

NOW,LET'S BEGIN.

   1.png


大家请看,这是一幅图。
这幅图上面有一行蓝色的"AAAAAAAA"和一行绿色的"BBBBBBBB"..
用千千静听的朋友肯定都知道,她那可爱的歌词秀功能就是她当初成名的关键。
而我们所要做的就是用强大的AS3来实现和这个相同功能。

歌词秀中显示为绿色的为当前正在播放的歌词,我们就用这张图上的"BBBBBB"来表示吧
假设这时我们已经通过这个帖子跟kaka做播放器(一) ————LRC歌词解析篇  提供的类解析LRC歌词得到了一个歌词数组,这个数组的每个元素都存有一个时间和一句歌词,下面我们首先要做的就是先把歌词用文本创建出来,这样才能显示嘛..

因此,我们创建一个方法,名叫"updateLrc",传入一个歌词数组,它就用数组里面每个子元素的第二个元素(第一个元素为时间信息)为内容创建一个文本框,同时加入到一个名为sprite_lyrics的Sprite对象里面

因为是横向滚动,所以我们的所有歌词都在同一行里面
  1.                 var sprite_lyrics:Sprite;
  2.                 var arr_splitedLyrics:Array;
  3.                 //歌词大小
  4.                 var _fontSize:int = 12;
  5.                 //正在显示的歌词样式
  6.                 var textFormat_show:TextFormat = new TextFormat('黑体', _fontSize, 0x66CC00);
  7.                 //默认歌词样式
  8.                 var textFormat_default:TextFormat = new TextFormat('黑体', _fontSize, 0x6699FF);

  9.                 public function updateLrc(arr_splitedLyrics:Array):void
  10.                 {
  11.                         this.arr_splitedLyrics = arr_splitedLyrics;
  12.                        
  13.                         //清空sprite_lyrics中的歌词文本
  14.                         while (sprite_lyrics.numChildren > 0)
  15.                         {
  16.                                 sprite_lyrics.removeChildAt(0);
  17.                         }
  18.                        
  19.                         //开始创建歌词显示文本                       
  20.                         //加入歌词
  21.                         for (var i:int = 0; i < arr_splitedLyrics.length; i++)
  22.                         {
  23.                                 var txt:TextField = new TextField();
  24.                                
  25.                                 txt.selectable = false;
  26.                                 txt.text = arr_splitedLyrics[i][1];
  27.                                 txt.setTextFormat(textFormat_default);
  28.                                 txt.autoSize = TextFieldAutoSize.LEFT;
  29.                                 txt.x = sprite_lyrics.width;
  30.                                 sprite_lyrics.addChild(txt);
  31.                                 //同时把该文本框的引用存入数组子元素的第3个位置,以便后面调用
  32.                                 arr_splitedLyrics[i][2] = txt;
  33.                         }
  34.                 }
复制代码
这样,只要我们
  1. addChild(sprite_lyrics)
复制代码
就可以显示出歌词啦


那么怎么让歌词随着歌曲动起来呢..?
理论上应该有很多种方法,kaka采用的是和AS2.0版本时一样的办法——用TWEEN类来控制歌词的滚动。
TWEEN类制作出来的是基于时间的动画,这样在改变帧频或者帧速不稳的情况下也可以确保歌词在规定的时间到达规定的位置而不会出现偏差。这点对于我们的歌词秀是非常重要的。

下面说说算法:
  1. 歌词横向移动的距离=该句歌词文本框的宽度
复制代码
时间上理论上是  歌词滚动时间=下一句歌词开始时间-本句歌词开始时间
但是我们要考虑到可能由于某时间系统负载过大导致TWEEN类没有能够及时发出finish事件导致下一句歌词被延迟,因此我们的时间算法改进如下:
  1. 歌词滚动时间=下一句歌词开始时间-歌曲播放头的当前位置
复制代码
这样当下一句歌词开始滚动的时候即使歌曲已经过了那个开始的时间也可以根据当前的歌曲播放位置来计算出合适的滚动时间。
  1.                 //横向滚动歌词的TWEEN
  2.                 var tween_sd:Tween;
  3.                 //歌词到第几句了
  4.                 var position_lyrics:int;

  5.                   //正常进入下一句歌词
  6.                 function nextLyrics():void
  7.                 {
  8.                         txt_green.setTextFormat(textFormat_default);
  9.                         txt_green = arr_splitedLyrics[position_lyrics][2];
  10.                         txt_green.setTextFormat(textFormat_show);
  11.                        
  12.                         tween_sd.begin = -arr_splitedLyrics[position_lyrics][2].x;
  13.                         tween_sd.finish = -(arr_splitedLyrics[position_lyrics][2].x + arr_splitedLyrics[position_lyrics][2].width);
  14.                         if (position_lyrics != arr_splitedLyrics.length - 1)
  15.                         {
  16.                                 tween_sd.duration = arr_splitedLyrics[position_lyrics + 1][0] - soundchannel.position / 1000;
  17.                         }
  18.                         else
  19.                         {
  20.                                 tween_sd.duration = (sound.length - soundchannel.position) / 1000;
  21.                         }
  22.                         tween_sd.duration == Infinity && (tween_sd.duration = 0.1);
  23.                         tween_sd.start();       
  24.                 }
复制代码
有了这个函数我们就可以侦听TWEEN的FINISH事件让他一句一句的滚动歌词了


好了  简单的说完了,下面来点有趣的,也就是大家感兴趣的歌词拖动定位部分:

为了做到和千千静听一样的歌词拖动定位歌曲方法,我们必须做到精确定位,而不是仅仅从拖到的那句的开始处播放
因此仅仅依靠数组中的时间信息是不行的
  这是就要靠我们的小强精神了...  其实当初kaka做这个功能的时候也在想好像不太可能实现呀.. 但是做着做着就发现其实很简单啦,只要取对数组中的值(索引不要差了)就OK


首先说说怎么判断拖动到哪一句了
kaka一开始用的是hitTestPoint方法,在歌词显示区域中心定义一个点,再拖动结束的时候依次遍历歌词文本框,看哪个与点重叠了,就判断为拖动到了该句歌词,后来发现没必要,只要判断哪个文本框的x值小于中心线(比如:x=250) 并且该文本框的x值+文本框的宽 > 中心线 就可以了  比hitTestPoint方法效率要高一点吧..

2.png
3.png

比如下张图中的文本框BBB他的x值=220小于中心线x=250,并且他的x值220+他的宽width=115结果是335大于x=250所以当前正在播放的歌词应该是BBB
而AAA虽然他的x=70小于x=250但是他的x=70+宽width=150结果是220还是小于中心线x=250因此他不是被播放的

4.png



如果实在想听AAA这个歌词那我们把歌词向前面拖回去一点就可以了

5.png


好了,现在总算已经可以定位到哪一句歌词了,喝口水庆祝一下吧(话说你们看没看懂..?  )


下面进入精确定位部分  先看图

6.png

算法描述:
  还记得开始时我们做得歌词容器嘛? sprite_lyrics  所有的歌词文本都一个个的紧挨着横向排列在这里面
  拖动结束的时候我们根据上面的思路确定是哪一句歌词被拖到了,然后通过该句歌词所对应的文本框的x坐标和中心线(x=250)之差 除以 歌词文本框的宽(也就是这句歌词需要移动的距离)  得到了被拖动得已经PASS掉歌词的百分比   

像上面图中的BBB文本框的计算过程就是
  1. var pec = (250-txt_BBB.x)/txt_BBB.width
复制代码
有了百分比,我们就可以计算出歌曲播放头跳转的精确位置了
在数组中取出本句歌词所对应的开始时间+百分比*(下一句歌词开始时间-本句歌词开始时间)=歌曲需要跳转到的位置
  1. for (var i:int = arr_splitedLyrics.length - 1; i >= 0; i--)                       
  2. {
  3. if (arr_splitedLyrics[i][2].x <= -sprite_lyrics.x)
  4. {
  5. break;
  6. }
  7. }                       

  8. var pec = (250-txt_BBB.x)/txt_BBB.width
  9. //歌曲定位到的新位置
  10. var position = arr_splitedLyrics[i][0] + pec * (arr_splitedLyrics[i+1][0] - arr_splitedLyrics[i][0]);
复制代码
这样我们就可以实现歌词拖动的功能了  最核心的东西也不过如此  大家看 简单吧?

这里我就主要说原理了,代码拆来拆去的是在很麻烦,直接看下面的整套源代码吧  

[[i] 本帖最后由 linchenrr 于 2008-9-22 17:34 编辑 ]
 楼主| 发表于 2008-9-22 16:43:03 | 显示全部楼层
为神圣的kaka的Player占地


  在实际制作中会碰到很多想不到的问题:
比如LRC歌词加载好了,但是这时歌曲已经播放到第二句第三句了,这时又怎么处理?   大家可以自己开动脑筋来相处解决办法
kaka也已经为你们准备好了根据歌曲播放头的位置来跳转歌词到相应位置的方法,其实是和定位歌曲的那个方法互为逆运算的

下面是所有的源代码下载  
kakaPlayer.part1.rar (195.31 KB, 下载次数: 221)
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|小黑屋|Archiver|手机版|blueidea.com ( ICP05002321 )  

GMT+8, 2019-12-14 18:49 , Processed in 0.147086 second(s), 11 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表