저는 충동적으로 Flex를 사용하기 시작했습니다. 원래는 Flex 블로그를 만들고 싶었지만 지금은 발표만 할 수 있게 되었습니다. . . 끝낼 방법이 없어, 넌 정말 엉망이야! Flex 레이아웃은 CSS와는 다릅니다. 아름다운 Flash 애니메이션은 하나 또는 두 개의 컨트롤을 드래그하여 생성되는 것이 아니라 한 번에 한 획씩 그려서 생성됩니다. 아직 이것저것 잘 모르는데 거의 일주일째 작업 중인데 매일 피곤할 때까지 잠도 못 자고 오늘 드디어 간단한 플레이어가 생겼네요.
저는 항상 음악을 좋아했습니다. Jay와 그의 노래도 더욱 좋아했습니다. 그의 Gray Space 한 곡을 들으면서 팟캐스트를 만들 수 있겠다는 생각이 들었습니다. 나르시시즘이 담긴 노래가 조금 더 만족감을 선사할 거예요. 어~ 이틀 전에 우연히 한 선생님들의 개인 블로그를 보았는데, 그 분들의 블로그 글이 기술에 관한 내용이든, 삶을 기록하는 내용이든, 글이 너무 현실적이어서 블로그를 고집하는군요. 예, 끈기있게 포기하지 마세요...
mx: ProgressBar는 로딩 노래 버퍼 진행률 표시줄을 구현합니다
ProgressBar에는 이벤트, 수동 및 폴링이라는 세 가지 주요 모드가 있습니다. 이벤트 중심 모드를 기반으로 소스 객체는 로딩 프로세스를 자동으로 표시하도록 설정할 수 있습니다. 수동은 폴링 모드로 스크롤 막대를 설정하려면 ProgressBar.setProgress() 메서드를 호출해야 합니다. 이 예제에서 사용된 모드에서는 Sound가 로드 요청 노래를 로드하여 ProgressEvent.PROGRESS를 추가합니다. 처리 중에 이벤트를 수신한 다음 Sound가 로드한 바이트 수와 bytesTotal을 기반으로 setProgress 진행률을 설정합니다. 노래를 전환할 때 ProgressEvent.PROGRESS 이벤트를 먼저 제거해야 합니다. 그렇지 않으면 이전에 재생된 노래의 로드가 완료되기 전에 새 노래를 로드하도록 전환할 때 ProgressBar가 여러 PROGRESS 이벤트를 트리거하고 진행 상황이 스크롤됩니다. 이리저리.
mx:HSlide는 슬라이더를 조정합니다
이 컨트롤은 이 예에서 재생 진행률과 사운드 볼륨을 제어하기 위해 두 곳에서 사용됩니다. 노래 재생 과정에서 HSlide가 자동으로 현재 재생 위치를 슬라이드해야 하고 동시에 재생을 수동으로 드래그할 수 있어야 하기 때문에 처음에는 재생 진행 조정 문제로 인해 오랫동안 당황했습니다. HSlide에는 원래 감지할 수 있는 좋은 변경 이벤트가 있는데, 타이머를 사용하여 HSlide의 값을 설정하면 변경 이벤트도 발생합니다. Adobe 공식 웹사이트의 도움말 문서를 참조하면 다음과 같습니다. Slider 구성 요소의 값은 마우스 또는 키보드 상호 작용으로 인해 변경된다고 합니다. liveDraging 속성이 true인 경우 사용자가 슬라이더를 움직일 때 이벤트가 계속 전달됩니다. liveDragged가 false인 경우 사용자가 슬라이더를 놓을 때 이 이벤트가 전달됩니다. 그런데 어떻게 설정하더라도 코드에서 HSlide의 값이 변경될 때 변경 이벤트가 트리거될 수 있습니까? 사용자 상호 작용으로 인해 값이 변경될 때 예약된다는 의미는 아닙니까? 참 안타깝기 때문에 ThumbDrag 이벤트를 모니터링하면서 타협할 수밖에 없었습니다. Adobe에서는 이 이벤트가 슬라이더를 누른 후 마우스로 움직일 때 발생한다고 설명했습니다. 즉, 슬라이더를 드래그해야 한다는 것입니다. 줄기를 눌렀을 때만 작동하며 클릭에는 아무런 영향이 없습니다.
SoundMixer.computeSpectrum()은 오디오 곡선을 분석합니다
이 예에서 표시되는 오디오 곡선은 실제로 오른쪽에 스트립으로 그려진 64개의 캔버스 컨트롤과 타이머의 배열입니다. 는 곡선 변경의 효과를 표시하기 위해 100밀리초마다 scaleY 위치를 재설정하는 데 사용됩니다. 코드는 단 세 줄이며 매우 간단합니다. 자세한 내용은 아래 소스 코드에 제공된 타이머Tick 이벤트를 참조하세요. 여기서 타이머를 사용하는 이유는 무엇입니까? 다른 사람들이 Event.ENTER_FRAME 이벤트를 듣고 오디오 곡선을 다시 그리는 것을 인터넷에서 봤습니다. 큰 문제를 일으키고 싶지 않다면 타이머를 사용하면 bytesTotal 및 bytesLoaded를 기준으로 할 수 있습니다. 100밀리초 타이머를 사용하면 사이트 리소스가 많이 소모되지 않으며 CPU가 크게 증가하지 않습니다.
렌더링:
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 중국어 사이트를 주목해주세요!