Mp3Player.as

package ddw.adobe
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.net.URLRequest;
import flash.utils.Timer; import mx.controls.Alert;
import mx.events.FlexEvent; import org.osmf.events.TimeEvent; import spark.components.Label;
import spark.components.SkinnableContainer;
import spark.components.ToggleButton;
import spark.components.mediaClasses.ScrubBar;
import spark.components.mediaClasses.VolumeBar;
import spark.events.TrackBaseEvent; public class Mp3Player extends SkinnableContainer
{ /**
* 播放(暂停)按钮默认24×24
*/
public function Mp3Player()
{
super(); setStyle("skinClass", Class(ddw.adobe.Mp3PlayerSkin)); timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, handleTime);
} [SkinPart]
public var playPauseButton:ToggleButton;
[SkinPart]
public var scrubBar:ScrubBar;
[SkinPart]
public var currentTimeDisplay:Label;
[SkinPart]
public var durationDisplay:Label;
[SkinPart]
public var volumeBar:VolumeBar; override protected function partAdded(partName:String, instance:Object):void {
super.partAdded(partName, instance)
switch (instance){
case playPauseButton:
playPauseButton.addEventListener(MouseEvent.CLICK, playSound)
playPauseButton.selected = isPlaying;
break;
case scrubBar:
// add thumbPress and thumbRelease so we pause the video while dragging
scrubBar.addEventListener(TrackBaseEvent.THUMB_PRESS, scrubBar_thumbPressHandler);
scrubBar.addEventListener(TrackBaseEvent.THUMB_RELEASE, scrubBar_thumbReleaseHandler);
// add change to actually seek() when the change is complete
scrubBar.addEventListener(Event.CHANGE, scrubBar_changeHandler);
// add changeEnd and changeStart so we don't update the scrubbar's value
// while the scrubbar is moving around due to an animation
scrubBar.addEventListener(FlexEvent.CHANGE_END, scrubBar_changeEndHandler);
scrubBar.addEventListener(FlexEvent.CHANGE_START, scrubBar_changeStartHandler);
updateScrubBar();
break;
case volumeBar:
volumeBar.minimum = 0;
volumeBar.maximum = 1;
volumeBar.value = 1;
volumeBar.addEventListener(Event.CHANGE, volumeBar_changeHandler);
volumeBar.addEventListener(FlexEvent.MUTED_CHANGE, volumeBar_mutedChangeHandler);
volumeBar.value = volume
volumeBar.muted = muted;
break; }
} private var _autoPlay:Boolean = false; public function get autoPlay():Boolean
{
return _autoPlay;
} public function set autoPlay(value:Boolean):void
{
_autoPlay = value; if (_source && _autoPlay)play(); } private var _source:String; public function get source():String
{
return _source; } /**
* 修正更换地址时,如果修改当前地址,autoPlay=true;
* 如果第一次设置地址,那么autoPlay由设置决定;
* */
public function set source(value:String):void{
if(_source==value)return;
if(_source)
{
_source=null;
autoPlay=true;
}
_source = value;
if (_source)
loadSound();
if (autoPlay)
play();
} // ********************* PLAYBACK private var mySound:Sound;
private var myChannel:SoundChannel;
private var soundPosition:Number = 0;
private var isPlaying:Boolean = false;
private var timer:Timer; private function loadSound():void{
if (myChannel) myChannel.stop()
soundPosition = 0;
isPlaying = false;
timer.stop(); if (playPauseButton)
playPauseButton.selected = false mySound = new Sound()
mySound.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
mySound.addEventListener(ProgressEvent.PROGRESS, progressHandler); var request:URLRequest = new URLRequest(_source);
mySound.load(request) updateDisplay()
updateScrubBar()
} private function errorHandler(event:IOErrorEvent):void{
Alert.show(event.text, "Sound error");
} private function progressHandler(event:ProgressEvent):void{
updateDisplay()
updateScrubBar()
} private function updateScrubBar():void {
if (!scrubBar || !mySound) return; if (!scrubBarMouseCaptured && !scrubBarChanging){
scrubBar.minimum = 0;
scrubBar.maximum = mySound.length/1000;
scrubBar.value = soundPosition/1000
} if (mySound.bytesTotal == 0)
scrubBar.loadedRangeEnd = 0;
else
scrubBar.loadedRangeEnd = (mySound.bytesLoaded/mySound.bytesTotal)*scrubBar.maximum;
} private function updateDisplay():void{
if (currentTimeDisplay)
currentTimeDisplay.text = formatTimeValue(soundPosition/1000)
if (durationDisplay)
durationDisplay.text = formatTimeValue(mySound.length/1000);
} private function playSound(event:MouseEvent):void{
if (isPlaying){
pause();
if ((mySound.length-soundPosition)<500)
rewind();
}
else
play();
} public function play():void{
myChannel = mySound.play(soundPosition);
myChannel.addEventListener(Event.SOUND_COMPLETE,soundCompleteHandler)
volume = _volume;
muted = _muted; if (playPauseButton)
playPauseButton.selected = true
isPlaying = true timer.start()
} protected function soundCompleteHandler(event:Event):void
{
// TODO Auto-generated method stub
pause();
soundPosition = 0;
scrubBar.value = soundPosition/1000
updateDisplay();
} public function pause():void{
if (myChannel){
soundPosition = myChannel.position;
myChannel.stop();
}
if (playPauseButton)
playPauseButton.selected = false;
isPlaying = false; timer.stop();
} public function rewind():void{
soundPosition = 0;
updateScrubBar();
updateDisplay(); if (isPlaying){
myChannel.stop();
}
} public function seek(time:Number):void
{
soundPosition = time;
if (isPlaying){
myChannel.stop();
myChannel = mySound.play(soundPosition);
volume = _volume;
muted = _muted;
} } private function handleTime(event:TimerEvent):void{
if (!isPlaying) return;
soundPosition = myChannel.position;
updateDisplay();
updateScrubBar();
} protected function formatTimeValue(value:Number):String{
// default format: hours:minutes:seconds
value = Math.round(value); var hours:uint = Math.floor(value/3600) % 24;
var minutes:uint = Math.floor(value/60) % 60;
var seconds:uint = value % 60; var result:String = "";
if (hours != 0)
result = hours + ":"; if (result && minutes < 10)
result += "0" + minutes + ":";
else
result += minutes + ":"; if (seconds < 10)
result += "0" + seconds;
else
result += seconds; return result;
} // *************** SCRUBBAR /**
* @private
* When someone is holding the scrubBar, we don't want to update the
* range's value--for this time period, we'll let the user completely
* control the range.
*/
private var scrubBarMouseCaptured:Boolean; /**
* @private
* We pause the video when dragging the thumb for the scrub bar. This
* stores whether we were paused or not.
*/
private var wasPlayingBeforeSeeking:Boolean; /**
* @private
* We are in the process of changing the timestamp
*/
private var scrubBarChanging:Boolean; /**
* @private
*/
private function scrubBar_changeStartHandler(event:Event):void
{
scrubBarChanging = true;
} /**
* @private
*/
private function scrubBar_thumbPressHandler(event:TrackBaseEvent):void
{
scrubBarMouseCaptured = true;
if (isPlaying)
{
pause();
wasPlayingBeforeSeeking = true;
}
} /**
* @private
*/
private function scrubBar_thumbReleaseHandler(event:TrackBaseEvent):void
{
scrubBarMouseCaptured = false;
if (wasPlayingBeforeSeeking)
{
play();
wasPlayingBeforeSeeking = false;
}
} /**
* @private
*/
private function scrubBar_changeHandler(event:Event):void
{
seek(scrubBar.value * 1000);
} /**
* @private
*/
private function scrubBar_changeEndHandler(event:Event):void
{
scrubBarChanging = false;
} // ************************ VOLUME private var _volume:Number = 1; public function get volume():Number
{
return _volume;
} public function set volume(value:Number):void {
if (value<0 || value>1) return; _volume = value; if (volumeBar)
volumeBar.value = value; if(!myChannel)return;
var transform:SoundTransform = myChannel.soundTransform;
transform.volume = value;
myChannel.soundTransform = transform;
} private function volumeBar_changeHandler(event:Event):void
{
if (volume != volumeBar.value)
volume = volumeBar.value;
} private var _muted:Boolean = false; public function get muted():Boolean
{
return _muted;
} public function set muted(value:Boolean):void
{
_muted = value; if (volumeBar)
volumeBar.muted = value;
if(!myChannel)return;
var transform:SoundTransform = myChannel.soundTransform;
transform.volume = muted ? 0 : volume;
myChannel.soundTransform = transform;
} private function volumeBar_mutedChangeHandler(event:FlexEvent):void
{
if (muted != volumeBar.muted)
muted = volumeBar.muted;
} }
}

