Adobe
製品
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
その他の製品一覧
ソリューション
デジタルマーケティング
デジタルメディア
教育
金融機関
Web Experience Management
その他のソリューション
ラーニング サポート ダウンロード 会社情報
ご購入
アドビストア 安心のサポート& サービス
アカデミックストア 学生、教職員、個人向け
アドビライセンスストア 中小企業向け
ボリュームライセンスについて 企業、教育機関、官公庁向け
販売パートナー
キャンペーン情報
検索
 
情報 サインイン
ようこそ、 さん カート 注文状況 マイアカウント
マイアカウント
注文状況
アカウント情報の変更
コミュニケーションの設定を変更
サインアウト
サインインの目的 お客様のアカウントや体験版ダウンロード、製品の拡張機能、コミュニティエリアへのアクセスなどを管理するため
Adobe
製品 セクション ご購入   検索  
ソリューション 会社情報
サポート ラーニング
サインイン サインアウト 注文状況 マイアカウント
先行予約の提供開始予定日Date. 商品が発送されるまで、クレジットカードには課金されません。提供開始の予定日は変更される場合があります。 先行予約の提供開始予定日Date. ダウンロードの準備が整うまで、クレジットカードには課金されません。提供開始の予定日は変更される場合があります。
個数:
ご購入には学生・教職員個人版の購入資格の確認が必要です。
小計
カートの中身を見る
Adobe Developer Connection / Flashデベロッパーセンター /

Using timeline labels to dispatch events with the ActionScript 3.0 TimelineWatcher class

by Bobby van der Sluis

Bobby van der Sluis
  • Refunk
  • bobbyvandersluis.com

Content

  • The TimelineWatcher and TimelineEvent classes
  • Setting up the TimelineWatcher example
  • Using external ActionScript to tie everything together

Created

16 March 2009

ページ ツール

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

タグ

必要条件

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

You should have a good understanding of Adobe Flash Professional and ActionScript 3.0.

ユーザーレベル

中級

必要な製品

  • Flash Professional CS4 (Download trial)

サンプルファイル

  • timelinewatcher.zip (22 KB)

In many SWF applications, developers need a way to programmatically monitor a timeline as it is played back so the code can take some action when a frame label or the end of the timeline is reached. Techniques for achieving this, however, have often conflicted with the design goal of separating timelines from actions.

In the past decade Adobe Flash has grown from a simple animation tool into a comprehensive authoring environment for creating rich content. Nowadays many rich media agencies have implemented a workflow where multiple people in different roles—including Flash designers and developers—can simultaneously work together on one project, and projects are split into many different FLA and ActionScript files that all fit a specific framework or conceptual structure.

As a result, it has become a key best practice to use FLA files primarily as a collection of multimedia elements and timeline animations, and to embody all logic in external ActionScript files. To enable this workflow, Flash CS3 Professional introduced the Document class as a default mechanism to link a FLA file to external ActionScript code.

Overall it has become pretty easy to separate timelines from actions or code. However, there is unfortunately one exception to the rule.

Consider the following scenario: A developer would like to run a piece of code after a certain timeline has played to a specific point, which is marked with a label. How does he know exactly when this point has been reached? To solve this problem, the developer might place the following action on a timeline inside a FLA file:

dispatchEvent(new Event("animationHasFinished"));

Although there is nothing invalid about this approach, it does have drawbacks. For developers, timeline actions are harder to author, adjust, and locate than code inside external ActionScript files. Many designers will also find this approach too technical. Lastly, it simply violates the principle of keeping your actions and timelines separated (yes, we "Flashers" are proud people).

At Refunk, where I work, we have developed a small utility that elegantly solves this problem. The TimelineWatcher class enables a developer's code to watch a timeline as it is played back and be notified when a frame label or the end of the timeline has been reached. By using frame labels as hooks—cue points, as in web video—timelines and actions can now be truly separated.

The TimelineWatcher and TimelineEvent classes

The TimelineWatcher class is a small, simple utility class. Here is the full documentation:


  • Package: com.refunk.timeline
  • Class: public class TimelineWatcher
  • Inheritance: TimelineWatcher > EventDispatcher > Object
  • Language version: ActionScript 3.0

Public methods

  • TimelineWatcher(timeline:MovieClip): Creates a TimelineWatcher object to watch a single timeline
  • dispose():void: Removes the TimelineWatcher object's internal listeners and references, so it can be garbage collected without any memory leaks

Events

  • labelReached: Dispatched when a new timeline label has been reached
Event Object Type: com.refunk.events.TimelineEvent
Event.type property: com.refunk.events.TimelineEvent.LABEL_REACHED
Custom property/value: currentFrame: The current frame (int)
currentLabel: The current timeline label (String)
  • endReached: Dispatched when the end of a timeline has been reached
