搜索
首页php教程PHP开发Flex播放器(实现播放、缓冲进度条和音频曲线显示)

一时兴起,玩起了Flex,本来还想要做个Flex博客,不过目前还只能在里面树个公告。。。没办法做完啊,河蟹的个杯具的!Flex布局不像是CSS,精美Flash动画不是拖一个两个控件就能做出来滴,而是一笔一条线绘制出来滴!这些我都还不熟悉,所有折腾快一个星期了,每天都是搞到头大才睡觉,今天终于能出一个简单的播放器。

一直很喜欢音乐这个东西,喜欢Jay,更喜欢他的歌,也很崇拜小猪,他的一段灰色空间曾让我激流奋进,想过自己能做个播客放自己喜欢听的歌曲,出于自恋那样会更有一点点满足感。呃~走神了,前二天无意看到一群教师的个人博客,深深的被他们的博文所吸引,无论是谈技术还是记录生活的,写得都是那么的真切,还有坚持每日一博的,坚持不放弃...

mx:ProgressBar实现加载歌曲缓冲进度条

ProgressBar有三大mode模式,分别为event、manual、polled,event为基于事件驱动模式,可设置source对象自动显示加载进程;manual为手动模式,需要调用ProgressBar.setProgress()方法设置滚动条进度;polled为轮询模式,本例使用的manual模式,Sound加载load请求歌曲添加一个ProgressEvent.PROGRESS处理中监听事件,然后根据Sound已加载的bytes和bytesTotal数,设置setProgress进度。这里需要注意在切换歌曲的时候先要移除ProgressEvent.PROGRESS事件,否则之前播放歌曲还未加载完又切换load新歌曲时回出现ProgressBar触发多个PROGRESS事件被设置进度出现来回滚动的问题。

mx:HSlide调节滑秆

这个控件在本例中2处使用,实现对播放进度和声音大小的控制。最一开始调整播放进度的问题难倒了我很久,因为在歌曲播放过程中HSlide要自动滑动当前播放位置,同时又需要能手动拖动播放位置,HSlide本来有一个很好的change事件用来侦听改变,但是我使用定时器设置HSlide的value的时竟然也给我触发change事件,参考了Adobe哥官网的帮助文档,说是Slider 组件的值因鼠标或键盘交互操作而改变时调度,如果 liveDragging 属性是 true,则在用户移动滑块时持续调度该事件。 如果 liveDragging 是 false,则在用户释放滑块时调度该事件。但是无论我怎么设置,在代码里改变了HSlide的value值怎会触发change事件,不是说在用户交互操作而改变时调度吗?无赖啊,后来只能折中采取监听thumbDrag滑秆拖动时事件,这个事件Adobe哥的解释是当按下滑块并随后随鼠标移动时调度,这样会有一个小问题,就是需要拖动滑秆按下时才会触发,点击无效。

SoundMixer.computeSpectrum()分析音频曲线

本例你看到显示的音频曲线其实是右64个绘制成条状的Canvas控件排列而成,然后使用定时器每间隔100毫秒重新设置他们的scaleY位置以呈现出变幻曲线的效果,代码只有三行很简单,具体可参见我下面源码给出的timerTick事件。这里为什么要用定时器呢?在网上看别人是监听Event.ENTER_FRAME事件重绘音频曲线的,不想搞那么麻烦就直接用定时器了,随便根据bytesTotal和bytesLoaded计算下歌曲播放时间,使用100毫秒的定时器也并好耗站资源,CPU没有涨很高。

效果图:

Flex播放器(实现播放、缓冲进度条和音频曲线显示)