Mp3PlayerSkin.mxml

<?xml version="1.0" encoding="utf-8"?>

<!---
Default skin for Mp3Player. It uses the same graphical assets as spark VideoPlayer. @see org.flashcommander.components.Mp3Player
--> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabledStates="0.5"
height="24" minWidth="100" > <fx:Metadata>
[HostComponent("ddw.adobe.Mp3Player")]
</fx:Metadata> <s:states>
<s:State name="normal" />
<s:State name="disabled" stateGroups="disabledStates" />
</s:states> <!--- @copy spark.components.VideoPlayer#playerControls -->
<s:Group bottom="0" top="0" left="0" right="0" id="playerControls"> <!--- @copy spark.components.VideoPlayer#playPauseButton默认大小24×24 -->
<s:ToggleButton id="playPauseButton" left="0" bottom="0"
skinClass="ddw.adobe.PlayPauseButtonSkin"
focusIn="event.target.depth=1" focusOut="event.target.depth=0" /> <!--把( scrubbar + the currentTime/duration labels) 组成一个group放在这个容器(Group)里-->
<s:Group left="25" right="38" top="0" bottom="0"> <!-- background for scrubbar + the currentTime/duration -->
<s:Rect left="0" right="0" top="0" bottom="0">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" />
<s:GradientEntry color="0xDCDCDC" />
</s:LinearGradient>
</s:fill>
</s:Rect> <!-- fill highlight -->
<s:Rect left="1" right="1" top="1" height="11" >
<s:fill>
<s:SolidColor color="0xFFFFFF" alpha="0.3" />
</s:fill>
</s:Rect> <!-- one pixel border -->
<s:Rect left="1" right="1" top="1" bottom="1">
<s:stroke>
<s:LinearGradientStroke weight="1" rotation="90">
<s:GradientEntry color="0xFEFEFE" />
<s:GradientEntry color="0xEAEAEA" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect> <!-- border for the scrubbar/time label controls -->
<s:Rect left="-1" right="0" top="0" bottom="0">
<s:stroke>
<s:SolidColorStroke color="0x131313" />
</s:stroke>
</s:Rect> <!-- 按照水平方向布局scrubBar+currentTimeDisplay+timeDivider+durationDisplay -->
<!-- 按照垂直方向居中布局scrubBar+currentTimeDisplay+timeDivider+durationDisplay -->
<s:Group left="0" right="0" height="23" bottom="0">
<s:layout>
<s:HorizontalLayout verticalAlign="middle" gap="1" />
</s:layout> <!-- 左边留7个像素空间
<s:Rect width="7" height="11">
<s:fill>
<s:SolidColor color="0xFF0000" />
</s:fill>
</s:Rect>--> <!--- @copy spark.components.VideoPlayer#scrubBar -->
<s:ScrubBar id="scrubBar" width="100%" liveDragging="true"
skinClass="ddw.adobe.ScrubBarSkin" /> <!-- 右边留8个像素空间
<s:Rect width="8" height="1" />--> <!--- @copy spark.components.VideoPlayer#currentTimeDisplay -->
<s:Label id="currentTimeDisplay" /> <!--- @private -->
<s:Label id="timeDivider" text="/" /> <!--- @copy spark.components.VideoPlayer#durationDisplay -->
<s:Label id="durationDisplay" /> <!-- spacer -->
<s:Rect width="8" height="1" />
</s:Group> </s:Group> <!--- @copy spark.components.VideoPlayer#volumeBar -->
<s:VolumeBar id="volumeBar" snapInterval=".01" stepSize=".01" liveDragging="true"
right="0" bottom="0"
skinClass="spark.skins.spark.mediaClasses.normal.VolumeBarSkin"
focusIn="event.target.depth=1" focusOut="event.target.depth=0" /> </s:Group> </s:SparkSkin>

