How to Build a Basic Slider Widget (AS2)

Flash ActionScript 2.0

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.

43 Responses to “How to Build a Basic Slider Widget (AS2)”

  1. kweku Says:

    David,

    thanks a lot for this great tutorial.

  2. kweku Says:

    hi David,

    i forgot to ask you this. is it possible to add mute/unmute buttons along side this volume slider to control the video’s sound?

    many thanks.

  3. David Stiller Says:

    kweku,

    Sure thing! I know you’re interested in learning how to make a toggle button, and I have that on my to-do list for the blog as well, but for the time being, consider two buttons. Each button would have to do two things: a) set the volume appropriately and b) move the knob movie clip. Using the suggested instance names above, you might try …

    btnMute.onRelease = function():Void {
      videoVolume.setVolume(0);
      knob._x = track._x;
    }
    
    btnUnMute.onRelease = function():Void {
      videoVolume.setVolume(100);
      knob._x = track._x + track._width;
    }

    Ah, but actually, that’s not quite good enough, yet. The user may have dragged the slider somewhere other than 100 before using the buttons. If the user had dragged the slider to 50%, for example, the above unMute button would raise the volume to 100% again. To remedy that, you might create a new variable altogether, volumeLevel, and have the updateKnobOutput() function update that in addition to what it currently does. That way, your new unMute code could be updated like this:

    btnUnMute.onRelease = function():Void {
      videoVolume.setVolume(volumeLevel);
      knob._x = track._x + volumeLevel * ratio;
    }
  4. kweku Says:

    THANKS a lot David, you’ve always been my savior. Wishing you the best of luck as a Jugde in the upcoming Flash Forward Festival.

  5. David Stiller Says:

    kweku,

    Hey, thanks! If you’re at Flashforward this year, make sure to say hi.

  6. Oscar Says:

    Youre the man! Thanks!

  7. David Stiller Says:

    Oscar,

    Thanks!

  8. kweku Says:

    wow, wish i could be there but i live in Ghana and will be kind of hard for me to come over. thanks for everything David. All the best.

  9. kweku Says:

    Hi David,

    Please help me with this. In Flash, is there a way of embedding titles and graphics in FLV, while stilling using NetStream? I believe you understand what I’m trying to explain.

    Or if you could help me with an apprioprate software that can import FLV and work on them. I understand After Effects CS3 can but is too expensive.

    Thanks.

  10. David Stiller Says:

    kweku,

    Wow, Ghana is certainly far from Virginia Beach (or anywhere else in this country)! The closest I’ve been to your country was Tunisia, just over a year ago. I loved it. Who knows, maybe we’ll meet some day after all. ;)

    Flash CS3 makes what you’re describing very easy (titles, subtitles, closed captions, and the like), but it’s certainly possible in previous versions of Flash. Your best bet is to use cue points — with either the FLVPlayback Component or the Video object/NetStream approach — and include the desired text as a parameter of each cue point (empty strings to indicate the end of a span of text), then populate the TextField.text property of a dynamic text field in response to your cue point handler.

    My next blog entry will be the pause/play button you’ve been asking for, and I’ll add a titles tutorial to the list. Let me know if I’m misunderstood what you’re asking for.

  11. kweku Says:

    Hi David,

    If this approach will help embed the titles in my FLV files, then that’s exactly what I’m refering to. Anyway I’ll give it a try and see what happens. I’ll also wait for the upcomming blogs.

    Thanks for everything.

  12. David Stiller Says:

    kweku,

    Aha. Well, if you want to actually embed titles (or any other visuals) directly into your FLV files, you’ll have to do that with a video editor during the original processing of your video. That would mean Premiere, After Affects, Final Cut Pro, etc. That said, because of its layered nature, and because videos are manipulable in Flash like movie clips, Flash can superimpose graphics and text over FLVs in a synchronized manner, thanks to cue points.

  13. kweku Says:

    ok David,

    I’ll be working on that and many thanks. best regards.

  14. freelancebloke Says:

    Hi David
    Just like to say that your blog has really helped me out, many thanks.

    Kevin

  15. David Stiller Says:

    Kevin,

    Glad to hear it. :)

  16. kweku Says:

    hi David,

    it’s been a while, I’ve been a bit busy with my flash studies. I just want to know if you could make the volume slider behave like YouTubes’s. When someone mutes and unmutes the volume, the knob moves to where it was before it was muted.

    But in our case it kind of moves to a fixed point. Maybe you could compare this to youtube and you’ll understand what I’m trying to get at. If only your coding support that, then please help me out.

    Many Thanks.

  17. David Stiller Says:

    kewku,

    To achieve what you’re aiming for, you’ll have to create another couple variables: one to store the fact that volume either is or isn’t currently muted and another to store the last position of the knob. In addition to the existing code above, add something like the following:

    var isMuted:Boolean = false;
    var prevVolume:Number = 0;
    mute.onRelease = function():Void {
      if (isMuted) {
        isMuted = false;
        knob._x = prevVolume;
      } else {
        isMuted = true;
        prevVolume = knob._x;
        knob._x = track._x;
      }
    }

    The isMuted variable is a Boolean (true/false) and starts out as false — after all, volume isn’t muted yet. The prevVolume variable is initialized to zero. Assuming the instance name of your mute button is mute, you’ll see that its Button.onRelease event is handled to perform the following routine: a) check if volume is currently muted; b) if so, set isMuted back to false and set knob’s horizontal position back to what it was before, which is stored in the prevVolume variable; c) otherwise, set isMuted to true, set the value of prevVolume to whatever knob’s horizontal position is at that moment, and set knob’s current position to the left edge (or wherever) of track.

    In addition to the above snippet you will, of course, have to add the appropriate Sound methods to adjust the volume.

  18. kweku Says:

    ok david thanks a lot for your time and everything. i’ll give a try.

    many thanks!!

  19. Chad Says:

    Hey David,

    I am trying to build a basic volume slider just like the one you’re talking about here in your blog, but it is a vertical slider. With all the _x and _y and startDrag stuff you have in here, it’s not as easy as it looks to convert this to a vertical slider bar.

    Would you be willing to help me a little with making the actionscript work with a vertical bar?

  20. David Stiller Says:

    Chad,

    The constraint parameters of the MovieClip.startDrag() method are: left, top, right, and bottom, so for a vertical slider, the dragging portion might look like this:

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

    And to suit, the updateKnobOutput() might look like this:

    var ratio:Number = track._height / 100;
    
    function updateKnobOutput():Void {
      trace(100 - (knob._y - track._y) / ratio);
    }

    Notice that the ratio variable is not based on height rather than width, and the sample trace() statement notes vertical position rather than horizontal. As shown, that slider would be 100% when the knob is at the top and 0% when the knob is at the bottom. If you wanted to reverse that, you could remove the expression 100 - immediately inside the trace() statement.

  21. Chad Says:

    Awesome, thanks for the response!

  22. Chris Says:

    Hello David! I LOVE your blog, thanks for all the great tips you’ve supplied. I have a volume question :)

    I have a SWF that plays a component-based FLV. I also have a SWF with a volume slider based on your sample provided. What I need to do is keep the SWFs separate files, and have the volume slider SWF control the volume of the FLV SWF. Any thoughts? I just can’t get it working.

    thanks! Chris

  23. David Stiller Says:

    Chris,

    Thanks for the kind words! :)

    To control audio in AS2, you’ll need to associate your Sound instance with a particular MovieClip instance (there isn’t a formal SoundChannel class until ActionScript 3.0, so movie clips are your channels until then). If you use the main timeline as your MovieClip instance, you can control the volume for the whole SWF — but it sounds like you want to control the video separately. If you’re using the FLVPlayback component, you can even use the component as your movie clip, because FLVPlayback inherits from MovieClip.

    I see you’ve already checked out “How to Adjust the Audio Portion of Flash Video,” but that’s not the way to do it for FLVPlayback. For your component use the ideas covered in “Understanding the Sound Constructor” and use the FLVPlayback instance as your movie clip parameter in the Sound constructor.

    See if that gets you started, and come back if you need additional help.

  24. Chris Says:

    Hi Dave,

    Sorry I’m stuck…I am a graphic designer by trade and so far haven’t been able to wrap my head around the concept yet. The way my file is built, I have a video component playing my flv files, but it is called from a variable set in my HTML.

    In your code example, it is looking for a specific flv name in the NetConnection command. I guess I am wondering also what the code would be for establishing my sound object on frame 1, and for my volume slider on frame 20. I just can’t seem to make that connection!

  25. Chris Says:

    Hi again Dave-

    I was able to make the connection between the slider and the FLV component’s audio. My final (hopefully!) task is now to make the slider function with selectable volume “zones” of 0%, 25%, 50%, 75% and 100%. I’m sure that won’t be covered here but thanks for helping me get this far!

    chris

  26. David Stiller Says:

    Chris,

    I was able to make the connection between the slider and the FLV component’s audio.

    Hey, good for you!

    My final (hopefully!) task is now to make the slider function with selectable volume “zones” of 0%, 25%, 50%, 75% and 100%.

    That’s a good question, Chris. That posed a fun challenge to solve, actually. :) In order to make your slider snap to increments, you’ll need to do away with the automatic startDrag() behavior. Instead, you can handle the mouseMove event to update the _x (or _y for vertical) property of the knob. Here’s a revision of the above code — without snapping yet — that shows how to “drag” without using MovieClip.startDrag().

    knob.onPress = function():Void {
     this.onMouseMove = drag;
    }
    knob.onRelease = function():Void {
     delete this.onMouseMove;
    }
    knob.onReleaseOutside = knob.onRelease;
    
    function drag():Void {
      if (
        track._xmouse >= 0 &&
        track._xmouse <= track._width
      ) {
        this._x = track._x + track._xmouse;
        updateAfterEvent();
      }
    }

    This makes use of a custom function drag(). Pressing on knob with the mouse activates this function as the mouse moves; releasing unassigns the function. The if statement in the drag() function checks if the mouse is within bounds, based on the MovieClip._xmouse property for the track. If the mouse is over the left edge of the track, track’s _xmouse value is 0; if the mouse is over the right edge, the _xmouse value is whatever track’s width is.

    So … if that’s true, knob’s _x property is set to whatever track’s _xmouse value is. With me so far? Now, in order to snap to increments, I chose to resolve the issue with another custom function, snapTo(), which accepts three parameters: the current value of _x, the total span of the draggable area, and the percentage desired. I’m going to just paste the code for now, but this would probably make a good blog article on its own.

    knob.onPress = function():Void {
     this.onMouseMove = drag;
    }
    knob.onRelease = function():Void {
     delete this.onMouseMove;
    }
    knob.onReleaseOutside = knob.onRelease;
    
    function drag():Void {
      if (
        track._xmouse >= 0 &&
        track._xmouse <= track._width
      ) {
        this._x = track._x + snapTo(
          track._xmouse,
          track._width,
          25
        );
        updateAfterEvent();
      }
    }
    
    function snapTo(input:Number,
                    span:Number,
                    per:Number):Number {
      var inc:Number = Math.round(span*per/100);
      var len:Number = Math.round(100/per);
      for (i:Number = 0; i < len; i++) {
        if (input < inc/2) return 0;
        if (
          input >= (inc*i - inc/2) &&
          input < (inc*i + inc/2)
        ) return inc*i;
      }
      return span;
    }

    The third parameter, 25, means your slider will snap to five places: 0, 25, 50, 75, and 100 percent of the width of your track. A value of 33 would snap to four places: 0, 33, 66, and 99 (actually, 100) percent of the width. Any value higher than 50 will turn the slider into a switch: 0 or 100 percent of the width.

  27. Chris Says:

    Wow great job! Thanks again for the explanations, it really helps (vs. just posting a block of code).

  28. David Stiller Says:

    Chris,

    Sure thing! :) When I was starting, I had a hard time with the block-of-code answers, too. Mostly, I just try to answer questions the way I would have wanted them answered myself.

  29. Melissa Says:

    Hi there Dave,
    Awesome site!
    I am a total beginner in Flash and have just about completed my first project…My problem is that I just can’t seem to figure out how to make play and stop buttons control a movie clip symbol.
    What is the best way to bring in wmv files and be able to control them (with like play and stop buttons,etc.)? [AS2/CS3]
    What action script should be applied to the play/stop buttons and the video itself (I currently have my imported/embedded video created as a movie clip symbol, and for the moment have it playing when the scene starts).
    Thanks for your time!

  30. David Stiller Says:

    Melissa,

    For videos of any substantial length (for example, longer than a few seconds), I definitely recommend that you use either the FLVPlayback component or the Video object/NetConnection/NetStream approach suggested elsewhere on this blog.

    That said, there’s certainly nothing wrong with importing WMVs and putting them in movie clip timelines. It’s just that you may run into timing issues between the framerate of the video and the framerate of your FLA — and videos displayed in this way fall completely under the auspices of the MovieClip class. In a sense, that makes things easier, because movie clip timelines are less complicated than the NetStream class.

    The movie clip that holds your video will need an instance name. Select the movie clip on the Stage and look to the Property inspector to do that. This allows that movie clip to be addressed by name and told what to do. The available instructions are listed in the MovieClip class entry of the ActionScript 2.0 Language Reference. The MovieClip.play() method, for example, tells a movie clip to play.

    myVideoHolderClip.play();

    You’ll see other methods that allow you to stop and jump around. The trick is, classes define objects, so class entries are a kind of Owner’s Manual for the object at hand (in this case, movie clips). Characteristics of the object are called properties, things it can do are called methods, and things it can react to are called events.

    Give you buttons instance names as well, and they can also be programmed. Your code will go in a keyframe, and you’ll look to the Button class to see what events are available for button symbols.

    playButton.onRelease = function():Void {
      myVideoHolderClip.play();
    }
    stopButton.onRelease = function():Void {
      myVideoHolderClip.stop();
    }
  31. Melissa Says:

    Thank you, David, for the quick response!

    Great information.
    I had attempted something like this before to no avail, thanks for clarifying I was on the right track; I think I may just be adding the buttons in the wrong area.
    My movie clip instsance name is everydayMovie, and my stop and play button instances are named playEveryday and stopEveryday.

    Where do I drag the buttons in from the library? Do I double click the movie clip and drag them in during its edit mode? Or do I need to add them to the main stage of my scene?
    What action script needs to be within the movie clip?
    Does the action script for the buttons need to be in the first and last keyframes of that layer so that they are available throughout the movie playing?
    Can a seek bar work the same way?

    Sorry for the barrage, I’ve just been working on this for 6 days straight and feel like I am so close.

    Thank you a million times over for your time and your expert advice!
    :)

  32. David Stiller Says:

    Melissa,

    Where do I drag the buttons in from the library?

    Flash is very flexible about this. The key is to give each button an instance name (again, see the Property inspector while you have a button selected), then use that instance name in a valid object reference in order to tell it what to do. Think of object references like folders on your hard drive. If you were in the root of your computer (usually C:\ on Windows machines), how would you have to travel in order to get to a particular file?

    If your code is in a keyframe of the main timeline and your buttons are also in the main timeline, the object reference would simply be the instance name of a given button. If those buttons were inside a movie clip symbol, that movie clip would also have to be given an instance name — and the your object reference would be the movie clip’s instance name, then a dot, then the button’s instance name. Make sense?

    Do I double click the movie clip and drag them in during its edit mode? Or do I need to add them to the main stage of my scene?

    Wherever you decide to put them, just make sure you use the correct object reference from the point of view of the ActionScript that speaks to them. I personally tend to put 99% of my ActionScript in a layer of its own (named “scripts”) in the main timeline.

    What action script needs to be within the movie clip?

    None. You could put your code in the movie clip, but that would the “point of view” of that code and might affect your object references.

    Does the action script for the buttons need to be in the first and last keyframes of that layer so that they are available throughout the movie playing?

    Think of your timeline like a grid with rows (horizontal) and columns (vertical). Keyframe ActionScript needs to be in the same column as the object(s) it’s trying to talk to. If your buttons span from frame 5 to frame 50, you would put your button event handlers into a keyframe of your scripts layer on frame 5 (the first frame that “meets” the buttons on a vertical column).

    Can a seek bar work the same way?

    The slider widget described in the blog entry works by the same principles of code “point of view” (that is, object references and where each object is in relation to other objects it needs).

    Does that help? :)

  33. Melissa Says:

    David,
    Thank you for all of this detailed information, it all certainly helps!
    Unfortunately I did not get my buttons to work yet.
    I used the script you posted for me above for each button (substituting of course the correct instance names for the button and the clip), but I keep getting a compiler error msg about ‘expecting the on event handler’.
    I think I will try creating a brand new project and brand new buttons and going from there with what you have given me.
    It may just come down to something I am overlooking in my current project. I will come back crying to you if I can’t get it to work in a brand new one! :) Thanks again….we are so fortunate to have access to brilliant people miles away….

  34. David Stiller Says:

    Melissa,

    If you’re seeing something about the on event handler, my guess is that you’ve placed your code on the buttons themselves, rather than in a timeline keyframe. The Actions panel updates its focus depending on what you’ve selected when you start typing. In pre-AS3 documents, you can select objects (buttons, movie clips, components) and add code directly to the object — in which case you don’t need instance names because Flash already knows which object(s) you mean.

    Because you’re using instance names (the more modern, and Adobe-recommended, approach), you’ll need to remove that code from the buttons. See if my museum pieces article helps you out. Chin up!

  35. Chris Says:

    Hi again Dave-

    I have successfully implemented the volume slider on my page with your suggestions, thanks again! Works great on a single HTML page.

    I’ve encountered a situation in my application where my SWF needs to be loaded into a sequence of HTML pages, and the volume slider value is getting reset to 100% with each new load. I currently have a single SWF that has an FLV component (plus the slider code), the FLV file name itself is set via a variable so the name of the file is called inside the HTML page.

    I need to find a way to have the slider value carry from page to page as the SWF is loaded and show the slider in that “variable” position.

    I’ve looked into using a shared object but I am unable to have it affect the volume slider. It keeps setting the volume to 100% when it’s loaded. Any suggestions, or is the shared object not the way to go?

    Thanks!! Chris

    I will need to carry over the current volume setting and slider position

  36. David Stiller Says:

    Chris,

    The SharedObject class is exactly the solution I was going to suggest! :) Have you made a few small tests first, just to make sure you’ve got the hang of how it works? You can use SharedObject to carry over whatever data you want, but because you’re also dealing with FLVPlayback and other ActionScript, there might simply be too much going on for you to see clearly what you’re dealing with. (I do this all the time! Then I have to remind myself to slow down, isolate the new idea in a completely new FLA [or set of FLAs] and take small steps until I understand exactly what the new code does.)

    You might very well be carrying over the volume, but not retrieving it correctly from the next page — or maybe you’re not carrying it over, and the 100% winds up occurring because it’s default.

    For every page that has this slider, you’re going to want to: a) use ShareObject.getLocal() to check for the existence of your “Flash cookie”; b) if a cookie exists, use the volume setting from that or an arbitrary default; and c) in addition, use the same getLocal() method whenever the slider sets the volume, then follow that with flush(), to make sure the cookie does get created and set immediately.

  37. shrikant Says:

    Hi David,

    I am beginner in flash, i am working on one flash video player. In that i want to run 10 flv on one same seek bar continually like one FLV. Is there any solution?

    can i join the 10 flv to produce one flv as a result, if yes please help me

  38. David Stiller Says:

    shrikant,

    Someone else recently asked me the same question, and it’s a good one. I told the other reader I would add this question to my to-do list (and I have!), but I don’t know when I’ll get the chance to write about that particular one. I’m in the middle of a new book for O’Reilly (as of Feb 2008) and have been falling behind on everything else!

  39. mike simpson Says:

    Because i’m very new to AS i have found this blog to be an incredible source of knowledge so firstly thank you to David.

    I’m surprised i can’t find the answer to my issue here already.

    I’ve been using this blog/thread to work out how to control a volume knob for my FLV player and to work out how to control a mute button.
    Thanks to this thread and others i have a working fader and had managed to have a mute button that toggles on and off and puts the fader knob back to the correct place when toggled back off etc…

    If i mute my audio then i drag the slider the audio responds as i would like HOWEVER…my mute button does not respond on the first click but does if it is clicked a second time.

    I’m guessing this is because i have some code in the wrong place or just got something horribly wrong!

    I’d really appreciate some help and expect this to be useful for others too if they are having the same problem.

    hers my code i hope:

    // sound control starts here
    _root.createEmptyMovieClip(”vSound”,_root.getNextHighestDepth());
    vSound.attachAudio(ns);

    var so:Sound = new Sound(vSound);

    so.setVolume(50);
    // set initial volumeknob position to half way along track
    // ****
    volumeknob._x = track._x + (track._width/2)
    volumeknob._y = track._y

    // trace various positions to check position of volumeknob compared to track
    trace(track._x);
    var trackpositionr:Number
    trackpositionr = (track._x + track._width);
    trace(trackpositionr);
    // trace the sidth of track and store in var
    trace(trackpositionr - track._x);
    var trackwidth = (trackpositionr - track._x);
    // these next two values should be the same if all is well
    trace(track._x + trackwidth/4);
    trace(volumeknob._x);
    // ****

    // slider sound controls start here i hope
    var ratio:Number = track._width / 100;

    volumeknob.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;
    // make “mute” state display the not muted position because the volumeknob as ben moved
    mute.gotoAndStop(”on”);
    }

    volumeknob.onRelease = function():Void {
    this.stopDrag();
    delete this.onMouseMove;

    // set preVolume to equal the volumeknob current position value so that
    // if “mute” is depressed again the volumeknob doesn’t get altered
    // not sure if this is the correct way of implementing but it seems to work
    prevVolume = volumeknob._x;
    }

    volumeknob.onReleaseOutside = knob.onRelease;

    function updateKnobOutput():Void {
    so.setVolume((volumeknob._x - track._x) / ratio);

    }
    // slider sound controls end here

    // ****
    // new mute on or off starts here

    var isMuted:Boolean = false;
    var prevVolume:Number = 0;
    mute.onRelease = function():Void {
    if (isMuted) {
    isMuted = false;
    volumeknob._x = prevVolume;
    so.setVolume((volumeknob._x - track._x) / ratio);
    mute.gotoAndStop(”on”);

    }
    else {
    isMuted = true;
    prevVolume = volumeknob._x;
    volumeknob._x = track._x;
    so.setVolume((volumeknob._x - track._x) / ratio);
    mute.gotoAndStop(”mute”);
    }
    }

    // me trying to get the rollover states of mute working again
    // ****
    // this was the code for the mute prior to having a volume slider
    // with code that automatically turned the mute on or off and
    // reset the position of the volumeknob when pressed
    // ****
    //mute.onRollOver = function() {
    // if(so.getVolume()== 100) {
    // this.gotoAndStop(”onOver”);
    // }
    // else {
    // this.gotoAndStop(”muteOver”);
    // }
    //}

    //mute.onRollOut = function() {
    // if(so.getVolume()> 100) {
    // this.gotoAndStop(”on”);
    // }
    // else {
    // this.gotoAndStop(”mute”);
    // }
    //}
    //
    //mute.onRelease = function() {
    // if(so.getVolume()== 100) {
    // so.setVolume(0);
    // this.gotoAndStop(”muteOver”);
    // }
    // else {
    // so.setVolume(100);
    // this.gotoAndStop(”onOver”);
    // }
    //}
    // ****

    // mute on or off ends here
    // ****
    // Still need to check when mute is on so that if it is and the volumeslider is moved
    // the “mute” button movie clip moves to the “on” label therefore displaying
    // the mute off state
    // ****

  40. mike simpson Says:

    I forgot to add…

    my mute button has four different state with frame labels for each and a stop action in frame 1. labels are as follows:
    on, onOver, mute and muteOver

    i would like to be able to control the playhead for the mute movieclip position via the AS. I hope that makes sense and sorry for not mentioning the movieclip before, (although i guess you may have spotted what i was doing/trying to do.)

    Thanks in advance for any help,

    Mike

  41. David Stiller Says:

    mike,

    I read through the relevant parts of your code (at least, what I thought would be relevant!), and it looks all right so far. Granted, it’s the end of a long day for me. ;) I do notice you have an if statement in the mute button’s event handler, so that means it isn’t just a click-and-respond item: there’s some decision-making involved, and that might lead to what you’re seeing.

    Do you know about the trace() function? That might really come in handy for you, because it lets you see what’s going on under the hood. It’s one of those very lightweight, but indispensable, tools that eventually become a consistent part of your everyday workflow.

    The first thing you’ll want to do, as you begin troubleshooting, is get into the habit of questioning your assumptions. It seems like the button doesn’t respond on the first click — but are you sure? (You might actually be right; if so, there’s a reason for the necessary second click … but you might just as well have misjudged something, and trace() will help you track down whatever’s unclear.

    All trace() does is send message to your Output panel, but that’s a useful thing. Pop that function into your event handler just prior to the if:

    mute.onRelease = function():Void {
      trace("mute button clicked")
      if (isMuted) {
        isMuted = false;
        // ...

    … that’ll tell you right off the bat if the button does (or does not) respond to the first click. If it does, you’ll see the phrase “mute button clicked” in the Output panel, even if nothing else seems to happen. At that point, you can start tracing other values, such as variables like isMuted, to start poking around even more.

    I confess, I didn’t pore through every line of your code carefully, but a couple probably unrelated things jumped out at me: a) you probably don’t want to send mute’s timeline to a frame in response to an onMouseMove event, simply because that event can fire hundreds of times in succession (seems like all you really need to do is invoke that gotoAndStop() method once, during the course of the onPress handler you’re already in, and b) in one of your commented mute button event handlers, you’re checking of so’s volume is greater than 100. In theory, it should only ever fall between 0 and 100, so you might want an >= comparison there instead.

  42. mike simpson Says:

    HI David,

    Thanks for taking a look at this and making me dig around a bit more…it’s good to learn that way and i like the challenge.
    I do know about the trace function and have used it in other parts of my code but hadn’t actually thought of using it to check when the button had been pressed.

    Also, thanks for the pointer on the onMouseMove event….makes perfect sense.

    Sorry the code was so long but i just copied and pasted it as it stood and there’s a lot of comments and old code in there for me to be able to see what’s going on.

    watch this space please and thanks again.

    Mike

  43. mike simpson Says:

    On Second thoughts….

    the onMouseMove event is to make the volume “knob” appear at the correct position along the “track” - this needs to update whenever the “knob” moves so it seems logical to use the onMouseMove event…please correct me if i’m missing something here.

    However - It appears that the mute button does work i.e. i have traced to see if it knows it has been clicked and it does. I’m gonna take a while to work out what it is that doesn’t work though!

    Mike

Leave a Reply