Ignorance is 9/10ths of the law

Flash AS3: dynamically draw a mask with lines

I just finished a project that allowed a user to dynamically draw lines on a chalkboard. Obviously, I used the Flash drawing API to draw the lines, but I wanted to give the lines a chalk texture. I figured it would be simple – just create a background texture that looked like chalk and use the dynamically drawn lines as a mask…

Wrong! Flash can’t use dynamically drawn lines as a mask. It can use dynamically drawn shapes (like circles and rectangles) without a problem as long as they have a fill color. Unfortunately, Flash considers all lines to be infinitely thin vectors, so they don’t work as a mask. Even if you set the lineStyle property to be really wide, Flash simply can’t use the lines to create a mask.

I figured out a relatively easy way to do this. Check out the example below:

How is this done? Essentially, you can get around Flash's issues by creating a transparent bitmap copy of your dynamically drawn lines and then using the bitmap as your mask. Do this on every frame and you have a dynamic mask using the drawing API! Of course, with Flash, there is always a catch. The catches are:

  • You must set the BitmapData properties correctly to create a transparent bitmap (download the example and check it out)
  • You must set cacheAsBitmap to true for both the new mask and the masked object or this doesn't work.

As always, I've included a source file download. I commented this one VERY thoroughly, so you should be able to implement it pretty easily. You can toggle the "enableMasking" property in the code to see the line drawing without the masking. Combine this with my earlier post on drawing smooth lines and you can make something really cool. Good Luck!

Previous

Flash AS3: The simple way to create an API reference with ASDoc

Next

Flash AS3: check if an AS3 method exists

14 Comments

  1. Tri

    I really like the effect created here
    Flash AS3: dynamically draw a mask with lines.
    Had a question regarding classes our packages (not sure which is the right term).
    the folder structure
    com/wastedpotential/MaskTestMain.as
    com/wastedpotential/MWpButton.as
    is it possible to place these scripts in the fla on a frame?
    tried to place in the first frame of the fla and got errors regarding packages

  2. admin

    It’s easy to place the scripts on the timeline. Mostly, it’s a lot of cut-and-paste. You won’t need the “package” or “class” declarations or the import statements. The main variables and the code inside the constructor (the first function in each class) simply becomes timeline code. Then cut and paste the other functions into the timeline. You will need to remove all of the “public” and “private” (you can’t declare things as public or private on the timeline). You also have to remove the class linkages from the button in the library and from the main timeline.

    BTW, a class is a single file and a package is a group of related classes. It took me a while to figure out how to program with classes, but it makes things much easier to work with – no more hunting around the timeline for some mystery snippet of code.

    Thanks,
    Andy

  3. flo

    Your source code was exactly what I was searching for – thanks alot! I want to “dig” my way through several videoclips, but I never figured out how to do this – a dynamically drawn mask is the key. keep up the great work 🙂

  4. onryou

    I am using this type of technique for a friend’s website intro, he’s a tattoo artist. I am a freelance graphic designer. The problem is that I am using the mask in conjunction with a movie clip cursor that erases the mask and reveals a tattoo. I’m trying to get the sprite to be a radial gradient instead of a circle with no feather. Can you help me, I can’t figure this out and it is the one thing that is making this look hokey. I tried messing with the GradientLine code but I can’t get it to do the same thing as what you have here, but with a feathered edge.

    Thanks.

  5. admin

    Hey, you can’t use gradients in a mask, so the gradientLine won’t help you. I think you need to approach it a different way: create a round bitmap sprite that uses a halftone-style fade. Think of it like a GIF – each pixel must be either 0% transparency or 100% transparency (because masks work the same way). Then, as you move your cursor, you are rapidly adding copies of the sprite to your mask layer. You’ll probably want to use some bitmapData techniques for performance. This is the only way you can get a gradient effect that I know of. It may still look hokey, though. You’ll just have to do some experiments.

  6. Much more Info For Me

  7. mnashwan

    Thank you it was a very helpful

  8. chris

    the object that you are revealing, does it have to be a bitmap or can I reveal a movieclip that inside has pieces. Basically the image I am revealing will be animated to flap it’s wings and fly once revealed. Also, does the code have to be on the main timeline or can it be inside the movie clip that has all the layers: the mask, drawing area, the image (in my case a movie clip with bitmap pieces inside that will be animated). I put in the code and change the instance names, but it’s not working what am I doing wrong. The image that I want to reveal is already there when I compile, as if there’s no mask. Thanks for this example, much easier than this other one that I saw, but it would be better if I could get it to work. =)

  9. admin

    The code can be inside the movieclip that contains the mask, movieclip, etc. I’m not sure if it will work with an animated movieclip under the mask. the masked object has to have cacheAsBitmap set to TRUE. As soon as your animated movieclip moves to the next frame, I *think* it turns cacheAsBitmap to FALSE, which may break it. You may be able to hack in a workaround that resets cacheAsBitmap to TRUE on every frame. If you are having problems with it, do one step at a time:
    1) move my example and the code into a container movieclip. Make sure it still works.
    2) replace my sample image with your animated movieclip. Make sure it still works.
    3) change the instance names. Make sure it still works.
    4) cut and paste everything into your project. Make sure it still works.
    5) Modify the code a little at a time to size the mask correctly, etc. Make sure it still works at every step along the way.
    You just need to make small, incremental changes and test it after each one. Then you can narrow down where you’re going wrong. If you try to make all the changes at once, it’s a lot harder to find the error.
    Good Luck!

  10. Mark

    No need to convert to a bitmap first. Just set cache as bitmap to true and it will use lines as masks.

  11. Zach

    You saved me man… Thanks a lot!!!

  12. Lisa

    Just exactly what I was looking for, most awesome! I just need to make it mask several items at once, shouldn’t be too hard to add objects to an array and loop through them setting the mask, I think it should be easy anyway, never used actions to make before.

  13. Hi, How to check whether mask completed or not?

  14. Raed

    thank you very much for sharing this example , it was very helpful 🙂
    i got a question ,, is it possible to determine when the mask fills all chunks in the stage , so that we can trigger an action once the mask is complete allover the stage ?

Powered by WordPress & Theme by Anders Norén