PlayPauseButtonSkin.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabledStates="0.5"> <!-- host component -->
<fx:Metadata>
/**
* @copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.ToggleButton")]
</fx:Metadata> <fx:Script fb:purpose="styling">
/* Define the skin elements that should not be colorized. */
static private const exclusions:Array = ["playSymbol", "pauseSymbol"]; /**
* @private
*/
override public function get colorizeExclusions():Array {return exclusions;} /* Define the symbol fill items that should be colored by the "symbolColor" style.*/
static private const symbols:Array = ["playSymbolFill", "pauseSymbolFill1_1", "pauseSymbolFill1_2",
"pauseSymbolFill1_3", "pauseSymbolFill1_4", "pauseSymbolFill1_5",
"pauseSymbolFill2_1", "pauseSymbolFill2_2", "pauseSymbolFill2_3",
"pauseSymbolFill2_4", "pauseSymbolFill2_5"]; /**
* @private
*/
override public function get symbolItems():Array {return symbols}; /**
* @private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
</fx:Script> <!-- states -->
<s:states>
<s:State name="up" />
<s:State name="over" stateGroups="overStates" />
<s:State name="down" stateGroups="downStates" />
<s:State name="disabled" stateGroups="disabledStates" />
<s:State name="upAndSelected" stateGroups="selectedStates, selectedUpStates" />
<s:State name="overAndSelected" stateGroups="overStates, selectedStates" />
<s:State name="downAndSelected" stateGroups="downStates, selectedStates" />
<s:State name="disabledAndSelected" stateGroups="selectedUpStates, disabledStates, selectedStates" />
</s:states> <!-- layer 1: 背景但不包括边框,边框为layer 5 left="0" right="0" top="0" bottom="0"-->
<s:Rect left="1" right="1" top="1" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF"
color.overStates="0xCACACA"
color.downStates="0xA8A8A8" />
<s:GradientEntry color="0xDCDCDC"
color.overStates="0x8D8D8D"
color.downStates="0x6B6B6B"/>
</s:LinearGradient>
</s:fill>
</s:Rect> <!-- layer 2: 除了downStates状态外出现的一个像素的内边框 -->
<s:Rect left="1" right="1" top="1" bottom="1" excludeFrom="downStates">
<s:stroke>
<s:LinearGradientStroke weight="1" rotation="90">
<s:GradientEntry color="0xFEFEFE" alpha.overStates="0.22" />
<s:GradientEntry color="0xEAEAEA" alpha.overStates="0.22" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect> <!-- layer 3: 除了downStates状态外出现的上部高光 -->
<s:Rect left="1" right="1" top="1" height="11" excludeFrom="downStates">
<s:fill>
<s:SolidColor color="0xFFFFFF"
alpha="0.3"
alpha.overStates="0.12" />
</s:fill>
</s:Rect> <!-- layer 4:绘制 downStates状态下出现的内部凹陷 -->
<!--上边一个像素横线-->
<s:Rect left="1" top="1" right="1" height="1" includeIn="downStates">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.4" />
</s:fill>
</s:Rect>
<!--上边一个像素横线-->
<s:Rect left="1" top="2" right="1" height="1" includeIn="downStates">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect>
<!--左边一个像素竖线-->
<s:Rect left="1" top="1" bottom="1" width="1" includeIn="downStates">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect>
<!--右边一个像素竖线-->
<s:Rect right="1" top="1" bottom="1" width="1" includeIn="downStates">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect> <!-- layer 5: 整体边框,决定按钮默认大小 -->
<s:Rect left="0" right="0" top="0" bottom="0" width="24" height="24">
<s:stroke>
<s:SolidColorStroke color="0x131313" />
</s:stroke>
</s:Rect> <!--- 定义play 按钮.垂直居中及水平居中 -->
<s:Group horizontalCenter="0" verticalCenter="0" excludeFrom="selectedStates" id="playSymbol"> <!-- 三角形:evenOdd=奇偶缠绕类型,重叠不fill;nonZero=非零缠绕类型 ,同方向重叠填充,异方向重叠不填充-->
<s:Path winding="evenOdd" data="M 1 0 L 1 13 L 8 7 L 1 0 Z">
<s:fill>
<!--- @private -->
<s:SolidColor color="0x555555" alpha="0.75" id="playSymbolFill"/>
</s:fill>
</s:Path> <!-- triangle drop shadow on bottom/right -->
<s:Line xFrom="1" xTo="7" yFrom="0" yTo="7">
<s:stroke>
<s:SolidColorStroke color="0x000000" alpha="0.33" />
</s:stroke>
</s:Line> <!-- line on left of triangle -->
<s:Line x="0" yFrom="0" yTo="13">
<s:stroke>
<s:SolidColorStroke color="0x000000" alpha="0.5" />
</s:stroke>
</s:Line>
</s:Group> <!--- 定义 pause 按钮. -->
<s:Group horizontalCenter="0" verticalCenter="0" includeIn="selectedStates" id="pauseSymbol"> <!-- 左边竖线 -->
<s:Rect left="0" top="0" height="11" width="3">
<s:fill>
<s:LinearGradient rotation="90">
<!--- @private -->
<s:GradientEntry color="0x252525" alpha="0.75" ratio="0.1" id="pauseSymbolFill1_1"/>
<!--- @private -->
<s:GradientEntry color="0x404040" alpha="0.75" ratio="0.2" id="pauseSymbolFill1_2"/>
<!--- @private -->
<s:GradientEntry color="0x4B4B4B" alpha="0.75" ratio="0.55" id="pauseSymbolFill1_3"/>
<!--- @private -->
<s:GradientEntry color="0x424242" alpha="0.75" ratio="0.9" id="pauseSymbolFill1_4"/>
<!--- @private -->
<s:GradientEntry color="0xC4C4C4" alpha="0.75" ratio="1.0" id="pauseSymbolFill1_5"/>
</s:LinearGradient>
</s:fill>
</s:Rect> <!-- 右边竖线(left(4)+width(3)决定了pauseSymbol的宽=7) -->
<s:Rect left="4" top="0" height="11" width="3">
<s:fill>
<s:LinearGradient rotation="90">
<!--- @private -->
<s:GradientEntry color="0x252525" alpha="0.75" ratio="0.1" id="pauseSymbolFill2_1"/>
<!--- @private -->
<s:GradientEntry color="0x404040" alpha="0.75" ratio="0.2" id="pauseSymbolFill2_2"/>
<!--- @private -->
<s:GradientEntry color="0x4B4B4B" alpha="0.75" ratio="0.55" id="pauseSymbolFill2_3"/>
<!--- @private -->
<s:GradientEntry color="0x424242" alpha="0.75" ratio="0.9" id="pauseSymbolFill2_4"/>
<!--- @private -->
<s:GradientEntry color="0xC4C4C4" alpha="0.75" ratio="1.0" id="pauseSymbolFill2_5"/>
</s:LinearGradient>
</s:fill>
</s:Rect> </s:Group>
</s:SparkSkin>

ScrubBarSkin.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minHeight="14"
alpha.disabled="0.5">
<!--外观部件loadedRangeArea、playedArea不是继承Hslider,不参与自动布局-->
<!--thumb是继承Hslider不参与自动布局、track是继承Hslider参与自动布局-->
<!--通过updateSkinDisplayList()方法计算track、thumb的位置(依赖slider的value属性)来更新loadedRangeArea、playedArea-->
<fx:Metadata>
/**
* @copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.mediaClasses.ScrubBar")]
</fx:Metadata> <fx:Script fb:purpose="styling">
/* Define the skin elements that should not be colorized. */
static private const exclusions:Array = ["track", "thumb"]; /**
* @private
*/
override public function get colorizeExclusions():Array {return exclusions;} /**
* @private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
</fx:Script> <s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states> <fx:Declarations>
<!--- Defines the appearance of the ScrubBar skin's data tip. To customize the data tip's appearance, create a custom ScrubBarSkin class. -->
<fx:Component id="dataTip">
<s:DataRenderer minHeight="24" minWidth="40" y="-34">
<s:RectangularDropShadow id="shadow" distance="3"
angle="90" color="#999999" left="0" top="0" right="0" bottom="0"/> <s:Rect top="0" left="0" right="0" bottom="0">
<s:fill>
<s:SolidColor color="0x000000" alpha=".9"/>
</s:fill>
</s:Rect> <s:Label id="labelDisplay" text="{data}"
horizontalCenter="0" verticalCenter="1"
left="5" right="5" top="5" bottom="5"
textAlign="center" verticalAlign="middle"
fontWeight="normal" color="white" fontSize="11">
</s:Label>
</s:DataRenderer>
</fx:Component>
</fx:Declarations> <!--- The skin pat that defines the video timeline. The timeline shows the current playhead location
in the video, the amount of the video previously played, and the loaded in part of the video. -->
<s:Button id="track" left="0" right="0" top="0" height="11"
skinClass="ddw.adobe.ScrubBarTrackSkin" /> <!--- @copy spark.components.mediaClasses.ScrubBar#loadedRangeArea父容器的布局不影响该对象 -->
<!---->
<s:Group id="loadedRangeArea" x="0" y="0" height="11" includeInLayout="false" alpha="0"> <!-- inset 7 and 6 pixels because that's thumbSize/2 -->
<s:Group left="7" right="6" top="0" bottom="0" minWidth="0"> <!-- fill0xD7D7D7 -->
<s:Rect left="1" right="1" top="1" bottom="1">
<s:fill>
<s:SolidColor color="0xff0000" />
</s:fill>
</s:Rect> <!-- inner glow -->
<!-- set height to 100%, maxHeight=1, minHeight=0 b/c only want this line to show up
if there's room for it -->
<s:Rect left="1" top="1" bottom="1" width="100%" maxWidth="1" minWidth="0">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect>
<s:Rect left="2" right="1" top="1" height="100%" maxHeight="1" minHeight="0">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect> <!-- black line on right -->
<!-- set width to 100%, maxWidth=1, minWidth=0 b/c only want this line to show up
if there's room for it -->
<s:Rect right="0" top="1" bottom="1" width="100%" maxWidth="1" minWidth="0">
<s:fill>
<s:SolidColor color="0x000000" alpha=".5"/>
</s:fill>
</s:Rect> </s:Group>
</s:Group> <!--- @copy spark.components.mediaClasses.ScrubBar#playedArea父容器的布局不影响该对象 -->
<s:Group id="playedArea" x="0" y="0" height="11" includeInLayout="false" alpha="0"> <!-- inset 7 and 6 pixels because that's thumbSize/2 -->
<s:Group left="7" right="6" top="0" bottom="0" minWidth="0"> <!-- inner glow -->
<s:Rect left="1" right="1" top="1" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFEFEFE"/>
<s:GradientEntry color="0xECECEC"/>
</s:LinearGradient>
</s:fill>
</s:Rect> <!-- fill -->
<s:Rect left="2" right="2" top="2" bottom="2">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" alpha="0.85"/>
<s:GradientEntry color="0xE1E1E1" alpha="0.85"/>
</s:LinearGradient>
</s:fill>
</s:Rect> <!-- black line on right -->
<!-- set width to 100%, maxWidth=1, minWidth=0 b/c only want this line to show up
if there's room for it -->
<s:Rect right="0" top="1" bottom="1" width="100%" maxWidth="1" minWidth="0">
<s:fill>
<s:SolidColor color="0x131313"/>
</s:fill>
</s:Rect> </s:Group>
</s:Group> <!--- A skin part that defines a button that can be dragged along the track to increase or decrease
the playhead location in the video.父容器的布局不影响该对象 -->
<s:Button id="thumb" x="0" y="0" width="14" height="19" includeInLayout="false"
skinClass="ddw.adobe.ScrubBarThumbSkin" /> </s:SparkSkin>

ScrubBarThumbSkin.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"> <fx:Metadata>
/**
* @copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.Button")]
</fx:Metadata> <fx:Script fb:purpose="styling">
/**
* @private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
</fx:Script> <s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states> <!-- black line on top -->
<s:Rect width="1" x="7" y="0" height="7">
<s:fill>
<s:SolidColor color="0x000000"/>
</s:fill>
</s:Rect> <!-- now the base shape of the component -->
<s:Group y="6"> <!-- drop shadow for shape -->
<s:Line xFrom="4" xTo="11" y="10">
<s:stroke>
<s:SolidColorStroke color="0x000000" alpha="0.12" />
</s:stroke>
</s:Line> <!-- shape border -->
<s:Path winding="evenOdd" data="M 4 2 L 4 10 L 11 10 L 11 3 L 10 3 L 10 2 L 9 2 L 9 1 L 6 1 L 6 2 L 5 2 L 5 3 L 4 3 L 4 2 Z">
<s:fill>
<s:SolidColor color="0x000000"/>
</s:fill>
</s:Path> <!-- shape fill -->
<s:Path winding="evenOdd" data="M 5 4 L 5 9 L 10 9 L 10 4 L 9 4 L 9 3 L 8 3 L 8 2 L 8 1 L 8 2 L 7 2 L 7 3 L 6 3 L 6 4 L 5 4 Z">
<s:fill>
<s:SolidColor color="0xFFFFFF"/>
</s:fill>
</s:Path> <!-- shape fill highlight -->
<s:Path winding="evenOdd" data="M 5 4 L 5 9 L 10 9 L 10 4 L 9 4 L 9 3 L 8 3 L 8 2 L 8 1 L 8 2 L 7 2 L 7 3 L 6 3 L 6 4 L 5 4 Z">
<s:fill>
<s:SolidColor color="0xFFFFFF" alpha="0.22"/>
</s:fill>
</s:Path> </s:Group> <!-- for sizing/hit-test only -->
<s:Rect width="13" height="19">
<s:fill>
<s:SolidColor color="0x000000" alpha="0" />
</s:fill>
</s:Rect> </s:SparkSkin>

ScrubBarTrackSkin.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"> <fx:Metadata>
/**
* @copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.Button")]
</fx:Metadata> <fx:Script fb:purpose="styling">
/**
* @private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
</fx:Script> <s:states>
<s:State name="up" />
<s:State name="down" />
<s:State name="over" />
<s:State name="disabled" />
</s:states>
<!--宽高属性到父容器里去设置-->
<!-- inset 7 and 6 pixels because that's thumbSize/2 -->
<s:Group left="7" right="6" top="0" bottom="0"> <!-- fill -->
<s:Rect left="0" right="0" top="0" bottom="0">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0x7B7B7B"/>
<s:GradientEntry color="0xA2A2A2"/>
</s:LinearGradient>
</s:fill>
</s:Rect> <!-- inset shadow -->
<s:Rect left="1" right="1" top="1" height="1">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect>
<s:Rect left="1" top="2" bottom="1" width="1">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect>
<s:Rect right="1" top="2" bottom="1" width="1">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect> <!-- border -->
<s:Rect left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:SolidColorStroke color="0x131313" weight="1" />
</s:stroke>
</s:Rect> <!-- outside highlight -->
<s:Rect left="-1" right="-1" top="-1" bottom="-1">
<s:stroke>
<s:LinearGradientStroke rotation="90">
<s:GradientEntry color="0xFFFFFF" alpha="0.12"/>
<s:GradientEntry color="0xFFFFFF" alpha="0.8"/>
</s:LinearGradientStroke>
</s:stroke>
</s:Rect> </s:Group>
</s:SparkSkin>

flex-mp3的更多相关文章

  1. Flex Flash Player回声消除的最佳方法

    Adobe Flash Player 已经成为音频和视频播放的非常流行的工具.实际上,目前大多数因特网视频均使用 Flash Player观看. Flash Player 通过将许多技术进行组合可以提 ...

  2. 博客中 Flex4/Flash mp3音乐播放器实例 含演示地址

    要求 必备知识 本文要求基本了解 Adobe Flex编程知识和JAVA基础知识. 开发环境 MyEclipse10/Flash Builder4.6/Flash Player11及以上 演示地址 演 ...

  3. Flex性能优化常用手法总结 转

    转自:http://bbs.51aspx.com/showtopic-43693.html 随着Flex越来越多的被人们所熟知,越来越多的互联网也开始了RIA应用.众所周知,目前国内的宽带应用并不是像 ...

  4. 使用Flex 和 Red5开发简单视频直播功能

    Flex 是一个高效.免费的开源框架,可用于构建具有表现力的 Web应用程序,这些应用程序利用Adobe Flash Player和Adobe AIR, 可以实现跨浏览器.桌面和操作系统.虽然只能使用 ...

  5. Flex回声消除的最佳方法

    Adobe Flash Player 已经成为音频和视频播放的非常流行的工具.实际上,目前大多数因特网视频均使用 Flash Player观看. Flash Player 通过将许多技术进行组合可以提 ...

  6. Flash&Flex大全

    官方在线帮助(没标英文的都是中文) 用于 Adobe Flash Platform 的 ActionScript 3.0 参考 更多参考使这样的链接下载离线版:http://help.adobe.co ...

  7. Vue实现mp3音乐播放及动态进度条

    今天碰到一个Vue点击mp3播放及进度条动态走动的小功能,记录一下: 首先是通过HTML5 audio标签引入音频: <template> <div class="x-fo ...

  8. flex embed 使用

    Flex 软件中经常需要使用一些外部的资源,如图片.声音.SWF或字体,虽然你也可以在软件运行的时候引入和载入,但是也可能经常需要直接将这些资源编译(Compile)到软件中,也就是直接嵌入资源(Em ...

  9. OpenCASCADE Expression Interpreter by Flex & Bison

    OpenCASCADE Expression Interpreter by Flex & Bison eryar@163.com Abstract. OpenCASCADE provide d ...

  10. Flex 布局教程:语法篇

    作者: 阮一峰 网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便 ...

随机推荐

  1. java/python中获取当前系统时间,并与字符串相互转换格式,或者转化成秒数,天数等整数

    java转换成秒数 Date类有一个getTime()可以换回秒数,例如: public class DateToSecond { public static void main(String[] a ...

  2. 【编程基础】const与#define的区别

    [前言] 相信大家看别人代码的时候都遇到过,有人用#define定义,也有人用const定义. 那么两者的区别到底是什么呢?哪个更好用呢? 网上查了又查,下面总结一下. [总结] 编译器处理方式不同 ...

  3. HDU 5001-Walk(概率dp)

    题意: 给你一个图,求在长度为d的所有路径,不经过每个结点的概率 分析: 枚举每个结点,正推求概率 #include <map> #include <set> #include ...

  4. SSH超时断开(ClientAliveInterval和ClientAliveCountMax )的使用

    有 2个方法 1 配置服务器 打开 /etc/ssh/sshd_config 找到 ClientAliveInterval 参数,如果没有就自己加一行 数值是秒,比如你设置为300,就是5分钟. Cl ...

  5. 《Python基础教程(第二版)》学习笔记 -> 第八章 异常

    什么是异常 Python用 异常对象(exception object)来表示异常情况.遇到错误后,会引发异常,如果异常对象并未被处理或者捕捉,程序就会用所谓的回溯(Traceback,一种错误信息) ...

  6. Apache benchmark对网站进行压力测试

    Apache Benchmark下载:http://down.tech.sina.com.cn/page/3132.html ab 的全称是 ApacheBench , 是 Apache 附带的一个小 ...

  7. ASP.NET 日期 时间 年 月 日 时 分 秒 格式及转换

    在平时编码中,经常要把日期转换成各种各样的形式输出或保持,今天专门做了个测试,发现DateTime的ToString()方法居然有这么多的表现形式,和大家一起分享. DateTime time=Dat ...

  8. 【JSONCpp】简介及demo

    一.JSON简介 JSON 一种轻量级的数据交换格式,易于阅读.编写.解析,全称为JavsScript ObjectNotation. JSON由两种基本结构组成 ①   名字/值 对的集合,可以理解 ...

  9. 为cocos2d-x项目增加Lua支持

    开始为游戏增加Lua脚本支持,今天主要配置了一下开发环境:cocos2d-x 2.2.1,xcode5. 1. 创建cocos2d-x-lua项目 类似于创建C++项目,用以下命令即可: python ...

  10. Javascript——说说js的调试

    最近比较吐槽,大家都知道,现在web前端相对几年前来说已经变得很重了,各种js框架,各种面对对象,而且项目多了,就会提取公共模块. 这些模块的UI展示都一样,不一样的就是后台逻辑,举个例子吧,我们做企 ...