Event Object Type: com.refunk.events.TimelineEvent
Event.type property: com.refunk.events.TimelineEvent.END_REACHED
Custom property/value: currentFrame: The current frame (int)
currentLabel: The current timeline label (String)

Because the TimelineWatcher class extends the built-in EventDispatcher class you can add event listeners using the standard addEventListener() method. It goes hand-in-hand with the TimelineEvent class, which is a custom event class that explicitly types the events used by TimelineWatcher. These events additionally store the current frame number and label, so they can be retrieved via the event object.

You can find the TimelineWatcher and TimelineEvent classes in the sample file for this article (timelinewatcher.zip). Both classes are made available as free code by Refunk and are distributed under the GNU General Public License.

Setting up the TimelineWatcher example

To see a working example of TimelineWatcher, start by unzipping the timelinewatcher.zip file and opening index.html in your desktop web browser (make sure you have Flash Player 9 or later installed). You will see a simple timeline animation of a red ball that animates from the left to the right and back. It loops three times before the animation stops. A text field in the top left corner displays the timeline label that is currently playing and the number of loops the animation has made (see Figure 1).

Simple TimelineWatcher example
Figure 1. Simple TimelineWatcher example

Open the test.fla file in your Flash authoring environment, and you will see a white canvas with a MovieClip of a red ball (see Figure 2).

Canvas at frame 1 showing a red ball
Figure 2. Canvas at frame 1 showing a red ball

The main Timeline contains two classic tweens, one that moves the ball to the right and one that moves it back to the left, with two frame (or timeline) labels—moveRight and moveLeft—indicating the direction of the animation (see Figure 3).

Timeline showing two simple tweens with corresponding frame labels
Figure 3. Timeline showing two simple tweens with corresponding frame labels

That's all the design work that went into the example. When you test this movie—without the attached Document class, as I will discuss next—you will see an endlessly looping animation of a red ball that moves back and forth.

The next step is to add an external ActionScript file that will do the following:

  • Display the dynamic text field on the top left of the canvas that indicates the current Timeline label and the amount of loops that have been completed
  • Stop the animation after three loops

To link the external ActionScript file named Test.as to the test.fla file, type Test as the Class in the Publish settings of the Properties panel (see Figure 4). At compile-time this Document class will be associated with the main Timeline, and will be able to provide functionality much like actions on the main Timeline.

Document class field in the Properties panel
Figure 4. Document class field in the Properties panel

Before examining the external ActionScript file, there is one additional setting you need to be aware of. Choose File > Publish Settings and click the Flash tab. Make sure ActionScript 3.0 is specified in the Script menu and click Settings to open the Advanced ActionScript 3.0 dialog box (see Figure 5).

Automatically Declare Stage Instances check box in the Advanced ActionScript 3.0 Settings dialog box
Figure 5. Automatically Declare Stage Instances check box in the Advanced ActionScript 3.0 Settings dialog box

By default the Automatically Declare Stage Instances check box is selected, which means that Flash will automatically declare any element with an instance name that resides on the main Timeline at compile time. Although this is a handy feature for designers and developers who use the Flash authoring environment for ActionScript development, it also can cause problems for developers who use external code editors, because these editors will complain that these declarations have not been created. (Flash acts as if they have been created—it kind of creates them for you in memory—so it's not really a matter of visibility; they are required but don't exist, and Flash creates them for you automagically.)

To make your code editable in multiple development environments, you are better off unchecking this option and explicitly declaring every element with an instance name that resides on the main Timeline as a public class variable in your Document class. Without these declarations, Flash will throw a compile-time error. In the example there is just one MovieClip on the main Timeline with the instance name ball, so the following declaration is required:

public var ball:MovieClip;

From this point onwards you automatically have a reference to the ball instance on the main Timeline.

Using external ActionScript to tie everything together

Here is the basic scaffolding for the Document class named Test.as:

package { import flash.display.MovieClip; public class Test extends MovieClip { public var ball:MovieClip; public function Test() { super(); stop(); } } }

The code above declares the ball MovieClip on the main Timeline and stops its playback. Although Flash implicitly calls the super() method in the constructor, I usually add it for all extended classes as a best practice; this reminds me to make the method call when additional arguments are required. Starting with the basic scaffolding above, I add the text field for the current timeline label to the top left of the screen (highlighted text indicates the newly added code):

