How to Build a Basic Slider Widget (AS2)

ActionScript 2.0 Flash

In reply to a request from kweku, here’s another look at the basic slider used in the two-part “How to Build a Flash Video (FLV) Progress Bar” series.  This time, the slider widget, comprised again of two movie clips, will be used to adjust the volume of an FLV video file.  The ActionScript 2.0 involved is fairly straightforward and, in fact, can be cobbled together from existing articles on this blog.  Let’s break it down. 

Building the slider itself

Refer to part 1 of the other how-to for slightly more specific detail, but in a super-quick nutshell, you’ll want two movie clips to associate with the following code:  a horizontal, thin rectangle with the instance name track (registration point in the upper left) and a small circle or almond shape with the instance name knob (registration point in the center).  Arrange those on the Stage in separate layers with the knob above the track, and positioned at track’s left edge.  Type the following into your scripts layer:

knob.onPress = function():Void {
 var vertical:Number = track._y + (track._height / 2);
 this.startDrag(
  true,
  track._x,
  vertical,
  track._x + track._width,
  vertical
 );
 this.onMouseMove = updateKnobOutput;
}
knob.onRelease = function():Void {
 this.stopDrag();
 delete this.onMouseMove;
}
knob.onReleaseOutside = knob.onRelease;

The mechanics are explained in the earlier article — but again, to recap very quickly, we’re assigning two event handlers to the knob movie clip.  When the user presses, a dragging session is begun by way of the MovieClip.startDrag() method, as invoked on knob.  Because the dragging is supposed to be constrained, five optional parameters are provided in the method.  Just prior to that, an arbitrary variable, vertical, is declared and set to the location of the track movie clip plus half its own height.  Why?  Because the expression that refers to that location is used twice in the startDrag() method, and the variable saves a bit of typing now and calculation later.

One interesting aspect, at the end of this first event handler, is that the onPress function actually defines a new event handler, MovieClip.onMouseMove.  The custom function, updateKnobOutput (yet to be written), is associated with knob by way of the global this property, which here refers to knob itself, because it appears within the function assigned to one of knob’s event handlers.  (Event handling syntax differs quite a bit in AS3, but the basic idea is essentially the same.)

A function assigned to the MovieClip.onRelease event of the knob object means that the dragging stops when the user lets go — and that onMouseMove event handler is also stopped.  The onReleaseOutside event handler is a duplicate and ensures that the onRelease function occurs even if the user releases the knob while no longer over it with the mouse.

Hold up, a sec!

If this is moving too fast, don’t lose heart.  ;)   I normally go over practically every line of code, but in this particular blog entry, I’d like to show a concept, more than anything else.  Creative problem solving is always the true puzzle to wrestle.  In this case, the concept is that of referencing one movie clip’s position in relation to another, then applying a touch of math to shoehorn that relationship into whatever use you need.  As with the progress bar in  the other article, this example also uses an arbitrarily named variable, ratio, to accomplish the key ingredient.  Put the following line above the ActionScript already shown:

var ratio:Number = track._width / 100;

The ratio variable now records the quotient (division result) of the width of the track movie clip and the number 100.  Why 100?  Well, in ActionScript 2.0, audio volume runs from zero to one hundred.  Hold that thought.  Add the following code at the bottom of the existing ActionScript:

function updateKnobOutput():Void {
 trace((knob._x - track._x) / ratio);
}

That’s the previously alluded to updateKnobOutput() function.  All it does, so far, is take the current position of knob and subtract the position of track, which effectively zeroes out knob._x when knob is on the left edge of track.  The difference of this subtraction is divided against ratio.  The result?  When knob is on the left side of track, the full expression amounts to zero.  When knob is on the right side of track, the expression amounts to approximately 100.  Currently, this result is traced to the Output panel, so you can test even without a video or audio file.

Putting it to work

At this point … well, it’s up to you.  I’m betting kweku will use the slider to adjust the volume of an FLV file.  This can be used, in its current configuration, to set the value of any object’s property that needs to fall between the range discussed.  If you play with the math a bit, you can use ratio to convert the result to a range between -100 and 100, which would allow you to use the slider to pan audio.

For panning, you might, for example, change the opening line from what it is to this:

var ratio:Number = track._width / 200;

… and change the function from what it is to this:

function updateKnobOutput():Void {
 trace(((knob._x - track._x) / ratio) - 100);
}

Sky’s the limit.  Going back to the original implementation, let’s use the math forumula to adjust the volume of an FLV file.  I’m going to breeze through this one, too, by the way, because a fuller account is spelled out in “How to Adjust the Audio Portion of Flash Video.”  The new code below expects a Video object on the Stage with the instance name videoPlayer.

var ratio:Number = track._width / 100;

knob.onPress = function():Void {
 var vertical:Number = track._y + (track._height / 2);
 this.startDrag(
  true,
  track._x,
  vertical,
  track._x + track._width,
  vertical
 );
 this.onMouseMove = updateKnobOutput;
}
knob.onRelease = function():Void {
 this.stopDrag();
 delete this.onMouseMove;
}
knob.onReleaseOutside = knob.onRelease;

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
videoPlayer.attachVideo(ns);
ns.play("externalVideo.flv");
this.createEmptyMovieClip("videoAudioContainer", this.getNextHighestDepth());
videoAudioContainer.attachAudio(ns);

var videoVolume:Sound = new Sound(videoAudioContainer);

function updateKnobOutput():Void {
 videoVolume.setVolume((knob._x - track._x) / ratio);
}

In the “How to Adjust Audio” article, the newest lines in the above sample appear almost unchanged from how you see them here.  The slider widget comes into play in that the expression (knob._x - track._x) / ratio has now been passed to Sound.setVolume(), as invoked on the videoVolume instance, as a parameter.

kewku, if you want to use one slider for volume and another as your video’s progress bar, you’ll have to give each pair of track/knob movie clips their own instance names and update the ActionScript to match.  You’ll also have to create unique ratio variables for each implementation, otherwise they’ll interfere with each other.  You might, for example, name the volume ratio ratioVolume and the other one ratioProgress.

Leave a Reply