You are viewing…

[Flash How-To] Accelerated Mousewheel Scrolling

15th May 2007 in Design, Flash, 5 comments  Share This  

Recently I have been working on a Flash project which included an XML gallery. My goal in the design was to make navigating the thumbnails and images as hassle-free and intuitive as possible. One of the interactive features is for the gallery to be scrollable via the mousewheel.

I have never really used the mousewheel features in Flash so I had to read up actionscript tutorials and do some homework. Unfortunately for me, all of the tutorials I have read online only touch on the surface, dull scrolling just by adding or subtracting delta values. What I wanted was scrolling that is like what you have in a browser. The faster you scroll, the more lines is scrolled. I couldn't find any tutorial that did that and challenging the online community didn't yield anything useful either. Perhaps it's something that is less important to people but to me it's an important interactivity aspect and I ought to challenge it.

Frankly speaking, I'm not good at mathematics. I failed terribly in secondary school. For those of you non-Singaporeans, a secondary school is the equivalent of a high school. Figuring out the code was pretty much a huge drain on my dormant left brain. I finally got it and I shall share my code in this post.

Example
Click on the flash movie to set focus.

Code

Actionscript:
  1. stop();
  2.  
  3. #include "mc_tween2.as"
  4.  
  5. var story:String = "<font size="14">Insert lots of html text here</font>";
  6.  
  7. mcText.createTextField("theText", this.getNextHighestDepth(), 0, 0, 400, 500);
  8. mcText.theText.wordWrap = true;
  9. mcText.theText.autoSize = true;
  10. mcText.theText.multiline = true;
  11. mcText.theText.html = true;
  12. mcText.embedFonts = true;
  13. var fmt:TextFormat = new TextFormat();
  14. fmt.font = "Arial";
  15. fmt.color = 0x000000;
  16. mcText.theText.setTextFormat(fmt);
  17.  
  18. mcText.theText.htmlText = story;
  19.  
  20.  
  21. // Scroll-related
  22. var totalScroll:Number = 0;
  23. var steps:Number = 0;
  24. var line:Number = 17; // 17: line-height, 3: numbers of lines to scroll
  25. var linesToScroll:Number = 3;
  26. var scrollDist:Number;
  27. var destination:Number;
  28. var maxTop:Number = Stage.height - mcText._height;
  29. var interval:Number = 100;
  30.  
  31.  
  32. function applyScroll(delta) {
  33.    
  34.     steps = Math.floor(totalScroll/delta);
  35.     scrollDist = (line * linesToScroll) * steps;
  36.    
  37.     var scrollSpeed:Number = 0.5 + 0.1 * steps;
  38.    
  39.     if(delta <0) {
  40.  
  41.         destination = mcText._y - scrollDist;
  42.        
  43.         // Ensures the scroll stays within boundaries
  44.         if(destination <maxTop) {
  45.             destination = maxTop;
  46.         }
  47.  
  48.     } else if (delta> 0) {
  49.        
  50.         destination = mcText._y + scrollDist;
  51.        
  52.         // Ensures the scroll stays within boundaries
  53.         if(destination> 0) {
  54.             destination = 0;
  55.         }
  56.     }
  57.    
  58.     mcText.ySlideTo(destination, scrollSpeed, "easeOutExpo");
  59.    
  60.     totalScroll = 0;
  61.     steps = 0;
  62.     clearInterval(applyScrollInterval);
  63. }
  64.  
  65.  
  66. var mouseLis:Object = new Object();
  67. mouseLis.onMouseWheel = function(delta) {
  68.     totalScroll += delta;
  69.     clearInterval(applyScrollInterval);
  70.     applyScrollInterval = setInterval(applyScroll, interval, delta);
  71. };
  72.  
  73. Mouse.addListener(mouseLis);

Let me break the code down into separate parts and I'll explain what each does.

Actionscript:
  1. stop();
  2.  
  3. #include "mc_tween2.as"