package { import flash.display.MovieClip; import flash.text.TextField; public class Test extends MovieClip { public var ball:MovieClip; private var output:TextField; public function Test() { super(); stop(); output = new TextField(); addChild(output); output.text = "testing: 1, 2, 3"; // just for testing purposes } } }

At this point it starts to get more interesting. I add the TimelineWatcher and TimelineEvent classes as well as the necessary logic:

package { import flash.display.MovieClip; import flash.text.TextField; import com.refunk.events.TimelineEvent; import com.refunk.timeline.TimelineWatcher; public class Test extends MovieClip { public var ball:MovieClip; private var output:TextField; private static const MOVE_LEFT:String = "moveLeft"; private static const MOVE_RIGHT:String = "moveRight"; private var timelineWatcher:TimelineWatcher; public function Test() { super(); stop(); output = new TextField(); addChild(output); timelineWatcher = new TimelineWatcher(this); timelineWatcher.addEventListener(TimelineEvent.LABEL_REACHED, handleTimelineEvent); gotoAndPlay(1); } private function handleTimelineEvent(e:TimelineEvent):void { if (e.currentLabel === MOVE_LEFT || e.currentLabel === MOVE_RIGHT) { output.text = "label: " + e.currentLabel; } } } }

First I import both classes so the Flash compiler knows where to find them. Next I add two constants named MOVE_LEFT and MOVE_RIGHT that match the timeline labels. This is a good practice to avoid errors due to typing mistakes.

Next I declare the TimelineWatcher instance named timelineWatcher as a private class variable. In the main constructor named Test(), I create the actual TimelineWatcher instance and pass it the timeline that I want it to watch as a parameter. In this case I can use the keyword this, because it reflects the main Timeline.

I also add an event listener to listen for the TimelineEvent.LABEL_REACHED event, which triggers the custom handleTimelineEvent() method. Next, I start playing the main Timeline again.

The handleTimelineEvent() method uses the returned event object named e to retrieve the current label and checks if it corresponds with the predefined labels I am monitoring. If so, it updates the timeline label on the screen.

When you run this example you will see the red ball continuously moving back and forth with the current timeline label in the top left of the canvas. After adding only a few lines of external ActionScript code I now know exactly what's going on with the main Timeline. And, look mum, I used no timeline actions at all!

The edits to the code below stop the timeline after it has played three loops:

package { import flash.display.MovieClip; import flash.text.TextField; import com.refunk.events.TimelineEvent; import com.refunk.timeline.TimelineWatcher; public class Test extends MovieClip { public var ball:MovieClip; private var output:TextField; private static const MOVE_LEFT:String = "moveLeft"; private static const MOVE_RIGHT:String = "moveRight"; private var timelineWatcher:TimelineWatcher; private var loops:uint = 1; public function Test() { super(); stop(); output = new TextField(); addChild(output); timelineWatcher = new TimelineWatcher(this); timelineWatcher.addEventListener(TimelineEvent.LABEL_REACHED, handleTimelineEvent); timelineWatcher.addEventListener(TimelineEvent.END_REACHED, handleTimelineEvent); gotoAndPlay(1); } private function handleTimelineEvent(e:TimelineEvent):void { switch (e.type) { case TimelineEvent.LABEL_REACHED: if (e.currentLabel === MOVE_LEFT || e.currentLabel === MOVE_RIGHT) { output.text = "label: " + e.currentLabel + "\nloops: " + loops; } break; case TimelineEvent.END_REACHED: loops++; if (loops > 3) { stop(); timelineWatcher.removeEventListener(TimelineEvent.LABEL_REACHED, handleTimelineEvent) timelineWatcher.removeEventListener(TimelineEvent.END_REACHED, handleTimelineEvent); timelineWatcher.dispose(); timelineWatcher = null; } break;} } } }

I have added a second listener to listen for the TimelineEvent.END_REACHED event to count each timeline loop, and I stop the timeline playback after three loops.

Finally, I clean up by removing the two listeners, disposing the TimelineWatcher instance, and setting its reference to null.

That completes all the code for the example! When you test this code you should see the example as displayed in Figure 1.

Where to go from here

In this article you've seen how to use the TimelineWatcher class to dispatch an event when a frame label or the end of a timeline is reached, while keeping timelines and actions separate.

Thibault Imbert from ByteArray.org recently blogged about the FrameLabel event, a new feature request for the next version of Adobe Flash Player.

For more information about ActionScript, visit the ActionScript Technology Center.

Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License

More Like This

  • Getting started with the Adobe SiteCatalyst extension for Flash Professional CS5
  • ActionScript 2からActionScript 3への移行:重要な概念と変更点
  • Using the Flash OSMF Media Player template
  • Understanding ActionScript 3 debugging in Flash
  • Formatting text for localized Flash projects
  • Introducing the ActionScript 3.0 debugger
  • Multitouch and gesture support on the Flash Platform
  • Examining the ActionScript 3 Flash video gallery source files
  • Creating the Kuler panel for Flash CS3 Professional
  • Skinning the ActionScript 3 FLVPlayback component

製品

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • モバイルアプリ
  • Photoshop
  • Touch Apps

ソリューション

  • デジタルマーケティング
  • コンテンツオーサリング
  • Web Experience Management

業種別ソリューション

  • 教育
  • 金融機関

サポート

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

ラーニング

  • 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
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

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

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

利用条件 | プライバシーポリシーとCookie (更新)

Reviewed by TRUSTe: site privacy statement