So now the left task is to change the logic of the latest version, to what we want it to be.
Finally, this player would be different with respect of:
1. there is no mouse_over|mouse_out event at all, because it is for touch device, then volume control needs to change, there will be no mute function, the volume slider should show/hide by touching on the sound button;
2. it will not load xml data on its own, these data would be passed;
3. auto hiding vcr will work in different way;
4. playOverlay is stick to the vcr, show or hide with it together;
Volume Function
version b.0
There is one basic method, which perform the real work to change the volume value setVol():
public function setVol($value:Number):void
{
if ($value < 0 || $value > 1)
{
$value = 0;
trace("volume input Error");
}
st.volume = $value;
ns.soundTransform = st;
vcr.volumeB.slider.bar.scaleY = $value;
vcr.volumeB.slider.handle.y = $value * (-(vcr.volumeB.slider.outline.height - vcr.volumeB.slider.handle.image.height));
if ($value != 0)
{
if ($value <= 0.33)
{
vcr.volumeB.speaker.gotoAndStop("low");
}
else if ($value <= 0.66)
{
vcr.volumeB.speaker.gotoAndStop("medium");
}
else if ($value <= 1)
{
vcr.volumeB.speaker.gotoAndStop("high");
}
}
else
{
vcr.volumeB.speaker.gotoAndStop("mute");
}
return;
}
One control logic functions as: clicking on vcr.volumeB.overlay will mute/numute the volume:
internal var muteStep:Number = 0.08;
muteTimer = new Timer(10);
muteTimer.addEventListener(TimerEvent.TIMER, muteStatus);
public function muteStatus($e:TimerEvent):void
{
var $vol:Number = NaN;
if (isMuting)
{
$vol = ns.soundTransform.volume - muteStep;
if ($vol > goalVol)
{
setVol($vol);
}
else
{
setVol(goalVol);
muteTimer.stop();
isMuting = false;
}
}
else if (isUnmuting)
{
$vol = ns.soundTransform.volume + muteStep;
if ($vol < goalVol)
{
setVol($vol);
}
else
{
setVol(goalVol);
muteTimer.stop();
isUnmuting = false;
}
}
return;
}
vcr.volumeB.overlay.addEventListener(MouseEvent.MOUSE_DOWN, volDown);
public function volDown($e:MouseEvent):void
{
if (ns.soundTransform.volume > 0)
{
unmuteVol = ns.soundTransform.volume;
goalVol = 0;
isMuting = true;
isUnmuting = false;
muteTimer.start();
}
else
{
goalVol = unmuteVol;
isMuting = false;
isUnmuting = true;
muteTimer.start();
}
return;
}
It saves the current volume value to unmuteVol, for recovery later. But it doesn't turn off the sound suddenly, that is where the muteTimer comes into play.
And another logic is to define how to show/hide volume slider, by responding on roll_over|roll_out events on vcr.volumeB:
internal var volOverTime:uint = 0;
internal var volOutTime:uint = 0;
internal var volOverTimeMax:uint = 2;
volOverTimer = new Timer(100);
volOverTimer.addEventListener(TimerEvent.TIMER, volOverStatus);
public function volOverStatus($e:TimerEvent):void
{
volOverTime++;
if (volOverTime > volOverTimeMax)
{
vcr.volumeB.slider.visible = true;
com.greensock.TweenNano.to(
vcr.volumeB.slider,
fadeDuration,
{
"alpha":fadeInAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
volOverTimer.stop();
volOverTime = 0;
}
return;
}
volOutTimer = new Timer(100);
volOutTimer.addEventListener(TimerEvent.TIMER, volOutStatus);
public function volOutStatus($e:TimerEvent):void
{
volOutTime++;
if (volOutTime > volOverTimeMax * 3)
{
com.greensock.TweenNano.to(
vcr.volumeB.slider,
fadeDuration / 2,
{
"alpha":fadeOutAlpha,
"ease":com.greensock.easing.Quad.easeOut,
"onComplete":hideVolumeSlider
}
);
volOutTimer.stop();
volOutTime = 0;
}
return;
}
public function hideVolumeSlider():void
{
vcr.volumeB.slider.visible = false;
return;
}
vcr.volumeB.addEventListener(MouseEvent.ROLL_OVER, volOver);
public function volOver($e:MouseEvent):void
{
volOverTimer.start();
volOutTimer.stop();
volOverTime = 0;
volOutTime = 0;
return;
}
vcr.volumeB.addEventListener(MouseEvent.ROLL_OUT, volOut);
public function volOut($e:MouseEvent):void
{
volOverTimer.stop();
volOutTimer.start();
volOverTime = 0;
volOutTime = 0;
return;
}
The thought of the design can be reflected with these two functionalities, the response is not occurring immediately after user event, instead, a delay is introduced vie using Timer. What we would do about this is somehow to simplify and combine them:
a. remove the logic on ROLL_OVER and ROLL_OUT events on vcr.volumeB.
b. re-define the body of volDown() method, it just toggle the visible property of vcr.volumeB.slider, means, it now responses to show/hide slider;
So, remove the codes in the above block, and get rid of variables: volOverTime, volOutTime, volOverTimeMax, volOverTimer and volOutTimer.
Then, add one method:
public function toggleVolumeSlider():void
{
vcr.volumeB.slider.visible = !vcr.volumeB.slider.visible;
return;
}
Replace volDown() definition:
public function volDown($e:MouseEvent):void
{
if (ns.soundTransform.volume > 0)
{
unmuteVol = ns.soundTransform.volume;
goalVol = 0;
isMuting = true;
isUnmuting = false;
muteTimer.start();
}
else
{
goalVol = unmuteVol;
isMuting = false;
isUnmuting = true;
muteTimer.start();
}
return;
}
with:
public function volDown($e:MouseEvent):void
{
toggleVolumeSlider();
return;
}
version b.1
All the above discussion is about show/hide volume slider. And now we take care of the function that really sets volume. There are two routines to do that, one is pressing on the slider:
internal var isMuting:Boolean=false;
internal var isUnmuting:Boolean=false;
internal var muteStep:Number=0.08;
vcr.volumeB.slider.outline.addEventListener(MouseEvent.MOUSE_DOWN, volPress);
vcr.volumeB.slider.fill.addEventListener(MouseEvent.MOUSE_DOWN, volPress);
vcr.volumeB.slider.bar.addEventListener(MouseEvent.MOUSE_DOWN, volPress);
public function volPress($e:MouseEvent=null):void
{
goalVol = vcr.volumeB.slider.mouseY / (-vcr.volumeB.slider.fill.height);
muteTimer.stop();
if (ns.soundTransform.volume > goalVol)
{
isMuting = true;
isUnmuting = false;
muteTimer.start();
}
else
{
isMuting = false;
isUnmuting = true;
muteTimer.start();
}
return;
}
When click on the slider's body, the mouse Y position will be used to calculate the goal volume value, and depends on the goal value, it might be turning up or down the volume, so different marker is reset and the left is tackled by mute timer, about it we have talked above. So, now we want to remove this behavior, remove the timer. Then, replace the body of volPress() with:
public function volPress($e:MouseEvent=null):void
{
goalVol = vcr.volumeB.slider.mouseY / (-vcr.volumeB.slider.fill.height);
setVol(goalVol);
return;
}
But we can't remove muteTimer for now.
The other one is dragging the handle, and that is simple and straightforward, it register a drag handler, it will calculate the handle's y position, and set the volume value.
We will not change it.
VCR panel and OverlayPlay showing/hiding function
version b.2
Now take a look at the logic that controls the showing/hiding of vcr.
internal var mouseStill:Number=0;
internal var mouseStillMax:Number=3;
internal var mouseTimer:Timer;
internal var hide_vcr:String="auto";
mouseTimer = new Timer(1000);
vcr.addEventListener(MouseEvent.MOUSE_MOVE, showVCR);
mouseTimer.addEventListener(TimerEvent.TIMER, mouseStatus);
mouseTimer.start();
public function hideVCR($e:MouseEvent=null):void
{
if (hide_vcr != "false")
{
mouseTimer.stop();
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeOutAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = false;
vcr.timeTotal.timeDisplay.visible = false;
}
return;
}
public function showVCR($e:MouseEvent):void
{
if (!vcr.timeCurrent.timeDisplay.visible && !(hide_vcr == "true"))
{
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeInAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = true;
vcr.timeTotal.timeDisplay.visible = true;
mouseTimer.start();
}
mouseStill = 0;
return;
}
public function mouseStatus($e:TimerEvent):void
{
if (mouseY < vcr.y || mouseY > vcr.height + vcr.y)
{
mouseStill++;
}
if (mouseStill > mouseStillMax)
{
mouseStill = 0;
hideVCR();
}
return;
}
There is one variable: hide_vcr, its initial value is "auto", and it has been reset when reading XML:
if ($xml.settings.@hide_vcr == "true" || $xml.settings.@hide_vcr == "false")
{
hide_vcr = $xml.settings.@hide_vcr;
if (hide_vcr == "true")
{
vcr.visible = false;
}
}
But there is no such field in XML, which causes it left its original value all through the run time, and all the judgement on it:
hide_vcr != "false"
!(hide_vcr == "true")
will be always evaluated as true. So, we actually remove it. And replace
public function hideVCR($e:MouseEvent=null):void
{
if (hide_vcr != "false")
{
mouseTimer.stop();
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeOutAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = false;
vcr.timeTotal.timeDisplay.visible = false;
}
return;
}
with:
public function hideVCR($e:MouseEvent=null):void
{
mouseTimer.stop();
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeOutAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = false;
vcr.timeTotal.timeDisplay.visible = false;
return;
}
replace:
public function showVCR($e:MouseEvent):void
{
if (!vcr.timeCurrent.timeDisplay.visible && !(hide_vcr == "true"))
{
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeInAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = true;
vcr.timeTotal.timeDisplay.visible = true;
mouseTimer.start();
}
mouseStill = 0;
return;
}
with:
public function showVCR($e:MouseEvent):void
{
if (!vcr.timeCurrent.timeDisplay.visible)
{
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeInAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = true;
vcr.timeTotal.timeDisplay.visible = true;
mouseTimer.start();
}
mouseStill = 0;
return;
}
And we will change the logic here, only when the video is playing, the mouseTimer works; and touch on videofg would cause vcr be showed.
So, replace:
videofg.addEventListener(MouseEvent.MOUSE_DOWN, playDown);
with:
videofg.addEventListener(MouseEvent.MOUSE_DOWN, toggleVCR);
and add toggleVCR():
public function toggleVCR($e:MouseEvent=null):void
{
if (vcr.timeCurrent.timeDisplay.visible)
{
hideVCR();
}
else
{
showVCR();
}
}
comment all:
mouseTimer.start();
change showVCR() to:
public function showVCR($e:MouseEvent=null):void
{
if (!vcr.timeCurrent.timeDisplay.visible)
{
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeInAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = true;
vcr.timeTotal.timeDisplay.visible = true;
//mouseTimer.start();
}
//mouseStill = 0;
return;
}
And now, vcr will be showed/hided by clicking on videofg, however, we want the overlay play button show/hide with vcr together. Before that, let's look at playOverlay.
version b.3
The other 3 frames are entirely redundant, remove them.
About this MovieClip, there are lines:
playOverlay.addEventListener(MouseEvent.MOUSE_DOWN, playDown);
public function playOverlayLayout():void
{
var $scale:Number;
playOverlay.scaleY = $scale = 5 * video.width / 640;
playOverlay.scaleX = $scale;
playOverlay.sXY = playOverlay.scaleX;
playOverlay.x = video.width / 2 + video.x;
playOverlay.y = video.height / 2 + video.y;
return;
}
public function disablePlayOverlay():void
{
playOverlay.alpha = 0;
hide_PlayOverlay = true;
return;
}
public function hidePlayOverlay():void
{
com.greensock.TweenNano.to(
playOverlay,
0.2,
{
"alpha":0,
"scaleX":playOverlay.sXY * 0.8,
"scaleY":playOverlay.sXY * 0.8,
"ease":com.greensock.easing.Back.easeOut
}
);
return;
}
public function showPlayOverlay():void
{
if (!hide_PlayOverlay)
{
playOverlay.icon.gotoAndStop(vcr.playB.icon.frame); // ?
com.greensock.TweenNano.to(
playOverlay,
0.2,
{
"alpha":0.75,
"scaleX":playOverlay.sXY,
"scaleY":playOverlay.sXY,
"ease":com.greensock.easing.Back.easeOut,
"overwrite":false
}
);
}
return;
}
First of all, playOverlayLayout() will be called by playerLayout():
public function playerLayout():void
{
...
playOverlayLayout();
return;
}
by videoComplete(), before calling showPlayOverlay():
public function videoComplete():void
{
...
playOverlayLayout();
showPlayOverlay();
...
return;
}
and within playDown(), before each time calling hidePlayOverlay();
public function playDown($e:MouseEvent=null):void
{
...
switch ($cs)
{
case "ready":
{
...
playOverlayLayout();
hidePlayOverlay();
...
break;
}
case "playing":
{
...
showPlayOverlay();
break;
}
case "paused":
{
...
playOverlayLayout();
hidePlayOverlay();
...
break;
}
case "complete":
{
...
playOverlayLayout();
hidePlayOverlay();
...
break;
}
default:
{
...
}
}
return;
}
It is obvious that there is no need to invoke playOverlayLayout() so many times: at the very beginning of app, after playing the video, each interchanging between play and pause, even the playOverlay its scale is based on the video's aspect ratio. Further more, we will hard code the playOverlay size, so, comment all of invocation to playOverlayLayout(), except the first one, inside playerLayout()
Well, just leave it inside playerLayout() would cause the playOverlay never show up, because playerLayout() will be called on receiving video meta data, and that would be after playDown() first execution, so the hidePlayOverlay() would arise error.
Finally, the best position to put it is in constructor. And then delete all playOverlayLayout() calls. And why not do the same to vcrLayout().
Now we would make the playOverlay show/hide with vcr together.
Remove all calls to showPlayOverlay() or hidePlayOverlay() inside playDown() method, to eliminate its current logic. In current logic, even the playOverlay is hidden, it still works, because, it just be transparent, so we need make use of its mouseEnabled property to disable/enable its function, otherwise, this function will be confused if user touch on the playOverlay area.
change:
public function hidePlayOverlay():void
{
com.greensock.TweenNano.to(
playOverlay,
0.2,
{
"alpha":0,
"scaleX":playOverlay.sXY * 0.8,
"scaleY":playOverlay.sXY * 0.8,
"ease":com.greensock.easing.Back.easeOut
}
);
return;
}
to
public function hidePlayOverlay():void
{
playOverlay.mouseEnabled = false;
com.greensock.TweenNano.to(
playOverlay,
0.2,
{
"alpha":0,
"scaleX":playOverlay.sXY * 0.8,
"scaleY":playOverlay.sXY * 0.8,
"ease":com.greensock.easing.Back.easeOut
}
);
return;
}
change:
public function showPlayOverlay():void
{
if (!hide_PlayOverlay)
{
playOverlay.icon.gotoAndStop(vcr.playB.icon.frame);
com.greensock.TweenNano.to(
playOverlay,
0.2,
{
"alpha":0.75,
"scaleX":playOverlay.sXY,
"scaleY":playOverlay.sXY,
"ease":com.greensock.easing.Back.easeOut,
"overwrite":false
}
);
}
return;
}
to
public function showPlayOverlay():void
{
if (!hide_PlayOverlay)
{
playOverlay.mouseEnabled = true;
com.greensock.TweenNano.to(
playOverlay,
0.2,
{
"alpha":0.75,
"scaleX":playOverlay.sXY,
"scaleY":playOverlay.sXY,
"ease":com.greensock.easing.Back.easeOut,
"overwrite":false
}
);
}
return;
}
and add one statement to the constructor:
playOverlay.mouseChildren = false;
And toggle its alpha with vcr:
public function toggleVCR($e:MouseEvent=null):void
{
if (vcr.timeCurrent.timeDisplay.visible)
{
hideVCR();
hidePlayOverlay();
}
else
{
showVCR();
showPlayOverlay();
}
}
Here, variable hide_PlayOverlay is redundant, its value is always false. Then remove it:
internal var hide_PlayOverlay:Boolean=false;
if ($xml.settings.@hide_handle == "true")
{
vcr.bar.scrub.alpha = 0;
}
if ($xml.settings.@hide_PlayOverlay == "true")
{
disablePlayOverlay();
}
and replace:
public function showPlayOverlay():void
{
if (!hide_PlayOverlay)
{
playOverlay.mouseEnabled = true;
com.greensock.TweenNano.to(
playOverlay,
0.2,
{
"alpha":0.75,
"scaleX":playOverlay.sXY,
"scaleY":playOverlay.sXY,
"ease":com.greensock.easing.Back.easeOut,
"overwrite":false
}
);
}
return;
}
with:
public function showPlayOverlay():void
{
playOverlay.mouseEnabled = true;
com.greensock.TweenNano.to(
playOverlay,
0.2,
{
"alpha":0.75,
"scaleX":playOverlay.sXY,
"scaleY":playOverlay.sXY,
"ease":com.greensock.easing.Back.easeOut,
"overwrite":false
}
);
return;
}
Now we want to get rid of vcr.playB, instead, apply playOverlay to replace it, add lines to change playOverlay.icon's frame when vcr.playB.icon's frame change:
switch ($cs)
{
case "ready":
{
...
playOverlay.icon.gotoAndStop("playing");
vcr.playB.icon.gotoAndStop("playing");
...
break;
}
case "playing":
{
...
playOverlay.icon.gotoAndStop("paused");
vcr.playB.icon.gotoAndStop("paused");
...
break;
}
case "paused":
{
...
playOverlay.icon.gotoAndStop("playing");
vcr.playB.icon.gotoAndStop("playing");
...
break;
}
case "complete":
{
...
playOverlay.icon.gotoAndStop("playing");
vcr.playB.icon.gotoAndStop("playing");
...
break;
}
default:
{
trace("ERROR: " + currentStatus);
}
}
these lines are in playDown(), and do the same to videoComplete();
and remove other lines operating on vcr.playB. Then remove it from the stage.
public function CirclecubeVideoPlayer()
{
...
vcr.playB.visible = false;
...
vcr.playB.addEventListener(MouseEvent.MOUSE_DOWN, playDown);
...
}
public function vcrLayout():void
{
...
vcr.playB.visible = true;
vcr.playB.myWidth = 20;
...
vcr.playB.x = 10;
vcr.playB.y = 0;
}
public function initColors():void
{
...
Color_cc.setColor(vcr.playB.icon, color_light);
...
}
And the vcr has the same problem as playOverlay, so we should use mouseChildren to make sure it works correctly:
public function hideVCR($e:MouseEvent=null):void
{
//mouseTimer.stop();
vcr.mouseChildren = false;
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeOutAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = false;
vcr.timeTotal.timeDisplay.visible = false;
return;
}
public function showVCR($e:MouseEvent=null):void
{
if (!vcr.timeCurrent.timeDisplay.visible)
{
vcr.mouseChildren = true;
com.greensock.TweenNano.to(
vcr,
fadeDuration,
{
"alpha":fadeInAlpha,
"ease":com.greensock.easing.Quad.easeOut
}
);
vcr.timeCurrent.timeDisplay.visible = true;
vcr.timeTotal.timeDisplay.visible = true;
//mouseTimer.start();
}
//mouseStill = 0;
return;
}