mxml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" verticalGap="0" scroll="false" backgroundAlpha="0"
     horizontalScrollPolicy="off" verticalScrollPolicy="off" verticalAlign="middle" horizontalAlign="center"
     initialize="init(event)" layout="vertical" fontSize="14" paddingLeft="0" paddingTop="0" paddingRight="0" paddingBottom="0" >
    <mx:Script>
        <![CDATA[
            import mx.formatters.DateFormatter;
        
            import mx.effects.SoundEffect;
            import mx.events.SliderEvent;
            import mx.core.SoundAsset;
        
            import mx.controls.Alert;
            import mx.managers.CursorManager;
            import flash.media.*;
            
            import flash.utils.Timer;
            
            [Embed(source="images/cursor.gif")] 
            private var cursorHand : Class;//图标
            
            private var xml:XML; 
            private var xmlPath:String = "/flex/bin-debug/song.xml";
            private var currIndex : Number = 0; 
            
            private var song :Sound;
            private var channel :SoundChannel;
            private var position : Number = 0;
            // 保存 512 个声音波形的快照
            private var bytes:ByteArray = new ByteArray();
            // SoundBar 的个数
            private var barNum:uint = 64;
            // 保存所有 SoundBar 的引用
            private var soundBars:Array = new Array();
            
            //定时器
            private var timer : Timer;
            
            //Application的initialize初试化事件
            private function init(event:Event):void
            {
                var loader:URLLoader = new URLLoader(); 
                loader.load(new URLRequest(xmlPath)); 
                loader.addEventListener(Event.COMPLETE,Xml_Complete);
                
                timer = new Timer(100);
                timer.addEventListener(TimerEvent.TIMER,timerTick);
                
                var barWidth:Number = boxSoundBar.width*1.00/barNum;
                // 初始化Canvas为音频条,放入舞台并加入数组
                for (var i:uint = 0; i < barNum; i++)  {
                   var soundBar:Canvas = new Canvas();
                   soundBar.width = barWidth;
                   soundBar.height = boxSoundBar.height;
                   soundBar.x = i * barWidth;
                      soundBar.y =  0;
                   var g:Graphics = soundBar.graphics;
                   g.lineStyle(1,0x6688AA,1);
                   g.beginGradientFill(GradientType.RADIAL,[0x33cc00,0x456628],[1,1],[0,255],null,SpreadMethod.REFLECT,InterpolationMethod.RGB,0);
                   g.drawRect(0,0,soundBar.width,soundBar.height);
                   g.endFill();
                   boxSoundBar.addChild(soundBar);
                   soundBars.push(soundBar);
                }
                // 隐藏一些内建的鼠标右键菜单项
                this.contextMenu.hideBuiltInItems(); 
                var contextMenuItem : ContextMenuItem = new ContextMenuItem("Powered By: Jonllen");
                contextMenuItem.enabled = false;
                contextMenu.customItems.push(contextMenuItem);
                this.contextMenu.customItems.push(contextMenuItem);
                
                //更改鼠标图标
                CursorManager.setCursor(cursorHand);
            }
            
            //读取XML文件完成事件
            private function Xml_Complete(event:Event):void 
            {
                xml = new XML(event.target.data);
                if(xml.item.length()>=1)
                {
                    listSong.dataProvider= xml.item.name;
                    listSong.selectedIndex = 0;
                    //手动触发List的Change事件
                    listSong.dispatchEvent(new mx.events.ListEvent(Event.CHANGE, true, false));
                }
            }
            
            //List选择歌曲改变事件
            private function Xml_Change(event:Event):void
            {
                currIndex = event.target.selectedIndex;
                
                timer.stop();
                
                //停止声音文件的加载
                if( song!=null )
                {
                    //移除之前加载PROGRESS事件对songProgress进度条的控制
                    song.removeEventListener(ProgressEvent.PROGRESS,songProgress_Change);
                    if( song.isBuffering )
                        song.close();
                }
                
                song = new Sound();
                var url : String = xml.item[currIndex].url;
                var source:URLRequest = new URLRequest(url);
                song.load(source);
                song.addEventListener(ProgressEvent.PROGRESS, songProgress_Change);
                song.addEventListener(IOErrorEvent.IO_ERROR, songProgress_Error);
                
                position = 0;
                songStart();
            }
            
            //歌曲播放完成
            private function songProgress_Complete(e:Event):void {
                if(currIndex == xml.item.length()-1) {
                    currIndex = 0;
                }else {
                    currIndex++;
                }
                listSong.selectedIndex = currIndex;
                listSong.dispatchEvent(new mx.events.ListEvent(Event.CHANGE, true, false));
            }
            
            //加载歌曲失败
            private function songProgress_Error(e:IOErrorEvent):void {
                Alert.show("文件不存在!","系统提示");
            }
            
            //开始播放歌曲
            private function songStart():void {
                
                if ( channel != null ){
                    channel.stop();
                }
                
                lblName.text = xml.item[currIndex].name;
                channel = song.play(position,int.MAX_VALUE);
                
                var length :Number = song.length*song.bytesTotal/song.bytesLoaded;
                var date : Date = new Date();
                date.time = length;                
                var dt : DateFormatter = new DateFormatter();
                dt.formatString="NN:SS";
                var totalTime : String = dt.format(date);
                
                date.time = channel.position;
                lblTime.text = dt.format(date) + " | " + totalTime;
                lblStatus.text = "播放";
                
                var soundcontrol : SoundTransform = channel.soundTransform;
                soundcontrol.volume = volumeSlider.value;
                channel.soundTransform= soundcontrol;
                
                timer.start();
                boxSoundBar.visible = true;
            }
            
            //停止歌曲播放
            private function songStop():void {
                timer.stop();
                position = 0;
                boxSoundBar.visible = false;
                lblTime.text = "00:00 |"+lblTime.text.split("|")[1];
                lblStatus.text = "停止";
                songSlider.value = songSlider.minimum;
                songProgress.setProgress(songProgress.minimum,songProgress.maximum);
                if ( channel != null )
                {
                    channel.stop();
                }
            }
            
            //暂停歌曲播放
            private function songPause():void {
                if ( channel != null ){
                    timer.stop();
                    position = channel.position;
                    channel.stop();
                    lblStatus.text = "暂停";
                }
            }
            
            //加载歌曲进度条显示
            private function songProgress_Change(e:ProgressEvent):void {
                var percent:int = Math.round(e.bytesLoaded * 100 / e.bytesTotal);
                songProgress.setProgress(e.bytesLoaded,e.bytesTotal);
            }
            
            //定时器方法
            private function timerTick( e:TimerEvent):void {
                
                if( channel!=null) {
                    
                    var length :Number = song.length*song.bytesTotal/song.bytesLoaded;
                    var date : Date = new Date();
                    date.time = length;                
                    var dt : DateFormatter = new DateFormatter();
                    dt.formatString="NN:SS";
                    var totalTime : String = dt.format(date);
                    
                    date.time = channel.position;
                    lblTime.text = dt.format(date) + " | " + totalTime;
                    
                    songSlider.value=100*channel.position/length;
                    if( songSlider.value>=songSlider.maximum){
                        timer.stop();
                        songProgress_Complete(null);
                        return;
                    }
                    
                    SoundMixer.computeSpectrum(bytes, false, 0);
                    for (var i:uint = 0; i < barNum; i++)  {
                       soundBars[i].scaleY = bytes.readFloat();
                    }
                    
                }
            }
            
            //歌曲进度调整事件
            internal function songSlider_Change(e:SliderEvent):void{
                timer.stop();
                if ( channel != null ){
                    var length :Number = song.length*song.bytesTotal/song.bytesLoaded;
                    position = e.value*length/100;
                    songStart();
                }
            }
            
            //声音大小调整事件
            internal function changeVolume(evt:SliderEvent):void{
                if ( channel != null ){
                    var soundcontrol : SoundTransform = channel.soundTransform;
                    soundcontrol.volume = evt.value;
                    channel.soundTransform= soundcontrol;
                }
            }
            
            //设置歌曲播放时间和总时间
            private function setTimeStatus():void {
                var length :Number = song.length*song.bytesTotal/song.bytesLoaded;
                var date : Date = new Date();
                date.time = length;                
                var dt : DateFormatter = new DateFormatter();
                dt.formatString="NN:SS";
                var totalTime : String = dt.format(date);
                
                date.time = channel.position;
                lblTime.text = dt.format(date) + " | " + totalTime;
            }
            
        ]]>
    </mx:Script>
    <mx:HBox width="100%" verticalGap="0" verticalAlign="middle" horizontalAlign="center">
        <mx:Canvas width="440" borderColor="#CCCCCC" borderStyle="solid" height="171">
            <mx:Label id="lblName" x="5" fontSize="18" y="10" text=""/>
            <mx:HBox id="boxSoundBar" horizontalGap="0" verticalAlign="middle"
                 width="192" height="50" x="5" y="39" visible="false"></mx:HBox>
            <mx:ProgressBar id="songProgress" label="" 
                width="290" height="3" mode="manual" textAlign="left" 
                labelPlacement="center" fontSize="3" x="10" y="97" 
                minimum="0" maximum="100" barColor="yellow"
                trackColors="[white, haloSilver]"/>
            <mx:HSlider id="songSlider" styleName="song" value="0"
                 showTrackHighlight="true" x="5" y="85" thumbDrag="songSlider_Change(event)"
                 width="300" height="22" minimum="0" maximum="100" 
                 liveDragging="false" snapInterval="1"  toolTip="拖动调整播放进度">
            </mx:HSlider>
            <mx:Label id="lblStatus" x="243" y="41" text=""/>
            <mx:Label id="lblTime" x="205" y="66" text="00:00 | 5:23"/>
            <mx:Button x="10" y="124" label="Play" click="songStart()"/>
            <mx:Button x="74" y="124" label="Pause" click="songPause()"/>
            <mx:Button x="152" y="124" label="Stop" click="songStop()"/>
            <mx:HSlider id="volumeSlider" styleName="volume" change="changeVolume(event)"
                 showTrackHighlight="true" value="0.5" x="222" y="133"
                  width="81" minimum="0" maximum="10" liveDragging="true"
                   snapInterval="0.1" toolTip="音量调节" />
            <mx:Label x="308" fontSize="18" y="10" text="歌曲列表"/>
            <mx:List id="listSong" alpha="0.25" x="308" y="43" height="116"
                 change="Xml_Change(event)" width="130" toolTip="点击选择歌曲"></mx:List>
        </mx:Canvas>
    </mx:HBox>
</mx:Application>

更多Flex播放器(实现播放、缓冲进度条和音频曲线显示)相关文章请关注PHP中文网!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用