This stops the timeline and prevents the movie from advancing from the 1st frame. The MC Tween 2 class, which is needed for the vertical scrolling motion is included.

Actionscript:
  1. var story:String = "<font size="14">Insert lots of html text here</font>";
  2.  
  3. mcText.createTextField("theText", this.getNextHighestDepth(), 0, 0, 400, 500);
  4. mcText.theText.wordWrap = true;
  5. mcText.theText.autoSize = true;
  6. mcText.theText.multiline = true;
  7. mcText.theText.html = true;
  8. mcText.embedFonts = true;
  9. var fmt:TextFormat = new TextFormat();
  10. fmt.font = "Arial";
  11. fmt.color = 0x000000;
  12. mcText.theText.setTextFormat(fmt);
  13.  
  14. mcText.theText.htmlText = story;

A variable is set to store the text to be scrolled. In a real application, this text can come from a textfile or database.
A textfield is created within the mcText movieclip via actionscript and formatted as html. Colors and fonts are also set.
We will be scrolling the movieclip containing the textfield and not the textfield itself.

Actionscript:
  1. var totalScroll:Number = 0;
  2. var steps:Number = 0;
  3. var line:Number = 17; // 17: line-height, 3: numbers of lines to scroll
  4. var linesToScroll:Number = 3;
  5. var scrollDist:Number;
  6. var destination:Number;
  7. var maxTop:Number = Stage.height - mcText._height;
  8. var interval:Number = 100;

The variables for the scroll functions are set here.
totalScroll: We will store delta values here
steps: The number of steps (increments/decrements) to scroll
line: The line-height of the textfield. This will depend on your font-size and leading.
linesToScroll: How many lines of text to scroll per nudge of the scrollwheel.
scrollDist: How far mcText will scroll vertically.
destination: For use in MC Tween, where the tween movieclip will end up.
maxTop: The last line.
interval: How fast should the number of steps be calculated. The lower the more responsive but the CPU cannot handle anything lower than 50ms so 100ms is a good balance.

Actionscript:
  1. function applyScroll(delta) {
  2.    
  3.     steps = Math.floor(totalScroll/delta);
  4.     scrollDist = (line * linesToScroll) * steps;
  5.    
  6.     var scrollSpeed:Number = 0.5 + 0.1 * steps;
  7.    
  8.     if(delta <0) {
  9.  
  10.         destination = mcText._y - scrollDist;
  11.        
  12.         // Ensures the scroll stays within boundaries
  13.         if(destination <maxTop) {
  14.             destination = maxTop;
  15.         }
  16.  
  17.     } else if (delta> 0) {
  18.        
  19.         destination = mcText._y + scrollDist;
  20.        
  21.         // Ensures the scroll stays within boundaries
  22.         if(destination> 0) {
  23.             destination = 0;
  24.         }
  25.     }
  26.    
  27.     mcText.ySlideTo(destination, scrollSpeed, "easeOutExpo");
  28.    
  29.     totalScroll = 0;
  30.     steps = 0;
  31.     clearInterval(applyScrollInterval);
  32. }
  33.  
  34. var mouseLis:Object = new Object();
  35. mouseLis.onMouseWheel = function(delta) {
  36.     totalScroll += delta;
  37.     clearInterval(applyScrollInterval);
  38.     applyScrollInterval = setInterval(applyScroll, interval, delta);
  39. };
  40.  
  41. Mouse.addListener(mouseLis);

This is the heart of the application. Every time the mousewheel is scroll, the delta value is added to the totalScroll variable. After 100ms (1 tenth of a second), the applyScroll function is called with the parameter delta (see mouseLis part of code). From the time you first started scrolling to 100ms later when the function is called, the totalScroll value would have changed depending on how fast you spunned the mousewheel. The faster you spin, the more times the delta value is added to totalScroll.

