Adobe
製品
Creative Suiteファミリー
Photoshopファミリー
Acrobatファミリー
Flash Platform
Digital Marketing Suite
Digital Enterprise Platform
Digital Publishing Suite
その他の製品一覧
ソリューション
コンテンツオーサリング
教育
金融機関
デジタルマーケティングソリューション
その他のソリューション
ラーニング サポート ダウンロード 会社情報
ご購入
アドビストア安心のサポート& サービス
アカデミック版のご購入学生、教職員、個人
ライセンスのご購入企業、教育機関、官公庁
販売パートナー
検索
 
情報 サインイン
ようこそ、 カート 注文状況 ユーザー登録
マイアカウント
サインアウト
サインインの目的 お客様のアカウントや体験版ダウンロード、製品の拡張機能、コミュニティエリアへのアクセスなどを管理するため
Adobe
製品 セクション   検索  
ソリューション 会社情報
サポート ラーニング
サインイン ようこそ、 注文状況 ユーザー登録
Qty:
Subtotal
Checkout
Adobe Developer Connection / Flashデベロッパーセンター /

Creating movie clips with reflections in ActionScript 3.0

著者 Ben Pritchard

Ben Pritchard
  • pixelfumes.com

Modified

23 July 2007

ページ ツール

Facebookでシェア
Twitterでツイート
LinkedInでシェア
ブックマーク
印刷

Tags

必要条件

この記事に必要な予備知識

This article is intended for Flash developers who have an intermediate to advanced understanding of ActionScript 2.0 or 3.0 and also of ActionScript classes.

ユーザーレベル

中級

必要な製品

  • Flash Professional (Download trial)
  • Flash Player

サンプルファイル

  • reflect_class_as3.zip (4 KB)

You're probably aware of those nice reflections appearing in some of the latest websites, online ads, and even software. It's an effect common to "Web 2.0" designs, in which something like an album cover or video player appears to reflect some sort of virtual floor beneath it. This tutorial steps you through the creation of the Reflect class, a custom ActionScript 3.0 class that you can apply to reflections on movie clips (and use to modify them) in your Flash CS3 Professional projects.

The Reflect class is intended for any developer or designer who would like to achieve an effect that gives a great impact to your design, but with little effort. Typically it would take a fair amount of effort to manually create reflections in your Flash files. This task would likely involve copying and pasting a clip and then modifying it to achieve the look of the reflection. Every time a change was made, you would need to update your effect. If you had an animated clip or video that you wanted to reflect, it might become completely unfeasible or even impossible. However, the Reflect class allows you to apply the reflection only once because it dynamically updates itself as a true mirror of the clip which it is reflecting.

My work on this ActionScript 3.0 class is a testament to my own love of the Flash community, which is unlike any other pool of developers or designers I know. If you ever need any help with code or features, they are willing to help. After my original code for reflecting movie clips in ActionScript 2.0 was released on my blog, many gracious members of the Flash community posted helpful comments, feature requests, and even code snippets to help improve the class. The updated class described in this article takes into consideration these additions from users who dedicated their time and effort to help me improve it.

Getting started with reflections

Before we get started, it might be useful to demonstrate the effect I am describing. As you drag the sliders in the Reflection Explorer (see Figure 1), you will notice that the Reflection Code box dynamically updates and provides you with the code necessary for applying the reflection to the Flash file. This example, which requires Adobe Flash Player 9 (version 9,0,45,0 or later), assumes a movie clip with an instance name of ref_mc.

Flash playerがありません Flash 10が必要ですか? Flash 10が必要ですか?

Figure 1. Reflection Explorer (drag the sliders to see the effect)

Click the Show Video button at the top of the Reflection Explorer to toggle between a video and its image-based reflection. You may notice that when you are applying the Reflect class to the image, you are setting an update time of –1. This saves on processor overhead because you don't need to constantly update the reflection, as you would with the video. I will cover all of these parameters later in this article.

Examining the Reflect class

Whenever you start a class file, you should set the package library. The following line defines the package library path for the Reflect class:

package com.pixelfumes.reflect

For practical purposes, I named this file Reflect.as and nested it within a specific folder structure. This helps ensure that my code does not conflict with any other existing Reflect class code library that exists. For my purposes, I nested the class in the package path of com.pixelfumes.reflect. You really could make this whatever you want, but remember that the Reflect.as file needs to be in a folder structure that follows the package library. As you can see in the code download, the \com folder contains a \pixelfumes folder, which contains a \reflect folder in which the Reflect.as file lives.

