Adding a thumb dragger to the slider

Time to add a button to our slider that we can drag back and forth to position the playhead. To do this, we will need a button to drag. So create a button named "dragger", create a layer above the highlight layer and name it "dragger" as well, and put your new dragger button on that layer. Give it an Instance Name of "draggerBTN". We will need this to access our dragger in code to find out where it is and to move it.

For starters, we will just make it move along the slider as the sound plays. When we have that working, we will add code to let us control the sound playback by dragging the slider.

To keep the next bit of math simple when we work out where to put our dragger when the sound is playing, we need to align the registration point of the dragger with the top left of our highlight, like this:

When it is aligned, double-click on the dragger button to edit the graphics and put it where you want it. Make sure that you move all of your keyframed graphics when you do this!

Now that we have done our alignment visually, we won't have to compensate by doing weird coding! Using this approach, we don't need to add corrections to our formulas to compensate for where the registration point is for the dragger. We get rid of a lot of "+4.5" and "-5" sort of things from the code that never make sense when you go back and try to modify it later.

Flash is a visual tool: try to work visually as much as you can and only add code as a last resort.

The code we need is basically the same as the code that we used for the progress bar. We have to go up from the mover movie clip to where our sound is, work out what the current frame is as a fraction of the total frames, and calculate where that position is along our 170 wide progress bar. Once we have that value, we need to go up to our draggerBTN and move it to that position.

Time to add another function to our functions layer:

function setDraggerPosition() {
        var targetPosition = 170 * _parent._parent._currentframe / _parent._parent._totalframes;
        draggerBTN._x = targetPosition;
}

Now we need to create a dummy movie that won't be seen and will simply hold a bit of onEnterFrame code that will call our setDraggerPosition function to move our dragger as the sound is playing. So go back up to the progress-bar movie clip and create a layer named "movieMover", draw in a rectangle, convert the rectangle to a symbol (F8) named "mover".

This code needs to go on the mover movie clip to call the setDraggerPosition function:

onClipEvent (enterFrame) {
        _parent.setDraggerPosition();
}

I don't really want the mover movie clip to be visible, so let's set its Alpha to 0% in the Properties panel and we're done.

Test the movie (Ctrl+Enter). When you hit play, the slider should move across as the sound plays. We haven't got any code on the dragger yet to handle dragging: we're going to do that next! But we have a little problem when we get to the end of the sound: it loops back to the start again and continues playing. If you want to, this may be fixed by replacing the setDraggerPosition function with this code:

function setDraggerPosition() {
        var targetPosition = 170 * _parent._parent._currentframe / _parent._parent._totalframes;
        draggerBTN._x = targetPosition;
        if (_parent._parent._currentframe == _parent._parent._totalframes) {
                _parent._parent.gotoAndStop(1);
                _parent.playBTN._visible = true;
        }
}

The "if" statement checks to see if the playhead is at the end of the sound. When it gets there we put it back to the beginning and stop playing. We also show the Play button again for the visitor.

As an exercise, you could add a Loop button toggle that works similarly to the Play/Pause button. When the Loop button is active, the movie would loop continuously; when the Loop button is inactive, the sound playhead would return to the beginning of the sound and stop.

Save now.

Dragger states

Our dragger will need to perform two tasks. When the visitor is not dragging the slider control, we need to move the dragger so that it matches where the sound playhead is. When the visitor is dragging the slider control, we will need to stop playing the sound and move the sound playhead to match the movement of the slider. Let's call the first task (also known as a "state" in geek-talk) "mediaPlaying" and the second task "moveMedia".

We have already done the first bit: our dragger is being moved around when the sound is playing or paused. When we do the second bit, we need to stop moving the dragger and let the visitor do the dragging. While the visitor is dragging the slider control around, we need to work out where the dragger is and move the sound playhead to the appropriate frame.

Currently, our mover movie clip on the movieMover layer has onClipEvent code that works well for our mediaPlaying state.

The easiest way to give our slider two states is to use two frames in the progress-bar movie clip: frame 1 for the mediaPlaying state and frame 2 for the moveMedia state. If we keyframe our movieMover layer on both frame 1 and frame 2, we can have different onClipEvent code for mediaPlaying and moveMedia.

Our mediaPlaying code stays the same (it moves the dragger to a position that is appropriate for where the sound playhead is). Our moveMedia code will be new (it will move the sound playhead to a frame that is appropriate for where the dragger is dragged to).

We will give frames 1 and 2 Frame Labels so that our gotoAndStop commands that we add soon will be easier to understand. Instead of gotoAndStop(1) we will be able to write gotoAndStop("mediaPlaying") if we use labels.

How do we do this? Add a "labels" layer to the top of the progress-bar timeline.

Select frame 2 for all of the layers and do an "Insert > Frame" command (F5).

Select frame 2 of the labels layer and "Insert > Keyframe" it.

Select frame 2 of the movieMover layer and "Insert > Keyframe" it as well.

Select frame 1 of the labels layer and in the Properties panel, enter "mediaPlaying" in the text box.

Select frame 2 of the labels layer and in the Properties panel, enter "moveMedia" in the text box.

Select frame 2 of the movieMover layer and click on the mover movie clip. In the Actions panel, you should see a copy of the onClipEvent code that we entered before (the code to move the dragger to a position that is appropriate for where the sound playhead is). Select all of the code in the Actions panel and delete it. We don't want this code trying to keep the dragger in one place while the visitor is trying to drag it!

Check that the code for frame 1 of the movieMover layer is still there. Select frame 1 of the movieMover layer and click on the mover movie clip. In the Actions panel, you should see a copy of the onClipEvent code that we entered before (the code calls setDraggerPosition).

To finish this off, we need to add an "actions" layer between labels and functions. Add a keyframe to frame 2. Put a stop() command on actions frame 1. Also put a stop() command on actions frame 2. This will make sure that whenever we change state, our progress bar movie won't repeatedly play through all of our states and cause hard-to-track-down bugs.

In this section, we have only prepared our slider for the playhead positioning code. We did this by making our controller movie (movieMover) execute different code in frame 1 and frame 2. This way the ActionScript we develop in the next two sections can be simpler.