As the mouse setting is different on every computer, the delta value will be different. So to standardize the scrolling speed, we will not be using the actual delta values but the multiples of delta values in totalScroll. This detrmines the value of steps. So let's say your mouse setting has a delta of 15. Within 100ms, you spunned the mousewheel so fast resulting in a totalScroll value of 75. It means that delta got added to totalScroll 5 times, as 75/5 = 15.

Once we have the number of steps, we can calculate how far mcText movieclip has to travel based on line and linesToSroll and in which direction (up or down) depending on whether delta is positive (downwards spin) or negative (upwards spin). scrollDist is calculated and used in the ySlideTo function provided by the MC Tween 2 class.

At the end of it, steps and totalScroll is reset to 0 and the interval is cleared. Ready for another scroll. Note that the interval is cleared both times, at the end of the function and at the start of the onMouseWheel event. This is to ensure setInterval doesn't get called more than once if you have superhuman fingers and managed to spin the mousewheel more than once within 100ms or the interval value.

Download source FLA
LINK (Flash 8, 60KB, both PC and Mac versions zipped)

I'm not so good at explaining programming logic so if you didn't get what I was writing, please feel free to download the source code and play with it. Feel free to adapt my code in your projects also. If you used it in a project, please email me a link so I can check it out.

UPDATE
As the Flash Player for Macs doesn't have support for Mousewheel events, I have updated the source code with a mac version which uses a javascript workaround. You'll also need to download the SWFMacMouseWheel class from pixelbreaker. I have tested it on Mac OS X Safari and Firefox, works fine.
To install the class, copy the "com" folder and paste it into your Actionscript 2.0 class folder. Typical paths are
Windows: Hard Disk\Documents and Settings\user\Local Settings\Application Data\Adobe\Flash CS3\language\Configuration\Classes
Macintosh: Hard Disk/Users/user/Library/Application Support/Adobe/Flash CS3/language/Configuration/Classes

5 comments/trackbacks

  • Gravtar

    Aen on May 15, 07 – 10:53 am

    Please digg the article for me if you like it. Thanks!

  • Gravtar

    Accelerated Mousewheel Scrolling Tutorial - DesignersTalk on May 17, 07 – 8:41 pm

    […] Accelerated Mousewheel Scrolling Tutorial I’ve written a short article/tut on the mechanics accelerated mousewheel scrolling in Actionscript. If you want to give your flash projects more interactivity, you should read this. FLA source is included, compatible with Macs (with SWFMacMouseWheel). [Flash How-To] Accelerated Mousewheel Scrolling — AEN DIRECT — Art Director […]

  • Gravtar

    Bruce Brandligt on Jun 04, 07 – 10:53 am

    Hey, I’ve been banging my head against the wall trying to get MouseWheel scrolling to work on the mac… I downloaded your FLA and the included SWF works fine, however, if I try to create a SWF from the FLA, it complains that the mc_tween2.as is missing and the resulting SWF file doesn’t work. I looked at the files in the Zip archive and the mc_tween2.as appears to be missing. Could you please email me the missing mc_tween2.as ? Also, you might want to add this to the Zip archive for others as well. One last thing, the scrolling text example on your site isn’t working (not a SWF)… looks like a jpeg place holder for where you were going to put the working version. Your help is greatly appreciated.

    ~bruce

  • Gravtar

    Bruce Brandligt on Jun 04, 07 – 11:06 am

    Oops… never-mind… didn’t realize this was an existing extension. Here’s the link for others that haven’t run into it yet:
    http://hosted.zeh.com.br/mctween/

  • Gravtar

    Aen on Jun 04, 07 – 11:07 am

    Hi Bruce! Sorry about not including MC Tween. You can download it at http://hosted.zeh.com.br/mctween/ Install the extension.

    The example on this page is a swf. Just that you need to click within the movie to set focus before you can scroll it. It’s a security feature of the Flash Player.

    You can go to http://blog.pixelbreaker.com/flash/swfmacmousewheel/ to see the mousewheel implementation on the mac in detail.

Leave a comment

Close
E-mail It