Importing other classes

The Reflect class takes advantage of a number of classes. As you follow through the code, you will see objects from these classes in use. First import the classes in order to make use of them within the Reflect class:

package com.pixelfumes.reflect{ import flash.display.MovieClip; import flash.display.DisplayObject; import flash.display.BitmapData; import flash.display.Bitmap; import flash.geom.Matrix; import flash.display.GradientType; import flash.display.SpreadMethod; import flash.utils.setInterval; import flash.utils.clearInterval;

Writing the Reflect class

Now that you have the imported classes set, you can start writing the actual Reflect class. In this case, you are extending the MovieClip class. The following code opens the Reflect class and sets several variables that are used for tracking the information pertinent to the Reflect class:

public class Reflect extends MovieClip{ //Created By Ben Pritchard of Pixelfumes 2007 //Thanks to Mim, Jasper, Jason Merrill and all the others who //have contributed to the improvement of this class //static var for the version of this class private static var VERSION:String = "4.0"; //reference to the movie clip we are reflecting private var mc:MovieClip; //the BitmapData object that will hold a visual copy of the mc private var mcBMP:BitmapData; //the BitmapData object that will hold the reflected image private var reflectionBMP:Bitmap; //the clip that will act as out gradient mask private var gradientMask_mc:MovieClip; //how often the reflection should update (if it is video or animated) private var updateInt:Number; //the size the reflection is allowed to reflect within private var bounds:Object; //the distance the reflection is vertically from the mc private var distance:Number = 0;

Once you have the global variables for the class's scope defined, you can write the constructor function. The constructor function of the Reflect class accepts an object, which is referred to as args in the example below. The args object is responsible for passing the user-defined data into the Reflect class. For example, a typical instantiation of the Reflect class would look something like this within the Flash document:

import com.pixelfumes.reflect.*; var r1:Reflect = new Reflect({mc:ref_mc, alpha:50, ratio:50, distance:0, updateTime:0, reflectionDropoff:1});

Notice that to use the class, you have to import the Reflect class using the package's code library path already defined—namely, com.pixelfumes.reflect. After importing the class for use, define a variable to hold a reference to the Reflect class instance and pass it several items wrapped in an object. In this case, pass in the movie clip being reflected, the alpha for the reflection, the ratio to use in the gradient mask, the distance of the reflection, the update time, and the reflection dropoff.

The arguments are then pulled from the args object and used to set the class variables defined earlier. Based on the data passed into the class, you can set some additional variables within the class, such as the clip's height and width and the bounds in which the reflection can appear:

function Reflect(args:Object){ /*the args object passes in the following variables /we set the values of our internal vars to math the args*/ //the clip being reflected mc = args.mc; //the alpha level of the reflection clip var alpha:Number = args.alpha/100; //the ratio opaque color used in the gradient mask var ratio:Number = args.ratio; //update time interval var updateTime:Number = args.updateTime; //the distance at which the reflection visually drops off var reflectionDropoff:Number = args.reflectionDropoff; //the distance the reflection starts from the bottom of the mc var distance:Number = args.distance; //store width and height of the clip var mcHeight = mc.height; var mcWidth = mc.width; //store the bounds of the reflection bounds = new Object(); bounds.width = mcWidth; bounds.height = mcHeight;

Now that you have that out of the way, you can start getting into the meat of the class. The Reflection class makes heavy use of the BitmapData class, which enables you to take visual snapshots of movie clips with its draw method. Using the draw method, you can snapshot the movie clip passed into the class and use the data to populate a Bitmap object. Once you have the Bitmap object created, you can flip it upside down, position it, and add it to the Display Object stack. The following code handles the creation of the BitmapData and Bitmap objects, as well as handles their positioning:

//create the BitmapData that will hold a snapshot of the movie clip mcBMP = new BitmapData(bounds.width, bounds.height, true, 0xFFFFFF); mcBMP.draw(mc); //create the BitmapData the will hold the reflection reflectionBMP = new Bitmap(mcBMP); //flip the reflection upside down reflectionBMP.scaleY = -1; //move the reflection to the bottom of the movie clip reflectionBMP.y = (bounds.height*2) + distance; //add the reflection to the movie clip's Display Stack var reflectionBMPRef:DisplayObject = mc.addChild(reflectionBMP); reflectionBMPRef.name = "reflectionBMP";

If you were to finish the class here by closing up the constructor and package, you would be presented with a movie clip that looks like Figure 2.

Image after creating the BitmapData and Bitmap objects
Figure 2. Image after creating the BitmapData and Bitmap objects

As you can see, the class is copying the visual representation of the movie clip, flipping it upside down and positioning itself under the original movie clip.

Creating the gradient

Now that you have the reflected image in the proper position, you can create a movie clip that holds the gradient that you'll use to create the gradient mask:

//add a blank movie clip to hold our gradient mask var gradientMaskRef:DisplayObject = mc.addChild(new MovieClip()); gradientMaskRef.name = "gradientMask_mc"; //get a reference to the movie clip - cast the DisplayObject that is returned as a MovieClip gradientMask_mc = mc.getChildByName("gradientMask_mc") as MovieClip;

With the gradient mask clip added to the display, you can now work on the actual gradient. This gradient uses several values of interest. To create the gradient, you can use the alpha and ratio variables that were passed. These variables, along with the bounds I defined earlier, construct a gradient box within the gradientMask_mc clip.

The following code steps you through the creation of the linear gradient you will be using. Feel free to experiment with different fillType and spreadMethod instances, as these will alter the final appearance of your gradient mask:

//set the values for the gradient fill var fillType:String = GradientType.LINEAR; var colors:Array = [0xFFFFFF, 0xFFFFFF]; var alphas:Array = [alpha, 0]; var ratios:Array = [0, ratio]; var spreadMethod:String = SpreadMethod.PAD; //create the Matrix and create the gradient box var matr:Matrix = new Matrix(); //set the height of the Matrix used for the gradient mask var matrixHeight:Number; if (reflectionDropoff<=0) { matrixHeight = bounds.height; } else { matrixHeight = bounds.height/reflectionDropoff; } matr.createGradientBox(bounds.width, matrixHeight, (90/180)*Math.PI, 0, 0);

With the variables for the gradient mask now populated, you can now use the graphics property of the gradientMask_mc clip to create the GradientFill fill. Once the fill is created within the clip, position gradientMask_mc over reflectionBMP:

//create the gradient fill gradientMask_mc.graphics.beginGradientFill(fillType, colors, alphas, ratios, matr, spreadMethod); gradientMask_mc.graphics.drawRect(0,0,bounds.width,bounds.height); //position the mask over the reflection clip gradientMask_mc.y = mc.getChildByName("reflectionBMP").y - mc.getChildByName("reflectionBMP").height;

For the reflection to be properly masked with the gradient mask, you need to ensure that both the gradient mask and the reflectionBMP are set to cacheAsBitmap = true:

//cache clip as a bitmap so that the gradient mask will function gradientMask_mc.cacheAsBitmap = true; mc.getChildByName("reflectionBMP").cacheAsBitmap = true; //set the mask for the reflection as the gradient mask mc.getChildByName("reflectionBMP").mask = gradientMask_mc;
//cache clip as a bitmap so that the gradient mask will function gradientMask_mc.cacheAsBitmap = true; mc.getChildByName("reflectionBMP").cacheAsBitmap = true; //set the mask for the reflection as the gradient mask mc.getChildByName("reflectionBMP").mask = gradientMask_mc;

Checking your constraints

For the final part of the constructor, check to see if you have a valid update time, which refreshes the BitmapData that contains a snapshot of the movie clip you are reflecting. Clips that don't move and are not animated do not need an update time. If you pass in –1, you can avoid creating an interval to update the BitmapData object and save processing overhead. Movie clips containing videos or buttons that change upon rollover should have an update applied to them, so that the reflection remains visually accurate:

//if we are updating the reflection for a video or animation do so here if(updateTime > -1){ updateInt = setInterval(update, updateTime, mc); }

Adjusting the reflection with methods

With the bulk of the class out of the way, all you need now are a few methods to adjust the reflection. The setBounds method allows you to define an area in which the reflection is available. Keep in mind that, because you are taking a snapshot of the area defined by this method; larger bounds will use more memory. The setBounds method is ideal for clips that animate along a horizontal access within their own timeline.

Take a look at the animation in Figure 3 (click Start Demo to see the effect, Stop Demo to pause it). If a clip has the Reflect class applied to it at runtime, and then the clip's timeline moves items outside of the initial bounds of the clip, the Reflect class will not show them because it had its bounds defined by the size of the clip at runtime.

Flash playerがありません Flash 10が必要ですか? Flash 10が必要ですか?

Figure 3. Animation using setBounds (click Start Demo to see the effect)

Using setBounds enables the user to compensate for the size difference by increasing the size of the bounds if needed:

public function setBounds(w:Number,h:Number):void{ //allows the user to set the area that the reflection is allowed //this is useful for clips that move within themselves bounds.width = w; bounds.height = h; gradientMask_mc.width = bounds.width; redrawBMP(mc); }

The redrawBMP method, used by the setBounds class, serves the role of destroying the current BitmapData and creating a new one to compensate for the new bounds that were defined:

public function redrawBMP(mc:MovieClip):void { // redraws the bitmap reflection - Mim Gamiet [2006] mcBMP.dispose(); mcBMP = new BitmapData(bounds.width, bounds.height, true, 0xFFFFFF); mcBMP.draw(mc); }

The update method refreshes the data held within the BitmapData snapshot of the movie clip. The more often the update method is run, the more processer-intensive the class becomes but the smoother the reflection playback looks. A good rule of thumb is to use as high a number as the visual performance will allow when setting the update time:

private function update(mc):void { //updates the reflection to visually match the movie clip mcBMP = new BitmapData(bounds.width, bounds.height, true, 0xFFFFFF); mcBMP.draw(mc); reflectionBMP.bitmapData = mcBMP; }

Terminating the reflection

You need a way to get rid of that reflection once you have created it. For this, you can create the destroy method, which removes the reflection items from the DisplayObject stack, clears the intervals, and removes all traces of the reflection:

public function destroy():void{ //provides a method to remove the reflection mc.removeChild(mc.getChildByName("reflectionBMP")); reflectionBMP = null; mcBMP.dispose(); clearInterval(updateInt); mc.removeChild(mc.getChildByName("gradientMask_mc")); }

Where to go from here

The Reflect class still has quite a few possibilities, and it leaves plenty of room for extension and improvement. Although using the Reflect class is pretty straightforward when working with static images, it becomes a bit different when reflecting items such as video. If you plan on reflecting a clip containing video, it is best to wait until the video is completely loaded before applying the class.

I would love to see any improvements and additions you would like to add to the Reflect class. Contact me at my blog, pixelfumes.com/blog. The more that we in the Flash community can push one another, the further we will push the boundaries of Flash as a platform.

More Like This

  • Introducing the ActionScript 3.0 debugger
  • 3D moving stars in Flash using ActionScript 3
  • Filtering XML data in Flash applications using ECMAScript for XML
  • Creating ActionScript 3.0 components in Flash – Part 2: MenuBar component prototype
  • Using timeline labels to dispatch events with the ActionScript 3.0 TimelineWatcher class
  • Deconstructing the ActionScript 3 Flash video gallery application
  • Creating the Kuler panel for Flash CS3 Professional
  • Controlling the appearance of text elements with the Text Layout Framework
  • Optimizing transparent images for projects in Flash using ActionScript 3
  • Using screen orientation APIs for smartphone application development

製品

  • Creative Suiteファミリー
  • Photoshopファミリー
  • Acrobatファミリー
  • Flashプラットフォーム
  • Digital Marketing Suite
  • Digital Enterprise Suite
  • Digital Publishing Suite
  • モバイルアプリ

ソリューション

  • カスタマーエクスペリエンスマネジメント
  • コンテンツオーサリング
  • デジタルマーケティング

業種別ソリューション

  • 教育
  • 金融機関

サポート

  • ヘルプ&サポート
  • 注文と返品
  • ダウンロードに関するヘルプ
  • ユーザー登録に関するヘルプ

ラーニング

  • ADC: Adobe Developer Center
  • Adobe TV
  • Design Magazine
  • Photoshop Magazine
  • Focus In

ご購入方法

  • アドビストア
  • アカデミック版のご購入
  • ライセンスのご購入

ダウンロード

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

会社情報

  • プレスルーム
  • パートナープログラム
  • 企業の社会的責任(英語)
  • 採用情報
  • 投資家の皆様へ(英語)
  • イベント&セミナー
  • Legal(英語)
  • お問い合わせ
国・地域および言語の選択 日本(変更)
国・地域および言語の選択 閉じる

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • España
  • France
  • Deutschland
  • Hrvatska
  • Ireland
  • Israel - English
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • Magyarország
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Österreich - Deutsch
  • Polska
  • Portugal
  • România
  • Россия
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Slovenija
  • Slovensko
  • Srbija
  • Suomi
  • Sverige
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • Pacific - English
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

当Webサイトをご利用のお客様は、利用条件およびプライバシーポリシー(2011年9月30日更新)にご同意いただいたものとみなされます。

Reviewed by TRUSTe: site privacy statement