Stáhnout PDF s nápovědou( 10MB)
Transkript
Programování v jazyce ADOBE ACTIONSCRIPT 3.0 ® ® © 2008 Adobe Systems Incorporated. Všechna práva vyhrazena. Copyright Programování v jazyce Adobe® ActionScript® 3.0 pro aplikaci Adobe® Flash® Pokud je tato příručka distribuovaná se softwarem, ke kterému patří smlouva s koncovým uživatelem, je tato příručka stejně jako v ní popisovaný software poskytována na základě licence a může být používána nebo kopírována pouze podle podmínek této licence. S výjimkami povolenými v takové licenci nesmí být žádná část této příručky reprodukována, ukládána ve vyhledávacím systému a přenášena v jakékoliv formě nebo jakýmikoliv prostředky, elektronickými, mechanickými, záznamovými nebo jinými, bez předchozího písemného povolení společnosti Adobe Systems Incorporated. Uvědomte si prosím, že obsah této příručky je chráněn copyrightem i v případě, že není šířena se softwarem, ke kterému patří licenční smlouva s koncovým uživatelem. Obsah této příručky slouží pouze pro informaci, může se měnit bez upozornění a nelze ho vykládat jako závazek společnosti Adobe Systems Incorporated. Společnost Adobe Systems Incorporated nepřebírá žádnou odpovědnost za chyby nebo nepřesnosti, které se v informačním obsahu této příručky mohou objevit. Uvědomte si prosím, že existující umělecká díla nebo obrazy, které byste chtěli zahrnout do svých projektů, mohou být chráněny copyrightem. Neautorizované začlenění takových materiálů do vaší nové práce může být porušením práv majitele copyrightu. Opatřete si prosím vyžadované povolení pro použití díla od majitele copyrightu. Všechny odkazy na názvy společností ve vzorových předlohách jsou pouze pro demonstrační účely a nejsou zamýšleny jako odkaz na jakoukoliv skutečnou organizaci. Adobe, the Adobe logo, Adobe AIR, ActionScript, Flash, Flash Lite, Flex, Flex Builder, MXML, and Pixel Bender are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries. ActiveX and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and other countries. Macintosh is a trademark of Apple Inc., registered in the United States and other countries. Java is a trademark or registered trademark of Sun Microsystems, Inc. in the United States and other countries. All other trademarks are the property of their respective owners. This product includes software developed by the Apache Software Foundation (http://www.apache.org/). MPEG Layer-3 audio compression technology licensed by Fraunhofer IIS and Thomson Multimedia (http://www.mp3licensing.com) Speech compression and decompression technology licensed from Nellymoser, Inc. (www.nellymoser.com). Video compression and decompression is powered by On2 TrueMotion video technology. © 1992-2005 On2 Technologies, Inc. All Rights Reserved. http://www.on2.com. This product includes software developed by the OpenSymphony Group (http://www.opensymphony.com/). This product contains either BSAFE and/or TIPEM software by RSA Security, Inc. Sorenson Spark™ video compression and decompression technology licensed from Sorenson Media, Inc. Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA Notice to U.S. government end users. The software and documentation are “Commercial Items,” as that term is defined at 48 C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software Documentation,” as such terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as Commercial items and (b) with only those rights as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S. Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR Parts 60-1 through 60-60, 60-250 ,and 60-741. The affirmative action clause and regulations contained in the preceding sentence shall be incorporated by reference. iii Obsah Kapitola 1: O této příručce Používání této příručky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Přístup k dokumentaci jazyka ActionScript ............................................................................. 2 Zdroje pro vzdělávání v jazyce ActionScript ............................................................................ 3 Kapitola 2: Úvodní informace k jazyku ActionScript 3.0 O ActionScriptu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Výhody jazyka ActionScript 3.0 ......................................................................................... 4 Co je nového v jazyce ActionScript 3.0 Kompatibilita s předchozími verzemi ................................................................................. 5 ................................................................................... 7 Kapitola 3: Začínáme s ActionScriptem Základy programování . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Práce s objekty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Společné prvky programu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Příklad: animace kusu portfolia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Vytváření aplikací v jazyce ActionScript Vytváření vlastních tříd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Příklad: Vytváření základních aplikací Spuštění následných příkladů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Kapitola 4: Jazyk ActionScript a jeho syntaxe Přehled jazyka . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Objekty a třídy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Balíčky a jmenné prostory Proměnné . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Typy dat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Operátory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Podmíněné příkazy Opakování Funkce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Kapitola 5: Objektově orientované programování v jazyce ActionScript Základy objektově orientovaného programování . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Třídy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Rozhraní . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Zdědění . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Pokročilá témata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Příklad: GeometricShapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Kapitola 6: Práce s daty a časy Základy data a času . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Správa kalendářních dat a časů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH iv Obsah Kontrola časových intervalů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Příklad: Jednoduché analogové hodiny . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Kapitola 7: Práce s řetězci Základy řetězců . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Vytváření řetězců . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Vlastnost length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Práce se znaky v řetězci Porovnávání řetězců . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Získání vyjádření řetězce z jiných objektů Zřetězení řetězců . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Vyhledání podřetězců a vzorků v řetězci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Převod řetězců mezi velkými a malými písmeny Příklad: kresba ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Kapitola 8: Práce s poli Základní informace o polích . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Indexovaná pole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Asociativní pole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Vícedimenzionální pole Klonování polí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Pokročilá témata Příklad: PlayList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Kapitola 9: Zpracování chyb Základy zpracování chyb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Typy chyb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Zpracování chyb v jazyce ActionScript 3.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Práce s ladicími verzemi aplikací Flash Player a AIR Zpracování synchronních chyb v aplikaci Vytvoření vlastních tříd chyb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Reakce na chybové události a stavy Porovnání tříd Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 Příklad: použití třídy CustomErrors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Kapitola 10: Používání regulárních výrazů Základní informace o regulárních výrazech . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Syntaxe regulárního výrazu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 Metody pro použití regulárních výrazů s řetězci Příklad: analyzátor Wiki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Kapitola 11: Práce s jazykem XML Základy jazyka XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Přístup E4X ke zpracování XML Objekty XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Objekty XMLList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 Inicializace proměnných XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Sestavování a transformace objektů XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH v Obsah Procházení struktur XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Použití jmenných prostorů XML Převod typu XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 Čtení externích dokumentů XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Příklad: Načtení dat RSS z Internetu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 Kapitola 12: Zpracování událostí Základy zpracování událostí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Jak se zpracování událostí v jazyce ActionScript 3.0 liší od předchozích verzí Tok událostí Objekty událostí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Posluchače událostí Příklad: budík . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 Kapitola 13: Programování zobrazení Základy programování zobrazení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 Základní třídy zobrazení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Výhody přístupu seznamu zobrazení Práce s objekty zobrazení Manipulace s objekty zobrazení Animace objektů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Dynamické načtení obsahu zobrazení Příklad: SpriteArranger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 Kapitola 14: Používání kreslicího rozhraní API Základy použití kreslicího rozhraní API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 Vysvětlení třídy Graphics Kreslení čar a křivek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 Kreslení tvarů pomocí vestavěných metod Vytváření čar a výplní přechodu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Použití třídy Math s kreslicími metodami Animování s kreslicím rozhraním API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 Příklad: Algoritmický vizuální generátor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 Pokročilé použití kreslicího rozhraní API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 Cesty kreslení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 Definování pravidel vinutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Používání tříd grafických dat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 O použití metody drawTriangles() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 Kapitola 15: Práce s geometrií Základy geometrie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 Používání objektů Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 Používání objektů Rectangle Používání objektů Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 Příklad: Použití transformace matice na objekt zobrazení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH vi Obsah Kapitola 16: Filtrování objektů zobrazení Základní informace o filtrování objektů zobrazení Vytváření a používání filtrů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 Dostupné filtry zobrazení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 Příklad: Filter Workbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369 Kapitola 17: Práce s shadery Pixel Bender Základy shaderů Pixel Bender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376 Načtení nebo vložení shaderu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 Přístup k metadatům shaderu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 Určení hodnot vstupu a parametrů shaderu Používání shaderu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 Kapitola 18: Práce s filmovými klipy Základy filmových klipů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 Práce s objekty MovieClip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400 Ovládání přehrávání filmových klipů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400 Vytváření objektů MovieClip pomocí kódu ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 Načítání externích souborů SWF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 Příklad: RuntimeAssetsExplorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 Kapitola 19: Práce s doplněními pohyby Základy doplnění pohybu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 Kopírování skriptů doplnění pohybu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411 Začlenění skriptů doplnění pohybu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Popisování animace Přidávání filtrů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 Přidružování doplnění pohybů k jejich objektům zobrazení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417 Kapitola 20: Práce s inverzní kinematikou Základy inverzní kinematiky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418 Přehled Animování Armatur IK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 Získávání informací o armatuře IK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Konkretizace IK Mover a omezení pohybu Posun armatury IK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 Používání událostí IK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 Kapitola 21: Práce s textem Základy práce s textem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 Použití třídy TextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425 Používání funkce Flash Text Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446 Kapitola 22: Práce s bitmapami Základy práce s bitmapami . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473 Třídy Bitmap a BitmapData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 Manipulace s obrazovými body Kopírování dat bitmapy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479 Vytváření textur s funkcemi šumu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH vii Obsah Posouvání bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482 Využívání výhod mipmappingu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483 Příklad: Animovaný otáčející se měsíc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484 Kapitola 23: Práce ve třech rozměrech (3D) Základy 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 Vysvětlení 3D funkcí runtime programů Flash Player a AIR Vytváření a posouvání 3D objektů Zobrazení 3D objektů na 2D zobrazení Příklad: perspektivní projekce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 Provádění komplexních 3D transformací Používání trojúhelníků pro 3D efekty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507 Kapitola 24: Práce s videem Základy videa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515 Vysvětlení formátů videa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517 Vysvětlení třídy Video . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519 Načítání souborů videa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520 Ovládání přehrávání videa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520 Přehrávání videa v režimu celé obrazovky Streamování souborů videa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526 Vysvětlení startovacích bodů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526 Zapisování zpětně volaných metod pro metadata a startovací body Používání startovacích bodů a metadat Zachycování vstupu z kamery Odeslání videa na server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547 Další témata pro soubory FLV Příklad:Video Jukebox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549 Kapitola 25: Práce se zvukem Základy práce se zvukem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554 Porozumění architektuře zvuku . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556 Načítání externích zvukových souborů Práce s vloženým zvukem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559 Práce s datovým přenosem zvukových souborů Práce s dynamicky generovaným zvukem Přehrávání zvuku . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563 Bezpečnost načítání a přehrávání zvuku Řízení hlasitosti zvuku a jeho vyvážení Práce s metadaty zvuku . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569 Přístup k nezpracovaným zvukovým datům . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570 Záznam zvukového vstupu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574 Příklad: přehrávač podcastů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577 Kapitola 26: Zachycování uživatelských vstupů Základy uživatelského vstupu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585 Zachycení vstupu z klávesnice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH viii Obsah Zachycení vstupu z myši Příklad: WordSearch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592 Kapitola 27: Sítě a komunikace Základy práce v síti a komunikace Práce s externími daty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599 Připojování k instancím přehrávače Flash Player a programu AIR Připojení soketu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609 Ukládání lokálních dat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 613 Práce s datovými soubory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615 Příklad: Budování klienta Telnet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629 Příklad: nahrávání a stahování souborů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632 Kapitola 28: Prostředí klientského systému Základy prostředí klientského systému . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638 Použití třídy System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640 Použití třídy Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641 Použití třídy ApplicationDomain Použití třídy IME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644 Příklad: Zjištění schopností systému . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649 Kapitola 29: Kopírování a vkládání Základy kopírování a vkládání . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653 Načítání ze systémové schránky a zápis do této schránky Schránka:formáty dat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654 Kapitola 30: Tisk Základy tisku . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 659 Tisk stránky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660 Úlohy přehrávačů Flash Player a AIR a systémový tisk Nastavení velikosti, měřítka a orientace Příklad: Vícestránkový tisk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 665 Příklad: Změna velikosti, ořezání a reakce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667 Kapitola 31: Používání externího rozhraní API Základy používání externího rozhraní API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670 Požadavky a výhody externího rozhraní API Používání třídy ExternalInterface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673 Příklad: Používání externího rozhraní API s kontejnerem webové stránky Příklad: Používání externího rozhraní API s kontejnerem ActiveX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 682 Kapitola 32: Zabezpečení přehrávače Flash Player Přehled zabezpečení přehrávače Flash Player . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 688 Karantény zabezpečení Ovládání práv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 690 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 692 Omezení síťových rozhraní API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699 Zabezpečení režimu celé obrazovky Načítání obsahu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 702 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH ix Obsah Křížové skriptování . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704 Přístup k načteným médiím jako datům Načítání dat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709 Načítání vloženého obsahu ze souborů SWF importovaných do domény zabezpečení Práce s obsahem ze starších verzí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712 Nastavení povolení LocalConnection Ovládání výchozího přístupu URL Sdílené objekty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715 Přístup kamery, mikrofonu, schránky, myši a klávesnice Rejstřík . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 711 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717 1 Kapitola 1: O této příručce Tato příručka je základem pro vývoj aplikací v Adobe® ActionScript® 3.0. chcete-li lépe porozumět návrhům a technikám zde popsaným, měli byste již být seznámeni s obecnými koncepty programování, jako jsou například datové typy, proměnné, cykly a funkce. Měli byste také rozumět základním konceptům objektově orientovaného programování, jako jsou třídy a dědičnost. Předchozí znalosti jazyků ActionScript 1.0 nebo 2.0 jsou užitečné, nejsou však nezbytné. Používání této příručky Kapitoly v této příručce jsou organizovány do následujících logických skupin, což y vám mělo lépe pomoci nalézt jednotlivé oblasti dokumentace jazyka ActionScript: Kapitoly Popis Kapitoly 2 až 5, přehled programování v jazyce ActionScript Věnuje se hlavním konceptům jazyka ActionScript 3.0, včetně syntaxe jazyka, příkazů a operátorů a programování v jazyce ActionScript orientovanému na objekt. Kapitoly 6 až 11, klíčové datové typy a třídy jazyka ActionScript 3.0 Popisuje datové typy na nejvyšší úrovni v jazyce ActionScript 3.0. Kapitoly 12 až 32, rozhraní API přehrávače Flash Player a aplikace Adobe AIR Popisuje důležité vlastnosti, které jsou implementovány v balíčcích specifických pro aplikaci Adobe Flash Player a Adobe AIR, včetně zpracování událostí, práce s objekty zobrazení a seznamem zobrazení, práce v síti a komunikace, vstupu a výstupu souborů, externího rozhraní, modelu zabezpečení aplikace a další. Tato příručka také obsahuje různé vzorové soubory, které ukazují koncepty aplikačního programování pro důležité nebo běžně používané třídy. Vzorové soubory jsou obsaženy způsobem, které usnadňuje jejich načítání a používání v aplikaci Adobe® Flash® CS4 a mohou obsahovat také soubory obalu. Klíčový vzorový kód je však ryzím kódem jazyka ActionScript 3.0, který můžete používat v kterémkoliv vývojovém prostředí, kterému dáváte přednost. Jazyk ActionScript 3.0 může být psán a kompilován mnoha způsoby, včetně následujících: • Používání vývojového prostředí Adobe Flex Builder 3 • Používání libovolného textového editoru a kompilátorů s příkazovým řádkem, například takovým, který se dodává k vývojovému prostředí Flex Builder 3 • Používání vývojového nástroje aplikace Adobe® Flash® CS4 Professional Další informace o vývojovém prostředí jazyka ActionScript, viz také „Úvodní informace k jazyku ActionScript 3.0“ na stránce 4 Chcete-li porozumět vzorovému kódu v této příručce, není nutné mít předchozí zkušenost s používáním integrovaného vývojového prostředí jazyka ActionScript, například vývojového prostředí Flex Builder nebo vývojového nástroje Flash. Bude však vhodné se informovat v dokumentaci těchto nástrojů a naučit se je používat k zapisování a kompilování kódu jazyka ActionScript 3.0. Další informace naleznete v části „Přístup k dokumentaci jazyka ActionScript“ na stránce 2. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 2 O této příručce Přístup k dokumentaci jazyka ActionScript Protože se tato příručka zaměřuje na popisování jazyka ActionScript 3.0, který je bohatým a výkonným objektově orientovaným programovacím jazykem, nepokrývá rozsáhle proces vývoje aplikací nebo pracovní postup v rámci specifických nástrojů nebo serverové architektury. Takže kromě programování v jazyce ActionScript 3.0 bude vhodné využívat také další zdroje dokumentace s tím, jak budete postupně navrhovat, vyvíjet, testovat a nasazovat aplikace vytvořené v jazyce ActionScript 3.0. Dokumentace jazyka ActionScript 3.0 Tato příručka vás seznámí s koncepty, které stojí za programovacím jazykem ActionScript 3.0, nabídne podrobnosti o implementaci a vzory popisující důležité vlastnosti jazyka. Tato příručka však není vyčerpávajícím referenčním dokumentem jazyka. Takovým dokumentem je Referenční příručka jazyka ActionScript 3.0 a jeho součástí, která popisuje každou třídu, metodu, vlastnost a událost použité v jazyce. Referenční příručka jazyka ActionScript 3.0 a jeho komponent poskytuje podrobné referenční informace o klíčovém jazyce, a součástech vývojového nástroje Flash (v balících flash) a rozhraních API přehrávače Flash Player (v balících flash). Dokumentace aplikace Flash Pokud budete používat vývojový nástroj Flash, může být vhodné se informovat v následujících příručkách: Kniha Popis Používání programu Flash Popisuje způsob vývoje dynamických webových aplikací ve vývojovém nástroji Flash Programování v jazyce ActionScript 3.0 Popisuje specifické použití jazyka ActionScript 3.0 a jádra rozhraní API aplikace Flash Player a Adobe AIR Referenční příručka jazyka ActionScript 3.0 a jeho součástí Uvádí syntaxi, použití a příklady kódu pro komponenty vývojového nástroje Flash a rozhraní API jazyka ActionScript 3.0 Používání součástí jazyka ActionScript 3.0 Vysvětluje podrobnosti používání komponent k vývoji aplikací vytvořených nástrojem Flash Vývoj aplikací Adobe AIR pomocí programu Adobe Flash Popisuje způsob vývoje a nasazení aplikací Adobe AIR pomocí jazyka ActionScript CS4 Professional 3.0 a rozhraní API jazyka Adobe AIR v programu Flash. Jak se naučit jazyk ActionScript 2.0 v aplikaci Adobe Flash Uvádí přehled syntaxe jazyka ActionScript 2.0 a vysvětluje způsob použití jazyka ActionScript 2.0 při práci s různými typy objektů ActionScript 2.0 Language Reference Uvádí syntaxi, použití a příklady kódu pro komponenty vývojového nástroje Flash a rozhraní API jazyka ActionScript 2.0 Používání součástí jazyka ActionScript 2.0 Podrobně vysvětluje způsob použití součástí jazyka ActionScript 2.pro vývoj aplikací vytvořených nástrojem Flash Reference součástí jazyka ActionScript 2.0 Popisuje každou součást dostupnou v architektuře součástí Adobe, verze 2, společně s programovacím rozhraním API Rozšíření programu Flash Popisuje objekty, metody a vlastnosti dostupné v rozhraní API jazyka JavaScript Začínáme s aplikací Flash Lite 2.x Vysvětluje způsob použití aplikace Adobe® Flash® Lite™ 2.x pro vývoj aplikací a popisuje syntaxi, použití a uvádí příklady kódu vlastností jazyka ActionScript, které jsou dostupní v Flash Lite 2.x Vývoj aplikací Adobe Flash Lite 2.x Vysvětluje způsob vývoje aplikací Flash Lite 2.x Úvod do Flash Lite 2.x ActionScript Uvádí způsob vývoje aplikací s pomocí Flash Lite 2.x a popisuje všechny funkce ActionScript dostupné pro vývojáře Flash Lite 2.x PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 3 O této příručce Kniha Popis Referenční příručka jazyka ActionScript pro Adobe Flash Lite Popisuje syntaxi, použití a uvádí příklady kódu rozhraní API jazyka ActionScript 2.x 2.0, které jsou k dispozici v Flash Lite 2.x Začínáme s aplikací Flash Lite 1.x Uvádí aplikaci Flash Lite 1.x a popisuje, jak testovat obsah pomocí emulátoru aplikace Adobe® Device Central CS4 Vývoj aplikací Adobe Flash Lite 1.x Popisuje způsob vývoje aplikací pro mobilní zařízení pomocí aplikace Flash Lite 1.x Učíme se jazyk ActionScript v aplikaci Flash Lite 1.x Vysvětluje způsob použití jazyka ActionScript v aplikaci Flash Lite 1.x a popisuje všechny funkce jazyka ActionScript dostupné v aplikaci Flash Lite 1.x Referenční příručka jazyka ActionScript pro Adobe Flash Lite Popisuje syntaxi a použití prvků jazyka ActionScript, které jsou dostupné v aplikaci 1.x Flash Lite 1.x Zdroje pro vzdělávání v jazyce ActionScript Kromě obsahu uvedeného v těchto příručkách poskytuje společnost Adobe pravidelně aktualizované články, nápady pro vývoj a příklad prostřednictvím vývojového centra Adobe Developer Center a návrhářského centra Adobe Design Center. Adobe Developer Center Vývojové centrum Adobe Developer Center je zdrojem nejnovějších informací o jazyce ActionScript, článků o vyvinutých aplikacích z reálného světa a informací o důležitých objevujících se problémech. Vývojové centrum Adobe Developer Center naleznete na adrese www.adobe.com/devnet/. Adobe Design Center Nejnovější novinky z digitálního designu a filmové grafiky. Můžete procházet díly předních umělců, objevovat nové trendy designu a zdokonalovat své dovednosti pomocí výukových programů, klíčových pracovních kroků a pokročilých technik. Dvakrát měsíčně si můžete prohlédnout nejnovější výukové programy a články a inspirující exponáty galerií. Návrhářské centrum Adobe Design Center naleznete na adrese www.adobe.com/designcenter/. 4 Kapitola 2: Úvodní informace k jazyku ActionScript 3.0 Tato kapitola poskytuje přehled produktu Adobe®ActionScript® 3.0, nejnovější a nejrevolučnější verze jazyka ActionScript. O ActionScriptu ActionScript je programovací jazyk pro prostředí přehrávače Adobe® Flash® Player a programu Adobe® AIR™ v době běhu. Umožňuje interakce, zpracovávání dat a další možnosti v obsahu a v aplikacích Flash, Flex a AIR. Jazyk ActionScript je prováděn pomocí aplikace ActionScript Virtual Machine (AVM), která je součástí přehrávače Flash Player a programu AIR. Kód jazyka ActionScript je obvykle kompilován do formátu bytového kódu (druh programovacího jazyka, který je zapsán a chápán počítači) kompilátorem, například kompilátorem, který je součástí produktu Adobe® Flash® CS4 Professional nebo Adobe® Flex™ Builder™, nebo který je dostupný v sadě SDK Adobe® Flex™. Bytový kód je vnořen do souborů SWF, které jsou spouštěny přehrávačem Flash Player a programem AIR. Jazyk ActionScript 3.0 nabízí stabilní programovací model, který dobře znají vývojáři se základní znalostí objektově orientovaného programování. Některé z klíčových funkcí jazyka ActionScript 3.0, které vylepšují předchozí verze jazyka ActionScript, zahrnují následující: • Nový nástroj ActionScript Virtual Machine nazvaný AVM2, který používá novou sadu pokynů bytového kódu a nabízí o mnoho lepší výkon • Modernější základ pro kód kompilátoru, který provede hlubší optimalizaci než předcházející verze kompilátoru • Rozšířené a vylepšené programovací rozhraní aplikace (API) s nízkoúrovňovým ovládáním objektů a správným na objekt orientovaným modelem • Rozhraní API XML založené na ECMAScript pro specifikaci XML (E4X) (ECMA-357 vydání 2). E4X je rozšíření jazyka pro ECMAScript, které přidává XML jako nativní datový typ jazyka. • Model události založený na specifikaci událostí na úrovni 3 modelu objektu dokumentu (DOM) Výhody jazyka ActionScript 3.0 Jazyk ActionScript 3.0 předčí skriptovací schopnosti předcházejících verzí jazyka ActionScript. Jeho účelem je umožnit vytváření vysoce komplexních aplikací s velkými sadami dat a na objekt orientovanými, opětovně použitelnými základnami kódů. Zatímco jazyk ActionScript 3.0 není vyžadován pro obsah, který je spuštěn v přehrávači Adobe Flash Player, umožňuje vylepšení výkonu, které je k dispozici pouze v případě AVM2, nového virtuálního zařízení. Kód v jazyce ActionScript 3.0 umí provádět operace až desetkrát rychleji než kód v dřívějších verzích jazyka ActionScript. Starší verze ActionScript Virtual Machine, AVM1, pracuje s kódem v jazyce ActionScript 1.0 a ActionScript 2.0. AVM1 je podporován přehrávačem Flash Player 9 a 10 pro zpětnou kompatibilitu se stávajícím obsahem i obsahem z předcházejících verzí. Více informací naleznete v části „Kompatibilita s předchozími verzemi“ na stránce 7. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 5 Úvodní informace k jazyku ActionScript 3.0 Co je nového v jazyce ActionScript 3.0 Ačkoliv jazyk ActionScript 3.0 obsahuje mnoho tříd a funkcí, které budou pro programátory jazyka ActionScript známé, jazyk ActionScript 3.0 je architektonicky a koncepčně odlišný od předcházejících verzí ActionScript. Vylepšení v jazyce ActionScript 3.0 zahrnují nové funkce základního jazyka a vylepšené rozhraní API přehrávače Flash Player, které poskytuje lepší kontrolu objektů na nižších úrovních. Poznámka: Aplikace produktu Adobe® AIR™ mohou také použít rozhraní API přehrávače Flash Player. Základní jazykové prvky Základní jazyk definuje základní stavební bloky programovacího jazyka, například příkazy, výrazy, podmínky, opakování a typy. Jazyk ActionScript 3.0 obsahuje mnoho nových funkcí, které urychlují proces vývoje. Výjimky v době běhu Jazyk ActionScript 3.0 hlásí více stavů chyb než předcházející verze jazyka ActionScript. Výjimky v době běhu jsou použity pro běžné stavy chyb, vylepšují zkušenosti s laděním a umožňují vám vyvinout aplikace, které účinně zpracovávají chyby. Chyby v době běhu mohou poskytnout sledování zásobníku, které je anotováno se zdrojovým souborem a informací a počtu řádků. Tím vám umožňují rychlé a přesné určení chyb. Typy v době běhu V jazyce ActionScript 2.0 byly anotace určeny primárně pro pomoc vývojářům; v době běhu byly všechny hodnoty dynamicky typovány. V jazyce ActionScript 3.0 je informace typu v době běhu zachována a použita k několika účelům. Runtime přehrávače Flash Player a programu Adobe AIR provádějí kontrolu typu v době běhu a vylepšují tak zabezpečení typu systému. Informace o typu se také používá pro znázornění proměnných v nativních reprezentacích počítače, vylepšování výkonu a snižování využití paměti. Uzavřené třídy Jazyk ActionScript 3.0 zavádí koncept uzavřených tříd. Uzavřená třída má pouze fixní sadu vlastností a metod, které byly definovány v době běhu; další vlastnosti a metody přidat nelze. To umožňuje přísnější kontrolu v době kompilace, která přinese stabilnější programy. Vylepšuje také využití paměti tím, že nevyžaduje pro každou instanci objektu interní tabulku křížku. Dynamické třídy jsou také přístupné pomocí klíčového slova dynamic. Všechny třídy v definici jazyka ActionScript 3.0 jsou implicitně uzavřeny, ale lze je deklarovat tak, aby byly dynamické, a to s klíčovým slovem dynamic. Uzavření metody: Jazyk ActionScript 3.0 umožňuje uzavření metody pro automatické zapamatování si původní instance objektu. Tato funkce je užitečná pro zpracovávání událostí. V jazyce ActionScript 2.0 by si uzavření metody nepamatovala, z jaké instance objektu byla vyjmuta, což by vedlo k nečekanému chování při iniciaci uzavření metody. Třída mx.utils.Delegate byla oblíbením způsobem obejití tohoto problému, ale již není potřeba. ECMAScript pro XML (E4X) Jazyk ActionScript 3.0 implementuje ECMAScript pro XML (E4X), nedávno standardizovaný jako ECMA-357. E4X nabízí přirozenou plynulou sadu jazykových konstruktů pro manipulaci s XML. Oproti tradiční analýze XML rozhraní API má XML s E4X funkce stejné jako nativní datový typ jazyka. E4X urychluje vývoj aplikací, které manipulují s XML, a to značným snížením potřebného množství kódu. Více informací o implementaci jazyka ActionScript 3.0 E4X naleznete v části „Práce s jazykem XML“ na stránce 222. Pro zobrazení specifikace E4X ECMA přejděte na www.ecma-international.org. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 6 Úvodní informace k jazyku ActionScript 3.0 Regulární výrazy Jazyk ActionScript 3.0 zahrnuje nativní podporu pro regulární výrazy, takže můžete rychle vyhledávat řetězce a manipulovat s nimi. Jazyk ActionScript 3.0 implementuje podporu pro regulární výrazy dle jejich definice ve specifikaci jazyka ECMAScript (ECMA-262), 3. vydání. Jmenné prostory Jmenné prostory se podobají tradičním specifikátorům přístupu používaným pro ovládání viditelnosti deklarací (public, private, protected). Pracují jako vlastní specifikátory přístupu, které můžete pojmenovat dle svého výběru. Pro zabránění kolizím jsou jmenné prostory vybaveny identifikátorem Universal Resource Identifier (URI) a jsou také používány pro reprezentaci jmenných prostorů XML při práci s E4X. Nové primitivní typy Jazyk ActionScript 2.0 má jediný numerický typ, číslo, dvojitou přesnost a číslo s plovoucí čárkou. Jazyk ActionScript 3.0 obsahuje typy int a uint. Typ int je 32-bitové celé číslo se znaménkem, které umožňuje kódu jazyka ActionScript využít výhody rychlých matematických schopností celého čísla CPU. Typ int je užitečný pro čítače opakování a proměnné tam, kde jsou použita celá čísla. Typ uint je typ 32-bytového celého čísla bez znaménka, který je užitečný pro barevné hodnoty RGB, počty bytů, atd. Funkce rozhraní API přehrávače Flash Player Rozhraní přehrávače Flash Player API v jazyku ActionScript 3.0 obsahují mnoho tříd, které vám umožňují ovládat objekty na nízké úrovni. Architektura jazyka je navržena tak, aby byla intuitivnější než předchozí verze. Protože zde existuje příliš mnoho nových tříd, aby jsme se jim věnovali podrobně, zdůrazníme v následujících částech některé významné změny. Poznámka: Aplikace produktu Adobe® AIR™ mohou také použít rozhraní API přehrávače Flash Player. Model události DOM3 Model události Document Object Model Level 3 (DOM3) nabízí standardní způsob generování a zpracovávání hlášení událostí, takže objekty v rámci aplikací mohou navzájem reagovat a komunikovat, zachovají si svůj statut a budou reagovat na změny. Protože je tento model vytvořený dle Specifikací událostí konsorcia www (World Wide Web Consortium DOM Level 3 Events Specification), poskytuje jasnější a účinnější mechanismus než systémy událostí dostupné v předchozích verzích jazyka ActionScript. Události a události chyb jsou umístěny v balíku flash.events. Rámec komponent programu Flash používá stejný model událostí jako rozhraní přehrávače Flash Player API, takže je systém událostí na celé platformě Flash jednotný. Rozhraní API seznamu zobrazení Rozhraní API pro získání přístupu k seznamu zobrazení přehrávače Flash Player a programu Adobe API - stromová struktura, která obsahuje jakékoliv vizuální elementy v aplikaci - se skládá z tříd pro práci se základními vizuálními tvary. Nová třída Sprite je lehkým stavebním prvkem a podobá se třídě MovieClip, ale je vhodnější jako základní třída pro komponenty UI. Nová třída Shape představuje prosté vektorové tvary. Tyto třídy lze přirozeně konkretizovat pomocí operátoru new a lze je kdykoliv dynamicky znovu přiřadit jako nadřazené. Ovládání hloubky je nyní automatické a vestavěné do přehrávače Flash Player a programu Adobe AIR. Přiřazení čísel hloubky během vykreslování již není nutné. Pro určení a ovládání z-pořadí objektů jsou k dispozici nové metody. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 7 Úvodní informace k jazyku ActionScript 3.0 Zpracovávání dynamických dat a obsahu Jazyk ActionScript 3.0 obsahuje mechanismy pro načítání a zpracovávání datových zdrojů a dat ve vaší aplikaci, které jsou intuitivní a ve všech rozhraních API stejné. Nová třída Loader poskytuje jediný mechanismus pro načítání souborů SWF a datových zdrojů obrazů a nabízí způsob získání přístupu k podrobným informacím o načteném obsahu. Třída URLLoaderposkytuje samostatný mechanismus pro načítání textu a binárních dat v aplikacích zaměřených na data. Třída Socket poskytuje způsob načtení a zapsání binárních dat na servery soketů, a to v jakémkoliv formátu. Přístup k datům na nízké úrovni Různá rozhraní API poskytují přístup nízké úrovně k datům, který v jazyce ActionScript nikdy před tím dostupný nebyl. Pro načítaná data poskytuje třída URLStream, která je implementována URLLoader, při načítání přístup k datům jako k prvotním binárním datům. Třída ByteArray vám umožňuje optimalizovat čtení, zapisování a práci s binárními daty. Nové rozhraní API Sound poskytuje podrobné ovládání zvuku pomocí tříd SoundChannel a SoundMixer. Nová rozhraní API zabývající se zabezpečením poskytují informace o právech zabezpečení souboru SWF nebo načteného obsahu, a umožňují vám tak lepší zpracování chyb zabezpečení. Práce s textem Jazyk ActionScript 3.0 obsahuje balík flash.text pro všechna rozhraní API související s textem. Třída TextLineMetrics poskytuje podrobnou metriku pro řádek textu v rámci textového pole; nahrazuje metodu TextFormat.getTextExtent() v jazyce ActionScript 2.0. Třída TextField obsahuje několik zajímavých nových metod nízké úrovně, které mohou poskytnout specifické informace o řádku textu nebo jednotlivém znaku v textovém poli. Mezi tyto metody patří getCharBoundaries(), která vrátí obdélník představující ohraničovací rámeček znaku, getCharIndexAtPoint(), která vrátí index znaku v určitém bodě a getFirstCharInParagraph(), která vrátí index prvního znaku v odstavci. Mezi metody na úrovni řádku patří getLineLength(), která vrátí počet znaků na určitém řádku textu, a getLineText(), která vrátí text určeného řádku. Nová třída Font poskytuje způsob ovládání vnořených písem v souborech SWF. Kompatibilita s předchozími verzemi Přehrávač Flash Player jako vždy poskytuje plnou zpětnou kompatibilitu s předchozím publikovaným obsahem. Jakýkoliv obsah, který mohl být spuštěn v předchozích verzích přehrávače Flash Player, lze spustit i v přehrávači Flash Player verze 9 a pozdější. Úvod k jazyku ActionScript 3.0 v přehrávači Flash Player 9 nicméně uvádí některé problémy týkající se vzájemné spolupráce mezi starým a novým obsahem spuštěným v přehrávači Flash Player 9 nebo pozdější. Mezi problémy se slučitelností patří: • Jediný soubor SWF nemůže kombinovat kód jazyka ActionScript 1.0 nebo 2.0 s kódem jazyka ActionScript 3.0. • Kód jazyka ActionScript 3.0 může načíst soubor SWF zapsaný v jazyce ActionScript 1.0 nebo 2.0, ale nemůže získat přístup k proměnným a funkcím daného souboru SWF. • Soubory SWF zapsané v jazyce ActionScript 1.0 nebo 2.0 nemohou načíst soubory SWF zapsané v jazyce ActionScript 3.0. To znamená, že soubory SWF vytvořené v programu Flash 8 nebo Flex Builder verze 1.5 nebo starší nemohou načíst soubory SWF jazyka ActionScript 3.0 SWF. Jedinou výjimkou tohoto pravidla je, že soubor SWF jazyka 2.0 SWF může nahradit sám sebe souborem SWF jazyka ActionScript 3.0, pokud soubor SWF jazyka ActionScript 2.0 dříve nenačetl nic na žádnou ze svých úrovní. Soubor SWF jazyka ActionScript 2.0 může tento postup provést voláním loadMovieNum() a předáním hodnoty 0 parametru level. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 8 Úvodní informace k jazyku ActionScript 3.0 • Obecně musí být soubory zapsané v jazyce ActionScript 1.0 nebo 2.0 migrovány, jestliže mají spolupracovat se soubory SWF zapsanými v jazyce ActionScript 3.0. Představte si například, že jste pomocí jazyka ActionScript 2.0 vytvořili přehrávač médií. Tento přehrávač médií načítá různý obsah, který byl také vytvořen pomocí jazyka ActionScript 2.0. Nemůžete vytvořit nový obsah v jazyce ActionScript 3.0 a načíst jej do daného přehrávače médií. Musíte daný přehrávač migrovat do jazyka ActionScript 3.0. Jestliže ale přehrávač vytvoříte v jazyce ActionScript 3.0, může daný přehrávač médií provést jednoduché načtení obsahu jazyka ActionScript 2.0. Následující tabulka uvádí souhrn omezení předchozích verzí přehrávače Flash Player ve vztahu k načítání nového obsahu a spouštění kódu, i omezení křížového skriptu mezi soubory SWF zaspanými v různých verzích jazyka ActionScript. Podporované funkce Flash Player 7 Flash Player 8 Flash Player 9 a 10 Načíst můžete soubory SWF publikované pro verzi 7 a starší verzi 8 a starší 9 (nebo 10) a dřívější Obsahuje tento AVM AVM1 AVM1 AVM1 a AVM2 Spustí soubory SWF zapsané v jazyce ActionScript 1.0 a 2.0 1.0 a 2.0 1.0 a 2.0 a 3.0 V následující tabulce se pojem „Podporované funkce“ vztahuje na obsah spuštěný v přehrávači Flash Player verze 9 nebo starší. Obsah spuštěný v přehrávači Flash Player verze 8 nebo starší lze načíst, zobrazit, spustit a křížově skriptovat pouze v jazyku ActionScript 1.0 a 2.0. Podporované funkce Obsah vytvořený v jazyce ActionScript 1.0 Obsah vytvořený v jazyce ActionScript 3.0 a 2.0 Může načíst obsah a spustit kód vytvořený pouze v jazyce ActionScript 1.0 a 2.0 v jazyce ActionScript 1.0 a 2.0 jazyce ActionScript 3.0 Může křížit obsah skriptu vytvořený pouze v jazyce ActionScript 1.0 a 2.0 (ActionScript 3.0 pouze pomocí místního připojení) v jazyce ActionScript 1.0 a 2.0 pomocí LocalConnection. ActionScript 3.0 9 Kapitola 3: Začínáme s ActionScriptem Tato kapitola je navržena tak, aby vám pomohla začít s programováním v jazyce ActionScript a poskytla vám základní informace nutné k porozumění konceptům a příkladům ve zbývající části této příručky. Začneme diskusí o základních konceptech programování, popsaných v kontextu jejich aplikování v jazyce ActionScript. Rovněž se podíváme na základy organizování a vytváření aplikací v jazyce ActionScript. Základy programování Protože ActionScript je programovací jazyk, bude při jeho studiu nejprve porozumět několika obecným konceptům počítačového programování. Co dělají počítačové programy Nejprve je vhodné koncepčně porozumět tomu, co počítačový program je a co má za úkol. Existují dva hlavní aspekty počítačového programu: • Program je sledem instrukcí nebo kroků, které má počítač provádět. • Každý krok znamená zpracování části informace nebo dat. V obecném smyslu je počítačový pouze seznamem posloupností instrukcí, které předáváme počítači, aby je jednu za druhou provedl. Každá jednotlivá instrukce se nazývá příkaz. Jak v této příručce dále uvidíte, v jazyce ActionScript je každý příkaz zapsán na konci se středníkem. V podstatě všechny instrukce uvedené v programu zpracovávají kus dat, který je uložen v paměti počítače. V jednoduchém případě můžete počítači vydat příkaz sečíst dvě čísla a uložit výsledek do paměti. Ve složitějších případech si představte, že existuje obdélník vykreslený na obrazovce a vy chcete napsat program, který jej přesune jinam na obrazovce. Počítač sleduje jisté informace o obdélníku - souřadnice X, Y umístění, jeho šířku a výšku, barvu atd. Každý takový kus informace je uložen kdesi v paměti počítače. Program pro přesunutí obdélníku do jiného umístění bude mít kroky, jako například „změnit souřadnici X na 200; změnit souřadnici Y na 150“ (jinými slovy, specifikování nových hodnot použitých pro souřadnice X a Y). Samozřejmě, že počítač s těmito daty cosi učiní, aby čísla přetvořil v obrázek, který se zobrazí na obrazovce počítače; ale v rámci podrobností, které nás zajímají, postačuje znát, že proces „přesouvání obdélníku na obrazovce“ pouze zahrnuje změny kusů dat v počítačové paměti. Proměnné a konstanty Protože programování převážně zahrnuje změnu kusů informace v paměti počítače, existuje potřeba vyjadřování kusů informací v programu. Proměnná je název vyjadřující hodnotu v paměti počítače. Když zapisujete příkaz pro zpracování hodnot, zapisujete název proměnné namísto hodnoty; kdykoliv počítač vidí v programu název proměnné, prohledá paměť a použije hodnotu, kterou zde nalezne. Například pokud máte dvě proměnné pojmenované value1 a value2 a každá obsahuje číslo, pro sečtené těchto dvou čísel můžete zapsat příkaz: value1 + value2 Při provádění těchto kroků počítač vyhledá hodnoty každé proměnné a poté je sečte. V jazyce ActionScript 3.0 je proměnná tvořena třemi různými součástmi: • Název proměnné PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 10 Začínáme s ActionScriptem • Typ dat, které lze do proměnné uložit • Skutečná hodnota uložená v paměti počítače Právě jsme popsali, jak počítač používá název jako vyhrazené místo pro hodnotu. Typ dat je také důležitý. Když v jazyce ActionScript vytvoříte proměnnou, zadáváte specifický typ dat, které bude uchovávat; poté mohou instrukce programu uložit pouze typ dat v proměnné a můžete zpracovat hodnotu pomocí specifické charakteristiky související s příslušným datovým typem. V jazyce ActionScript vytváříte proměnnou (nazývá se to deklarování proměnné) pomocí příkazu var: var value1:Number; V tomto případě sdělujeme počítači, aby vytvořit proměnnou pojmenovanou value1, která uchová pouze číselná data („číslo“ je specifický datový typ definovaný v jazyce ActionScript). Hodnotu můžete také uložit přímo do proměnné: var value2:Number = 17; V aplikaci Adobe Flash CS4 Professional existuje jiný způsob, jak deklarovat proměnnou. Když umístíte symbol filmového klipu, symbol tlačítka nebo textové pole na plochu, můžete jej pojmenovat názvem instance v Inspektoru vlastností. Na pozadí aplikace Flash vytvoří proměnnou se stejným názvem, jaký má instance, který můžete použít v kódu ActionScript k odkazování na položku plochy. Takže pokud máte například symbol filmového klipu na ploše a pojmenujete jej názvem instance rocketShipkdykoliv použijete proměnnou rocketShip v kódu jazyka ActionScript, budete ve skutečnosti zpracovávat daný filmová klip. Konstanta je velmi podobná proměnné v tom smysli, že její název zastupuje v paměti počítače hodnotu se stanoveným datovým typem. Rozdíl je v tom, že konstanta může mít přiřazenou hodnotu pouze v průběhu aplikace jazyka ActionScript. Jakmile je hodnota konstanty přiřazena, je stejná v celé aplikaci. Syntaxe pro deklarování konstanty je shodná jako pro deklarování proměnné, kromě toho, že použijete klíčové slovo const místo slova var: const SALES_TAX_RATE:Number = 0.07; Konstanta je užitečná pro definování hodnoty, která se používá na několika místech projektu, které se za normálních okolností nebudou měnit. Použitím konstanty namísto použití hodnoty literálu bude váš kód čitelnější. Například je snazší porozumět smyslu řádky kódu, který násobí cenu hodnotou SALES_TAX_RATE, ve srovnání s řádkem kódu, který násobí cenu hodnotou 0.07. Kromě toho, musí-li se hodnota definovaná konstantou někdy změnit, pokud použijete konstantu k vyjádření dané hodnoty v celém projektu, musíte pouze změnit hodnotu na jednom místě (deklarace konstanty), nemusíte ji tedy měnit na různých místech, jako by tomu bylo u pevně stanovených literálových hodnot. Typy dat V jazyce ActionScript existuje mnoho datových typů, které můžete použít jako datový typ vytvářené proměnné. Některé z těchto typů můžete považovat za „jednoduché“ nebo „základní“ datové typy: • String (řetězec): textová hodnota, například název nebo text kapitoly knihy • Numeric (číselný typ): jazyk ActionScript 3.0 zahrnuje tři specifické datové typy pro číselná data: • Number (číslo): kterákoliv číselná hodnota, zahrnující hodnoty se zlomkem nebo bez něj • int: celočíselná hodnota (celé číslo bez zlomku) • uint: celočíselná hodnota bez znaménka, což znamená, že celé číslo nemůže být záporné • Boolean (booleovská hodnota): logická hodnota PRAVDA nebo NEPRAVDA, například jako přepínač, který může být zapnutý nebo vypnutá, nebo zad se dvě hodnoty rovnají či nikoliv PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 11 Začínáme s ActionScriptem Jednoduché datové typy představují jednotlivý kus informací: například jedno číslo nebo jednu posloupnost textu. Většina datových typů definovaných v jazyce ActionScript by mohla být popsána jako komplexní datové typy, protože představují soubor seskupených hodnot. Například proměnná s datovým typem Date představuje jednu hodnotu časový okamžik. Datová hodnota je však zastoupena jako několik hodnot - den, měsíc, rok, hodina, minuta, sekunda atd., všechny ty jsou jednotlivými čísly. Takže když uvažujeme o datu jako o jednotlivé hodnotě (a můžeme jej zpracovat jako jednotlivou hodnotu vytvořením proměnné Date), vnitřně o něm počítač uvažuje jako o několika seskupených hodnotách, definujících jediné datum. Většina z vestavěných datových typů a také datových typů definovaných programátory, jsou komplexní datové typy. Některé komplexní datové typy jsou následující: • MovieClip: symbol filmového klipu • TextField: dynamické nebo vstupní textové pole • SimpleButton: symbol tlačítka • Date: informace o jednotlivém okamžiku v čase (datum a čas) Dvě slova, která jsou často používána jako synonymum pro datový typ, jsou třída a objekt. Třída je jednoduše definicí datového typu - je to jako šablona všech objektů datového typu, jako bychom tvrdili „všechny proměnné datového typu Example mají tyto vlastnosti: A, B a C.“ Object je na druhou stranu pouze stávající instancí třídy; proměnnou, jejíž datový typ je MovieClip, je možné popsat jako objekt MovieClip. Níže jsou uvedeny různé způsoby, jak vyjádřit stejnou věc: • Datový typ proměnné myVariable je Number. • Proměnná myVariable je instancí Number. • Proměnná myVariable je objektem Number. • Proměnná myVariable je instancí třídy Number. Práce s objekty Jazyk ActionScript znám jako objektově orientovaný programovací jazyk. Objektově orientované programování je jednoduše přístup k programování - nic více, než způsob organizování kódu v programu pomocí objektů. Dříve jsme definovali počítačový program jako soubor kroků nebo instrukcí, které počítač provádí. Koncepčně je pak možné si představit počítačový program jako jeden dlouhý seznam instrukcí. U objektově orientovaného programování jsou však instrukce programu rozděleny mezi různé objekty - kód je seskupen do kusů funkcí, takže související typy funkcí nebo související kusy informace jsou seskupeny dohromady v jednom kontejneru. Pokud jste v aplikaci Flash pracovali se symboly, již jste pracovali s objekty. Představte si, že jste definovali symbol filmového klipu - vykreslení obdélníku - a umístili jste jeho kopii na plochu. Tento symbol filmového klipu je (doslova) objektem v jazyce ActionScript, instancí třídy MovieClip. Existují různé charakteristiky filmového klipu, které můžete změnit. Například když jej vyberete, existují zde hodnoty, které můžete změnit v Inspektoru vlastností, například souřadnici X, nebo šířku či různá nastavení barvy, například změnit hodnotu alfa (průhlednost), nebo aplikování filtru vrženého stínu. Jiné nástroje aplikace Flash umožní provádět více změn, například používání nástroje Volná transformace k otočení obdélníku. Všechny tyto věci, které můžete provádět pro modifikování symbolu filmového klipu ve vývojovém prostředí Flash jsou také věci, které můžete provádět v jazyce ActionScript změnou kusů dat, které jsou složeny k sobě do jednoho svazku nazvaného objekt MovieClip. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 12 Začínáme s ActionScriptem V objektově orientovaném programování v jazyce ActionScript existují tři typy charakteristiky, které může obsahovat kterákoliv třída. • Vlastnosti • Metody • Události Společně jsou tyto prvky použity pro správu kusů dat použitých programem a pro rozhodování o tom, které činnosti jsou provedeny a v jakém pořadí. Vlastnosti Vlastnost představuje jeden z kusů dat, které jsou seskupené dohromady do objektu. Objekt song může mít vlastnosti pojmenované artist a title; třída MovieClip má vlastnosti rotation, x, width a alpha. S vlastnostmi pracujete jako s jednotlivými proměnnými - ve skutečnosti na vlastnosti můžete pohlížet jako na „podřízenou“ proměnnou obsaženou v objektu. Zde jsou některé příklady kódu jazyka ActionScript využívajícího vlastnosti. Tento řádek kódu pohybuje klipem MovieClip pojmenovaným square do souřadnice X o 100 obrazových bodů: square.x = 100; Tento kód používá vlastnost rotation k otočení MovieClip square tak, aby to odpovídalo otočení MovieClip triangle: square.rotation = triangle.rotation; Tento kód mění horizontální stupnici třídy MovieClip square tak, aby byla 1,5krát větší než předtím: square.scaleX = 1.5; Povšimněte si společné struktury: používáte proměnnou (square, triangle) jako název objektu, následuje tečka (.) a pak název vlastnosti (x, rotation, scaleX). Tečka, které se říká operátor dot, se používá k označení přístupu k jednomu z podřízených prvků objektu. Celá struktura společně, „název proměnné-tečka-název vlastnosti“ se používá jako jedna proměnná, jako název jedné hodnoty v paměti počítače. Metody Metoda je činností, kterou může provádět objekt. Například pokud vytvoříte v aplikaci Flash symbol filmového klipu několika klíčovými snímky a animaci v časové ose, tento filmový klip lze přehrát, zastavit nebo přesunou na specifický snímek. Tento kód vydává instrukci klipu MovieClip pojmenovanému shortFilm, aby se začal přehrávat: shortFilm.play(); Tato řádka způsobí zastavení klipu MovieClip pojmenovaného shortFilm (přehrávací hlava se zastaví na místě, jako při pozastavení videa): shortFilm.stop(); Tento kód vydává instrukci klipu MovieClip pojmenovanému shortFilm přesunout přehrávací hlavu na snímek Frame 1 a zastavit přehrávání (jako při převíjení videa): shortFilm.gotoAndStop(1); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 13 Začínáme s ActionScriptem Jak můžete vidět, metody, podobně jako vlastnosti, jsou přístupné zapsáním názvu objektu (proměnné), pak tečky, pak názvu metody následované závorkami. Závory jsou způsobem, jak naznačit, že voláte metodu - jinými slovy vydává objektu instrukci provést danou činnost. Někdy jsou hodnoty (či proměnné) umístěny do závorek, což je způsob předání dalších informace, které jsou nutné k provedení činnosti. Tyto hodnoty jsou známy jako parametry metody. Například metoda gotoAndStop() musí znát snímek na který má přejít, takže vyžaduje v závorce jeden parametr. Jiné metody, jako play() a stop(), jsou zřejmé a nevyžadují další informace. Nicméně jsou i přesto psány se závorkami. Na rozdíl od vlastností (a proměnných) nejsou metody použity jako vyhrazená místa pro hodnotu. Některé metody však mohou provádět výpočty a vracet výsledky, které lze použít jako proměnnou. Například metoda toString() třídy Number převádí číselnou hodnotu na textové vyjádření. var numericData:Number = 9; var textData:String = numericData.toString(); Například můžete použít metodu toString() v případě, že chcete zobrazit hodnotu proměnné Number v textovém poli na obrazovce. Vlastnost text třídy TextField (představující skutečný obsah textu zobrazený na obrazovce) je definován jako String, takže může obsahovat pouze textové hodnoty. Tento řádek kódu převádí číselnou hodnotu v proměnné numericData na text a pak jej zobrazí na obrazovce v objektu TextField pojmenovaném calculatorDisplay: calculatorDisplay.text = numericData.toString(); Události Popsali jsme počítačový program jako řadu instrukcí, které počítač vykonává krok za krokem. Některé jednoduché počítačové programy nejsou tvořeny ničím jiným - několika kroky, které počítač provede a poté se ukončí. Programy v jazyce ActionScript jsou však navrženy tak, aby se uchovaly v chodu, vyčkaly na vstup uživatele nebo jinou událost. Události jsou mechanismy jež stanoví, které instrukce počítač provede a kdy. V podstatě jsou události věci, které nastávají, kterých si je jazyk ActionScript vědom a může na ně reagovat. Mnoho událostí souvisí s interakcí uživatele - klepnutí na tlačítko, stisknutí kláves - ale existují také jiné typy událostí. Pokud například použijete jazyk ActionScript k načtení externího obrázku, existuje události, která vás vyrozumí, když načítání obrázku skončí. Když program jazyka ActionScript pracuje, aplikace Adobe Flash Player a Adobe AIR pouze vyčkají na to, než nastanou některé události, a když k nim dojde, spustí specifický kód jazyka ActionScript, který jste pro tyto události stanovili. Základní zpracování událostí Technika specifikování jistých činností, které by měly být provedeny v odezvě na specifické události, je známá jako zpracování událostí. Když zapisujete kód v jazyce ActionScript k provedení zpracování události, existují tři důležité prvky, které musíte identifikovat: • Zdroj události: který objekt je ten, jemuž se událost přihodí? Například na které tlačítko bude klepnuto, nebo který objekt Loader bude načítat obrázek? Zdroj události se také nazývá cíl události, protože se jedná o objekt, kde je událost cílena aplikací Flash Player nebo AIR (tj. kde k události ve skutečnosti dochází). • Událost: co je to za věc, která se stane, věc, na kterou chcete reagovat? To je důležité identifikovat, protože mnoho objektů spouští několik událostí. • Odezva: jaké kroky chcete provádět když k události dojde? Vždy když zapisujete kód ActionScript pro zpracování událostí, bude zahrnovat tyto tři prvky a kód bude dodržovat základní strukturu (prvky napsané tučně jsou vyhrazená místa, která pro specifický případ vyplníte): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 14 Začínáme s ActionScriptem function eventResponse(eventObject:EventType):void { // Actions performed in response to the event go here. } eventSource.addEventListener(EventType.EVENT_NAME, eventResponse); Tento kód provádí dvě věci. Nejprve definuje funkci, která je způsobem specifikace činností, které budou provedeny v odezvě na událost. Dále je zavolána metoda addEventListener() zdrojového objektu, v podstatě “odběr” specifikované události funkcí tak, že když k události dojde, jsou provedeny činnosti funkce. Každou z těchto částí popíšeme podrobněji. Funkce poskytuje způsob, kterým můžete seskupit činnosti dohromady, s jedním názvem, který je jako název zástupce k provedené činností. Funkce je shodná s metodou, kromě toho, že nemusí být nutně spojena se specifickou třídou (ve skutečnosti může být metoda definována jako funkce, která souvisí se specifickou třídou). Když vytváříte funkci pro zpracování událostí, musíte vybrat název této funkce (v tomto případě je pojmenovaná eventResponse). Musíte také specifikovat jeden parametr (v tomto případě je pojmenovaný eventObject). Specifikování parametru funkce je jako deklarování proměnné, takže musíte také uvést datový typ parametru. (V tomto příkladu je datový typ parametru EventType.) Každý typ události, které chcete naslouchat, má připojenou třídu jazyka ActionScript. Specifikovaný datový typ pro parametr funkce je vždy přidruženou třídou specifické události, na kterou chcete reagovat. Například událost click (spustí se, když uživatel klepne na položku myší) je připojena k třídě MouseEvent. Chcete-li zapsat funkci posluchače pro událost click, definuje funkci posluchače s parametrem datového typu MouseEvent. Nakonec mezi levou a pravou složenou závorkou ({ ... }) zapište instrukce, které má počítač provést. Jakmile zapíšete funkci pro manipulaci s událostí, musíte sdělit objektu zdroje události (objekt, kterému se událost stane - například tlačítko), že chcete zavolat funkci, kdy k události dojde. To provedete zavoláním metody addEventListener() tohoto objektu (všechny objekty, které mají události, mají také metodu addEventListener()). Metoda addEventListener()má dva parametry: • První, název specifické události, na kterou chcete reagovat. Znovu, každá událost je spojena se specifickou třídou a tato třída bude mít speciální hodnotu předdefinovanou pro každou událost - podobně jako jedinečný název události, který byste měli použít pro první parametr. • Druhý, název funkce odezvy na událost. Povšimněte si, že název funkce je zapsán bez závorek, když je předáván jako parametr. Prověření procesu zpracování události Následující podrobný popis se věnuje procesu, který nastává, když vytvoříte posluchače události. V tomto případě je příkladem vytvoření funkce posluchače, která je zavolaná po klepnutí na objekt nazvaný myButton. Skutečný programátorem zapsaný kód je následující: function eventResponse(event:MouseEvent):void { // Actions performed in response to the event go here. } myButton.addEventListener(MouseEvent.CLICK, eventResponse); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 15 Začínáme s ActionScriptem Zde je uvedeno, jak by kód pracoval při spuštění v aplikaci Flash Player. (Toho chování je také identické pro aplikaci Adobe AIR): 1 Když se načte soubor SWF, aplikace Flash Player si povšimne skutečnosti, že existuje funkce pojmenovaná eventResponse(). 2 Přehrávač Flash Player pak spustí kód (specificky řádky kódu, které nejsou funkcí). V tomto případě to je pouze jedna řádka kódu: zavolání metody addEventListener() pro objekt zdroje události (pojmenovaný myButton) a předávající funkci eventResponse jako parametr. a Vnitřně má objekt myButton seznam funkcí, které naslouchají jeho událostem, takže když je zavolána metoda addEventListener(), objekt myButton uloží funkci eventResponse() do seznamu posluchačů událostí. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 16 Začínáme s ActionScriptem 3 V některém bodě uživatel klepne na objekt myButton, spustí událost click (identifikována v kódu jako MouseEvent.CLICK). V tento okamžik nastane následující: a Přehrávač Flash Player vytvoří objekt, instanci třídy spojenou s dotyčnou událostí (v tomto příkladu MouseEvent). Pro mnoho události to bude instance třídy Event; pro události myši to bude instance MouseEvent a pro ostatní události to bude instance třídy, která je danou událostí spojena. Tento vytvořený objekt je znám jako objekt události a obsahuje specifické informace o událostí, které nastaly, o jaký typ události se jedná, kde k ní došlo a ostatní informace specifické pro danou události, pokud jsou k dispozici. b Přehrávač Flash Player poté vyhledá posluchače událostí uložené objektem myButton. Postupně projde těmito funkcemi, zavolá každou z nich a předá objekt události funkci jako parametr. Protože funkce eventResponse() je jednou z posluchačů objektu myButton, jako součást tohoto procesu aplikace Flash Player zavolá funkci eventResponse(). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 17 Začínáme s ActionScriptem c Když je zavolána funkce eventResponse(), kód v této funkci se spustí, takže jsou vykonány specifikované činnosti. Příklady zpracování událostí Zde je uvedeno několik dalších konkrétních příkladů událostí, které vám umožní získat představu o některých běžných prvcích událostí a možných dostupných změnách, když zapisujete kód zpracování události. • Klepnutím na tlačítko spustíte přehrávání stávajícího filmového klipu. V následujícím příkladu je playButton název instance tlačítka a this je speciální název, mající význam „stávající objekt“: this.stop(); function playMovie(event:MouseEvent):void { this.play(); } playButton.addEventListener(MouseEvent.CLICK, playMovie); • Detekce zadávání textu do pole. V tomto příkladu je entryText vstupní textové pole a outputText je dynamické textové pole: function updateOutput(event:TextEvent):void { var pressedKey:String = event.text; outputText.text = "You typed: " + pressedKey; } entryText.addEventListener(TextEvent.TEXT_INPUT, updateOutput); • Klepnutí na tlačítko a přesun na adresu URL. V tomto příkladu je linkButton názvem instance tlačítka: function gotoAdobeSite(event:MouseEvent):void { var adobeURL:URLRequest = new URLRequest("http://www.adobe.com/"); navigateToURL(adobeURL); } linkButton.addEventListener(MouseEvent.CLICK, gotoAdobeSite); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 18 Začínáme s ActionScriptem Vytváření instancí objektu Samozřejmě, že předtím, než můžete použít objekt v jazyce ActionScript, musí tento objekt existovat. Jednou z částí procesu vytváření objektu je deklarování proměnné. Toto deklarování však pouze vytvoří prázdné místo v paměti počítače. Proměnné musíte přiřadit skutečnou hodnotu - tj. vytvořit objekt a uložit jej do proměnné - před pokusem o použití nebo zpracování. Procesu vytváření objektu se říká konkretizace objektu - jinými slovy vytvoření instance specifické třídy. Jednoduchý způsob vytvoření instance objektu vůbec nevyžaduje jazyk ActionScript. V aplikaci Flash, když umístíte symbol filmového klipu, tlačítka nebo textové pole na plochu a přiřadíte mu název instance v Inspektoru vlastností, aplikace Flash automaticky deklaruje proměnnou s tímto názvem instance, vytvoří instanci objektu a uloží tento objekt do proměnné. Podobně, ve vývojovém prostředí Adobe Flex Builder, když vytváříte součást v aplikaci MXML (buď kódováním značky MXML nebo uložením součásti do editoru v režimu návrhu) a přiřadíte ID této součásti (v MXML nebo zobrazení Vlastnosti Flex), toto ID se stane názvem proměnné ActionScript a vytvoří se instance součásti, která se uloží v proměnné. Vždy však nebudete chtít vytvářet objekt vizuálně. Existuje několik způsobů, jak můžete vytvořit instance objektu pouze pomocí jazyka ActionScript. Nejprve s několika datovými typy ActionScript můžete vytvořit instanci pomocí literálového výrazu - hodnoty zapsané přímo do kódu jazyka ActionScript. Zde jsou uvedeny některé příklady: • Literálová číselná hodnota (zadejte číslo přímo): var someNumber:Number = 17.239; var someNegativeInteger:int = -53; var someUint:uint = 22; • Literálová hodnota řetězce (text uložte do uvozovek): var firstName:String = "George"; var soliloquy:String = "To be or not to be, that is the question..."; • Literálové booleovská hodnota (použijte literálové hodnoty true nebo false): var niceWeather:Boolean = true; var playingOutside:Boolean = false; • Literálová hodnota pole (seznam hodnot oddělených čárkami v vložte do hranatých závorek): var seasons:Array = ["spring", "summer", "autumn", "winter"]; • Literálová hodnota XML (zadejte XML přímo): var employee:XML = <employee> <firstName>Harold</firstName> <lastName>Webster</lastName> </employee>; Jazyk ActionScript také definuje literálové výrazy pro datové typy Array, RegExp, Object a Function. Podrobnosti o těchto třídách naleznete v části „Práce s poli“ na stránce 152, „Používání regulárních výrazů“ na stránce 202 a „Datový typ Object“ na stránce 58. V případě dalších datových typů, chcete-li vytvořit instanci objektu, použijte operátor new s názvem třídy, takto: var raceCar:MovieClip = new MovieClip(); var birthday:Date = new Date(2006, 7, 9); Vytváření objektu pomocí operátoru new je často označováno za „volání konstruktoru třídy“. Konstruktor je speciální metodou volanou jako část procesu vytváření instance třídy. Povšimněte si, že když vytváříte instanci tímto způsobem, závorky dáváte za název třídy a někdy zadáváte hodnoty parametru - dvě věci, které také činíte při volání metody. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 19 Začínáme s ActionScriptem I pro ty datové typy, které umožňují vytvářet instance pomocí literálového výrazu, můžete použít operátor new k vytvoření instance objektu. Například tyto dvě řádky kódu provádějí zcela stejnou činnost: var someNumber:Number = 6.33; var someNumber:Number = new Number(6.33); Je důležité se dobře seznámit s vytvářením objektů způsobem newClassName() . Pokud potřebujete vytvořit instanci datového typu jazyka ActionScript, který nemá vizuální znázornění (a proto jej nelze vytvořit uložením položky na plochu aplikace Flash nebo v režimu návrhu editoru MXML vývojového prostředí Flex Builder), může tak učinit pouze vytvořením objektu přímo v jazyce ActionScript pomocí operátoru new. Specificky v aplikaci Flash operátor new můžete také použít pro vytvoření instance symbolu filmového klipu, který je definován v knihovně, ale není umístěn na plochu. Další informace naleznete v části „Vytváření objektů MovieClip pomocí kódu ActionScript“ na stránce 402. Společné prvky programu Kromě deklarování proměnných, vytváření instancí objektů a manipulace s objekty pomocí jejich vlastností a metod existuje několik dalších stavebních bloků, které potřebujete vytvořit v programu jazyka ActionScript. operátory Operátory jsou speciální symboly (nebo příležitostně slova), která jsou používána k provádění výpočtů. Jsou většina používány pro matematické operace a rovněž pro porovnávání hodnot. Jako obecné pravidlo používá operátor jednu nebo více hodnot a „vypracuje“ jeden výsledek. Například: • Operátor sčítání (+) sečte dvě hodnoty a vytvoří jedno číslo: var sum:Number = 23 + 32; • Operátor násobení (*) vynásobí jednu hodnotu druhou a vytvoří jedno číslo: var energy:Number = mass * speedOfLight * speedOfLight; • Operátor rovnosti (==) porovná dvě hodnoty a poskytne výsledek ve formě jedné booleovské hodnoty (pravda nebo nepravda). if (dayOfWeek == "Wednesday") { takeOutTrash(); } Jak je zde znázorněno, operátor rovnosti a další operátory „porovnání“ jsou nejčastěji používány s příkazem if, zda mají být některé instrukce vykonány nebo nikoliv. Podrobnosti a příklady použití operátorů naleznete v kapitole „Operátory“ na stránce 68. Poznámky Když zapisujete kód jazyka ActionScript, často budete sami pro sebe zanechávat poznámky, vysvětlující jak části kódu pracují nebo proč jste provedli specifický výběr. Komentáře kódu jsou nástrojem pro zapsání textu, který by měl počítač v kódu ignorovat. Jazyk ActionScript zahrnuje dva typy komentářů: • Jednořádkový komentář: jednořádkový komentář je označen vložením dvou lomítek kdekoliv do řádky. Vše za lomítky až na konec řádky je počítačem ignorováno. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 20 Začínáme s ActionScriptem // This is a comment; it's ignored by the computer. var age:Number = 10; // Set the age to 10 by default. • Víceřádkový komentář: víceřádkový komentář zahrnuje značku počátku (/*), pak samotný obsah a nakonec značku konce (*/). Vše mezi počáteční a koncovou značkou je počítačem ignorováno, bez ohledu na počet řádku, na kterých se komentář nachází. /* This might be a really long description, perhaps describing what a particular function is used for or explaining a section of code. In any case, these lines are all ignored by the computer. */ Dalším běžným použitím komentáře je dočasné „vypnutí“ jednoho nebo několika řádků kódu - například testujete různé způsoby funkce, nebo zkoušíte zjistit, proč kód jazyka ActionScript nepracuje způsobem, kterým požadujete. Řízení toku Mnohokrát v programu budete potřebovat opakovat jisté činnosti, provést pouze jedny činnosti a nikoliv druhé, provést alternativní činnosti v závislosti na podmínkách atd. Řízení toku je ovládáním provádění jednotlivých činností. Existuje několik typů prvků řízení tok, které jsou v jazyce ActionScript dostupné. • Funkce: funkce jsou jako zástupci - poskytují možnost seskupení činnosti pod jedním názvem a mohou být použity k provedení výpočtů. Funkce jsou obzvláště důležité pro zpracování událostí, ale jsou také použity jako obecné nástroje pro seskupení řady instrukcí. Další informace o funkcích, viz „Funkce“ na stránce 78. • Cykly: struktury cyklů umožňují označit sadu instrukcí, kterou bude počítač provádět po stanovený počet opakování, nebo dokud se nezmění stanovená podmínka. Cykly se často používají pro zpracování několika souvisejících položek, pomocí proměnné, jejíž hodnota se změní pokaždé, když počítač dokončí jednotlivý cyklus. Další informace o cyklech, viz „Opakování“ na stránce 75. • Podmíněný příkaz: podmíněný příkaz poskytuje způsob, jak označit jisté instrukce, které mají být provedeny pouze za jistých okolností nebo pro poskytnutí alternativní sady instrukcí pro různé podmínky. Nejběžnějším typem podmíněného příkazu je příkaz if. Příkaz if kontroluje hodnotu nebo výraz v závorkách. Pokud je hodnota true, řádky kódu ve složených závorkách jsou provedeny, jinak jsou ignorovány. Například: if (age < 20) { // show special teenager-targeted content } Společník příkazu if, příkaz else, umožňuje označit alternativní instrukce, které mají být provedeny pokud podmínka nemá hodnotu true: if (username == "admin") { // do some administrator-only things, like showing extra options } else { // do some non-administrator things } Další informace o podmíněném příkazu, viz „Podmíněné příkazy“ na stránce 73. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 21 Začínáme s ActionScriptem Příklad: animace kusu portfolia Tento příklad je navržen tak, aby vám poskytl příležitost vidět, jak můžete sestavit kusy kódu ActionScript do kompletní, pokud ne rovnou kódem ActionScript propletené, aplikace. Animace kusu portfolia je příkladem, jak můžete vzít stávající lineární animaci (například kus vytvořený pro klienta) a přidat drobné interaktivní prvky vhodní pro vložení této animace do online portfolia. Interaktivní chování, které přidáme do animace, bude zahrnovat dvě tlačítka, na které může uživatel klepnout: jedno pro spuštění animace a druhé pro přechod na samostatnou adresu URL (například nabídka portfolia nebo úvodní stránka autora). Proces vytvoření tohoto kusu lze rozdělit do následujících hlavních částí: 1 Připravení souboru FLA pro přidání kódu v jazyce ActionScript a interaktivních prvků. 2 Vytvoření a přidání tlačítek. 3 Zapsání kódu v jazyce ActionScript. 4 Testování aplikace. Příprava na přidání interaktivních prvků Před přidáním interaktivních prvků do animace je vhodné nastavit soubor FLA vytvořením míst pro přidání nového obsahu. Sem patří vytvoření skutečného prostoru na ploše, kde lze umístit tlačítka a také vytvoření „prostoru“ v souboru FLA pro uchování samostatnosti různých položek. Chcete-li nastavit soubor FLA pro přidání interaktivních prvků: 1 Pokud zatím nemáte lineární animaci, do které byste přidali interaktivní prvky, vytvořte nový soubor FLA s jednoduchou animaci jako je jednotlivé doplnění pohybu nebo doplnění tvaru. Jinak otevřete soubor FLA obsahující animaci, kterou zobrazujete v projektu a uložte jej s novým názvem a vytvořte tak nový pracovní soubor. 2 Rozhodněte se, kde na obrazovce chcete zobrazit dvě tlačítka (jedno pro spuštění animace, druhé pro připojení k portfoliu autora nebo jeho výchozí stránce). V případě potřeby pro tento nový obsah uvolněte nebo přidejte další prostor na ploše. Pokud animace zatím nemá úvodní obrazovku, můžete ji vytvořit na prvním snímku (pravděpodobně budete chtít posunout animaci a začít od snímku 2 nebo později). 3 Přidání nové vrstvy nad ostatní vrstvy v časové ose a její přejmenování na buttons. Toto bude vrstva v místě, kde přidáte tlačítka. 4 Přidejte novou vrstvu na vrstvu tlačítek a pojmenujte ji actions. To bude místo, kde přidáte kód ActionScript do aplikace. Vytváření a přidávání tlačítek Dále musíte vytvořit a umístit tlačítka, která budou tvořit střed naší interaktivní aplikace. Vytvoření a přidání tlačítek do souboru FLA: 1 Pomocí nástrojů kreslení vytvořte vizuální vzhled prvního tlačítka (tlačítko přehrávání) na vrstvě tlačítek. Například můžete nakreslit vodorovný ovál s textem nad ním. 2 Pomocí nástroj výběru vyberte všechny součásti grafiky jednoho tlačítka. 3 V hlavní nabídce zvolte Změnit > Převést na symbol. 4 V dialogovém okně zvolte jako typ symbolu Tlačítko, zadejte název a klepněte na tlačítko OK. 5 S vybraným tlačítkem Inspektor vlastností stanoví pro tlačítko název instance playButton. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 22 Začínáme s ActionScriptem 6 Opakujte kroky 1 až 5 a vytvořte tlačítko, které přesune uživatele na výchozí webovou stránku autora. Pojmenujte toto tlačítko homeButton. Zápis kódu Kód ActionScript pro tuto aplikaci lze rozdělit do tří souborů funkčnosti, i když vše bude zadáváno na jednom místě. Tři věci, které kód musí učinit, jsou následující: • Zastavit přehrávací hlavu, jakmile se soubor SWF načte (když přehrávací hlava najede na snímek 1). • Naslouchat události, která spustí přehrávání souboru SWF, když uživatel klepne na tlačítko přehrávání. • Naslouchat události, která odešle prohlížeč na příslušnou stránku URL, když uživatel klepne na tlačítko výchozí webové stránky autora. Vytvoření kódu, který zastaví přehrávací hlavu po najetí na snímek 1: 1 Zvolte klíčový snímek jako snímek 1 vrstvy akcí. 2 Otevřete panel Akce z hlavní nabídky vybráním možnosti Okno > Akce. 3 V panelu Skript zadejte následující kód: stop(); Zapsání kódu, který spustí animaci, když klepnete na tlačítko přehrávání: 1 Na konci kódu zadaného v předchozích krocích přidejte dvě prázdné řádky. 2 Na konec skriptu zadejte následující kód: function startMovie(event:MouseEvent):void { this.play(); } Tento kód definuje funkci nazvanou startMovie(). Když zavoláte funkci startMovie(), způsobí spuštění přehrávání hlavní časové osy. 3 Na řádku za kódem přidaným v předchozím kroku zadejte tento řádek kódu: playButton.addEventListener(MouseEvent.CLICK, startMovie); Tento řádek kódu registruje funkci startMovie() jako posluchače pro událost click tlačítka playButton. Jinými slovy, kdykoliv klepnete na tlačítko pojmenované playButton, je zavolána funkce startMovie(). Chcete-li zapsat kód pro přesměrování prohlížeče na adresu URL, když je klepnuto na tlačítko výchozí stránky: 1 Na konci kódu zadaného v předchozích krocích přidejte dvě prázdné řádky. 2 Na konec skriptu zadejte následující kód: function gotoAuthorPage(event:MouseEvent):void { var targetURL:URLRequest = new URLRequest("http://example.com/"); navigateToURL(targetURL); } Tento kód definuje funkci nazvanou gotoAuthorPage(). Tato funkce nejprve vytvoří instanci URLRequest představující adresu URL http://example.com/ a pak předá tuto adresu URL funkci navigateToURL(), způsobí tak, že prohlížeč uživatele otevře tuto adresu URL. 3 Na řádku za kódem přidaným v předchozím kroku zadejte tento řádek kódu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 23 Začínáme s ActionScriptem homeButton.addEventListener(MouseEvent.CLICK, gotoAuthorPage); Tento řádek kódu registruje funkci gotoAuthorPage() jako posluchače pro událost click tlačítka homeButton. Jinými slovy, kdykoliv klepnete na tlačítko pojmenované homeButton, je zavolána funkce gotoAuthorPage(). Testování aplikace V tomto okamžiku by měla být aplikace zcela funkční. Otestujme ji a přesvědčme se o tom. Testování aplikace: 1 V hlavní nabídce zvolte Ovládání > Testovat film. Aplikace Flash vytvoří soubor SWF a otevře jej v okně Flash Player. 2 Vyzkoušejte obě tlačítka a ujistěte se, že provádějí přesně ty činnosti, které zamýšlíte. 3 Pokud tlačítka nepracují, měli byste ověřit následující: • Mají obě tlačítka odlišné názvy instancí? • Volají metody addEventListener() použití stejných názvů, jako jsou názvy instancí tlačítek? • Jsou použité správné názvy událostí ve volání metody addEventListener()? • Je specifikován správný parametr pro každou funkci? (Oba by měly mít jeden parametr s datovým typem MouseEvent.) Všechny tyto chyby a většina dalších by měly signalizovat chybové hlášení, buď když zvolíte příkaz Testovat film nebo když klepnete na tlačítko. Podívejte se na panel Chyby kompilátoru a vyhledejte chyby kompilace (chyby, ke kterým dochází při první zvolení příkazu Testovat film) a zkontrolujte panel Výstup, zda se zde vyskytují chybu běhu programu (chyby, které nastávají při přehrávání souboru SWF - například při klepnutí na tlačítko). Vytváření aplikací v jazyce ActionScript Proces psaní kódu v jazyce ActionScript a vytváření aplikace zahrnuje více než jenom znalost syntaxe a názvů tříd, které použijete. Zatímco většina informací v této příručce je směřována ke dvou tématům (syntaxe a použití tříd ActionScript), budete také musíte znát informace o tom, které programy lze pro zapisování kódu ActionScript používat, jak lze kód ActionScript organizovat a zahrnout do aplikace a jaké kroky byste měli sledovat při vývoji aplikace v kódu jazyka ActionScript. Možnosti organizování kódu Kód jazyka ActionScript 3.0 můžete použít pro cokoliv, od jednoduchých grafických aplikací, až po složité systém zpracování transakcí klient-server. V závislosti na typu vytvářené aplikace můžete dávat přednost použití jednoho nebo několika těchto různých způsobů zahrnutí kódu ActionScript do svého projektu. Uložení kódu do snímků časové osy aplikace Flash Ve vývojovém prostředí aplikace Flash můžete přidat kód ActionScript ke kterémukoliv snímku v časové ose. Tento kód bude vykonán při přehrávání filmu, když přehrávací hlava najede na daný snímek. Umístění kódu ActionScript dovnitř snímků poskytuje jednoduchý způsob, jak přidat do aplikace chování vestavěné ve vývojovém nástroji Flash. Můžete přidat kód ke kterémukoliv snímku v hlavní časové ose nebo ke kterémukoliv snímku v časové ose kteréhokoliv symbolu MovieClip. Tato flexibilita však není zdarma. Když vytváříte větší aplikace, snadno ztratíte povědomí o tom, které snímky obsahují které skripty. To může po čase způsobit obtížnější údržbu aplikace. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 24 Začínáme s ActionScriptem Mnoho vývojových pracovníků zjednodušuje organizaci kódu ActionScript ve vývojovém nástroji Flash vložením kódu přímo do prvního snímku časové osy, nebo do specifické vrstvy dokumentu Flash. To usnadňuje lokalizaci a údržbu kódu v souborech Flash FLA. Chcete-li však použít stejný kód v jiném projektu Flash, musíte nakopírovat a vložit kód do nového souboru. Pokud chcete použít kód ActionScript v jiném projektu Flash v budoucnosti, budete muset uložit kód do externího souboru ActionScript (textový soubor s příponou .as). Uložení kódu v souborech ActionScript Pokud projekt zahrnuje velkou část v kódu ActionScript, nejlepším způsobem organizace kódu je jeho oddělení do samostatných souborů ActionScript (textové soubory s příponou .as). Soubor ActionScript může být strukturován jedním ze dvou způsobů, v závislosti na tom, jak jej zamýšlíte použít v aplikaci. • Nestrukturovaný kód ActionScript: řádky kódu ActionScript, včetně definicí příkazů nebo funkcí, zaspané jako by byly zadány přímo do časové osy skriptu, souboru MXML atd. Kód ActionScript zapsaný tímto způsobem, je přístupný pomocí příkazu include v ActionScript, nebo pomocí značky <mx:Script> v Adobe Flex MXML. Příkaz include v jazyce ActionScript způsobí vložení obsahu externího souboru ActionScript do specifického umístění a v daném rozsahu skriptu, pokud zde byl zadán přímo. V jazyce Flex MXML značka <mx:Script> umožňuje specifikovat zdrojový atribut, který identifikuje externí soubor ActionScript, který se má v tomto okamžiku v aplikaci načíst. Například následující značka načte externí soubor ActionScript pojmenovaný Box.as: <mx:Script source="Box.as" /> • Definice třídy ActionScript: definice třídy ActionScript, včetně definicí metody a vlastnosti. Když definujete třídu, můžete zpřístupnit kód ActionScript v třídě vytvořením instance třídy a použitím jejích vlastností, metod a události, podobně jako v případě vestavěných tříd ActionScript. To vyžaduje dvě část: • Použití příkazu import pro specifikování úplného názvu třídy, aby kompilátor jazyka ActionScript věděl, kde jej má nalézt. Pokud chcete například použít třídu MovieClip v kódu ActionScript, musíte nejprve importovat tuto třídu pomocí úplného názvu, včetně balíku a třídy: import flash.display.MovieClip; Alternativně můžete importovat balík, který obsahuje třídu MovieClip, což je ekvivalent zapsání samostatného příkazu import pro každou třídu v balíku. import flash.display.*; Jediné výjimky z pravidla, že třída musí být importována v případě, že se na tuto třídu odkazujete ve svém kódu, jsou třídy nejvyšší úrovně, které nejsou v balíku definované. Poznámka: V aplikaci Flash jsou pro skripty připojené ke snímku v časové ose vestavěné třídy (v balících flash.*) automaticky importovány. Když však zapisujete vlastní třídy, nebo když pracujete s vývojovými součástmi aplikace Flash (balíky fl.*) nebo když pracujete ve vývojovém prostředí Flex, budete muset explicitně importovat jakoukoliv třídu a zapsat tak kód, který vytváří instance dané třídy. • Zapište kód, který specificky odkazuje na název třídy (obvykle deklarování proměnné s danou třídu jako datovým typem a vytváření instance třídy pro uložení proměnné). Odkazováním na jiný název třídy v kódu ActionScript sdělujete kompilátoru, aby načetl definici dané třídy. Například v případě uvedené externí třídy nazvané Box způsobí tento příkaz vytvoření nové instance třídy Box. var smallBox:Box = new Box(10,20); Když se kompilátor poprvé setká s odkazem na třídu Box, vyhledá načtený zdrojový kód a lokalizuje definici třídy Box. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 25 Začínáme s ActionScriptem Výběr správného nástroje V závislosti na potřebách projektu a dostupných zdrojích můžete použít jeden z několika nástrojů (nebo více nástrojů ve vzájemném spojení) pro zápis a editování kódu ActionScript. Vývojový nástroj Flash Kromě svých schopností vytváření grafiky a animace aplikace Adobe Flash CS4 Professional zahrnuje nástroje pro práci s kódem ActionScript, buď připojeným k prvkům v souboru FLA nebo v externím souboru ActionScript. Vývojový nástroj Flash je ideální pro projekty vyžadující mnoho animací nebo videa nebo kde potřebujte vytvořit většinu grafiky sami, obzvláště v projektech s minimální interakcí uživatele nebo funkcí vyžadující ActionScript. Dalším důvodem pro použití vývojového nástroje Flash pro vytvoření projektů ActionScript je případ, kdy preferujete vizuální prvky a zapisování kódu v jedné aplikaci. Můžete také používat vývojový nástroj Flash v případě, že chcete použít předem vytvoření součásti uživatelského rozhraní, ale prioritou projektu je menší velikost souboru SWF nebo snazší vizuální změny vzhledu. Aplikace Adobe Flash CS4 Professional zahrnuje dva nástroje pro zápis kódu ActionScript: • Panel Akce: dostupný při práci na souboru FLA. tento panel umožňuje zapisovat kód ActionScript připojený je snímkům v časové ose. • Okno Skript: okno Skript je vyhrazeným textovým editorem pro práci s kódem v jazyce ActionScript (soubory .as). Flex Builder Vývojové prostředí Adobe Flex Builder je špičkovým nástrojem pro vytváření projektů Flex. Kromě vizuálního rozvržení a editačních nástrojů MXML nabízí Flex Builder také plně vybavený editor jazyka ActionScript, takže jej lze použít pro vytváření projektů výhradně s Flex nebo ActionScript. Aplikace Flex mají několik výhod, včetně bohaté sady předem vytvořených ovládacích prvků uživatelského rozhraní, flexibilních ovládacích prvků dynamického uspořádání a vestavěných mechanismů pro práci s externími datovými zdroji a spojováním externích dat s prvky uživatelského rozhraní. V důsledku dodatečného kódu, který tyto funkce zajišťuje, však aplikace Flex mohou mít větší soubory SWF a nemohou mít zcela změněn vzhled tak snadno, jako tomu je u jejich protějšků ve Flash. Vývojové prostředí Flex Builder používejte v případě, že vytváříte plně vybavené, bohaté internetové aplikace Flex pracující s daty a chcete upravovat kód ActionScript, kód MXML a rozvrhnout aplikaci vizuálně, to vše v jediném nástroji. Editor jazyka ActionScript od jiných výrobců Protože soubory ActionScript (.as) jsou uloženy jako jednoduché textové soubory, všechny programy schopné editování prostého textu lze použít k psaní souborů ActionScript. Kromě produktů ActionScript od Adobe existuje několik textových editorů třetích stran, se specifickými schopnostmi práce s kódem ActionScript. Soubor MXML nebo třídy ActionScript můžete zapisovat pomocí kteréhokoliv textového editoru. Poté můžete vytvořit aplikaci SWF (buď aplikaci výhradně Flex nebo ActionScript) z těchto souboru pomocí aplikace Flex SDK, který zahrnuje třídy Flex a také kompilátor Flex. Alternativně mnoho vývojářů používá pro zapisování tříd ActionScript editor jazyka ActionScript od třetí strany, v kombinaci s vývojovým nástrojem Flash pro vytváření grafického obsahu. Použití editoru jazyka ActionScript od třetí strany můžete zvolit za následujících podmínek: • Upřednostňujete zapisování kódu ActionScript v samostatném programu, ve spojení s navrhováním vizuálních prvků v aplikaci Flash. • Používáte aplikaci pro programování v jiném jazyce, než ActionScript (například vytváření stránek HTML nebo vytváření aplikací v jiném programovacím jazyce), a chcete používat stejnou aplikaci pro zápis kódu v jazyce ActionScript. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 26 Začínáme s ActionScriptem • Chcete vytvořit projekty pouze ActionScript nebo Flex pomocí aplikace Flex SDK, bez vynaložení nákladů na vývojová prostředí Flash nebo Flex Builder. Některé vhodné editory programového kódu se specifickou podporou jazyka ActionScript zahrnují: • Adobe Dreamweaver® CS4 • ASDT • FDT • FlashDevelop • PrimalScript • SE|PY Proces vývoje kódu v jazyce ActionScript Bez ohledu na to, zda jsou vaše projekty ActionScript malé nebo velké, použití procesu pro návrh a vývoj aplikace vám pomůže pracovat efektivnější a účinněji. Následující kroky popisují základní proces vývoje aplikace pomocí ActionScript 3.0: 1 Navrhněte aplikaci. Před započetím vývoje byste měli aplikaci vhodným způsobem popsat. 2 Sestavte kód ActionScript 3.0. Kód ActionScript můžete vytvořit pomocí aplikací Flash, Flex Builder, Dreamweaver nebo textového editoru. 3 Vytvořte soubor aplikace Flash nebo Flex, který spustí váš kód. Ve vývojovém nástroji Flash toto vyžaduje vytvořené nového souboru FLA? nastavení publikování, přidání součástí uživatelského rozhraní do aplikace a odkazování na kód ActionScript. Ve vývojovém prostředí Flex zahrnuje vytvořené nového souboru aplikace definování a přidání součástí uživatelského rozhraní pomocí MXML a odkazování na kód ActionScript. 4 Publikujte a otestujte svou aplikaci ActionScript. Sem náleží spuštění aplikace z vývojového prostředí Flash nebo Flex a zkontrolování, zda vše pracuje podle potřeby. Povšimněte si, že není nutné postupovat těmito kroky v přesně uvedeném pořadí, nebo dokončit jeden krok před započetím jiného. Například můžete navrhnout jednu obrazovku aplikace (krok 1) a pak vytvořit grafiku, tlačítka atd (krok 3) a až poté napsat kód v jazyce ActionScript (krok 2) a provést otestování (krok 4). Nebo můžete navrhnout část, pak přidat jedno tlačítko nebo prvek rozhraní, zapsat kód v jazyce ActionScript pro každý tento prvek a otestovat v daném provedení. I když je vhodné si pamatovat tyto čtyři fáze procesu vývoje, při skutečném vývoji je obvykle efektivnější pohybovat se zpět a dopředu mezi fázemi vývoje podle potřeby. Vytváření vlastních tříd Proces vytváření tříd pro použití ve vašich projektech může vypadat skličující. Obtížnější části vytvoření třídy je však její návrh - identifikace metod, vlastností a událostí, které bude třída zahrnovat. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 27 Začínáme s ActionScriptem Strategie vytváření třídy Téma objektově orientovaného návrhu je komplexní. Celé kariéry mnoha osob byly věnovány akademickému studiu a profesionální praxi v této disciplíně. Existuje však několik doporučovaných přístupů. které mohou v začátcích pomoci. 1 Přemýšlejte o úloze, kterou bude instance této třídy hrát v dané aplikaci. Obecně objekty slouží jedné z těchto tří úloh: • Objekt Value: tyto objekty slouží primárně jako kontejnery dat - tj. mají pravděpodobně několik vlastnost a méně metod (někdy také nemají žádnou). Obecně se jedná o kódové vyjádření jasně definovaných položek, například třída Song (reprezentující jednu skutečnou píseň) nebo třída Playlist (reprezentující koncepční skupinu písní) v aplikaci hudebního přehrávače. • Objekt Display: tyto objekty se ve skutečnosti zobrazují na obrazovce. Mezi příklady náleží prvky uživatelského rozhraní, například rozvírací seznam nebo odečtení stavu, grafické prvky, jako jsou příšery ve video hře atd. • Struktura aplikace: tyto objekty hrají širokou škálu podpůrných úloh v logice a zpracování prováděném aplikací. Příklady zahrnují objekt provádějící jisté výpočty v biologické simulaci; objekt odpovědný za synchronizování hodnot mezi otočným ovladačem a odečtenou hodnotou hlasitosti v hudebním přehrávači; objekt spravující pravidla ve video hře; nebo objekt načítající uložené obrázky do kreslicí aplikace. 2 Rozhodněte se o specifické funkčnosti, kterou třída musí mít. Různé typy funkcí se často stávají metodami třídy. 3 Pokud má třída sloužit jako objekt hodnoty, rozhodněte se, která data budou instance zahrnovat. Tyto položky jsou vhodnými kandidáty pro vlastnosti. 4 Protože třída je navrhována specificky pro váš projekt, nejdůležitější je poskytnout funkčnost, kterou vyžaduje vaše aplikace. Mohlo by pomoci, pokud si sami odpovíte na následující otázky: • Jaké části informací bude aplikace ukládat, sledovat a zpracovávat? Rozhodnutí zde pomůže identifikovat všechny objekty a vlastnosti hodnot, které budete potřebovat. • Jaké soubory akcí budete muset provádět - například, kdy se aplikace poprvé načte, kdy je klepnuto na specifické tlačítko, kdy se film přestane přehrávat atd.? Toto jsou vhodní kandidáti na metody (nebo vlastnosti, pokud „akce“ zahrnují pouze změnu jednotlivých hodnot). • Pro kteroukoliv danou akci, jaké informace bude třída muset znát, aby tuto akci provedla? Tyto kusy informací se stávají parametry metody. • Když aplikace pokračuje v činnosti, aby vykonala svou práci, jaké věci se změní ve vaší třídě, o kterých budou jiné části této aplikace muset vědět? Toto jsou vhodní kandidáti na události. 5 Pokud existuje stávající objekt, který je podobný vámi požadovanému objektu, kromě toho, že mu chybí další funkce, které chcete přidat, zvažte vytvoření podtřídy (třídy postavené na funkčnosti stávající třídy, namísto definování zcela nové funkce). Například, pokud chcete vytvořit třídu, která bude vizuálním objektem na obrazovce, budete muset použít chování jednoho stávajícího objektu zobrazení (například Sprite nebo MovieClip) jako základ pro svou třídu. V takovém případě MovieClip (nebo Sprite) budou základní třídou a vaše třída tuto třídu bude rozšiřovat. Další informace o vytváření podtřídy, viz „Zdědění“ na stránce 106. Zápis kódu pro třídu Jakmile máte plán návrhu třídy, nebo alespoň představu, které informace bude muset sledovat a jaké akce bude muset provádět, je vlastní syntaxe zápisu třídy velmi přímočará. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 28 Začínáme s ActionScriptem Zde jsou minimální kroky, které byste měli vytvořit ve vlastní třídě ActionScript: 1 Otevřete nový textový dokument v programu specifickém pro jazyk ActionScript, například Flex Builder nebo Flash, v obecném programovacím nástroji, jako Dreamweaver, nebo jiném programu umožňujícím práci s dokumenty v prosté textové podobě. 2 Zadejte příkaz class a definujte název třídy. To provedete zadáním slov public class a pak názvu třídy, následovaným levou a pravou složenou závorkou, která bude obsahovat obsah třídy (definice metody a vlastnosti). Například: public class MyClass { } Slovo public označuje, že třída může být přístupná z jiného libovolného kódu. Jiné alternativy naleznete v kapitole „Atributy jmenného prostoru pro ovládání přístupu“ na stránce 93. 3 Zadejte příkaz package a označte název balíku, ve kterém lze vaši třídu nalézt. Syntaxe je slovo package, následované levou a pravou složenou závorkou (ve které je uveden blok příkazu class). Například chcete změnit kód v předchozím kroku na tento: package mypackage { public class MyClass { } } 4 Definujte každou vlastnost ve třídě pomocí příkazu var v těle třídy; syntaxe je shodná, jsou použijete pro deklarování kterékoliv proměnné (s přidáním modifikátoru public). Například přidání těchto řádek mezi levou a pravou složenou závorku definice třídy vytvoří vlastnosti pojmenované textVariable, numericVariable a dateVariable: public var textVariable:String = "some default value"; public var numericVariable:Number = 17; public var dateVariable:Date; 5 Definujte každou metodu ve třídě pomocí stejné syntaxe, kterou použijete pro definování funkce. Například: • Chcete-li vytvořit metodu myMethod(), zadejte: public function myMethod(param1:String, param2:Number):void { // do something with parameters } • Chcete-li vytvořit konstruktor (speciální metoda, která je volaná jako součást procesu vytváření instance třídy), vytvoření metody, jejíž název odpovídá přesně názvu třídy: public function MyClass() { // do stuff to set initial values for properties // and otherwise set up the object textVariable = "Hello there!"; dateVariable = new Date(2001, 5, 11); } Pokud nezahrnete metodu konstruktoru do své třídy, kompilátor automaticky vytvoří ve vaší třídě prázdný konstruktor (bez parametrů a příkazů). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 29 Začínáme s ActionScriptem Existuje několik dalších prvků třídy, které můžete definovat. Tyto prvky jsou častěji zapojené. • Zpřístupňovače jsou speciální přechody mezi metodou a vlastností. Když zapisujete kód pro definování třídy, zapisujete zpřístupňovač jak metodu, takže můžete provádět několik akcí (spíše než čtení nebo přiřazení hodnoty, což jediné můžete provádět, když definuje vlastnost). Nicméně když vytváříte instanci své třídy, zacházíte se zpřístupňovačem jako s vlastností - pouze používáte název k načtení nebo přiřazení hodnoty. Další informace, viz „Získání a nastavení metod mechanismů přístupu“ na stránce 99. • Události v jazyce ActionScript nejsou definované pomocí specifické syntaxe. Místo toho definujete události ve třídě pomocí funkce třídy EventDispatcher, abyste měli přehled o posluchačích události a mohli je informovat o událostech. Další informace o vytváření událostí ve vlastních třídách naleznete v kapitole „Zpracování událostí“ na stránce 243. Příklad: Vytváření základních aplikací Externí zdrojový soubor v jazyce ActionScript můžete vytvořit s příponou .as ve vývojovém prostředí Flash, Flex Builder, Dreamweaver, nebo v kterémkoliv textovém editoru. ActionScript 3.0 lze používat v několika vývojových prostředích, včetně vývojového prostředí Flash nebo Flex Builder. Tato část prochází kroky vytváření a zlepšení jednoduchých aplikací v kódu ActionScript 3.0 pomocí vývojového nástroje Flash nebo Flex Builder. Vytvořená aplikace představuje jednoduchý vzor použití externích souborů třídy ActionScript 3.0 v aplikacích Flash a Flex. Vzory platí pro všechny ostatní vzorové aplikace v této příručce. Návrh aplikace ActionScript Před započetím vytváření aplikace byste o ní měli mít jistou představu. Vyjádření návrhu může být jednoduché, jako pojmenování aplikace a stručné popsání jejího účelu, nebo tak komplikované, jako soubor dokumentů požadavků obsahující mnoho schématu unifikovaného modelovacího jazyka UML. Tato příručce nepopisuje disciplínu návrhu softwaru podrobně, ale je důležité mít na paměti, že návrh aplikace je základním krokem při vývoje aplikace v jazyce ActionScript. Naším prvním příkladem aplikace ActionScript bude standardní aplikace „Hello World“, jejíž návrh je velmi jednoduchý. • Aplikace se bude jmenovat HelloWorld. • Zobrazí textové pole se slovy „Hello World!“ • Aby ji bylo možné snadno opakovaně použít, použije jednu objektově orientovanou třídu pojmenovanou Greeter, kterou bude možné použít z dokumentu Flash nebo aplikace Flex. • Po vytvoření základní verze aplikace přidáte novou funkci, která vyzve uživatele k zadání jména a nechá aplikací zkontrolovat jméno podle seznamu známých uživatelů. Se stručným definováním můžete začít vytvářet aplikaci samotnou. Vytváření projektu Hello World a třídy Greeter Návrh aplikace Hello World říká, že by kód měl být snadno opakovaně použitelný. S tímto úmyslem aplikace použije jednu objektově orientovanou třídu pojmenovanou Greeter, který je použita v aplikaci vytvořené ve vývojovém prostředí Flex nebo ve vývojovém nástroji Flash. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 30 Začínáme s ActionScriptem Chcete-li vytvořit třídu Greeter ve vývojovém nástroji Flash: 1 Ve vývojovém nástroji Flash zvolte Soubor > Nový. 2 V dialogovém okně Nový dokument zvolte soubor ActionScript a klepněte na tlačítko OK. Zobrazí se nové editační okno ActionScript. 3 Vyberte Soubor > Uložit. Vyberte složku pro uložení aplikace, pojmenujte soubor ActionScript Greeter.as a klepněte na tlačítko OK. Pokračujte se „Zapisování kódu do třídy Greeter“ na stránce 30. Zapisování kódu do třídy Greeter Třída Greeter definuje objekt, Greeter, který budete moci použít v aplikaci HelloWorld. Chcete-li zapsat kód do třídy Greeter: 1 Zadejte do nového souboru následující kód: package { public class Greeter { public function sayHello():String { var greeting:String; greeting = "Hello World!"; return greeting; } } } Třída Greeter zahrnuje jednu metodu sayHello(), která vrací řetězec říkající „Hello World!“. 2 Vyberte Soubor > Uložit a uložte tento soubor ActionScript. Třída Greeter je nyní připravena k použití v aplikaci. Vytváření aplikace, která používá kód ActionScript Třída Greeter, kterou jste vytvořili, definuje samostatný soubor softwarových funkcí, ale nereprezentuje kompletní aplikaci. Chcete-li třídu použít, musíte vytvořit dokument Flash nebo aplikaci Flex. Aplikace HelloWorld vytvoří novou instanci třídy Greeter. Zde je popis, jak připojíte třídu Greeter ke své aplikaci. Chcete-li vytvořit aplikaci ActionScript pomocí vývojového nástroje Flash: 1 Zvolte Soubor > Nový. 2 V dialogovém okně Nový dokument zvolte Dokument Flash a klepněte na tlačítko OK. Zobrazí se nové okno aplikace Flash. 3 Vyberte Soubor > Uložit. Zvolte stejnou složku, která obsahuje soubor třídy Greeter.as, pojmenujte dokumentu Flash HelloWorld.fla a klepněte na tlačítko OK. 4 V paletě Nástroje Flash vyberte nástroj Text a přetažením přes plochu definujte nové textové pole, asi 300 obrazových bodů široké a 100 obrazových bodů vysoké. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 31 Začínáme s ActionScriptem 5 V panelu Vlastnosti s textovým polem stále vybraným na ploše, nastavte typ textu na „Dynamický text“ a zadejte mainText jako název instance textového pole. 6 Klepněte na první snímek v hlavní časové ose. 7 V panelu Akce zadejte následující skript: var myGreeter:Greeter = new Greeter(); mainText.text = myGreeter.sayHello(); 8 Uložte soubor. Pokračujte v části „Publikování a testování aplikace ActionScript“ na stránce 31. Publikování a testování aplikace ActionScript Vývoj softwaru je iterační proces. Napíšete část kódu, pokusíte se jej zkompilovat a upravíte kód tak, až je zkompilován čistě. Spustíte zkompilovanou aplikaci, otestujete, zda plní zamýšlené funkce a pokud ne, upravíte kód znovu, až je vše v pořádku. Vývojová prostředí Flash a Flex Builder nabízejí mnoho způsobů, jak publikovat, testovat a ladit aplikace. Zde jsou uvedeny některé základní kroky pro testování aplikace HelloWorld v každém prostředí. Chcete-li publikovat a testovat aplikaci ActionScript pomocí vývojového nástroje Flash: 1 Publikujte svou aplikaci a sledujte chyby kompilace. Ve vývojovém nástroji Flash zvolte Ovládání > Testovat film a zkompilujte kód v jazyce ActionScript a spusťte aplikaci HelloWorld. 2 Pokud se v okně Výstup během testování aplikace zobrazí nějaké chyby, odstraňte příčiny chyb v souboru HelloWorld.fla nebo HelloWorld.as a pak se pokuste aplikaci otestovat znovu. 3 Pokud žádné chyby během kompilace nenastanou, zobrazí se okno přehrávače Flash Player s aplikací Hello World. Právě jste vytvořili jednoduchou, objektově orientovanou aplikaci, která využívá kódu ActionScript 3.0. Pokračujte v části „Zlepšení aplikace HelloWorld“ na stránce 31. Zlepšení aplikace HelloWorld Chcete-li aplikaci poněkud vylepšit a učinit zajímavější, měli byste se nyní dotázat na jméno uživatele a ověřit jej vůči předdefinovanému seznamu jmen. Nejprve aktualizujte třídu Greeter a přidejte novou funkci. Pak aktualizujte aplikaci, aby novou funkci použila. Aktualizace souboru Greeter.as: 1 Otevřete soubor Greeter.as. 2 Změňte obsah souboru tak, aby byl následující (nové a změněné řádky jsou zobrazeny tučným písmem). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 32 Začínáme s ActionScriptem package { public class Greeter { /** * Defines the names that should receive a proper greeting. */ public static var validNames:Array = ["Sammy", "Frank", "Dean"]; /** * Builds a greeting string using the given name. */ public function sayHello(userName:String = ""):String { var greeting:String; if (userName == "") { greeting = "Hello. Please type your user name, and then press the Enter key."; } else if (validName(userName)) { greeting = "Hello, " + userName + "."; } else { greeting = "Sorry " + userName + ", you are not on the list."; } return greeting; } /** * Checks whether a name is in the validNames list. */ public static function validName(inputName:String = ""):Boolean { if (validNames.indexOf(inputName) > -1) { return true; } else { return false; } } } } Třída Greeter má nyní několik nových vlastností: • Pole validNames uvádí seznam s platnými uživatelskými jmény. Pole se inicializuje tak, aby po načtení třídy Greeter otevřelo seznam tří jmen. • Metoda sayHello() nyní přijme uživatelské jméno a změní pozdrav na základě některých podmínek. Pokud je userName prázdný řetězec (""), vlastnosti greeting je nastaven na zobrazení výzvy uživateli, aby zadal jméno. Pokud je uživatelské jméno platné, pozdrav bude "Hello, userName." Nakonec, pokud není ani jedna z těchto dvou podmínek, proměnná greeting se nastaví na "Sorry userName, you are not on the list." PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 33 Začínáme s ActionScriptem • Metoda validName() vrátí hodnotu true, pokud je nalezeno inputName v poli validNames, nebo hodnotu false, pokud nalezeno není. Příkaz validNames.indexOf(inputName) kontroluje každý řetězec v poli validNames proti řetězci inputName. Metoda Array.indexOf() vrací polohu indexu první instance objektu v poli, nebo hodnotu -1, pokud objekt v poli nalezen není. Dále budete muset upravit soubor Flash nebo Flex, který odkazuje na tuto třídu ActionScript. Chcete-li změnit aplikaci pomocí vývojového nástroje Flash: 1 Otevřete soubor HelloWorld.fla. 2 Změňte skript ve snímku 1 tak, aby prázdný řetězec ("") byl předán metodě sayHello() třídy Greeter: var myGreeter:Greeter = new Greeter(); mainText.text = myGreeter.sayHello(""); 3 Vyberte nástroj Text v paletě Nástroje a pak vytvořte dva nové textové soubory na ploše, vedle sebe a přímo pod stávajícím textovým polem mainText. 4 V prvním novém textovém poli zadejte text User Name:, který bude sloužit jako jmenovka. 5 Zvolte další nové textové pole a v Inspektoru vlastností zvolte InputText jako typ textového pole. Jako typ řádky zvolte jednotlivou řádku. Jako název instance zadejte textIn. 6 Klepněte na první snímek v hlavní časové ose. 7 V panelu Akce přidejte na konec stávajícího skriptu následující řádky: mainText.border = true; textIn.border = true; textIn.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); function keyPressed(event:KeyboardEvent):void { if (event.keyCode == Keyboard.ENTER) { mainText.text = myGreeter.sayHello(textIn.text); } } Nový kód přidá následující funkci: • První dva řádky jednoduše definují okraje dvou textových polí. • Vstupní textové pole, například pole textIn, nastavilo události, které může odeslat. Metoda addEventListener() umožňuje definovat funkci, která se spustí, když nastane typ události. V tomto případě je touto události stisknutí klávesy. • Uživatelská funkce keyPressed() kontroluje, zda stisknutou klávesou byla klávesa Enter. Pokud ani, funkce zavolá metodu sayHello() objektu myGreeter a předá text z textového pole textIn jako parametr. Tato metoda vrací řetězec pozdravu na základě předané hodnoty. Vrácený řetězec je pak přiřazen vlastnosti text textového pole mainText. Celý skript pro snímek 1 je následující: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 34 Začínáme s ActionScriptem var myGreeter:Greeter = new Greeter(); mainText.text = myGreeter.sayHello(""); mainText.border = true; textIn.border = true; textIn.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); function keyPressed(event:KeyboardEvent):void { if (event.keyCode == Keyboard.ENTER) { mainText.text = myGreeter.sayHello(textIn.text); } } 8 Uložte soubor. 9 Zvolte Ovládání > Testovat film a spusťte aplikaci. Když spustíte aplikaci, budete vyzváni k zadání uživatelského jména. Pokud je platné (Sammy, Frank nebo Dean), aplikace zobrazí hlášení s potvrzením „Hello“. Spuštění následných příkladů Nyní, když jste vyvinuli a spustili aplikaci „Hello World“ v kódu ActionScript 3.0, měli byste mít základní znalosti potřebné pro spuštění dalších příkladů kódu uvedených v této příručce. Testování příkladů kódu v této kapitole Během používání této příručky můžete vyzkoušet příklady kódu, které jsou použity k ilustrování některých témat. Testování může zahrnovat zobrazování hodnot proměnných v jistých místech programu, nebo sledování či interakci s obsahem na obrazovce. Pro testování vizuálního obsahu nebo interakce budou popsány potřebné prvky předem nebo v příslušném kódu - je nutné pouze vytvořit dokument s popsanými prvky a kód tak otestovat. V případě, že chcete sledovat hodnotu proměnné v daném místě programu, existuje několik způsobů, kterým toho můžete dosáhnout. Jedním způsobem je použití ladicího programu, například toho, který je součástí vývojového prostředí Flex Builder nebo Flash. Pro jednoduché testování může být však snazší vytisknout hodnoty proměnných a snadno je tak zobrazit. Následující kroky vám pomohou vytvořit dokument aplikace Flash, který můžete použít pro testování kódu a zobrazení hodnot proměnných: Chcete-li vytvořit dokument aplikace Flash pro testování příkladů v kapitole: 1 Vytvořte nový dokument Flash a uložte jej na pevný disk. 2 Chcete-li zobrazit testované hodnoty v textovém poli na ploše, aktivujte nástroj Text a vytvořte na ploše nové dynamické textové pole. Nejužitečnější bude široké a vysoké textové pole s typem řádky nastaveným na možnost Víceřádková a se zapnutým okrajem. V Inspektoru vlastnosti pojmenujte instanci textového pole (například „outputText“). Chcete-li zapsat hodnoty do textového pole, budete muset do kódu příkladu (popsáno níže) přidat kód, který volá metodu appendText(). 3 Alternativně můžete do kódu přidat volání funkce trace() (popsáno níže) a zobrazit tak výsledky příkladu. 4 Chcete-li daný příklad otestovat, zkopírujte kód do panelu Akce; pokud je to nutné, přidejte volání funkce trace() nebo přidejte hodnotu do textového pole pomocí metody appendText(). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 35 Začínáme s ActionScriptem 5 V hlavní nabídce zvolte Ovládání > Testovat film, vytvořte soubor SWF a zobrazte výsledky. Protože tento přístup je určen pro zobrazení hodnot proměnných, existují dva způsob, jak při zkoušení příkladů snadno zobrazit hodnoty proměnných: zapište hodnoty do instance textového pole na ploše, nebo použijte funkci trace() k vytištění hodnot do panelu Výstup. • Funkce trace(): funkce trace() jazyka ActionScript zapíše hodnoty kteréhokoliv parametru jí předaného (proměnné nebo literálové výrazy) do panelu Výstup. Mnoho z příkladů kódu v této příručce již obsahuje volání funkce trace(), takže tyto příklady kódu budete muset pouze zkopírovat do dokumentu a otestovat projekt. Pokud chcete použít funkci trace() k otestování hodnoty proměnné v kódu, který funkci ještě neobsahuje, pouze přidejte volání trace() do kódu a předejte proměnnou jako parametr. Například, pokud se setkáte s kódem, jako je tento v této kapitole, var albumName:String = "Three for the money"; můžete jej zkopírovat do panelu Akce, pak přidat volání funkce trace(), jako je toto, a otestovat výsledek v kódu: var albumName:String = "Three for the money"; trace("albumName =", albumName); Když spustíte program, vytiskne se tento řádek: albumName = Three for the money Každé volání funkce trace() může použít několik parametrů, které jsou všechny zřetězeny do jedné vytištěné řádky. Zalomení řádku je přidána na konec každého volání funkce trace(), takže samostatná volání trace() se vytisknou na samostatný řádek. • Textové pole na ploše: pokud dáváte přednost nepoužití funkce trace(), můžete přidat dynamické textové pole na plochu pomocí nástroje Text a zapsat hodnoty do tohoto pole a zobrazit tak výsledky výpisu kódu. Metoda appendText() třídy TextField může být použita k přidání hodnoty String na konec obsahu textového pole. Chceteli přistupovat k textovému poli pomocí jazyka ActionScript, musíte mu dát název instance v Inspektoru vlastností. Pokud má například vaše textové pole název instance outputText, měl by být použit následující kód ke kontrole hodnoty proměnné albumName: var albumName:String = "Three for the money"; outputText.appendText("albumName = "); outputText.appendText(albumName); Tento kód zapíše následující text do textového pole pojmenovaného outputText: albumName = Three for the money Jak je vidět na příklad, metoda appendText() přidá text do stejné řádky jako předchozí obsah, takže lze do stejné řádky textu přidat několik hodnot, pomocí několika volání appendText(). Chcete-li nuceně zobrazit text na následujícím řádku, můžete přidat znak nové řádky ("\n"): outputText.appendText("\n"); // adds a line break to the text field Na rozdíl od funkce trace(), metoda appendText() přijímá jako parametr pouze jedinou hodnotu. Tato hodnota musí být řetězcem (buď instance String nebo literálový řetězec). Chcete-li vytisknout hodnotu neřetězcové proměnné, musíte nejprve převést hodnotu na řetězec. Nejsnazším způsobem, jak toto provést, je zavolat metodu toString(): var albumYear:int = 1999; outputText.appendText("albumYear = "); outputText.appendText(albumYear.toString()); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 36 Začínáme s ActionScriptem Práce s příklady na konci kapitoly Jako tato kapitola, tak i většina ostatních v této příručce obsahuje na konci významné příklady, které spojují dohromady mnoho konceptů v kapitole popisovaných. Avšak na rozdíl od příkladu Hello World v této kapitole, tyto příklady nejsou prezentovány ve formě výukového příkladu krok za krokem. Odpovídající kód jazyka ActionScript 3.0 v každém příkladu bude zvýrazněn a popsán, ale pokyny pro spuštění příkladů ve specifickém vývojovém prostředí uvedeny nebudou. Soubory s příklady distribuované s touto příručkou budou zahrnovat všechny soubory, které potřebujete ke kompilaci a spuštění příkladů ve vybraném vývojovém prostředí 37 Kapitola 4: Jazyk ActionScript a jeho syntaxe Jazyk ActionScript 3.0 je tvořen jádrem jazyka ActionScript a programovacím rozhraním aplikace Adobe Flash Player API. Základní jazyk je částí jazyka ActionScript, která definuje syntaxi jazyka i datové typy na nejvyšší úrovni. Jazyk ActionScript 3.0 poskytuje programatický přístup k přehrávači Flash Player. Tato kapitola poskytuje stručný úvod k jádru jazyka ActionScript a jeho syntaxi. Po prostudování této kapitoly byste měli získat základní porozumění způsobu práce s datovými typy a proměnnými, jak používat správnou syntaxi a jak ovládat tok dat v programu. Přehled jazyka Objekty ležící v jádru jazyka ActionScript 3.0 - tvoří základní stavební bloky. Každá proměnná, kterou deklarujete, každá zapsaná funkce a každá vytvořená instance třídy je objektem. Program jazyka ActionScript 3.0 můžete považovat za skupinu objektů provádějících úlohy, reagujících na události a komunikujících navzájem mezi sebou. Programátoři seznámení s objektově orientovaným programováním (OOP) v jazyce Java nebo C++ mohou považovat objekty za moduly, obsahující dva typy členů: data uložená v členských proměnných nebo vlastnostech, a chování přístupné prostřednictvím metod. Jazyk ActionScript 3.0 definuje objekty podobným ale trochu odlišným způsobem. V jazyce ActionScript 3.0 jsou objekty jednoduše sbírkou vlastností. Tyto vlastnosti jsou kontejnery, které uchovávají nejenom data, ale také funkce nebo jiné objekty. Pokud je funkce tímto způsobem připojená k objektu, nazývá se metodou. Zatímco definice jazyka ActionScript 3.0 se může programátorům jazyků Java nebo C++ zdát poněkud podivná, v praxi definování typů objektů s třídami ActionScript 3.0 bude velmi podobná způsobu, kterým jsou definovány třídy v jazyce Java nebo C++. Rozdíl mezi dvěma definicemi objektu je důležitý při projednávání objektového modelu ActionScript a dalších pokročilých témat, ale ve většině jiných situací znamená termín vlastnosti proměnné členy tříd, což je protiklad metod. Referenční příručka jazyka ActionScript 3.0 a jeho součástí například používá termín vlastnosti pro popis proměnných nebo vlastností příjemce. Používá termín metody k popisu funkcí, které jsou součástí třídy. Jedním drobným rozdílem mezi třídou ActionScript a třídami v jazycích Java nebo C++ je to, že v jazyce ActionScript nejsou třídy pouhými abstraktními entitami. Třídy ActionScript jsou vyjádřeny objekty třídy, které ukládají vlastnosti třídy a metody. To umožňuje používat techniky, které se mohou zdát programátorům jazyků Java a C++ podivné, například zahrnutí příkazů nebo spustitelného kódu na horní úrovni třídy nebo balíku. Dalším rozdílem mezi třídami ActionScript a jazyka Java nebo C++ je v tom, že každá třída ActionScript má něco, co se nazývá prototypovýobjekt. V předchozích verzích jazyka ActionScript sloužily prototypové objekty spojené do řetězců prototypů jako základy dědičnosti celé hierarchie třídy. V jazyce ActionScript 3.0 však prototypové objekty hrají jenom malou úlohu v systému dědičnosti. Prototypový objekt může být i nadále užitečný, nicméně jako alternativa statickým vlastnostem a metodám, pokud chcete sdílet vlastnost a její hodnotu mezi všemi instancemi třídy. V minulosti programátoři ActionScript mohli přímo manipulovat s prototypovým řetězcem se zvláštními vestavěnými prvky jazyka. Nyní, když jazyk poskytuje zralejší implementaci programovacího rozhraní založeného na třídách, mnoho z těchto speciálních prvků jazyka, například __proto__ a __resolve, již není jeho součástí. Kromě toho optimalizace mechanismu vnitřní dědičnosti, která poskytuje významné zvýšení výkonů aplikace Flash Player a Adobe AIR, zabraňuje přímému přístupu k mechanismu dědičnosti. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 38 Jazyk ActionScript a jeho syntaxe Objekty a třídy V jazyce ActionScript 3.0 je každý objekt definovaný svou třídou. Třída může být šablonu nebo modrotiskem typu objektu. Definice třídy mohou zahrnovat proměnné a konstanty, které uchovávají datové hodnoty, a metody, které jsou funkcemi obsahujícími chování spojené s danou třídou. Hodnoty uložené ve vlastnostech mohou být primitivní hodnoty nebo jiné objekty. Primitivní hodnoty jsou čísla, řetězce a booleovské hodnoty. Jazyk ActionScript obsahuje několik vestavěných tříd, které jsou součástí jádra jazyka. Některé z těchto vestavěných tříd, například čísla, booleovské hodnoty a řetězce, představují primitivní hodnoty dostupné v jazyce ActionScript. Jiné, např. třídy Array, Math a XML, definují složitější objekty. Všechny třídy, vestavěné nebo definované uživatelem, jsou odvozeny od třídy Object. Pro programátory s předchozí zkušenosti s jazykem ActionScript, je důležité poznamenat, že datový typ Object již není výchozím typem, i když jsou všechny třídy od něj odvozeny. V jazyce ActionScript 2.0 byly následující dva řádky kódu shodné protože neexistovala anotace typu znamenající, že proměnná by byla typu Object: var someObj:Object; var someObj; Jazyk ActionScript 3.0 však zavádí koncept proměnných bez typu, které mohou být označeny následujícími dvěma způsoby: var someObj:*; var someObj; Proměnné bez typu nejsou stejné, jako proměnné typu Object. Klíčovým rozdílem je to, že proměnné bez typu mohou uchovávat speciální hodnotu undefined, zatímco proměnná typu Object tuto hodnotu uchovávat nemůže. Můžete definovat své vlastní třídy a to pomocí klíčového slova class. vlastnosti třídy deklarujete třemi způsoby: konstanty mohou být definovány klíčovým slovem const, proměnné mohou být definovány klíčovým slovem var a vlastnosti getter a setter mohou být definovány použitím atributu get a set v deklarování metody. Metody můžete deklarovat klíčovým slovem function. Instanci třídy můžete vytvořit pomocí operátoru new. Následující příklad vytváří instanci třídy Date nazvanou myBirthday. var myBirthday:Date = new Date(); Balíčky a jmenné prostory Balíčky a jmenné prostory jsou související koncepty. Balíčky umožňují spojit definice tříd způsobem, který usnadňuje sdílení kódu a minimalizuje konflikty pojmenování. Jmenné prostory umožňují řídit viditelnost identifikátorů, například názvů vlastnosti a metody, a mohou být použity v kódu bez ohledu na to, zda je umístěn vně nebo uvnitř balíčku. Balíčky umožňují organizovat soubory tříd, jmenné prostory umožňují zpracovat viditelnost jednotlivých vlastností a metod. Balíčky Balíčky v jazyce ActionScript 3.0 jsou implementovány s jmennými prostory, ale nejsou jejich synonymem. Když deklarujete balíček, implicitně vytváříte speciální typ jmenného prostoru, který je zaručeně znám v okamžiku kompilace. Jmenné prostory, když jsou vyjádřeny explicitně, nejsou nutně známy v čase kompilace. Následující příklad používá instrukci package k vytvoření jednoduchého balíčku obsahujícího jednu třídu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 39 Jazyk ActionScript a jeho syntaxe package samples { public class SampleCode { public var sampleGreeting:String; public function sampleFunction() { trace(sampleGreeting + " from sampleFunction()"); } } } Název třídy je v tomto příkladu SampleCode. Protože třída je uvnitř vzorového balíčku, kompilátor automaticky kvalifikuje název třídy v okamžiku kompilace do plně platného názvu: samples.SampleCode. Kompilátor také kvalifikuje názvy všech vlastností nebo metod, takže sampleGreeting a sampleFunction() se stanou samples.SampleCode.sampleGreeting a samples.SampleCode.sampleFunction(). Mnoho vývojářů, obzvláště pokud mají zkušenosti s programováním v jazyce Java, volí umístění pouze tříd na horní úrovni balíčku. Jazyk ActionScript 3.0 však podporuje nejenom třídy na horní úrovni balíčku, ale také proměnné, funkce a také příkazy. Pokročilým použitím této funkce je definování jmenného prostoru na horní úrovni balíčku tak, aby byl k dispozici všem třídám v daném balíčku. Povšimněte si však, že na horním úrovni balíčku jsou povoleny pouze dva specifikátory přístupu, public a internal. Na rozdíl od jazyka Java, který umožňuje deklarovat vnořené třídy jako soukromé, jazyk ActionScript 3.0 nepodporuje ani vnořené, ani soukromé třídy. Mnoha jinými způsoby jsou však balíčky jazyka ActionScript 3.0 podobné balíčkům v programovacím jazyce Java. Jak jste mohli vidět na předchozím příkladu, zcela platné reference balíčku jsou vyjádřeny pomocí operátoru tečka (.), stejně jako v jazyce Java. Balíčky můžete použít k organizování kódu do intuitivní hierarchické struktury pro použití jinými programátory. To usnadňuje sdílení kódu a umožňuje vytvářet vlastní balíčky pro sdílení s ostatními a používat balíčky vytvořené jinými programátory ve vlastním kódu. Používání balíčků rovněž pomáhá zajistit, aby použité názvy identifikátorů byly unikátní a nebyly ve střetu s jinými názvy identifikátorů. Ve skutečnosti by někdo mohl říci, že se jedná o primární výhodu balíčků. Například dva programátoři, kteří si přejí sdílet svůj kód navzájem, mohou vytvořit třídu nazvanou SampleCode. Bez balíčků by to vedlo ke konfliktu názvů a jediným řešením by bylo přejmenování jedné ze tříd. Díky balíčkům je však konflikt názvů snadno odstranitelný a to vložením jedné, nebo lépe obou tříd do balíčku s unikátními názvy. Můžete také zahrnout integrované tečky do názvů svých balíčků a vytvořit tak vnořené balíčky. To umožňuje vytvářet hierarchické organizování balíčků. Dobrým příkladem je balík flash.xml v jazyce ActionScript 3.0. Balík flash.xml je vložen do balíku flash. Balíček flash.xml obsahuje dřívější syntaktický analyzátor XML, který byl použit v předchozích verzích jazyka ActionScript. Jedním z důvodů, proč je nyní umístěn v balíčku flash.xml je to, že název starší třídy XML je v konfliktu s názvem nové třídy XML, která implementuje XML pro funkci specifikace ECMAScript (E4X) dostupnou v ActionScript 3.0. I když přesunutí starší třídy XML do balíčku je dobrým prvním krokem, většina uživatelů starších tříd XML importuje balíček flash.xml, který vygeneruje stejný konflikt názvů, pokud nepoužijete vždy plně kvalifikovaný název starší třídy XML (flash.xml.XML). Aby bylo možné se vyhnout této situaci, je starší třída XML nyní pojmenovaná XMLDocument, jak je vidět na následujícím příkladu. package flash.xml { class XMLDocument {} class XMLNode {} class XMLSocket {} } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 40 Jazyk ActionScript a jeho syntaxe Většina jazyka ActionScript 3.0 je organizována v rámci balíku flash. Například balíček flash.display obsahuje seznam zobrazení API, a balíček flash.events obsahuje nový model událostí. Vytváření balíčků Jazyk ActionScript 3.0 poskytuje významnou flexibilitu způsobu, kterým je možné organizovat balíčky, třídy a zdrojové soubory. Předchozí jazyk ActionScript povoloval pouze jednu třídu na zdrojový soubor a vyžadoval, aby název zdrojového souboru odpovídal názvu třídy. Jazyk ActionScript 3.0 umožňuje zahrnout více tříd do jednoho zdrojového souboru, avšak pouze jedna třída v každém souboru může být zpřístupněna kódu, který je pro daný soubor externí. Jinými slovy pouze jedna třída v každém souboru může být deklarována uvnitř deklarace balíčku. Musíte deklarovat všechny dodatečné třídy vně definice balíčku, což tyto třídy zneviditelní pro kód vně tohoto zdrojového souboru. Název třídy deklarované uvnitř definice balíčku musí odpovídat názvu zdrojového souboru. Jazyk ActionScript 3.0 také poskytuje vyšší stupeň flexibility způsobu deklarování balíčků. V předchozích verzích ActionScript balíčky představovaly pouze adresáře, ve kterých byly umístěny zdrojové soubory, a nebylo nutné deklarovat balíčky příkazem package, spíše se název balíčku zahrnul jako součást plně kvalifikovaného názvu třídy ve vaší deklaraci třídy. I když balíčky stále vyjadřují adresáře v jazyku ActionScript 3.0, mohou obsahovat více než třídy. V jazyku ActionScript 3.0 použijete příkaz package k deklarování balíčku, což znamená, že můžete také deklarovat proměnné, funkce a jmenné prostory na horní úrovni balíčku. Na horní úrovni balíčku můžete také zahrnout spustitelné příkazy. Pokud deklarujete proměnné, funkce nebo jmenné prostory na horní úrovni balíčku, jediným atributem dostupným na této úrovni je public a internal a pouze jedna deklarace na úrovni balíčku na soubor může použít atribut public, bez ohledu na to, zda je tato deklarace třídou, proměnnou, funkcí nebo jmenným prostorem. Balíčky jsou užitečné pro organizování kódu a zabránění konfliktů názvů. Nezaměňujte koncept balíčků s nesouvisejícím konceptem dědičnosti třídy. Dvě třídy spočívající ve stejném balíčku budou mít společný jmenný prostor, ale nejsou nutné spojené navzájem mezi sebou jiným způsobem. Podobně, vnořené prostory nemají žádný sémantický vztah s nadřazeným balíčkem. Importování balíčků Pokud chcete použít třídu uvnitř balíčku, musíte importovat balíček nebo jeho specifickou třídu. To je odlišné od jazyka ActionScript 2.0, kde importování tříd bylo volitelné. Například zvažte příklad s třídou SampleCode výše v této kapitole. Pokud třída spočívá v balíčku pojmenovaném samples, musíte použít jeden z následujících příkladů před použitím třídy SampleCode: import samples.*; nebo import samples.SampleCode; Obecně příkazy import by měly být co nejspecifičtější. Pokud plánujete použít pouze třídu SampleCode z balíčku samples, měli byste importovat pouze třídu SampleCode, spíše než celý balíček, ke kterému náleží. Importování celého balíčku může vést k neočekávaným konfliktům názvů. Musíte také umístit zdrojový kód, který definuje balíček nebo třídu do classpath. Třída classpath představuje uživatelem definovaný seznam cest místních adresářů, který stanoví, kde bude kompilátor vyhledávat importované balíčky a třídy. Třída classpath je někdy nazývána cesta sestavení nebo cesta zdroje. Po správném importování třídy nebo balíčku použijete buď plně kvalifikovaný název třídy (samples.SampleCode) nebo pouze název třídy samotné (SampleCode). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 41 Jazyk ActionScript a jeho syntaxe Plně kvalifikované názvy jsou užitečné v případě, že identicky pojmenované třídy, metody nebo vlastnosti vedou k nejednoznačnému kódu, ale jejich správa může být obtížná, pokud jsou použity pro všechny identifikátory. Například použití plně kvalifikovaného názvu vede k rozvláčnému kódu, když konkretizujete instanci třídy SampleCode: var mySample:samples.SampleCode = new samples.SampleCode(); Když se zvýší úroveň třídy vnořeného balíčku, čitelnost kódu se sníží. V případě, kdy si jste jisti, že nejednoznačné identifikátory nebudou problémem, můžete kód pro čtení zjednodušit pomocí jednoduchých identifikátorů. Například konkretizace nové instance třídy SampleCode je mnohem méně rozvláčná, pokud použijete pouze identifikátor třídy: var mySample:SampleCode = new SampleCode(); Pokud se pokusíte použít názvy identifikátorů bez předchozího importování příslušného balíčku nebo třídy, kompilátor nebude schopen nalézt definice třídy. Na druhou stranu, pokud importujete balíček nebo třídu, jakýkoliv pokus o definování názvu vedoucí ke konfliktu s importovaným názvem, povede je generování chyby. Když je vytvořen balíček, výchozí specifikátor přístupu pro všechny členy daného balíčku je internal, což znamená, že standardně jsou členové balíčku viditelné pouze ostatním členům tohoto balíčku. Pokud chcete, aby třída byla dostupná kódu vně balíčku, musíte deklarovat tuto třídu jako public. Například následující balíček obsahuje dvě třídy, SampleCode a CodeFormatter: // SampleCode.as file package samples { public class SampleCode {} } // CodeFormatter.as file package samples { class CodeFormatter {} } Třída SampleCode je viditelná vně balíčku, protože je deklarovaná jako třída public. Třída CodeFormatter je nicméně viditelná pouze v rámci samotného balíčku. Pokud se pokusíte přistupovat k třídě CodeFormatter mimo vzorový balíček, vygenerujete chybu, jak je vidět na následujícím příkladu: import samples.SampleCode; import samples.CodeFormatter; var mySample:SampleCode = new SampleCode(); // okay, public class var myFormatter:CodeFormatter = new CodeFormatter(); // error Pokud chcete obě třídy zpřístupnit vně balíčku, musíte je obě deklarovat jako public. Nemůžete použít atribut public pro deklarování balíčku. Plně kvalifikované názvy jsou užitečné pro vyřešení konfliktů názvů, které mohou při použití balíčků nastat. Takový scénář může nastat, pokud importujete dva balíčky definující třídy se stejným identifikátorem. Například zvažte následující balíček, který také obsahuje třídu pojmenovanou SampleCode: package langref.samples { public class SampleCode {} } Pokud importujete obě třídy následujícím způsobem, vytvoříte konflikt názvů při odkazování na třídu SampleCode: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 42 Jazyk ActionScript a jeho syntaxe import samples.SampleCode; import langref.samples.SampleCode; var mySample:SampleCode = new SampleCode(); // name conflict Kompilátor nemá žádnou možnost zjistit, kterou třídu SampleCode použít. Chcete-li vyřešit tento konflikt, musíte využít plně kvalifikovaného názvu každé třídy, a to následujícím způsobem: var sample1:samples.SampleCode = new samples.SampleCode(); var sample2:langref.samples.SampleCode = new langref.samples.SampleCode(); Poznámka: Programátoři se znalostí C++ často zaměňují příkaz import s příkazem #include. Instrukce #include je nutná v C++ proto, že kompilátory C++ zpracovávají postupně jeden soubor za druhým, a nebudou vyhledávat v dalších souborech definice třídy, pokud je soubor záhlaví explicitně zahrnut. Jazyk ActionScript 3.0 mí instrukci include, ale není navržen pro importování tříd a balíčků. Chcete-li importovat třídy nebo balíčky do jazyka ActionScript 3.0, musíte použít příkaz import a vložit zdrojový soubor obsahující balíček do cesty třídy. Jmenné prostory Jmenné prostory umožňují ovládat viditelnost vlastností a metod, které vytvoříte. Na specifikátory řízení přístupu public, private, protected, a internal můžete nahlížet jako na vestavěné jmenné prostory. Pokud tyto předdefinované specifikátory řízení přístupu nevyhovují vašim požadavkům, můžete vytvořit vlastní jmenné prostory. Pokud jste seznámeni se jmennými prostory XML, většina těchto informací pro vás nebude nová, i když syntaxe a podrobnosti o implementování jazyka ActionScript se mírně odlišuje od těch v XML. Pokud jste nikdy dříve nepracovali s jmennými prostory, koncept samotný je přímý, ale implementace má specifickou terminologii, kterou se musíte naučit. Chcete-li porozumět funkci jmenných prostorů, je dobré znát, že název vlastnosti nebo metody vždy obsahuje dvě části: identifikátor a jmenný prostor. Identifikátor je to, co obvykle považujete za název. Například identifikátory v následující definici třídy jsou sampleGreeting a sampleFunction(): class SampleCode { var sampleGreeting:String; function sampleFunction () { trace(sampleGreeting + " from sampleFunction()"); } } Kdykoliv definice nejsou předcházeny atributem jmenného prostoru, jejich názvy jsou kvalifikovány výchozím jmenným prostorem internal, což znamená, že jsou viditelné pouze volajícím ve stejném balíčku. Pokud je kompilátor nastaven do přísného režimu, vydá výstrahu, že jmenné prostory internal platí pro každý identifikátor bez atributu jmenného prostoru. Aby byl identifikátor dostupné všude, musíte specificky uvést v předponě název identifikátoru s atributem public. V předchozím příkladu kódu obě třídy sampleGreeting a sampleFunction() mají hodnotu jmenného prostoru internal. Existují tři základní kroky, které je nutné při používání jmenných prostorů používat. Nejprve musíte definovat jmenný prostor pomocí klíčového slova namespace. Například následující kód definuje jmenný prostor version1: namespace version1; Za druhé použijete jmenný prostor namísto specifikátoru řízení přístupu v deklaraci vlastnosti nebo metody. Následující příklad vkládá funkci pojmenovanou myFunction() do jmenného prostoru version1: version1 function myFunction() {} Za třetí, jakmile použijete jmenný prostor, můžete na něj odkazovat instrukcí use nebo kvalifikováním názvu identifikátoru jmenným prostorem. Následující příklad odkazuje na funkci myFunction() pomocí instrukce use: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 43 Jazyk ActionScript a jeho syntaxe use namespace version1; myFunction(); Můžete také použít kvalifikovaný název pro odkazování na funkci myFunction(), jak je vidět na následujícím příkladu: version1::myFunction(); Definování jmenných prostorů Jmenné prostory obsahují jednu hodnotu, Univerzální identifikátor zdroje (URI - Uniform Resource Identifier), která se někdy nazývá název jmenného prostoru. URI umožňuje zajistit, aby definice jmenného prostoru byla jedinečná. Vytváříte jmenný prostor deklarováním definice jmenného prostoru jedním ze dvou způsobů. Můžete buď definovat jmenný prostor s explicitní URI, jako byste definovali jmenný prostor XML, nebo můžete URI vynechat. Následující příklad ukazuje, jak lze jmenný prostor definovat pomocí URI: namespace flash_proxy = "http://www.adobe.com/flash/proxy"; URI slouží jako unikátní identifikační řetězec pro daný jmenný prostor. Pokud vynecháte URI, jako v následujícím příkladu, kompilátor vytvoří jedinečný vnitřní identifikační řetězec na místě URI. K tomuto vnitřnímu identifikačnímu řetězci nemáte přístup. namespace flash_proxy; Jakmile definujete jmenný prostor, s URI nebo bez, tento jmenný prostor nelze předefinovat ve stejném rozsahu. Pokus o definování jmenného prostoru, jak bylo uvedeno výše ve stejném rozsahu, vede k chybám kompilátoru. Pokud je jmenný prostor definován v balíčku nebo třídě, jmenný prostor nemůže být viditelný pro kód vně tohoto balíčku nebo třídy, pokud není použit příslušný specifikátor řízení přístupu. Například následující kód zobrazuje flash_proxy jmenný prostor definovaný v balíčku flash.utils. V následujícím příkladu chybějící specifikátor řízení přístupu znamená, že jmenný prostor flash_proxy bude viditelný pouze pro kód v balíčku flash.utils a nebude viditelný pro kód vně tohoto balíčku: package flash.utils { namespace flash_proxy; } Následující kód využívá atribut public pro zviditelnění jmenného prostoru flash_proxy pro kód vně balíčku: package flash.utils { public namespace flash_proxy; } Použití jmenných prostor Použití jmenných prostor znamená vložení definice do jmenného prostoru. Definice, které lze vložit do jmenného prostoru zahrnují funkce, proměnné a konstanty (třídu do vlastního jmenného prostoru vložit nelze). Zvažte například funkci deklarovanou pomocí jmenného prostoru řízení přístupu public. Pomocí atributu public v definici funkce vloží funkci do veřejného jmenného prostoru, což ji zpřístupní pro veškerý kód. Jakmile definujete jmenný prostor, můžete použít jmenný prostor, který jste definovali a to stejným způsobem, jako byste použili atribut public a definice bude dostupná pro kód, který může odkazovat na váš vlastní jmenný prostor. Pokud například definujete jmenný prostor example1, můžete přidat metodu nazvanou myFunction() pomocí example1 jako atributu, jak je vidět na následujícím příkladu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 44 Jazyk ActionScript a jeho syntaxe namespace example1; class someClass { example1 myFunction() {} } Deklarování metody myFunction() pomocí jmenného prostoru example1 jako atributu znamená, že metoda náleží jmennému prostoru example1. Při použití jmenného prostoru byste měli mít na paměti následující: • Můžete použít pouze jeden jmenný prostor pro každou deklaraci. • Neexistuje žádný způsob, jak aplikovat atribut jmenného prostoru pro více než jednu definici najednou. Jinými slovy, pokud chcete použít svůj jmenný prostor na deset různých funkcí, musíte přidat jmenné prostory jako atribut k jedné z deseti definic funkcí. • Pokud použijete pouze jmenný prostor, nemůžete také uvést specifikátor řízení přístupu, protože jmenné prostory a specifikátory řízení přístupu se vzájemně vylučují. Jinými slovy, nemůžete deklarovat funkci nebo vlastnosti jako public, private, protected nebo internal kromě použití jmenného prostoru. Odkazování jmenných prostory Není nutné explicitně definovat odkaz na jmenný prostor, když použijete metodu nebo vlastnost deklarovanou pomocí kteréhokoliv jmenného prostoru řízení přístupu, například public, private, protected a internal. Tak tomu je proto, že přístup k těmto speciálním jmenným prostorům je řízen kontextem. Například definice vložené do jmenného prostoru private jsou automaticky dostupné kódu ve stejné třídě. Pro vámi definované jmenné prostory nicméně taková citlivost na kontext neexistuje. Chcete-li použít metodu nebo vlastnosti, kterou jste vložili do vlastního jmenného prostoru, musíte jmenný prostor odkazovat. Jmenný prostor můžete odkazovat s použitím instrukce use namespace nebo můžete kvalifikovat název se jmenným prostorem pomocí symbolu kvalifikátoru názvu (::). Odkazování jmenného prostoru pomocí instrukce use namespace „otevře” jmenný prostor, takže jej lze použít pro všechny identifikátory, které nejsou kvalifikované. Pokud jste například definovali jmenný prostor example1, můžete přistupovat k názvům v tomto jmenném prostoru pomocí use namespace example1: use namespace example1; myFunction(); Můžete otevřít více než jeden jmenný prostor najednou. Jakmile otevřete jmenný prostor s use namespace, zůstane otevřený v celém bloku kódu, ve kterém byl otevřen. Neexistuje žádný způsob, jak explicitně jmenný prostor uzavřít. Pokud budete mít otevřený více než jeden jmenný prostor, zvyšuje se tak pravděpodobnost konfliktu názvů. Pokud dáváte přednost neotevírání jmenného prostoru, můžete se vyhnout instrukci use namespace kvalifikováním názvu metody nebo vlastnosti s jmenným prostorem a symbolem kvalifikátoru jména. Například následující kód znázorňuje, jak lze kvalifikovat název myFunction() pomocí jmenného prostoru example1: example1::myFunction(); Použití jmenného prostoru Ve třídě flash.utils.Proxy, která je součástí jazyka ActionScript 3.0, můžete nalézt reálný příklad jmenného prostoru, který je použit k zabránění konfliktům názvů. Třída Proxy, která je náhradou za Object.__resolve z jazyka ActionScript 2.0 umožňuje sledovat odkazy k nedefinovaným vlastnostem nebo metodám předtím, než se vyskytne chyba. Všechny metody třídy Proxy spočívají v jmenném prostoru flash_proxy, aby se zabránilo konfliktu názvů. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 45 Jazyk ActionScript a jeho syntaxe Pro lepší porozumění použití jmenného prostoru flash_proxy je nutné porozumět použití třídy Proxy. Funkce třídy Proxy je dostupná pouze třídám které z ní pocházejí. Jinými slovy, pokud chcete používat metody třídy Proxy na objekt, musí definice třídy objektu rozšiřovat třídu Proxy. Pokud chcete například sledovat pokusy volání nedefinované metody, rozšířili byste třídu Proxy a pak potlačili metodu callProperty() třídy Proxy. Můžete si pamatovat, že implementování jmenného prostoru je obvykle proces složený ze tří kroků definování, použití a pak odkazování jmenného prostoru. Protože nikdy explicitně nevoláte metody třídy Proxy, jmenný prostor flash_proxy je pouze definován a použit, ale nikdy není referencován. ActionScript 3.0, definuje jmenný prostor flash_proxy a použije jej na třídu Proxy. Kód musí pouze aplikovat jmenný prostor flash_proxy na třídy, které rozšiřují třídu Proxy. Jmenný prostor flash_proxy je definován v balíčku flash.utils způsobem obdobný následujícímu: package flash.utils { public namespace flash_proxy; } Jmenný prostor je aplikován na metody třídy Proxy, jak je znázorněno v následujícím výňatku z třídy Proxy: public class Proxy { flash_proxy function callProperty(name:*, ... rest):* flash_proxy function deleteProperty(name:*):Boolean ... } jak ukazuje následující kód, musíte nejprve importovat třídu Proxy a pak jmenný prostor flash_proxy. Musíte pak deklarovat svou třídu tak, aby rozšiřovala třídu Proxy (v případě, že kompilujete v přísném režimu, musíte také přidat atribut dynamic). Když potlačíte metodu callProperty(), musíte použít jmenný prostor flash_proxy. package { import flash.utils.Proxy; import flash.utils.flash_proxy; dynamic class MyProxy extends Proxy { flash_proxy override function callProperty(name:*, ...rest):* { trace("method call intercepted: " + name); } } } Pokud vytvoříte instanci třídy MyProxy a zavoláte nedefinovanou metodu, například metodu testing() volanou v následujícím příkladu, objekt Proxy sleduje volání metody a vykonává příkazy uvnitř potlačené metody callProperty() (v tomto případě jednoduchý příkaz trace()). var mySample:MyProxy = new MyProxy(); mySample.testing(); // method call intercepted: testing PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 46 Jazyk ActionScript a jeho syntaxe Existují dvě výhody, proč mít metody třídy Proxy uvnitř jmenného prostoru flash_proxy. První, mít samostatné jmenné prostory redukuje nepořádek ve veřejném rozhraní jakékoliv třídy, která rozšiřuje třídu Proxy. (Existuje asi tucet metod v třídě Proxy, které můžete potlačit, všechny nejsou navrženy pro přímé volání. Jejich umístění do veřejného jmenného prostoru může být matoucí.) Druhá, použití jmenného prostoru flash_proxy zabraňuje konfliktu názvů v případě, že vaše podtřída Proxy obsahuje metody instance s názvy odpovídajícími metodám třídy Proxy. Můžete například chtít pojmenovat jednu z vlastních metod callProperty(). Následující kód je přijatelný, protože vaše verze metody callProperty() je v jiném jmenném prostoru. dynamic class MyProxy extends Proxy { public function callProperty() {} flash_proxy override function callProperty(name:*, ...rest):* { trace("method call intercepted: " + name); } } Jmenné prostory mohou být také užitečné v případě, že chcete zajistit přístup k metodám nebo vlastnostem způsobem, který nelze uskutečnit se čtyřmi specifikátory řízení přístupu (public, private, internal a protected). Například můžete mít několik pomocných meto, které jsou rozprostřeny v několika balíčcích. Chcete například všechny tyto metody zpřístupnit všem svým balíčkům, ale nechcete je mít veřejně přístupné. To uskutečníte tak, že vytvoříte nový jmenný prostor a použijete jej jako vlastní speciální specifikátor řízení přístupu. Následující příklad používá uživatelem definovaný jmenný prostor k seskupení dvou funkcí, které spočívají v různých balíčcích. Jejich seskupením do stejného jmenného prostoru můžete obě funkce zviditelnit ve třídě nebo balíčku pomocí jediného příkazu use namespace. Tento příklad používá čtyři soubory k demonstrování této techniky. Všechny soubory musí být v cestě pro třídu. První soubor, myInternal.as, se použije pro definování jmenného prostoru myInternal. Protože soubor je v balíčku pojmenovaném podle příkladu, musíte umístit soubor do složky pojmenované podle příkladu. Jmenný prostor je označen jako public, takže jej lze importovat do ostatních balíčků. // myInternal.as in folder example package example { public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples"; } Druhý a třetí soubor, Utility.as a Helper.as, definují třídy obsahující metody, které by měly být dostupné pro ostatní balíčky. Třída Utility je v balíčku example.alpha, což znamená, že soubor by měl být umístěn dovnitř složky pojmenované alpha, která je podsložkou složky v příkladu. Třída Helper je v balíčku example.beta, což znamená, že soubor by měl být umístěn dovnitř složky pojmenované beta, která je podsložkou složky v příkladu. Oba tyto balíčky, example.alpha i example.beta, musí importovat jmenný prostor před jeho použitím. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 47 Jazyk ActionScript a jeho syntaxe // Utility.as in the example/alpha folder package example.alpha { import example.myInternal; public class Utility { private static var _taskCounter:int = 0; public static function someTask() { _taskCounter++; } myInternal static function get taskCounter():int { return _taskCounter; } } } // Helper.as in the example/beta folder package example.beta { import example.myInternal; public class Helper { private static var _timeStamp:Date; public static function someTask() { _timeStamp = new Date(); } myInternal static function get lastCalled():Date { return _timeStamp; } } } Čtvrtý soubor, NamespaceUseCase.as, je hlavní třídou aplikaci a měl by být příbuzným složky příkladu. V aplikaci Adobe Flash CS4 Professional tato třída bude použita jako třída dokumentu pro FLA. Třída NamespaceUseCase rovněž importuje jmenný prostor myInternal a používá jej pro zavolání statických metod, které spočívají v jiných balíčcích. Příklad používá statické metody pouze pro zjednodušení kódu. Statické a instanční metody mohou být vloženy do jmenného prostoru myInternal. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 48 Jazyk ActionScript a jeho syntaxe // NamespaceUseCase.as package { import flash.display.MovieClip; import example.myInternal; // import namespace import example.alpha.Utility;// import Utility class import example.beta.Helper;// import Helper class public class NamespaceUseCase extends MovieClip { public function NamespaceUseCase() { use namespace myInternal; Utility.someTask(); Utility.someTask(); trace(Utility.taskCounter); // 2 Helper.someTask(); trace(Helper.lastCalled); // [time someTask() was last called] } } } Proměnné Proměnné umožňují uložit hodnoty, které v programu používáte. Pro deklarování proměnné musíte použít příkaz var s názvem proměnné. V jazyce ActionScript 2.0 se použití příkazu var vyžaduje pouze v případě, že používáte anotace type. V jazyce ActionScript 3.0 je použití příkazu var vyžadováno vždy. Například následující řádek jazyka ActionScript deklaruje proměnnou pojmenovanou i: var i; Pokud vynecháte příkaz var když proměnnou deklarujete, zobrazí se chyba kompilátoru v přísném režimu a chyba spuštění v režimu standardní. Například následující řádek kódu způsobí chybu v případě, že proměnná i nebyla definována dříve: i; // error if i was not previously defined Pro spojení proměnné s datovým typem musíte toto učinit, když deklarujete proměnnou. Deklarování proměnné bez označení jejího typu je povoleno, ale způsobí výstrahu kompilátoru v přísném režimu. Typ proměnné definujete připojením dvojtečky (:) za název a typem proměnné. Například následující kód deklarujete proměnnou i typu int: var i:int; Můžete přiřadit hodnotu proměnné pomocí operátoru (=). Například následující kód deklarujete proměnnou i a přiřazuje jí hodnotu 20: var i:int; i = 20; Patrně bude pohodlnější přiřadit hodnotu proměnné ve stejný okamžik, když deklarujete proměnnou, jako v následujícím příkladu: var i:int = 20; PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 49 Jazyk ActionScript a jeho syntaxe Technika přiřazování hodnoty proměnné v době její deklarace je běžně použita nejenom pro přiřazování primitivních hodnot, jako jsou celočíselné hodnoty a řetězce, ale také při vytváření pole nebo konkretizaci instance třídy. Následující příklad zobrazuje pole, které má deklarovanou a přiřazenou hodnotu pomocí jedné řádky kódu. var numArray:Array = ["zero", "one", "two"]; Můžete vytvořit instanci třídy pomocí operátoru new. Následující příklad vytváří instanci pojmenovanou CustomClass a přiřazuje referenci nově vytvořené instanci třídy proměnné pojmenované customItem: var customItem:CustomClass = new CustomClass(); Pokud máte pro deklarován více než jednu proměnnou, můžete deklarovat všechny v jedné řádce pomocí operátoru čárka (,) a proměnné tak oddělit. Například následující kód deklarujete tři proměnné v jedné řádce kódu: var a:int, b:int, c:int; Můžete také přiřadit hodnoty každé proměnné ve stejné řádce kódu. Například následující kód deklaruje tři proměnné (a, b a c) a přiřazuje každé hodnotu: var a:int = 10, b:int = 20, c:int = 30; I když můžete použít operátor čárka pro seskupení deklarace proměnných do jednoho příkazu, může to snížit čitelnost kódu. Porozumění rozsahu proměnných Rozsah proměnné představuje oblast kódu, kde může být proměnná zpřístupněna lexikálním odkazem. Globální proměnná je taková, která je definovaná ve všech oblastech kódu, zatímco lokální proměnná je taková, která je definována pouze v jedné části kódu. V jazyce ActionScript 3.0 mají proměnné vždy přiřazen rozsah funkce nebo třídy, ve které jsou deklarované. Globální proměnná je taková, kterou definujete vně funkce nebo definice třídy. Například následující kód vytváří globální proměnnou strGlobal jejím deklarováním vně veškerých funkcí. Příklad ukazuje, že globální proměnná je k dispozici uvnitř a vně definice funkce. var strGlobal:String = "Global"; function scopeTest() { trace(strGlobal); // Global } scopeTest(); trace(strGlobal); // Global Místní proměnou deklarujete pomocí proměnné uvnitř definice funkce. Nejmenší oblast kódu, pro kterou lze definovat místní proměnnou, je definice funkce. Místní proměnná deklarovaná v rámci funkce bude existovat pouze v této funkci. Pokud například deklarujete proměnnou pojmenovanou str2 v rámci funkce nazvané localScope(), tato proměnná nebude vně funkce dostupná. function localScope() { var strLocal:String = "local"; } localScope(); trace(strLocal); // error because strLocal is not defined globally Pokud název proměnné použité jako místní proměnná bude již deklarován jako globální proměnná, místní definice skryje (nebo vytvoří stín) globální definici, když bude místní proměnná v jejím rozsahu. Globální proměnná se stále vyskytuje vně funkce. Například následující kód vytváří globální řetězcovou proměnnou pojmenovanou str1 a pak vytváří místní proměnou stejného názvu uvnitř funkce scopeTest(). Příkaz trace uvnitř funkce odesílá na výstup místní hodnotu proměnné, ale příkaz trace vně funkce odesílá na výstup globální hodnotu proměnné. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 50 Jazyk ActionScript a jeho syntaxe var str1:String = "Global"; function scopeTest () { var str1:String = "Local"; trace(str1); // Local } scopeTest(); trace(str1); // Global Proměnné jazyka ActionScript, na rozdíl od proměnných v C++ a Java, nemají rozsah blok-úroveň. Blok kódu je skupinou příkazů mezi levou složenou závorkou ( { ) a pravou složenou závorkou ( } ). V některých programovacích jazycích, například C++ a Java, proměnné deklarované uvnitř bloku kódu nejsou dostupné vně tohoto bloku. Toto omezení je nazváno rozsah blok-úroveň a v jazyce ActionScript neexistuje. Pokud deklarujete proměnnou uvnitř bloku kódu, tato proměnná nebude dostupná pouze v tomto bloku kódu, ale také v ostatních částech funkce, ke které blok kódu náleží. Například následující funkce obsahuje proměnné, které jsou definované v různých rozsazích bloku. Všechny proměnné jsou dostupné prostřednictvím funkce. function blockTest (testArray:Array) { var numElements:int = testArray.length; if (numElements > 0) { var elemStr:String = "Element #"; for (var i:int = 0; i < numElements; i++) { var valueStr:String = i + ": " + testArray[i]; trace(elemStr + valueStr); } trace(elemStr, valueStr, i); // all still defined } trace(elemStr, valueStr, i); // all defined if numElements > 0 } blockTest(["Earth", "Moon", "Sun"]); Zajímavým dopadem neexistence rozsahu blok-úroveň je to, že můžete číst proměnnou nebo do ní zapisovat předtím, než je deklarovaná, pokud je deklarovaný před ukončením funkce. Tak tomu je díky technice nazvané zvedání, což znamená, že kompilátor přesouvá všechny deklarace proměnných na horní stranu funkce. Například následující kód je zkompilován i v případě, že se počáteční funkce trace() pro proměnnou num vyskytuje před deklarováním proměnné num: trace(num); // NaN var num:Number = 10; trace(num); // 10 Kompilátor však "nezvedne" žádné příkazy přiřazení. To vysvětluje, proč počáteční trace() proměnné num vede k NaN (není číslo), což je výchozí hodnota proměnných datového typu Number. To znamená, že můžete přiřadit hodnoty proměnným ještě před jejich deklarováním, jak je vidět v následujícím příkladu: num = 5; trace(num); // 5 var num:Number = 10; trace(num); // 10 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 51 Jazyk ActionScript a jeho syntaxe Výchozí hodnoty Výchozí hodnota je hodnota, kterou proměnná obsahuje před nastavením její hodnoty. Proměnnou inicializujete, když poprvé nastavíte její hodnotu. Pokud deklarujete proměnou, ale nenastavíte její hodnotu, tato proměnná bude neinicializovaná. Hodnota neinicializované proměnné závisí na datovém typu. Následující tabulka popisuje výchozí hodnoty proměnných organizované podle datového typu: Typ dat Výchozí hodnota Boolean false int 0 Number NaN Object null String null uint 0 Není deklarováno (ekvivalent anotaci typu *) undefined Všechny ostatní třídy, včetně uživatelem definovaných tříd. null Pro proměnné typu Number je výchozí hodnota NaN (není číslo), což je speciální hodnota definovaná standardem IEEE-754 pro vyjádření hodnoty, která nepředstavuje číslo. Pokud deklarujete proměnnou, ale nikoliv její datový typ, bude platit výchozí datový typ *, což ve skutečnosti znamená, že proměnná je bez typu. Pokud také neinicializujete proměnnou bez typu pomocí hodnoty, její výchozí hodnota je undefined. Pro datové typy jiné, než Boolean, Number, int a uint je výchozí hodnota kterékoliv proměnné null. To platí pro všechny třídy definované jazykem ActionScript 3.0, stejně jako pro všechny vlastní třídy, které vytvoříte. Hodnota null není platnou hodnotou pro proměnné typu Boolean, Number, int nebo uint. Pokud se pokusíte přiřadit hodnotu null takové proměnné, hodnota je převedena na výchozí hodnotu pro daný datový typ. Pro proměnné typu Object můžete přiřadit hodnotu null. Pokud se pokusíte přiřadit hodnotu undefined proměnné typu Object, hodnota je převedena na null. Pro proměnné typu Number existuje speciální funkce horní úrovně pojmenovaná isNaN(), která vrací booleovskou hodnotu true v případě, že proměnná není číslem, jinak vrací hodnotu false. Typy dat Datový typ definuje soubor hodnot. Například datový typ booleovská hodnota je souborem přesně dvou hodnot: true a false. Kromě datového typu booleovská hodnota jazyk ActionScript 3.0 definuje několik běžně používaných datových typů, například String, Number a Array. Můžete definovat vlastní datové typy pomocí tříd nebo rozhraní a definovat tak vlastní soubor hodnot. Všechny hodnoty v jazyce ActionScript 3.0, ať už primitivní nebo komplexní, jsou objekty. Primitivní hodnota je hodnota náležející jednomu z následujících datových typů: booleovský, int, Number, String a uint. Práce s primitivními hodnotami je obvykle rychlejší než s komplexními hodnotami, protože jazyk ActionScript ukládá primitivní hodnoty speciálním způsobem, které umožňuje optimalizaci paměti a rychlosti. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 52 Jazyk ActionScript a jeho syntaxe Poznámka: Pro čtenáře se zájmem o technické podrobnosti jazyk ActionScript ukládá primitivní hodnoty interně jako nezměnitelné objekty. Ve skutečnosti to, že jsou uloženy jako nezměnitelné objekty znamená, že předání odkazem je efektivně shodné jako předání hodnotou. To snižuje využití paměti a zvyšuje rychlost vykonávání, protože odkazy jsou obvykle výrazně menší než hodnoty samotné. Komplexní hodnota je hodnota, která není primitivní. Datové typy definující komplexní hodnoty zahrnují: Array, Date, Error, Function, RegExp, XML a XMLList. Mnoho programovacích jazyků odlišuje mezi primitivními hodnotami a jejich objekty obalu. Například jazyk Java má primitivní hodnotu int a třídu java.lang.Integer, která jí obaluje. Primitivní hodnoty Java nejsou objekty, ale jejich obaly ano, což činí primitivní hodnoty užitečné pro jedny operace a objekty obalu vhodnější pro jiné operace. V jazyku ActionScript 3.0 primitivní hodnoty a jejich objekty obalu jsou z praktických účelů nerozlišitelné. Všechny hodnoty, i primitivní hodnoty, jsou objekty. Aplikace Flash Player a Adobe AIR pracují s těmito primitivními typy jako se speciálními případy, které se chovají jako objekty, ale nevyžaduje normální doplňky související s vytvářením objektů. To znamená, že následující dva řádky kódu jsou shodné: var someInt:int = 3; var someInt:int = new int(3); Všechny primitivní a komplexní datové typy uvedené výše jsou definovány třídami jádra jazyka ActionScript 3.0. Třídy jádra umožňují vytvářet objekty pomocí liberálových hodnot namísto pomocí operátoru new. Například můžete vytvořit pole pomocí literálové hodnoty nebo konstruktoru třídy Array, a to takto: var someArray:Array = [1, 2, 3]; // literal value var someArray:Array = new Array(1,2,3); // Array constructor Kontrola typu Kontrola typu může nastat buď v čase kompilace nebo v čase spuštění. Staticky zadávané jazyky, například C++ a Java, provádějí kontrolu typu v okamžiku kompilace. Dynamicky zadávané jazyky, například Smalltalk a Python, provádějí kontrolu typu v okamžiku spuštění. Jako dynamicky zadávaný má jazyk ActionScript 3.0 kontrolu typu během spouštění, ale podporuje také kontrolu během kompilace díky speciálnímu režimu kompilátoru, nazvanému přísný režim. V přísném režimu kontrola typu nastává v čase kompilace i spuštění, ale ve standardním režimu pouze v čase spuštění. Dynamicky zadávané jazyky nabízejí vynikající flexibilitu když svůj kód strukturujete, ale za cenu toho, že se chyby typu projeví až v době spuštění. Staticky zadávané jazyky hlásí chyby typu v době kompilace, ale za cenu toho, že vyžaduje známost informace typu v čase kompilace. Kontrola typu v čase kompilace Kontrola typu v čase kompilace je často vhodnější u větších projektů, protože s rostoucí velikostí projektu se obvykle důležitost flexibility datového typu snižuje, na rozdíl od odstranění chyb typu, která je nutná co nejdříve. Proto je standardně kompilátor jazyka ActionScript v aplikaci Adobe Flash CS4 Professional a Adobe Flex Builder nastaven na spouštění v přísném režimu. Pro zajištění kontroly typu v čase kompilace vyžaduje, aby kompilátor znal informace o datovém typu pro proměnné nebo výrazy ve vašem kódu. Chcete-li explicitně deklarovat datový typ pro proměnnou, přidejte operátor dvojtečku (:) následovanou datovým typem jako příponou názvu proměnné. Chcete-li připojit k datovému typu parametr, použijte operátor dvojtečku následovanou datovým typem. Například následující kód přidává informaci o datovém typu k parametru xParam a deklaruje proměnnou myParam s explicitním datovým typem: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 53 Jazyk ActionScript a jeho syntaxe function runtimeTest(xParam:String) { trace(xParam); } var myParam:String = "hello"; runtimeTest(myParam); V přísném režimu kompilátor jazyka ActionScript hlásí neshody typu jako chyby kompilátoru. Například následující kód deklaruje parametr funkce xParam typu Object, ale později se pokusí přiřadit hodnoty typu String a Number tomuto parametru. To v přísném režimu vede k chybě kompilátoru. function dynamicTest(xParam:Object) { if (xParam is String) { var myStr:String = xParam; // compiler error in strict mode trace("String: " + myStr); } else if (xParam is Number) { var myNum:Number = xParam; // compiler error in strict mode trace("Number: " + myNum); } } I v přísném režimu se můžete selektivně rozhodnout pro kontrolu v čase kompilace a to ponecháním pravé straně přiřazovacího příkazu nezadané. Můžete označit proměnnou nebo výraz jako bez typu buď vynecháním anotace typu nebo pomocí speciální anotace typu hvězdičky (*). Například pokud bude parametr xParam v předchozím příkladu modifikován tak, aby již neměl anotaci typu, kód bude zkompilován v přísném režimu: function dynamicTest(xParam) { if (xParam is String) { var myStr:String = xParam; trace("String: " + myStr); } else if (xParam is Number) { var myNum:Number = xParam; trace("Number: " + myNum); } } dynamicTest(100) dynamicTest("one hundred"); Kontrola typu v době spuštění Kontrola typu v době spuštění nastává v jazyce ActionScript 3.0 bez ohledu na to, zda kompilaci provádíte v přísném nebo standardním režimu. Zvažte situaci, ve které je hodnota 3 předána jako argument funkci, která očekává pole. V přísném režimu kompilátor vygeneruje chybu, protože hodnota 3 není kompatibilní s datovým typem Array. Pokud přísný režim vypnete a spustíte standardní režim, kompilátor nebude neshodu typu signalizovat, ale kontrola s okamžiku spuštění aplikace Flash Player a Adobe AIR povede k signalizaci chyby spuštění. Následující příklad zobrazuje funkci pojmenovanou typeTest(), která očekává argument Array, avšak předána je hodnota 3. To způsobí chybu v okamžiku spuštění ve standardním režimu, protože hodnota 3 není členem datového typu (Array) deklarovaných pro parametr. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 54 Jazyk ActionScript a jeho syntaxe function typeTest(xParam:Array) { trace(xParam); } var myNum:Number = 3; typeTest(myNum); // run-time error in ActionScript 3.0 standard mode Mohou také nastat situace, kde se zobrazí chyba dat při spuštění, i když pracujete v přísném režimu. To je možné v případě použití přísného režimu, ale rozhodnete se nepoužívat kontrolu v okamžiku kompilace pomocí proměnné bez stanoveného typu. Když použijete proměnnou bez stanoveného typu, neeliminujete kontrolu typu, ale spíše ji odkládejte na dobu spuštění. Pokud například proměnná myNum v předchozím příkladu nemá deklarovaný datový typ, kompilátor nemůže detekovat neshodu typu, ale aplikace Flash Player a Adobe AIR vygenerují chybu v době spuštění, protože porovnají hodnotu v době spuštění myNum, která je nastavena na 3 jako důsledek příkazu přiřazení, s typem xParam, který je nastaven na datový typ Array. function typeTest(xParam:Array) { trace(xParam); } var myNum = 3; typeTest(myNum); // run-time error in ActionScript 3.0 Kontrola typu v době spuštění rovněž umožňuje flexibilnější použití dědičnosti, než kontrola v době kompilace. Odložením kontroly typu na dobu spuštění ve standardním režimu umožňuje odkazovat vlastnosti podtřídy i v případě povýšení. Povýšení nastává v případě, že použijete základní třídu k deklarování typu instance třídy, ale ke konkretizaci použijete podtřídu. Můžete například vytvořit třídu pojmenovanou ClassBase, která může být rozšířena (třídy s atributem final nemohou být rozšířeny): class ClassBase { } Poté vytvoříte podtřídu pro ClassBase pojmenovanou ClassExtender, která má jednu vlastnost pojmenovanou someString, a to takto: class ClassExtender extends ClassBase { var someString:String; } Pomocí obou tříd můžete vytvořit instanci třídy, která je deklarovaná pomocí datového typu ClassBase, ale konkretizována je pomocí konstruktoru ClassExtender. Povýšení je považováno za bezpečnou operaci, protože základní třída neobsahuje žádné vlastnosti nebo metody, které nejsou v podtřídě. var myClass:ClassBase = new ClassExtender(); Podtřída však neobsahuje vlastnosti nebo metody, které nemá základní třída. Například třída ClassExtender obsahuje vlastnost someString, která ve třídě ClassBase neexistuje. V jazyce ActionScript 3.0 ve standardním režimu můžete odkazovat tuto vlastnost pomocí instance myClass bez generování chyby v době kompilace, jak je vidět na následujícím příkladu: var myClass:ClassBase = new ClassExtender(); myClass.someString = "hello"; // no error in ActionScript 3.0 standard mode PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 55 Jazyk ActionScript a jeho syntaxe Operátor is Operátor is, který je v případě ActionScript 3.0 nový, umožňuje testovat, zda je proměnná nebo výraz členem daného datového typu. V předchozí verzi jazyka ActionScript operátor instanceof zajišťovat tutéž funkci, ale v ActionScript 3.0 operátor instanceof by neměl být k testování členství v datovém typu používán. Operátor is by měl být použit namísto operátoru instanceof pro ruční kontrolu typu, protože výraz x instanceof y pouze kontroluje prototypový řetězec x, zda-li existuje y (a v ActionScript 3.0 prototypový řetězec neposkytuje kompletní obraz o hierarchii dědičnosti). Operátor is prověřuje správnou hierarchii dědičnosti a lze jej použít ke kontrole nejenom zda je objekt instancí specifické třídy, ale také ke kontrole, zda je objekt instancí třídy, která implementuje specifické rozhraní. Následující příklad vytváří instanci třídy Sprite pojmenovanou mySprite a používá operátor is k testování, zda je mySprite instancí tříd Sprite a DisplayObject a zda implementuje rozhraní IEventDispatcher: var mySprite:Sprite = new Sprite(); trace(mySprite is Sprite); // true trace(mySprite is DisplayObject);// true trace(mySprite is IEventDispatcher); // true Operátor is kontroluje hierarchii dědičnosti a správně hlásí, že mySprite je kompatibilní s třídami Sprite a DisplayObject (třída Sprite je podtřídou třídy DisplayObject). Operátor is rovněž kontroluje, zda je mySprite odvozená z některých tříd, které implementují rozhraní IEventDispatcher. Protože třída Sprite je odvozená z třídy EventDispatcher, která implementuje rozhraní IEventDispatcher, operátor is správně hlásí, že mySprite implementuje stejné rozhraní. Následující příklad zobrazuje stejné testy z předchozího příkladu, avšak s operátorem instanceof namísto is. Operátor instanceof správně identifikuje, že mySprite je instancí Sprite nebo DisplayObject, ale vrací false, když je použit pro testování, zda mySprite implementuje rozhraní IEventDispatcher. trace(mySprite instanceof Sprite); // true trace(mySprite instanceof DisplayObject);// true trace(mySprite instanceof IEventDispatcher); // false Operátor as Operátor as, který je v jazyce ActionScript 3.0 nový, rovněž umožňuje kontrolovat, zda je výraz členem daného datového typu. Na rozdíl od operátoru is nevrací operátor as booleovskou hodnotu. Místo toho operátor as vrací hodnotu výrazu, namísto true a hodnotu null namísto false. Následující příklad ukazuje výsledky použití operátoru as místo operátoru is v jednoduchém případě kontroly, zda je instance Sprite členem datových typů DisplayObject, IEventDispatcher a Number. var mySprite:Sprite = new Sprite(); trace(mySprite as Sprite); // [object Sprite] trace(mySprite as DisplayObject); // [object Sprite] trace(mySprite as IEventDispatcher); // [object Sprite] trace(mySprite as Number); // null Když použijete operátor as, operand na pravé straně musí být datovým typem. Pokus použít výraz jiný, než datový typ na pravé straně povede k chybě. Dynamické třídy Dynamické třídy definují objekt, který může být změně v době spuštění přidáním nebo změnou vlastností a metod. Třída, která není dynamická, například String, je zapouzdřenou třídou. Nemůžete přidávat vlastnosti nebo metody do zapouzdřené třídy v době spuštění. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 56 Jazyk ActionScript a jeho syntaxe Dynamické třídy vytváříte pomocí atributu dynamic při deklarování třídy. Například následující kód vytváří dynamickou třídu pojmenovanou Protean: dynamic class Protean { private var privateGreeting:String = "hi"; public var publicGreeting:String = "hello"; function Protean() { trace("Protean instance created"); } } Pokud následovně konkretizujete instanci třídy Protean, můžete k ní přidat vlastnosti nebo metody vně definice třídy. Například následující kód vytváří instanci třídy Protean a přidává vlastnost pojmenovanou aString a vlastnost pojmenovanou aNumber do instance: var myProtean:Protean = new Protean(); myProtean.aString = "testing"; myProtean.aNumber = 3; trace(myProtean.aString, myProtean.aNumber); // testing 3 Vlastnosti přidané do instance dynamické třídy jsou entity spuštění, takže jakákoliv kontrola typu je prováděna v době spuštění. Nemůžete přidat anotaci typu k vlastnosti, kterou přidáváte tímto způsobem. Můžete také přidat metodu instanci myProtean definování funkce a připojením funkce k vlastnosti instance myProtean. Následující kód přesouvá příkaz trace do metody pojmenované traceProtean(): var myProtean:Protean = new Protean(); myProtean.aString = "testing"; myProtean.aNumber = 3; myProtean.traceProtean = function () { trace(this.aString, this.aNumber); }; myProtean.traceProtean(); // testing 3 Metody takto vytvořené nemají přístup k žádným soukromým vlastnostem nebo metodám třídy Protean. Kromě toho, i reference na veřejné vlastnosti nebo metody třídy Protean musí být kvalifikovaná buď klíčový slovem this nebo názvem třídy. Následující příklad ukazuje metodu traceProtean() pokoušející se o přístup k soukromé a veřejné proměnné třídy Protean. myProtean.traceProtean = function () { trace(myProtean.privateGreeting); // undefined trace(myProtean.publicGreeting); // hello }; myProtean.traceProtean(); Popisy typů dat Primitivní datové typy zahrnují Boolean, int, Null, Number, String, uint a void. Třídy jádra ActionScript rovněž definují následující komplexní datové typy: Object, Array, Date, Error, Function, RegExp, XML a XMLList. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 57 Jazyk ActionScript a jeho syntaxe Datový typ Boolean Datový typ Boolean je tvořen dvěma hodnotami: true (pravda) a false (nepravda). Pro booleovskou hodnotu nejsou platné žádné jiné hodnoty. Výchozí hodnota booleovské proměnné, která byla deklarovaná, avšak neinicializována, je false. Datový typ int Datový typ int je uložen interně jako 32bitová celočíselná hodnota a je tvořena souborem celých čísel od -2 147 483 648 (-231) do 2 147 483 647 (231 - 1) včetně. Předchozí verze jazyka ActionScript nabízely pouze datový typ Number, který byl používán pro celočíselné hodnoty a hodnoty s desetinnou čárkou. V jazyce ActionScript 3.0 nyní máte přístup k nízko úrovňovým typům pro 32bitové celočíselné hodnoty se znaménkem nebo bez něj. Pokud proměnné nebude používat desetinná čísla, použití datového typu int místo Number by mělo být rychlejší a účinnější. Pro celočíselné hodnoty mimo rozsah minimální a maximální hodnoty int použijte datový typ Number, který dokáže pracovat s hodnotami mezi kladnou a zápornou hodnotu 9 007 199 254 740 992 (53bitová celočíselná hodnota). Výchozí hodnota pro proměnné, které jsou typu int, je 0. Datový typ null Datový typ null obsahuje pouze jednu hodnotu, null. Toto je výchozí hodnota pro datový typ String a všechny třídy, které definují komplexní datové typy, včetně třídy Object. Žádný jiný primitivní datový typ, například Boolean, Number, int a uint, neobsahuje hodnotu null. Aplikace Flash Player a Adobe AIR převedou hodnotu null na vhodnou výchozí hodnotu v případě, že se pokusíte o přiřazení hodnoty null proměnným typu Boolean, Number, int nebo uint. Nemůžete použít tento datový typ jako anotaci typu. Datový typ Number V jazyce ActionScript 3.0 datový typ Number může zastupovat celočíselné hodnoty, celočíselné hodnoty bez znaménka a desetinná čísla. Pro maximalizaci výkonu byste měli používat datový typ Number pouze pro celočíselné hodnoty vyšší, než mohou uložit 32bitové typy int a uint nebo pro desetinná čísla. Chcete-li uložit desetinné číslo, uveďte v čísle desetinnou čárku. Pokud desetinnou čárku vynecháte, číslo bude uloženo jako celočíselná hodnota. Datový typ Number využívá 64bitový formát s dvojitou přesností, jak je specifikováno standardem IEEE pro binární aritmetiku s plovoucí desetinou čárkou (IEEE-754). Tento standard určuje, jak mají být desetinná čísla uložena pomocí 64 dostupných bitů. Jeden bit se používá k označení, zda je číslo kladné nebo záporné. Jedenáct bitů se používá pro exponent, který je uložen jako základ 2. Zbývajících 52 bitů se používá pro uložení mantisy (také significand), což je číslo umocněné exponentem. Použitím některých bitů k uložení exponentu může datový typ Number uložit desetinná čísla významně větší, než pokud by byly všechny bity použity pro mantisu. Pokud například datový typ Number používá všech 64 bitů k uložení mantisy, může uložit číslo až o hodnotě 265 - 1. Použitím 11 bitů k uložení exponentu může datový typ Number zvýšit svou mantisu na mocninu 21023. Maximální a minimální hodnoty, které může typ Number vyjadřovat, jsou uloženy ve statických vlastnostech třídy Number nazvaných Number.MAX_VALUE a Number.MIN_VALUE. Number.MAX_VALUE == 1.79769313486231e+308 Number.MIN_VALUE == 4.940656458412467e-324 I když tento rozsah čísel je enormní, cenou za tento rozsah je přesnost. Datový typ Number používá 52 bitů k uložení mantisy s tím výsledkem, že čísla vyžadující k přesnému vyjádření více než 52 bitů, například zlomek 1/3, jsou pouze přibližné aproximace. Pokud aplikace vyžaduje absolutní přesnost s desetinnými čísly, musíte použít software implementující aritmetiku s desetinnými čísly v desítkové soustavě, jako protiklad aritmetiky desetinných čísel v soustavě binární. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 58 Jazyk ActionScript a jeho syntaxe Když uložíte celočíselné hodnoty jako datový typ Number, použije se pouze 52 bitů mantisy. Datový typ Number použije těchto 52 bitů a speciální skrytý bit k vyjádření celočíselné hodnoty od 9 007 199 254 740 992 (-253) do 9 007 199 254 740 992 (253). Aplikace Flash Player a Adobe AIR používají NaN hodnotu nejenom jako výchozí hodnotu pro proměnné typu Number, ale také jako výsledek každé operace, která by měla vrátit číslo, ale nečiní tak. Pokud se například pokusíte vypočítat druhou odmocninu záporného čísla, výsledek bude NaN. Jiné speciální hodnoty Number zahrnují kladné nekonečno a záporné nekonečno. Poznámka: Výsledkem dělení 0 je pouze NaN v případě, že dělitel je také 0. Dělení 0 dává ve výsledku infinity, pokud je dělenec kladný, nebo -infinity, pokud je dělenec záporný. Datový typ String Datový typ String představuje posloupnost 16bitových znaků. Data String jsou uložena interně jako znaky Unicode, pomocí formátu UTF-16. Data String jsou nezměnitelné hodnoty, stejně jako v programovacím jazyce Java. Operace s hodnotou String vrací novou instanci řetězce. Výchozí hodnota proměnné deklarované datovým typem String je null. Hodnota null není stejná, jako prázdný řetězec (""), i když obě vyjadřují nepřítomnost jakéhokoliv znaku. Datový typ uint Datový typ uint je uložen vnitřně jako 32bitová celočíselná hodnota bez znaménka a je tvořena souborem celočíselných hodnot od 0 do 4 294 967 295 (232 - 1) včetně. Datový typ uint použijte pro zvláštní okolnosti, které volají po nezáporných celočíselných hodnotách. Datový typ uint musíte například použít k vyjádření hodnot obrazového bodu, protože datový typ unit má vnitřní bit pro znaménko a nehodí se pro manipulaci s hodnotami barev. Pro celočíselné hodnoty větší než maximální hodnota uint použijte datový typ Number, který dokáže pracovat až s 53bitovými celočíselnými hodnotami. Výchozí hodnota pro proměnné, které jsou typu uint je 0. Datový typ void Datový typ void obsahuje pouze jednu hodnotu, undefined. V předchozích verzích jazyka ActionScript byla hodnota undefined výchozí pro instance třídy Object. V jazyce ActionScript 3.0 je výchozí hodnota pro instance Object null. Pokud se pokusíte přiřadit hodnotu undefined k instanci třídy Object, aplikace Flash Player nebo Adobe AIR převede hodnotu na null. Hodnotu undefined můžete přiřadit pouze k proměnným, které nemají stanoven typ. Proměnné bez typu jsou ty, které nemají anotaci typu, nebo používají symbol hvězdičky (*) jako anotaci typu. Můžete použít void pouze jako anotaci vráceného typu. Datový typ Object Datový typ Object je definován třídou Object. Třída Objekt slouží jako základní třída pro všechny definice tříd v jazyce ActionScript. Datový typ Object ve verzi ActionScript 3.0 se odlišuje od předchozích verzí třemi způsoby. První, datový typ Object již není výchozím pro proměnné bez anotace typu. Druhý, datový typ Object již nezahrnuje hodnotu undefined, která byla výchozí hodnotou pro instance Object. Třetí, v jazyce ActionScript 3.0 je výchozí hodnota instance třídy Object null. V předchozích verzích jazyka ActionScript byla proměnná bez anotace typu automaticky definována jako datový typ Object. Tak tomu již v jazyce ActionScript 3.0 není, protože zde se využívá proměnná skutečně bez definovaného typu. Proměnné bez anotace typu jsou nyní považovány za proměnné bez typu. Pokud dáváte přednost čtenářům objasnit ve svém kódu, že vaším záměrem je ponechat proměnnou bez definice typu, můžete použít nový symbol hvězdičky (*) pro anotaci typu, což je shodné jako byste anotaci typu vynechali. Následující příklad ukazuje dva shodné příkazy, které deklarují proměnnou bez typu x: var x var x:* PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 59 Jazyk ActionScript a jeho syntaxe Pouze proměnné bez typu mohou uchovávat hodnoty undefined. Pokud se pokusíte přiřadit hodnotu undefined pro proměnnou mající datový typ, aplikace Flash Player nebo Adobe AIR převedou hodnotu undefined na výchozí hodnotu daného datového typu. Pro instance datového typu Object je výchozí hodnota null, což znamená, že přehrávač Flash Player nebo Adobe AIR převede hodnotu undefined na null, pokud se pokusíte převést hodnotu undefined na instanci Object. Převody typu Převod typu nastává v případě, že hodnota je transformované do hodnoty odlišného datového typu. Převody typu mohou být buď implicitní nebo explicitní. Implicitní převod, také nazývaný vynucený, je někdy proveden aplikací Flash Player nebo Adobe AIR v době spuštění. Například, pokud je hodnota 2 přiřazena proměnné datového typu Boolean, aplikace Flash Player nebo Adobe AIR převedou hodnotu 2 na booleovskou hodnotu true dříve, než hodnotu přiřadí proměnné. Explicitní převod, nazývaný obsazování, nastává v případě, že kód vydává instanci kompilátoru, aby s proměnnou jednoho datového typu zacházel, jako by náležela jinému datovému typu. Když se procesu účastní primitivní hodnoty, obsazování ve skutečnosti převede hodnoty z jednoho datového typu na jiný. Chcete-li obsadit objekt jiným datovým typem, vložte jej do závorek a předsaďte název nového typu. Například následující kód přebírá booleovskou hodnotu a obsahuje ji celočíselnou hodnotou: var myBoolean:Boolean = true; var myINT:int = int(myBoolean); trace(myINT); // 1 Implicitní převody Implicitní převody nastávají v době spuštění v mnoha kontextech: • Během příkazu přiřazení • Když jsou hodnoty předány jako argumenty funkce • Když jsou hodnoty vráceny z funkcí • Ve výrazech využívajících jisté operátory, například přidání operátoru (+) Pro uživatelem definované typy uspějí implicitní převody tam, kde je převáděná hodnota instancí cílové třídy nebo třídy, které je odvozena od své cílové třídy. Pokud je implicitní převod neúspěšný, je signalizována chyba. Například následující kód obsahuje úspěšný i neúspěšný implicitní převod. class A {} class B extends A {} var objA:A = new A(); var objB:B = new B(); var arr:Array = new Array(); objA = objB; // Conversion succeeds. objB = arr; // Conversion fails. Pro primitivní typy jsou implicitní převody zpracovávány zavoláním stejného vnitřního převodního algoritmu, které jsou zavolány explicitními převodními funkcemi. Následující kapitola popisuje tyto převody primitivních typů podrobně. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 60 Jazyk ActionScript a jeho syntaxe Explicitní převody Je užitečné používat explicitní převody nebo obsazování, když kompilujete kód v přísném režimu, protože se mohou vyskytovat okamžiky, kdy nechcete, aby neshoda typu vygenerovala chybu v době kompilace. Tak tomu může být v případě, že vynucení převede vaše hodnoty správně v době spuštění. Například při práci s daty přijatým z formuláře se můžete spolehnout na vynucení a převést jisté řetězcové hodnoty na numerické hodnoty. Následující kód vygeneruje chybu v době kompilace, ale kód bude ve standardním režimu pracovat správně: var quantityField:String = "3"; var quantity:int = quantityField; // compile time error in strict mode Pokud chcete pokračovat v přísném režimu, ale chcete převést řetězec na celočíselnou hodnotu, můžete použít explicitní převod a to takto: var quantityField:String = "3"; var quantity:int = int(quantityField); // Explicit conversion succeeds. Obsazení do int, uint a Number Můžete obsadit kterýkoliv datový typ jedním ze tří typů čísel: int, uint a Number. Pokud aplikace Flash Player nebo Adobe AIR nedokáží číslo z nějakého důvodu převést, bude pro datové typy int a uint přiřazena výchozí hodnota 0 a pro datový typ Number pak hodnota NaN. Pokud převedete na číslo booleovskou hodnotu, z hodnoty true se stane hodnota 1 a z false bude 0. var myBoolean:Boolean = true; var myUINT:uint = uint(myBoolean); var myINT:int = int(myBoolean); var myNum:Number = Number(myBoolean); trace(myUINT, myINT, myNum); // 1 1 1 myBoolean = false; myUINT = uint(myBoolean); myINT = int(myBoolean); myNum = Number(myBoolean); trace(myUINT, myINT, myNum); // 0 0 0 Řetězcové hodnoty obsahující pouze číslice mohou být úspěšně převedeny do jednoho z číselných typů. Číselný typ může také převést řetězce, které vypadají jako záporná číselná hodnota nebo šestnáctková hodnota (například 0x1A). Proces převodu ignoruje prázdné znaky na začátku a na konci v hodnotě řetězce. Můžete také obsadit řetězce, které vypadají jako desetinná čísla a to pomocí Number(). Zahrnutí desetinné čárky způsobuje, že uint() a int() vrátí celočíselnou hodnotu a zkrátí se desetinná hodnota a znaky za ní následující. Například následující hodnoty řetězce mohou obsadit čísla. trace(uint("5")); // 5 trace(uint("-5")); // 4294967291. It wraps around from MAX_VALUE trace(uint(" 27 ")); // 27 trace(uint("3.7")); // 3 trace(int("3.7")); // 3 trace(int("0x1A")); // 26 trace(Number("3.7")); // 3.7 Hodnoty řetězce obsahující nečíselné znaky vrátí 0, když jsou obsazeny s int() nebo uint() a NaN, když jsou obsazeny Number(). Proces převodu ignoruje prázdné znaky na začátku a na konci, ale vrací 0 nebo NaN, pokud má řetězec prázdný znak oddělující dvě čísla. trace(uint("5a")); // 0 trace(uint("ten")); // 0 trace(uint("17 63")); // 0 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 61 Jazyk ActionScript a jeho syntaxe V jazyce ActionScript 3.0 funkce Number() již nepodporuje oktálová čísla, nebo čísla s osmičkovým základem. Pokud řetězec s nulou na začátku předáte v jazyce ActionScript 2.0 funkci Number(), číslo bude interpretováno jako oktálové číslo a převedeno na desítkovou hodnotu. V případě funkce Number() v jazyce ActionScript 3.0 tomu tak není, zde se první nula ignoruje. Například následující kód vygeneruje jiný výstup při kompilování v různých verzích jazyka ActionScript: trace(Number("044")); // ActionScript 3.0 44 // ActionScript 2.0 36 Obsazení není nutné, pokud hodnota jednoho číselného typu bude přiřazena proměnné s jiným číselným typem. I v přísném režimu jsou číselné typy implicitně převáděny na jiné číselné typy. To znamená, že v některých případech se mohou vyskytnout neočekávané hodnoty, pokud je překročen rozsah typu. Následující příklady jsou všechny kompilovány v přísném režimu, ačkoliv některé generují neočekávané hodnoty: var myUInt:uint = -3; // Assign int/Number value to uint variable trace(myUInt); // 4294967293 var myNum:Number = sampleUINT; // Assign int/uint value to Number variable trace(myNum) // 4294967293 var myInt:int = uint.MAX_VALUE + 1; // Assign Number value to uint variable trace(myInt); // 0 myInt = int.MAX_VALUE + 1; // Assign uint/Number value to int variable trace(myInt); // -2147483648 Následující tabulka uvádí souhrn výsledků obsazení do datového typu Number, int nebo uint z jiného datového typu. Datový typ nebo hodnota Výsledek převodu do Number, int nebo uint Booleovská hodnota Pokud je hodnota true, pak 1; jinak 0. Date Vnitřní vyjádření objektu Date, což je počet milisekund od půlnoci 1. ledna 1970 univerzálního času. null 0 Objekt Pokud je instance null a převedená na Number, pak NaN; jinak 0. String Číslo, pokud aplikace Flash Player nebo Adobe AIR mohou převést řetězec na číslo; jinak NaN pokud je převedeno na Number, nebo 0, pokud je převedeno na int nebo uint. undefined Pokud převedeno na Number, pak NaN; pokud převedeno na int nebo uint, tak 0. Obsazení do Booleovské hodnoty Obsazení do Booleovské hodnoty z kteréhokoliv číselného datového typu int, unit a Number) vede k hodnotě false, pokud je číselná hodnota 0, a v ostatních případech k hodnotě true. Pro datový typ Number hodnota NaN také vede k false. Následující příklad ukazuje výsledky obsazení čísel -1, 0 a 1: var myNum:Number; for (myNum = -1; myNum<2; myNum++) { trace("Boolean(" + myNum +") is " + Boolean(myNum)); } Výstup příklad ukazuje, že ze tří čísel pouze 0 vrací hodnotu false: Boolean(-1) is true Boolean(0) is false Boolean(1) is true PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 62 Jazyk ActionScript a jeho syntaxe Obsazení do Booleovské hodnoty z hodnoty String vrací false v případě, že řetězec je null nebo prázdný řetězec (""). V opačném případě vrací true. var str1:String; // Uninitialized string is null. trace(Boolean(str1)); // false var str2:String = ""; // empty string trace(Boolean(str2)); // false var str3:String = " "; // white space only trace(Boolean(str3)); // true Obsazení do Booleovské hodnoty z instance třídy Object vrací false, pokud je instance null; jinak vrací true: var myObj:Object; // Uninitialized object is null. trace(Boolean(myObj)); // false myObj = new Object(); // instantiate trace(Boolean(myObj)); // true Booleovská proměnná je v přísném režimu zpracovávána zvláštním způsobem v tom, že booleovské proměnné můžete přiřadit hodnoty kteréhokoliv datového typu bez obsazování. Implicitní vynucení ze všech datových typů do booleovského datového typu nastává i v přísném režimu. Jinými slovy na rozdíl od téměř všech ostatních datových typů obsazení do booleovské hodnoty není nutné k tomu, abyste se vyhnuli chybám přísného režimu. Následující příklad jsou všechny kompilovány v přísném režimu a chovají se v době spuštění podle očekávání. var myObj:Object = new Object(); // instantiate var bool:Boolean = myObj; trace(bool); // true bool = "random string"; trace(bool); // true bool = new Array(); trace(bool); // true bool = NaN; trace(bool); // false Následující tabulka uvádí souhrn výsledků obsazení do datového typu Boolean z jiných datových typů. Datový typ nebo hodnota Výsledky převodu do booleovské hodnoty String false, pokud je hodnota null nebo prázdný řetězec (""); jinak true. null false Number, int nebo uint false, pokud je hodnota NaN nebo 0; jinak true. Objekt false, pokud je instance null; jinak true. Obsazení do String Obsazení do datového typu String z kteréhokoliv číselného datového typu vrací řetězcové vyjádření čísla. Obsazení do datového typu String z booleovské hodnoty vrací řetězec"true", pokud je hodnota true, a řetězec "false", pokud je hodnota false. Obsazení do datového typu String z instance třídy Object vrací řetězec "null", pokud je instance null. Jinak obsazení do datového typu String z třídy Object vrací řetězec "[object Object]". Obsazení do datového typu String z instance třídy Array vrací řetězec tvořený seznamem všech prvků pole, oddělených čárkou. Například následující datový typ String vrací jeden řetěze obsahující všechny tři prvky pole: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 63 Jazyk ActionScript a jeho syntaxe var myArray:Array = ["primary", "secondary", "tertiary"]; trace(String(myArray)); // primary,secondary,tertiary Obsazení do datového typu String z instance třídy date vrací řetězec vyjadřující datum, které instance obsahuje. Například následující příklad vrací vyjádření instance třídy date (výstup ukazuje výsledek pro pacifický letní čas): var myDate:Date = new Date(2005,6,1); trace(String(myDate)); // Fri Jul 1 00:00:00 GMT-0700 2005 Následující tabulka uvádí souhrn výsledků obsazení do datového typu String z jiných datových typů. Datový typ nebo hodnota Výsledky převodu do řetězce Array Řetězec obsahující všechny prvky pole. Boolean "true" nebo "false" Date Řetězcové vyjádření objektu Date. null "null" Number, int nebo uint Řetězcové vyjádření čísla. Object Pokud je instance null, "null"; jinak "[object Object]". Syntaxe Syntaxe jazyka definuje soubor pravidel, které musí být dodrženy při zapisování spustitelného kódu. Rozlišování velkých a malých písmen Jazyk ActionScript 3.0 využívá rozlišování velkých a malých písmen. Identifikátory, které se liší pouze velkým/malým písmem, jsou považovány za odlišné identifikátory. Například následujíc kódy vytváří dvě různé proměnné var num1:int; var Num1:int; Tečková syntaxe Operátor tečka (.) poskytuje způsob přístupu k vlastnosti a metodě objektu. Pomocí tečkové syntaxe můžete odkazovat na vlastnost třídy nebo metodu pomocí názvu instance, za kterým následující operátor tečka a název vlastnosti nebo metody. Například zvažte následující definici třídy: class DotExample { public var prop1:String; public function method1():void {} } Pomocí tečkové syntaxe můžete přistupovat k vlastnosti prop1 a metodě method1() pomocí instance vytvořené následujícím kódem: var myDotEx:DotExample = new DotExample(); myDotEx.prop1 = "hello"; myDotEx.method1(); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 64 Jazyk ActionScript a jeho syntaxe Tečkovou syntaxi můžete použít při definování balíčků. Operátor tečka můžete použít k odkazování na vnořené balíčky. Například třída EventDispatcher spočívá uvnitř balíčku pojmenovaném events, který je vnořen do balíčku pojmenovaného flash. Pomocí výrazu následujícího můžete odkazovat na balíček events: flash.events Pomocí následujícího výrazu můžete také odkazovat na třídu EventDispatcher: flash.events.EventDispatcher Lomítková syntaxe Lomítková syntaxe není v jazyce ActionScript 3.0 podporována. Lomítková syntaxe byla používána v dřívějších verzích jazyka ActionScript pro označení cesty filmového klipu nebo proměnné. Literály Literál je hodnota zobrazující se přímo ve vašem kódu. Následující příklady jsou všechno literály: 17 "hello" -3 9.4 null undefined true false Literály mohou být také seskupeny do složených literálů. Literálová pole jsou uložena mezi závorkami ([]) a k oddělení prvků pole používají čárku. Literálové pole lze použít pro inicializaci pole. Následující příklady zobrazují dvě pole, která jsou inicializována pomocí literálových polí. Můžete použít příkaz new a předat složený literál jako parametr do konstruktoru třídy Array,ale můžete také přiřadit literálové hodnoty přímo, když konkretizujete instance následujících klíčových tříd ActionScript: Object, Array, String, Number, int, uint, XML, XMLList a Boolean. // Use new statement. var myStrings:Array = new Array(["alpha", "beta", "gamma"]); var myNums:Array = new Array([1,2,3,5,8]); // Assign literal directly. var myStrings:Array = ["alpha", "beta", "gamma"]; var myNums:Array = [1,2,3,5,8]; Literály mohou být také použity pro inicializaci generického objektu. Generický objekt je instancí třídy Object. Literálové objekty jsou uvedeny ve složených závorkách ({}) a k oddělení vlastností objektu používají čárku. Každá vlastnost je deklarovaná znakem dvojtečky (:), která odděluje název vlastnosti od její hodnoty. Generický objekt můžete vytvořit pomocí příkazu new a předat literálový objekt jako parametr do konstruktoru třídy Object, nebo můžete přiřadit literálový objekt přímo instanci, kterou deklarujete. Následující příklad ukazuje dva alternativní způsoby vytváření nového generického objektu a inicializace objektu s třemi vlastnostmi (propA, propB a propC), každá z těchto hodnot je nastavena na 1, 2 a 3: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 65 Jazyk ActionScript a jeho syntaxe // Use new statement and add properties. var myObject:Object = new Object(); myObject.propA = 1; myObject.propB = 2; myObject.propC = 3; // Assign literal directly. var myObject:Object = {propA:1, propB:2, propC:3}; Další informace viz „Základy řetězců“ na stránce 138, „Základní informace o regulárních výrazech“ na stránce 202 a „Inicializace proměnných XML“ na stránce 230. Středníky Středník (;) můžete použít k ukončení příkazu. Alternativně, pokud středník vynecháte, kompilátor bude předpokládat, že každá řádka kódu představuje jeden příkaz. Protože mnoho programátorů je zvyklých na středník jako znak ukončení příkazu, může být snazší kód číst, pokud jej budete používat k ukončení příkazů konzistentně. Použití středníku k ukončení příkazu umožňuje vložení více než jednoho příkazu do jedné řádky, ale to však může kód znepřehlednit. Závorky Závorky (()) můžete v jazyce ActionScript 3.0 použít třemi způsoby. Za prvé, závorky můžete použít pro změnu pořadí operací ve výrazu. Operace seskupené uvnitř závorek jsou vždy vykonávány jako první. Například závorky jsou použité pro změnu pořadí operací v následujícím kódu: trace(2 + 3 * 4); // 14 trace((2 + 3) * 4); // 20 Za druhé, závorky můžete použít s čárkou (,) pro vyhodnocení řady výrazů a vrácení výsledků konečného výrazu, jak je vidět na následujícím příkladu: var a:int = 2; var b:int = 3; trace((a++, b++, a+b)); // 7 Za třetí, závorky můžete použít jako funkce nebo metody, jak je vidět na následujícím příkladu, které předají hodnotu String funkci trace(): trace("hello"); // hello Poznámky Kód jazyka ActionScript 3.0 podporuje dva typy komentářů: jednořádkový a víceřádkový. Tyto mechanismy komentářů jsou podobné jazykům C++ a Java. Kompilátor bude ignorovat text, který je označen jako komentář. Jednořádkové komentáře začínají dopředným lomítkem (//) a pokračují na konec řádky. Například následující kód obsahuje jednořádkový komentář: var someNumber:Number = 3; // a single line comment Víceřádkový komentář začíná dopředným lomítkem a hvězdičkou(/*) a končí hvězdičkou a dopředným lomítkem (*/). /* This is multiline comment that can span more than one line of code. */ PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 66 Jazyk ActionScript a jeho syntaxe Klíčová slova jsou vyhrazená slova Vyhrazená slova jsou slova, která nemůžete použít jako identifikátory v kódu, protože jsou vyhrazena pro použití jazykem ActionScript. Vyhrazená slova zahrnují lexikální klíčová slova, která jsou vyňata z jmenného prostoru programu kompilátorem. Kompilátor nahlásí chybu, pokud lexikální klíčová slova použijete jako identifikátor. Následující tabulka uvádí seznam lexikálních klíčových slov jazyka ActionScript 3.0. as break case catch class const continue default delete do else extends false finally for function if implements import in instanceof interface internal is native new null package private protected public return super switch this throw to true try typeof use var void while with Existuje malá sada klíčových slov, nazvaných syntaktická klíčová slova, které mohou být použity jako identifikátory, ale mají v jistém kontextu speciální význam. Následující tabulka uvádí seznam syntaktických klíčových slov jazyka ActionScript 3.0. each get set namespace include dynamic final native override static Existuje také několik identifikátorů, které jsou někdy odkazovány jako budoucí vyhrazená slova. Tyto identifikátory nejsou jazykem ActionScript 3.0 vyhrazeny, ale některé z nich mohou být použita jako klíčová slova softwarem, který jazyk ActionScript 3.0 obsahuje. Může být možné mnoho z těchto identifikátorů ve vašem kódu použít, ale společnost Adobe doporučuje je nepoužívat, protože se mohou jako klíčová slova objevit v následujících verzích jazyka. abstract boolean byte cast char debugger double enum export float goto intrinsic long prototype short synchronized throws to transient type virtual volatile PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 67 Jazyk ActionScript a jeho syntaxe Konstanty Jazyk ActionScript 3.0 podporuje příkaz const, který můžete použít k vytváření konstant. Konstanty jsou vlastnosti s pevnou hodnotu, kterou nelze změnit. Konstantě můžete přiřadit hodnotu pouze jednou a přiřazení musí být provedeno v blízkosti deklarace konstanty. Pokud je například konstanta deklarována jako člen třídy, můžete přiřadit hodnotu této konstantě pouze jako součást deklarace nebo uvnitř konstruktoru třídy. Následující kód deklarujete dvě konstanty. První konstanta MINIMUM, má hodnotu přiřazenou jako součást příkazu deklarace. Druhá konstanta, MAXIMUM, má hodnotu přiřazenou v konstruktoru. Povšimněte si, že tento příklad se kompiluje pouze ve standardním režimu, protože v přísném režimu umožňuje přiřazení hodnoty konstanty pouze v době inicializace. class A { public const MINIMUM:int = 0; public const MAXIMUM:int; public function A() { MAXIMUM = 10; } } var a:A = new A(); trace(a.MINIMUM); // 0 trace(a.MAXIMUM); // 10 Pokud se pokusíte přiřadit počáteční hodnotu konstantě jiným způsobem, dojde k chybě. Pokud se například pokusíte nastavit počáteční hodnotu MAXIMUM vně třídy, dojde k chybě v době spuštění. class A { public const MINIMUM:int = 0; public const MAXIMUM:int; } var a:A = new A(); a["MAXIMUM"] = 10; // run-time error Jazyk ActionScript 3.0 definuje široké rozpětí konstant, které můžete použít. Na základě konvence konstanty v jazyce ActionScript používají všechna velká písmena, se slovy oddělenými podtržítkem (_). Například definice třídy MouseEvent používá tuto konvenci pojmenování pro své konstanty, každá z nich vyjadřuje událost související se vstupem od myši: package flash.events { public class MouseEvent extends Event { public static const CLICK:String = "click"; public static const DOUBLE_CLICK:String = "doubleClick"; public static const MOUSE_DOWN:String = "mouseDown"; public static const MOUSE_MOVE:String = "mouseMove"; ... } } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 68 Jazyk ActionScript a jeho syntaxe Operátory Operátory jsou speciální funkce, které mohou mít jeden nebo více operandů a vrací hodnotu. Operand je hodnota, obvykle literál, proměnná nebo výraz, kterou operátor používá jako vstup. Například v následujícím kódu doplnění (+) a násobení (*) operátorů je použito s třemi literálovými operandy (2, 3, a 4) a vrací hodnotu. Hodnota je pak použita operátorem přiřazení (=) k přiřazení vrácené hodnoty, 14, proměnné sumNumber. var sumNumber:uint = 2 + 3 * 4; // uint = 14 Operátory mohou být ternární, binární nebo unární. Unární operátor má jediný operand. Například přírůstkový operátor (++) je unárním operátorem, protože má jenom jeden operand. Binární operátor má dva operandy. Například operátor dělení (/) má dva operandy. Ternární operátor má tři operandy. Například operátor podmínky (?:) má tři operandy. Některé operátory jsou přetížené, což znamená, že se chovají odlišně v závislosti na typu nebo počtu operandu,, které jsou jim předané. Operátor sčítání (+) je příkladem přetíženého operátoru, který se chová odlišně v závislosti na datovém typu operandu. Pokud jsou oba operandy čísly, operátor sčítání vrací součet hodnot. Pokud jsou oba operandy řetězce, operátor sčítání vrací zkrácení obou operandů. Následující příklad kódu ukazuje, jak se operátor chová odlišně v závislosti na operandech: trace(5 + 5); // 10 trace("5" + "5"); // 55 Operátory se mohou také chovat odlišně na základě počtu operandů jim předaných. Operátor odčítání (-) je unární i binární operátor. Pokud je předán pouze jediný operand, operátor odčítání neguje operand a vrací výsledek. Po předání dvou operandů operátor odčítání vrací rozdíl mezi operandy. Následující příklad ukazuje operátor odčítání, použitý nejprve jako unární, pak jako binární operátor. trace(-3); // -3 trace(7 - 2); // 5 Přednost a asociativita operátorů Přednost a asociativita operátorů stanoví pořadí, ve kterém jsou operátory zpracovány. I když může vypadat přirozené všem, kteří jsou seznámeni s aritmetikou, že kompilátor zpracovává násobení (*) před sčítáním (+), vyžaduje kompilátor specifické instrukce o tom, které operátory má zpracovat jako první. Takové pokyny jsou souhrnně popisovány jako přednost operátorů. V jazyce ActionScript definuje výchozí operátor přednost, kterou můžete změnit pomocí závorek (()). Například následující kód mění výchozí přednost z předchozího příklad tak, aby donutil kompilátor zpracovat operátor sčítání před operátorem násobení: var sumNumber:uint = (2 + 3) * 4; // uint == 20 Můžete se setkat se situacemi, ve kterých mají dva nebo více operátorů stejnou přednost a jsou uvedeny ve stejném výrazu. V těchto případech kompilátor používá pravidlo asociativity ke stanovení, který operátor má být zpracován jako první. Všechny binární operátor, kromě operátorů přiřazení, jsou asociativní zleva, což znamená, že operátory vlevo jsou zpracovány před operátory vpravo. Operátory přiřazení a podmínkové operátory (?:) jsou zprava asociativní, což znamená, že operátory vpravo jsou zpracovány před operátory vlevo. Například uvažujme operátory menší než (<) a větší než (>), které mají stejnou přednost. Pokud jsou oba operátory použity ve stejném výrazu, operátor na levé straně je zpracován jako první, protože oba operátory jsou asociativní zleva. To znamená, že následující dva příkazy poskytnou stejný výsledek: trace(3 > 2 < 1); // false trace((3 > 2) < 1); // false PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 69 Jazyk ActionScript a jeho syntaxe Operátor větší než je zpracován jako první, což vede k hodnotě true, protože operand 3 je větší než operand 2. Hodnota true je pak předána operátoru menší než společně s operandem 1. Následující kód představuje tento mezistav: trace((true) < 1); Operátor menší než převádí hodnotu true na numerickou hodnotu 1 a porovnává tuto numerickou hodnotu s druhým operandem 1 a vrací hodnotu false (hodnota 1 není menší než 1). trace(1 < 1); // false Pomocí operátoru závorka můžete změnit výchozí asociativitu zleva. Kompilátoru můžete vydat pokyn zpracovat operátor menší než nejprve jeho umístěním do závorek i s jeho operandy. Následující příklad používá operátor závorka k dosažení jiného výsledku pomocí stejných čísel, jako v předchozím příkladu: trace(3 > (2 < 1)); // true Operátor menší než je zpracován jako první, což vede k hodnotě false, protože operand 2 není menší než operand 1. Hodnota false je pak předána operátoru větší než společně s operandem 3. Následující kód představuje tento mezistav: trace(3 > (false)); Operátor větší než převede hodnotu false na numerickou hodnotu 0 a porovná tuto numerickou hodnotu s druhým operandem 3 a vrátí hodnotu true (hodnota 3 je větší než 0). trace(3 > 0); // true Následující tabulka uvádí operátory pro jazyk ActionScript 3.0 v pořadí snižující se přednosti. Každá řádka v tabulce obsahuje operátory stejné přednosti. Každý řádka operátorů má vyšší přednost, než řádka následující v tabulce za ní. Skupina operátory Primární operátory [] {x:y} () f(x) new x.y x[y] <></> @ :: .. Příponové operátory x++ x-- Unární operátory ++x --x + - ~ ! delete typeof void Multiplikativní operátory * / % Aditivní + - Bitové operátory posunutí << >> >>> Relační operátory < > <= >= as in instanceof is Rovnost == != === !== Bitový operátor AND & Bitový operátor XOR ^ Bitový operátor OR | Logické AND && Logické OR || Podmínečný ?: Přiřazení = *= /= %= += -= <<= >>= >>>= &= ^= |= Čárka , PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 70 Jazyk ActionScript a jeho syntaxe Primární operátory Primární operátory zahrnují ty, které jsou použity pro vytvoření literálů Array a Object, seskupení výrazů, volání funkcí, konkretizaci instancí třídy a pro přístup k vlastnostem. Všechny primární operátory uvedené v následující tabulce mají stejnou přednost. Operátory, které jsou součástí specifikace E4X, jsou označeny poznámkou (E4X). Operátor Provedená operace [] Inicializace pole {x:y} Inicializace objektu () Seskupení výrazů f(x) Volání funkce new Volání konstruktoru x.y x[y] Přístup k vlastnostem <></> Inicializace objektu XMLList (E4X) @ Přistupuje k atributu (E4X) :: Kvalifikuje název (E4X) .. Přistupuje k dceřinému prvku XML (E4X) Příponové operátory Příponové operátory vezmou jeden operand a provedou zvýšení nebo snížení jeho hodnoty. I když tyto operátory jsou unárními operátory, jsou klasifikovány samostatně od zbytku unárních operátorů, díky jejich vyšší přednosti a zvláštnímu chování. Když je použít příponový operátor jako součást větší výrazu, hodnota výrazu je vrácena před zpracováním příponového operátoru. Například následující kód zobrazuje, jak je vracena hodnota xNum++ před svým zvýšením: var xNum:Number = 0; trace(xNum++); // 0 trace(xNum); // 1 Všechny příponové operátory uvedené v následující tabulce mají stejnou přednost. Operátor Provedená operace ++ Zvýšení hodnoty (přípona) -- Snížení hodnoty (přípona) Unární operátory Unární operátory pracující s jedním operandem. Operátory zvýšení hodnoty (++) a snížení hodnoty (--) v této skupině jsou předponovéoperátory, což znamená, že se ve výrazu zobrazují před operandem. Předponové operátory se liší od svých protějšků, příponových operátorů, a to v tom, že operace zvýšení nebo snížení hodnoty je dokončena předtím, než je vrácena hodnota celkového výrazu. Například následující kód zobrazuje, jak je vracena hodnota ++xNum po svém zvýšení: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 71 Jazyk ActionScript a jeho syntaxe var xNum:Number = 0; trace(++xNum); // 1 trace(xNum); // 1 Všechny unární operátory uvedené v následující tabulce mají stejnou přednost. Operátor Provedená operace ++ Zvýšení hodnoty (předpona) -- Snížení hodnoty (předpona) + Unární operátor + - Unární operátor - (negace) ! Logický operátor NOT ~ Bitový operátor NOT delete Odstraňuje vlastnost typeof Vrací typ informace void Vrací nedefinovanou hodnotu multiplikativní operátory Multiplikativní operátory vezmou dva operandy a provedou s nimi násobení, dělení nebo výpočty s operandem modulu. Všechny multiplikativní operátory uvedené v následující tabulce mají stejnou přednost. Operátor Provedená operace * Násobení / Dělení % Modulo Aditivní operátory Aditivní operátory vezmou dva operandy a provedou sčítání nebo odčítání. Všechny aditivní operátory uvedené v následující tabulce mají stejnou přednost. Operátor Provedená operace + Sčítání - Odčítání Bitové operátory posunutí Bitové operátory posunutí vezmou dva operandy a provedou s nimi posunutí bitů prvního operandu v rozsahu specifikovaném druhým operandem. Všechny bitové operátory posunutí uvedené v následující tabulce mají stejnou přednost. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 72 Jazyk ActionScript a jeho syntaxe Operátor Provedená operace << Bitové posunutí vlevo >> Bitové posunutí vpravo >>> Bitové posunutí vpravo, bez znaménka Relační operátory Relační operátory vezmou dva operandy a provedou porovnání jejich hodnot a vrátí booleovskou hodnotu. Všechny relační operátory uvedené v následující tabulce mají stejnou přednost. Operátor Provedená operace < Menší než > Větší než <= Menší než nebo se rovná >= Větší než nebo rovno as Kontrola datového typu in Kontrola vlastností objektu instanceof Kontrola řetězu prototypu is Kontrola datového typu Operátory rovnosti Operátory rovnosti vezmou dva operandy a provedou porovnání jejich hodnot a vrátí booleovskou hodnotu. Všechny relační operátory uvedené v následující tabulce mají stejnou přednost. Operátor Provedená operace == Rovnost != Nerovnost === Přesná rovnost !== Přesná nerovnost Bitové logické operátory Bitové logické operátory vezmou dva operandy a provedou s nimi logické operace na úrovni bitů. Bitové logické operátory se odlišují svou předností a jsou uvedeny v následující tabulce v pořadí snižující se přednosti: Operátor Provedená operace & Bitový operátor AND ^ Bitový operátor XOR | Bitový operátor OR PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 73 Jazyk ActionScript a jeho syntaxe Logické operátory Logické operátory vezmou dva operandy a vrátí booleovskou hodnotu. Logické operátory se odlišují svou předností a jsou uvedeny v následující tabulce v pořadí snižující se přednosti: Operátor Provedená operace && Logické AND || Logické OR Podmínečný operátor Podmínečný operátor je ternární operátor, což znamená, že pracuje se třemi operandy. Podmínečný operátor je rychlou metodou aplikace podmíněného příkazu if..else. Operátor Provedená operace ?: Podmínečný Operátory přiřazení Operátory přiřazení vezmou dva operandy a přiřadí hodnotu jednomu z nich, na základě hodnoty druhého operandu. Všechny operátory přiřazení uvedené v následující tabulce mají stejnou přednost. Operátor Provedená operace = Přiřazení *= Přiřazení násobení /= Přiřazení dělení %= Přiřazení modulo += Přiřazení sčítání -= Přiřazení odčítání <<= Přiřazení bitového posunutí vlevo >>= Přiřazení bitového posunutí vpravo >>>= Přiřazení bitového posunutí vpravo, bez znaménka &= Přiřazení bitového operátoru AND ^= Přiřazení bitového operátoru XOR |= Přiřazení bitového operátoru OR Podmíněné příkazy Jazyk ActionScript 3.0 poskytuje tři základní podmíněné příkazy, které můžete používat pro ovládání chodu programu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 74 Jazyk ActionScript a jeho syntaxe if..else Podmíněný příkaz if..else umožňuje testovat podmínku a vykonávat blok kódu v případě, že podmínka existuje, nebo vykonávat alternativní blok kódu, pokud podmínka neexistuje. Například následující kód testuje, zda hodnota x přesahuje 20, a vygeneruje funkci trace() v případě, že ano, nebo vygeneruje jinou funkci trace(), pokud ne: if (x > 20) { trace("x is > 20"); } else { trace("x is <= 20"); } Pokud nechcete vykonat alternativní blok kódu, můžete použít příkaz if bez příkazu else. if..else if Pomocí podmíněného příkazu if..else if můžete testovat více než jednu podmínku. Například následující kód testuje nejenom, zda hodnota x přesahuje 20, ale také, zda hodnota x je záporná: if (x > 20) { trace("x is > 20"); } else if (x < 0) { trace("x is negative"); } Pokud je příkaz if nebo else následován pouze jedním příkazem, příkaz nevyžaduje vložení do závorek. Například následující kód nepoužívá závorky: if (x > 0) trace("x else if (x < trace("x else trace("x is positive"); 0) is negative"); is 0"); Společnost Adobe však doporučuje používat závorky vždy, protože pokud budou později příkazy přidány do podmíněného příkazu bez závorek, může se vyskytnout neočekávané chování. Například v následujícím kódu se hodnota positiveNums zvyšuje o 1 bez ohledu na to, zda je podmínka vyhodnocena true: var x:int; var positiveNums:int = 0; if (x > 0) trace("x is positive"); positiveNums++; trace(positiveNums); // 1 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 75 Jazyk ActionScript a jeho syntaxe switch Příkaz switch je užitečný v případě, že máte několik cest vykonání kódu, které závisí na stejném podmíněném výrazu. Poskytuje funkci podobnou dlouhé řadě příkazů if..else if, ale snáze se čte. Namísto testování podmínky s ohledem na booleovskou hodnotu, příkaz switch vyhodnocuje výraz a používá výsledek ke stanovení, který blok kódu je nutné vykonat. Bloky kódu začíná příkazem case a končí příkazem break. Například následující příkazy switch vytisknou den v týdnu na základě čísla dne, vráceného metodou Date.getDay(): var someDate:Date = new Date(); var dayNum:uint = someDate.getDay(); switch(dayNum) { case 0: trace("Sunday"); break; case 1: trace("Monday"); break; case 2: trace("Tuesday"); break; case 3: trace("Wednesday"); break; case 4: trace("Thursday"); break; case 5: trace("Friday"); break; case 6: trace("Saturday"); break; default: trace("Out of range"); break; } Opakování Opakování příkazu umožňuje provádět specifické bloky kódu opakovaně pomocí řady hodnot nebo proměnných. Společnost Adobe doporučuje vždy uzavřít blok kódu do závorek ({}). I když můžete závorky vynechat v případě, že kód obsahuje pouze jeden příkaz, tento postup se nedoporučuje ze stejného důvodu, jako se nedoporučuje pro podmíněné příkazy: zvyšuje pravděpodobnost, že posléze přidané příkazy budou neúmyslně vyloučeny z bloku kódu. Pokud později přidáte příkaz, který chcete zahrnout do bloku kódu, ale zapomenete přidat potřebné závorky, příkaz nebude vykonán jako součást opakování cyklu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 76 Jazyk ActionScript a jeho syntaxe for Opakování (cyklus) for umožňuje iterovat proměnnou ve specifickém rozsahu hodnot. Do příkazu for musíte zadat tři výrazy: proměnnou, která je nastavena na počáteční hodnotu, podmíněný příkaz, který stanoví, když cyklus končí, a výraz, který mění hodnotu proměnné po každém cyklu. Například následující příkaz se bude opakovat pětkrát. Hodnota proměnné i začíná na hodnotě 0 a končí na hodnotě 4 a výstup bude tvořen čísly 0 až 4, každý na vlastní řádce. var i:int; for (i = 0; i < 5; i++) { trace(i); } příkaz for..in Příkaz for..in iteruje vlastnosti objektu, nebo prvky pole. Například můžete použít cyklus for..in a iterovat vlastnosti generického objektu (vlastnosti objektu nejsou žádným specifickým způsobem řazeny, takže se mohou zobrazovat ve zdánlivě náhodném pořadí): var myObj:Object = {x:20, y:30}; for (var i:String in myObj) { trace(i + ": " + myObj[i]); } // output: // x: 20 // y: 30 Iterovat můžete také prvky pole: var myArray:Array = ["one", "two", "three"]; for (var i:String in myArray) { trace(myArray[i]); } // output: // one // two // three Co však nemůžete dělat, je iterování vlastností objektu v případě, že se jedná o instanci uživatelem definované třídy, pokud třída není dynamickou třídou. I s instancemi dynamických tříd budete moci iterovat pouze vlastnosti, které jsou přidávané dynamicky. for each..in Příkaz for each..in iteruje položky sbírky, což mohou být značky v objektu XML nebo XMLList, hodnoty uchovávané vlastnostmi objektu, nebo prvky pole. Například následující výňatek ukazuje, že můžete použít cyklus for each..in k iterování vlastností generického objektu, ale na rozdíl od cyklu for..in iterační proměnná v cyklu for each..in obsahuje hodnotu uchovávanou vlastností namísto názvu vlastnosti: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 77 Jazyk ActionScript a jeho syntaxe var myObj:Object = {x:20, y:30}; for each (var num in myObj) { trace(num); } // output: // 20 // 30 Můžete iterovat objekty XML nebo XMLList, jak ukazuje následující příkaz: var myXML:XML = <users> <fname>Jane</fname> <fname>Susan</fname> <fname>John</fname> </users>; for each (var item in myXML.fname) { trace(item); } /* output Jane Susan John */ Můžete také iterovat prvky pole, jak ukazuje následující příkaz: var myArray:Array = ["one", "two", "three"]; for each (var item in myArray) { trace(item); } // output: // one // two // three Nemůžete iterovat vlastnosti objektu, pokud je objekt instancí zapouzdřené třídy. Ani pro instance dynamických tříd nemůžete iterovat žádnou pevnou vlastnosti, která je vlastností definovanou jako součást definice třídy. while Příkaz cyklu while je podobný příkazu if, který se opakuje, dokud má podmínka hodnotu true. Například následující kód produkuje stejný výstup, jako příklad cyklu for: var i:int = 0; while (i < 5) { trace(i); i++; } Jednou z nevýhod používání cyklu while místo cyklu for je to, že nekonečné cykly se zapisují snáze s cykly while. Příklad kódu cyklu for se nezkompiluje v případě, že vynecháte výraz, který zajistí zvýšení hodnoty proměnné counter, ale příklad cyklu while se zkompiluje, pokud tento krok vynecháte. Bez výrazu, který zajistí zvýšení hodnoty i se cyklus stane nekonečným. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 78 Jazyk ActionScript a jeho syntaxe do..while Příkaz cyklu do..while je cyklem while, který zaručuje, že blok kódu je vykonán alespoň jednou, protože podmínka je kontrolována po vykonání bloku kódu. Následující kód zobrazuje jednoduchý příklad cyklu do..while, který generuje výstup i v případě, že podmínka není splněna: var i:int = 5; do { trace(i); i++; } while (i < 5); // output: 5 Funkce Funkce jsou bloky kódu, které provádějí specifické úlohy a mohou být v programu použity opakovaně. V jazyce ActionScript 3.0 existují dva typy funkcí: metody a uzavřené funkce. To, zda je funkce nazvaná metodou nebo uzavřenou funkcí, závisí na kontextu, ve kterém je funkce definována. Funkce se nazývá metoda, pokud ji definujete jako součást definice třídy nebo ji připojíte k instanci objektu. Funkce se nazývá uzavřenou funkcí, pokud je definována jiným způsobem. Funkce byly v jazyce ActionScript vždy extrémně důležité. V jazyce ActionScript 1.0 klíčové slovo class neexistovalo, takže „třídy“ byly definovány funkcemi konstruktoru. I když klíčové slovo class byl od té doby do jazyka přidáno, dobré porozumění funkcím je i nadále důležité, pokud chcete plně využít to, co jazyk nabízí. To může být výzvou programátorům, kteří očekávají, že se funkce ActionScript budou chovat podobně, jako funkce v jazycích jako C++ nebo Java. Ačkoliv základní definice funkce a její volání by nemělo pro zkušené programátory představovat žádnou výzvu, některé pokročilejší vlastnosti funkcí jazyka ActionScript vyžadují podrobnější vysvětlení. Základní koncepty funkcí Tato část popisuje základní definice funkce a techniky jejího volání. Volání funkcí Funkci voláte pomocí jejího identifikátoru, následovaného operátorem závorky (()). Operátor závorky použijete k uzavření parametrů funkce, které chcete funkci odeslat. Například v celé této knize se používá funkce trace(), která je funkcí horní úrovně v jazyce ActionScript 3.0. trace("Use trace to help debug your script"); Pokud voláte funkci bez parametrů, musíte použít prázdný pár závorek. Můžete například použít metodu Math.random(), která nepoužije žádný parametr, a vygenerovat náhodné číslo: var randomNum:Number = Math.random(); Definování vlastních funkcí Existují dva způsoby, jak definovat funkci v jazyce ActionScript 3.0: můžete použít příkaz funkce nebo výraz funkce. Vybraná technika závisí na tom, zda dáváte přednost statickému nebo dynamickému stylu programování. Definujte funkce s příkazy, pokud preferujete statický, nebo přísný režim programování. Definujte funkce s výrazy, pokud k tomu máte specifický důvod. Výrazy funkce jsou častěji používaný v dynamickém, nebo standardním režimu programování. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 79 Jazyk ActionScript a jeho syntaxe Příkazy funkce Příkazy funkce jsou upřednostňovanou technikou definování funkcí v přísném režimu. Příkazy funkce začínají klíčovým slovem function, za kterým následuje: • Název funkce • Parametry, ve formě seznamu odděleného čárkami v závorkách • Tělo funkce, tj. v jazyce ActionScript kód, který má být vykonán při zavolání funkce, uzavřené do složených závorek Například následující kód vytváří funkci, která definuje parametr a pak zavolá funkci pomocí řetězce "hello" jako hodnoty parametru: function traceParameter(aParam:String) { trace(aParam); } traceParameter("hello"); // hello Výrazy funkce Druhým způsobem, jak deklarovat funkci, je použití příkazu přiřazení s výrazem funkce, což se také někdy nazývá literál funkce nebo anonymní funkce. Existuje kompletnější metoda, která byla široce používána v předchozích verzích jazyka ActionScript. Příkaz přiřazení s výrazem funkce začíná klíčovým slovem var, po kterém následuje: • Název funkce • Operátor dvojtečka (:) • Třída function pro definování datového typu • Operátor přiřazení (=) • Klíčové slovo function • Parametry, ve formě seznamu odděleného čárkami v závorkách • Tělo funkce, tj. v jazyce ActionScript kód, který má být vykonán při zavolání funkce, uzavřené do složených závorek Například následujíc kód deklaruje funkci traceParameter pomocí výrazu funkce: var traceParameter:Function = function (aParam:String) { trace(aParam); }; traceParameter("hello"); // hello Povšimněte si, že nespecifikujete název funkce, jako v příkazu funkce. Dalším důležitým rozdílem mezi výrazy a příkazy funkce je to, že výraz funkce je spíše výrazem než příkazem. To znamená, že výraz funkce nemůže stát samostatně, jako může příkaz funkce. Výraz funkce může být použit pouze jako součást příkazu, obvykle jako příkazu přiřazení. Následující příklad ukazuje výraz funkce, přiřazený prvku pole: var traceArray:Array = new Array(); traceArray[0] = function (aParam:String) { trace(aParam); }; traceArray[0]("hello"); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 80 Jazyk ActionScript a jeho syntaxe Výběr mezi příkazy a výrazy Všeobecné pravidlo zní používat příkaz funkce, pokud specifické okolnosti nevyžadují použití výrazu. Příkazy funkce jsou méně kompletní a poskytují konzistentnější spolupráci mezi přísným a standardním režimem, než výrazy funkce. Příkazy funkce se snáze čtou, než výrazy funkce, které obsahují výrazy. Příkazy funkce činí kód stručnějším; jsou méně matoucí, než výrazy funkce, které vyžadují použití klíčových slov var i function. Příkazy funkce umožňují konzistentnější spolupráci mezi dvěma režimy kompilátoru, než tečková syntaxe v přísném a standardním režimu, pokud je nutné vyvolat metodu deklarovanou pomocí příkazu funkce. To není nutné pravdivé pro metody deklarované výrazem funkce. Například následující kód definuje třídu pojmenovanou Example dvěma metodami: methodExpression(), která je deklarovaná výrazem funkce, a methodStatement(), která je deklarovaná příkazem funkce. V přísném režimu nemůžete používat tečkovou syntaxi k vyvolání metody methodExpression(). class Example { var methodExpression = function() {} function methodStatement() {} } var myEx:Example = new Example(); myEx.methodExpression(); // error in strict mode; okay in standard mode myEx.methodStatement(); // okay in strict and standard modes Výrazy funkce jsou vhodnější k programování, které se zaměřuje n a chování programu během jeho spuštění (dynamické). Pokud dáváte přednost použití přísného režimu, ale rovněž potřebujte volat metodu deklarovanou výrazem funkce, použijte jednu z dvou technik. První, můžete zavolat metodu pomocí hranatých závorek ([]) namísto tečky (.) operátor. Následující volání metody je úspěšné v přísném i standardním režimu: myExample["methodLiteral"](); Druhá, můžete deklarovat celou třídu jako dynamickou třídu. I když toto umožňuje volat metodu pomocí operátoru tečka, nevýhodou je to, že obětujete část funkčnosti přísného režimu pro všechny instance dané třídy. Například kompilátor negeneruje chybu při pokusu o přístup k nedefinované vlastnosti instance dynamické třídy. Existují jisté okolnosti, za kterých jsou výrazy funkce užitečné. Běžné využití výrazu funkce je pro funkce, které jsou používány pouze jednou a pak jsou vyřazeny. Dalším, méně běžným použitím, je připojení funkce k vlastnosti prototypu. Více informací naleznete v části „Objekt prototypu“ na stránce 118. Existují dva drobné rozdíly mezi příkazem a výrazem funkce, které byste měli vzít v úvahu při volbě použité techniky. První rozdíl spočívá v tom, že výrazy funkce neexistují nezávisle jako objekty, s ohledem na správu paměti a čištění uvolněné paměti. Jinými slovy, když přiřadíte výraz funkce jinému objektu, například prvku pole nebo vlastnosti objektu, vytvoříte pouze referenci na tento výraz funkce ve svém kódu. Pokud se pole nebo objekt, ke které je váš výraz funkce připojen, dostane mimo rozsah, nebo je jinak nedostupný, nebudete již mít přístup k výrazu funkce. Pokud je pole nebo objekt odstraněn, paměť použitá výrazem funkce bude připravena k čištění uvolněné paměti, což znamená, že paměť bude moci být použita pro jiné účely. Následující příklad ukazuje, že pro výraz funkce nebude tato funkce již dále dostupná, jakmile je odstraněna vlastnost, ke které je výraz přiřazen. Třída Test je dynamická, což znamená, že můžete přidat vlastnosti pojmenovanou functionExp, která uchovává výraz funkce. Funkce functionExp() může být volána operátorem tečka, ale jakmile je vlastnost functionExp odstraněna, funkce již není přístupná. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 81 Jazyk ActionScript a jeho syntaxe dynamic class Test {} var myTest:Test = new Test(); // function expression myTest.functionExp = function () { trace("Function expression") }; myTest.functionExp(); // Function expression delete myTest.functionExp; myTest.functionExp(); // error Pokud na druhou stranu bude funkce nejprve definována příkazem funkce, existuje jako vlastní objekt a existuje i poté, co odstraníte vlastnost, ke které byla funkce připojena. Operátor delete je funkční pouze pro vlastnosti objektů, takže i volání pro odstranění funkce stateFunc() samotné nepracuje. dynamic class Test {} var myTest:Test = new Test(); // function statement function stateFunc() { trace("Function statement") } myTest.statement = stateFunc; myTest.statement(); // Function statement delete myTest.statement; delete stateFunc; // no effect stateFunc();// Function statement myTest.statement(); // error Druhým rozdílem mezi výrazem a příkazem funkce je to, že výraz funkce existuje v rámci rozsahu, ve kterém je definován, včetně příkazů in, které se objevují před příkazem funkce. Výrazy funkce jsou oproti tomu definovány pouze pro následující příkazy. Například následující kód úspěšně volá funkci scopeTest() před jejím definováním: statementTest(); // statementTest function statementTest():void { trace("statementTest"); } Výrazy funkce nejsou dostupné před definováním, takže následující kód vede k chybě při spuštění kódu: expressionTest(); // run-time error var expressionTest:Function = function () { trace("expressionTest"); } Vracení hodnot z funkcí Chcete-li, aby funkce vrátila hodnotu, použijte příkaz return následovaný výrazem nebo literálovou hodnotou, kterou chcete vrátit. Například následující kód vrací výraz, představující parametr: function doubleNum(baseNum:int):int { return (baseNum * 2); } Povšimněte si, že příkaz return končí funkcí, takže všechny příkazy pod příkazem return nebudou vykonány a to následujícím způsobem: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 82 Jazyk ActionScript a jeho syntaxe function doubleNum(baseNum:int):int { return (baseNum * 2); trace("after return"); // This trace statement will not be executed. } V přísném režimu musíte vrátit hodnotu vhodného typu, protože nevrací platnou hodnotu: Například následující kód generuje v přísném režimu chybu, protože nevrací platnou hodnotu: function doubleNum(baseNum:int):int { trace("after return"); } Vnořené funkce Funkce můžete vnořovat, což znamená, že funkce mohou být deklarovány uvnitř jiných funkcí. Vnořená funkce je dostupná pouze ve své nadřazené funkci, pokud není odkaz na tuto funkci předán externímu kódu. Například následující kód deklaruje dvě vnořené funkce uvnitř funkce getNameAndVersion(): function getNameAndVersion():String { function getVersion():String { return "10"; } function getProductName():String { return "Flash Player"; } return (getProductName() + " " + getVersion()); } trace(getNameAndVersion()); // Flash Player 10 Když jsou vnořené funkce předány externímu kódu, jsou předány jako uzavřené funkce, což znamená, že funkce si uchovává všechny definice, které jsou v rozsahu při definování funkce. Další informace, viz „Rozsah funkce“ na stránce 87. Parametry funkce Jazyk ActionScript 3.0 poskytuje některé funkčnosti pro parametry funkcí, které mohou novým programátorům tohoto jazyka připadat jako neobvyklé. I když princip předávání parametrů hodnotou nebo odkazem by měl být většině programátorů znám, objekt arguments a parametr ... (zbytek) mohou být pro mnoho z nich nové. Předávání argumentů hodnotou nebo odkazem V mnoha programovacích jazycích je důležité porozumět odlišnosti mezi předáváním argumentů hodnotou nebo odkazem; rozdíl může ovlivňovat způsob tvorby kódu. Předání hodnotou znamená, že hodnota argumentu je kopírována do místní proměnné pro použití v rámci funkce. Předání odkazem znamená, že je předán pouze odkaz na argument, místo skutečné hodnoty. Není zhotovena žádná kopie stávajícího argumentu. Místo toho se vytvoří odkaz na proměnnou předaný jako argument a je přiřazen místní proměnné pro použití v rámci funkce. Jako odkaz na proměnnou vně funkce umožňuje místní proměnné změnit hodnotu původní proměnné. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 83 Jazyk ActionScript a jeho syntaxe V jazyce ActionScript 3.0 jsou všechny argumenty předávány formou odkazu, protože všechny hodnoty jsou uloženy jako objekty. Nicméně objekty, které náleží primitivním datovým typům, což zahrnuje Boolean, Number, int, uint a String, mají speciální operátory, které jim umožňují chovat se, jako by byly předány hodnotou. Například následující kód vytvoří funkci pojmenovanou passPrimitives(), která definuje dva parametry pojmenované xParam a yParam, obojí typu int. Tyto parametry jsou podobné místním proměnným, deklarovaným uvnitř těla funkce passPrimitives(). Když je zavolána funkce s argumenty xValue a yValue, parametry xParam a yParam jsou inicializovány s odkazy na objekty int zastoupené xValue a yValue. Protože argumenty jsou primitivní, chovají se jako by předaly hodnotu. I když xParam a yParam v počátku obsahují pouze odkazy na hodnotu objektů xValue a yValue, všechny změny proměnných v těle funkce generují nové kopie hodnoty v paměti. function passPrimitives(xParam:int, yParam:int):void { xParam++; yParam++; trace(xParam, yParam); } var xValue:int = 10; var yValue:int = 15; trace(xValue, yValue);// 10 15 passPrimitives(xValue, yValue); // 11 16 trace(xValue, yValue);// 10 15 Ve funkci passPrimitives() jsou hodnoty xParam a yParam zvýšeny, to však neovlivňuje hodnoty xValue a yValue, jak je znázorněno v posledním výrazu trace . To by bylo pravdivé v případě, že parametry byly pojmenovány shodně s proměnnými, xValue a yValue, protože xValue a yValue uvnitř funkce by ukazovaly do nového umístění v paměti, které existuje odděleně od proměnných stejného názvu vně funkce. Všechny ostatní objekty, tj. objekty nenáležící primitivním datovým typům, jsou vždy předány odkazem, což umožňuje změnit hodnotu původní proměnné. Například následující kód vytváří objekt pojmenovaný objVar se dvěma vlastnostmi, x a y. Objekt je předán jako argument funkci passByRef(). Protože objekt není primitivním typem, nejenom, že je předán jako odkaz, ale také tímto odkazem zůstane. To znamená, že změny provedené v parametru ve funkci ovlivní vlastnosti objektu vně funkce. function passByRef(objParam:Object):void { objParam.x++; objParam.y++; trace(objParam.x, objParam.y); } var objVar:Object = {x:10, y:15}; trace(objVar.x, objVar.y); // 10 15 passByRef(objVar); // 11 16 trace(objVar.x, objVar.y); // 11 16 Parametr objParam odkazuje na stejný objekt, jako globální proměnná objVar. Jak je možné vidět na příkazech trace v příkladu, změny vlastností x a y objektu objParam se odrazí v objektu objVar. Výchozí hodnoty parametru Novinkou v jazyce ActionScript 3.0 je schopnost deklarovat výchozí hodnoty parametru pro danou funkci. Pokud volání funkce s výchozími hodnotami parametrů vynechá parametr s výchozími hodnotami, použije se hodnota uvedená v definice funkce pro daný parametr. Všechny parametry s výchozími hodnotami musí být umístěny na konci seznamu parametrů. Hodnoty přiřazené jako výchozí hodnoty musí být konstanty z času kompilace. Existence výchozí hodnoty pro parametr efektivně činí tento parametr volitelným parametrem. Parametr bez výchozí hodnoty je považován za vyžadovaný parametr. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 84 Jazyk ActionScript a jeho syntaxe Například následující kód vytváří funkci se třemi parametry, dva z nich mají výchozí hodnoty. Když je funkce volaná pouze jedním parametrem, použijí se pro parametry výchozí hodnoty. function defaultValues(x:int, y:int = 3, z:int = 5):void { trace(x, y, z); } defaultValues(1); // 1 3 5 Objekt arguments Když jsou funkci předány parametry, můžete použít objekt arguments pro přístup k informacím o parametrech předaných vaší funkci. Některé důležité aspekty objektu arguments zahrnují následující: • Objekt arguments je polem, které zahrnuje všechny parametry předané funkci. • Vlastnost arguments.length hlásí počet parametrů předaných funkci. • Vlastnost arguments.callee poskytuje odkaz na samotnou funkci, což je užitečné pro rekurzivní volání výrazů funkce. Poznámka: Objekt arguments není dostupný v případě, že některý parametr je pojmenován arguments, nebo pokud použijete parametr ... (zbytek). Jestliže je objekt argumentsodkazován v těle funkce, jazyk ActionScript 3.0 umožňuje, aby volání funkce zahrnovalo více parametrů, než je definováno v definici funkce, ale vygeneruje chybu kompilátoru v přísném režimu, pokud počet parametrů neodpovídá počtu vyžadovaných parametrů (a volitelně libovolných volitelných parametrů). Můžete použít aspekt pole objektu arguments a přistupovat k libovolnému parametru předanému funkci, bez ohledu na to, zda je funkce definovaná v definici funkce, nebo nikoliv. Následující příklad, který se kompiluje pouze ve standardním režimu, používá pole arguments společně s vlastností arguments.length ke sledování všech parametrů předaných funkci traceArgArray(): function traceArgArray(x:int):void { for (var i:uint = 0; i < arguments.length; i++) { trace(arguments[i]); } } traceArgArray(1, 2, 3); // // // // output: 1 2 3 Vlastnost arguments.callee je často používána v anonymních funkcí pro vytvoření rekurze. Můžete ji používat ke zvýšení flexibility svého kódu. Pokud se název rekurzivní funkce změní v průběhu cyklu vývoje, nemusíte se starat o změnu rekurzivního volání ve své funkci, pokud použijete arguments.callee místo názvu funkce. Vlastnost arguments.callee se používá v následujícím výrazu funkce pro umožnění rekurze: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 85 Jazyk ActionScript a jeho syntaxe var factorial:Function = function (x:uint) { if(x == 0) { return 1; } else { return (x * arguments.callee(x - 1)); } } trace(factorial(5)); // 120 Pokud použijete parametr ... (zbytek) ve své deklaraci funkce, objekt arguments vám nebude dostupný. Místo toho musíte přistupovat k parametrům pomocí názvů, které pro ně deklarujete. Měli byste být také opatrní a vyhnout se používání "arguments" jako názvu parametru, protože dojde k vytvoření stínových objektů arguments. Pokud je například funkce traceArgArray()přepsána tak, aby byl přidán parametr arguments, odkazy na arguments v těle funkce odkazují na parametr, spíše než na objekt arguments. Následující kód nevytváří žádný vstup: function traceArgArray(x:int, arguments:int):void { for (var i:uint = 0; i < arguments.length; i++) { trace(arguments[i]); } } traceArgArray(1, 2, 3); // no output Objekt arguments v předchozí verzi jazyka ActionScript také obsahoval vlastnost pojmenovanou caller, která je odkazem na funkci volanou stávající funkcí. Vlastnost caller není v jazyce ActionScript 3.0 zastoupena, ale pokud potřebujete odkaz na volající funkci, můžete ji změnit tak, aby předala dodatečný parametr, který je odkazem na sebe samotný. Parametr ... (zbytek) Jazyk ActionScript 3.0 zavádí novou deklaraci parametru nazvanou parametr ... (zbytek). Tento parametr umožňuje specifikovat parametr pole, který přijímá jakýkoliv počet argumentů oddělených čárkou. Parametr může mít jakýkoliv název, který není vyhrazeným slovem. Tato deklarace parametru musí být posledním specifikovaným parametrem. Použití tohoto parametru činí objekt arguments nedostupným. I když parametr ... (zbytek) poskytuje stejnou funkčnost, jako pole arguments a vlastnost arguments.length, neposkytuje funkčnost podobnou té, kterou nabízí arguments.callee. Měli byste zajistit, že nebudete muset použít arguments.callee před použitím parametru ... (zbytek). Následující příklad přepisuje funkci traceArgArray() pomocí parametru ... (zbytek) namísto objektu arguments: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 86 Jazyk ActionScript a jeho syntaxe function traceArgArray(... args):void { for (var i:uint = 0; i < args.length; i++) { trace(args[i]); } } traceArgArray(1, 2, 3); // // // // output: 1 2 3 Parametr ... (zbytek) může být také použit s ostatními parametry, pokud se jedná o poslední parametr v seznamu. Následující příklad modifikuje funkci traceArgArray() tak, aby její první parametr x byl typu int a druhý parametr používal parametr ... (zbytek). Výstup vynechává první hodnotu, protože první parametr již není součástí pole vytvořeného parametrem ... (zbytek). function traceArgArray(x: int, ... args) { for (var i:uint = 0; i < args.length; i++) { trace(args[i]); } } traceArgArray(1, 2, 3); // output: // 2 // 3 Funkce jako objekty Funkce v jazyce ActionScript 3.0 jsou objekty. Když vytvoříte funkci, vytváříte objekt, kterýž nemůže být předán jako parametr jiné funkci, ale má k sobě také připojené vlastnosti a metody. Funkce předané jako argumenty jiné funkci jsou předány formou odkazu a nikoliv hodnotou. Když předáte funkci jako argument, použijete pouze identifikátor a nikoliv operátor závorky, který používáte k zavolání metody. Například následující kód předává funkci pojmenovanou clickListener() jako argument metody addEventListener(): addEventListener(MouseEvent.CLICK, clickListener); Metoda Array.sort() rovněž definuje parametr, který funkci přijímá. Příklad funkce uživatelského třídění, která je použita jako argument pro funkci Array.sort(), viz také „Třídění pole“ na stránce 159. I když se to může zdát novým programátorům jazyka ActionScript podivné, funkce mohou mít vlastnosti a metody, stejně jako kterékoliv ostatní objekty. Ve skutečnosti každá funkce má vlastnost pouze ke čtení, pojmenovanou length, která ukládá několik parametrů definovaných pro funkci. To je odlišné od vlastnosti arguments.length, která hlásí počet argumentů odeslaných funkci. Vzpomeňte si, že v jazyce ActionScript počet argumentů odeslaných funkci může překročit počet parametrů definovaných pro tuto funkci. Následující příklad, který se kompiluje pouze ve standardním režimu, protože přísný režim vyžaduje přesnou shodu mezi počtem předaných argumentů a počtem argumentů definovaných, zobrazuje rozdíl mezi dvěma vlastnostmi: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 87 Jazyk ActionScript a jeho syntaxe // Compiles only in standard mode function traceLength(x:uint, y:uint):void { trace("arguments received: " + arguments.length); trace("arguments expected: " + traceLength.length); } traceLength(3, 5, 7, 11); /* output: arguments received: 4 arguments expected: 2 */ Ve standardním režimu můžete definovat své vlastní vlastnosti funkce jejich nadefinováním vně těla funkce. Vlastnosti funkce mohou sloužit jako kvazi-statické vlastnosti, umožňující uložit stav proměnné, související s funkcí. Například můžete chtít sledovat počet volání specifické funkce. Taková funkce může být užitečná v případě, že píšete hru a chcete sledovat počet použití specifického příkazu uživatelem, i když proto můžete také použít vlastnost třídy static. Následující příklad, který se kompiluje pouze ve standardním režimu, protože přísný režim neumožňuje přidávat k funkci dynamické vlastnosti, vytváří vlastnost funkce mimo deklarování funkce a zajišťuje zvýšení hodnoty vlastnosti při každém zavolání funkce: // Compiles only in standard mode var someFunction:Function = function ():void { someFunction.counter++; } someFunction.counter = 0; someFunction(); someFunction(); trace(someFunction.counter); // 2 Rozsah funkce Rozsah funkce stanoví nejenom to, kde může být program zavolán, ale také k jakým definicím může funkce přistupovat. Stejný rozsah pravidel, který platí pro identifikátory proměnné, platí také pro identifikátory funkce. Funkce deklarované v globálním rozsahu je přístupná prostřednictvím vašeho kódu. Například jazyk ActionScript 3.0 obsahuje globální funkce, například isNaN() a parseInt(), které jsou dostupné kdekoliv ve vašem kódu. Vnořená funkce - funkce deklarovaná v jiné funkci - může být použita kdekoliv ve funkci, ve které byla deklarovaná. Řetěz rozsahu Při každém spuštění vykonávání funkce je vytvořeno několik objektů a vlastností. Za prvé je vytvořen speciální objekt nazvaný aktivační objekt, který uloží parametr a všechny místní proměnné nebo funkce deklarované v těle funkce. Nemůžete přistupovat k objektu aktivace přímo, protože se jedná i interní mechanismu. Za druhé je vytvořen řetěz rozsahu, který obsahuje seznam objektů, které aplikace Flash Player nebo Adobe AIR kontroluje, zda obsahují deklarace identifikátoru. Každá funkce, která je spouštěna, má řetěz rozsahu, který je uložen ve vnitřní vlastnosti. Pro vnořené funkce řetěz rozsahu začíná vlastní aktivací objektu, následovanou aktivačním objektem nadřazené funkce. Řetěz pokračuje tímto způsobem, dokud nedosáhne globálního objektu. Spustí se globální objekt, který je vytvořen v programu v jazyce ActionScript, a obsahuje všechny globální proměnné a funkce. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 88 Jazyk ActionScript a jeho syntaxe Uzavřené funkce Uzavřená funkce je objektem, který obsahuje snímek funkce a jeho lexikální prostředí. Lexikální prostředí funkce zahrnuje všechny proměnné, vlastnosti, metody a objekty v řetězu rozsahu funkce, společně s jejich hodnotami. Uzavřené funkce jsou vytvořeny vždy při vykonání funkce, odloučeně od objektu nebo třídy. Skutečnost, že uzavřené funkce si uchovávají rozsah, ve kterém byly definovány, vytváří zajímavé výsledky, když je funkce předána jako argument nebo vrací hodnotu jinému rozsahu. Například následující kód vytváří dvě funkce: foo(), která vrací vnořenou funkci pojmenovanou rectArea(), která vypočítává plochu trojúhelníku a funkci bar(), která volá foo() a ukládá vrácenou uzavřenou funkci do proměnné nazvané myProduct. I když funkce bar() definuje vlastní místní proměnnou x (s hodnotou 2), když je zavolána uzavřená funkce myProduct(), uchovává proměnnou x (s hodnotou 40) definovanou ve funkci foo(). Funkce bar() proto vrací hodnotu 160 místo 8. function foo():Function { var x:int = 40; function rectArea(y:int):int // function closure defined { return x * y } return rectArea; } function bar():void { var x:int = 2; var y:int = 4; var myProduct:Function = foo(); trace(myProduct(4)); // function closure called } bar(); // 160 Metody se chovají podobně v tom, že si uchovávají informace o lexikálním prostředí, ve kterém byly vytvořeny. Tato charakteristika je nejznatelnější v případě, že metoda je extrahována ze své instance, což vytvoří vázanou metodu. Hlavní rozdíl mezi uzavřenou funkcí a vázanou metodou je v tom, že hodnota klíčového slova this ve vázané metodě vždy odkazuje na instanci, ke které byla původně připojena, zatímco v uzavřené funkci se hodnota klíčového slova this může měnit. Další informace naleznete v části „Metody“ na stránce 96. 89 Kapitola 5: Objektově orientované programování v jazyce ActionScript Tato kapitola popisuje prvky jazyka ActionScript, které podporují objektově orientované programování (OOP). Tato kapitola nepopisuje obecné principy OOP, jako je navrhování objektu, abstrakce, zapouzdření, dědičnost a polymorfizmus. Tato kapitola je zaměřena na způsob použití těchto principů pomocí jazyka ActionScript 3.0. Díky kmenům jazyka ActionScript jako skriptového jazyka, je podpora OOP ActionScript 3.0 volitelná. To nabízí programátorům flexibilitu ve výběru nejlepšího přístupu pro projekty různého rozsahu a složitosti. U malých úloh můžete zjistit, že používání jazyka ActionScript s paradigmatem procedurálního plánování je vše, co potřebujete. U větších projektů bude díky použití principů OOP snazší váš kód pochopit, udržovat a rozšiřovat. Základy objektově orientovaného programování Úvod k objektově orientovanému programování Objektově orientované programování (OOP) je způsob organizování kódu v programu jeho seskupením do objektů jednotlivé elementy, které zahrnují informace (hodnoty dat) a funkčnost. Používání přístupu orientovaného na objekt k organizování programu vám umožňuje seskupit určité informace (například hudební informace jako je název alba, název stopy, nebo jméno interpreta) společně s funkcí nebo akcemi spojenými s danou informací (např. „přidat stopu k seznamu přehrávání” nebo „přehrát všechny písně od tohoto interpreta”). Tyto položky jsou zkombinovány do jedné jediné položky, a to objektu (například „Album” nebo „MusicTrack”). Možnost seskupit tyto hodnoty a funkce dohromady nabízí několik výhod, včetně potřeby sledovat pouze jedinou proměnnou, nikoliv několik proměnných, společné organizace souvisejících funkcí a schopnosti strukturovat programy tak, aby lépe odpovídaly reálnému světu. Běžné úlohy objektově orientovaného programování V praxi má objektově orientované programování dvě části. Jednou částí jsou strategie a techniky pro navrhování programu (často se nazývají navrhování orientované na objekt). Toto je široké téma a v této kapitole není zmíněno. Další částí OOP jsou vlastní struktury programování, které jsou dostupné v daném programovacím jazyce pro vytvoření programu pomocí přístupu orientovaného na objekt. Tato kapitola se věnuje následujícím běžným úlohám v OOP: • Definování tříd • Vytváření vlastností, metod a přístupových mechanismů získání a nastavení (metody přístupových mechanismů) • Ovládání přístupu ke třídám, vlastnostem, metodám a přístupovým mechanismům • Vytváření statických vlastností a metod • Vytváření struktur vyčíslení • Definování a používání rozhraní • Práce s dědičností, včetně potlačení prvků tříd PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 90 Objektově orientované programování v jazyce ActionScript Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Atribut: Charakteristika přiřazená k prvku třídy (například vlastnost nebo metoda) v definici třídy. Atributy jsou běžně používány pro definování, zda daná vlastnost nebo metoda bude dostupná pomocí kódu v jiných částech programu. Například private a public jsou atributy. Soukromá metoda může být vyvolána pouze kódem v rámci třídy, zatímco veřejná metoda může být vyvolána jakýmkoliv kódem v programu. • Třída: Definice struktury a chování objektů určitého typu (například šablony nebo modrotisku pro objekty daného typu dat). • Hierarchie třídy: Struktura několika souvisejících tříd určující, které třídy dělí funkčnost z jiných tříd. • Konstruktor: Zvláštní metoda, kterou můžete definovat ve třídě, a která je vyvolána při vytvoření instance dané třídy. Konstruktor je běžně používán pro určení výchozích hodnot nebo pro jiné provedení operací nastavení pro daný objekt. • Typ dat: Typ informace, kterou může určitá proměnná uchovat. Obecně znamená datový typto samé jako třída. • Operátor tečky: Znak periody (.), který je v jazyce ActionScript (a mnoha dalších programovacích jazycích) používán k označení, že název odkazuje na podřízený prvek objektu (například vlastnost nebo metodu). Například ve výrazu myObject.myProperty označuje operátor tečky, že pojem myProperty odkazuje na stejnou hodnotu, která je prvkem objektu nazvaného myObject. • Výčet: Množina souvisejících konstantních hodnot, pro usnadnění seskupená jako vlastnosti jediné třídy. • Dědičnost: Mechanismus OOP, který umožňuje, aby jedna definice třídy zahrnovala všechny funkce definicí různých tříd (a obecně funkce rozšiřuje). • Instance: Skutečný objekt vytvořený v programu. • Jmenný prostor: V podstatě vlastní atribut umožňující lepší kontrolu nad tím, který kód má přístup k jinému kódu. Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. Protože kódy uvedené v této kapitole se primárně zabývají definováním a manipulací s datovými typy, bude vyzkoušení těchto příkladů zahrnovat vytvoření instance definované třídy, manipulaci s danou instancí pomocí jejích vlastností nebo metod a poté zobrazení hodnot vlastností dané instance. Pro zobrazení těchto hodnot budete chtít zapsat hodnoty do instance textového pole na ploše, nebo použít funkci trace() pro vytištění hodnoty na panel Výstup. Tyto techniky jsou podrobně popsány v části „Testování příkladů kódu v této kapitole“ na stránce 34. Třídy Třída je abstraktní reprezentací objektu. Třída uchovává informace o typech dat, které objekt může mít a o chování, které může objekt vykazovat. Užitečnost této abstrakce nemusí být zřejmá při psaní malých skriptů, které obsahují pouze několik navzájem reagujících objektů. Se zvětšujícím se rozsahem programu se nicméně počet objektů, které je nutné spravovat, zvětšuje a můžete zjistit, že vám třídy umožňují lepší kontrolu způsobu vytváření objektů a způsobu jejich vzájemné interakce. Již od jazyka ActionScript 1.0 mohli programátoři využívající jazyk ActionScript použít objekty funkce pro vytvoření konstruktů, které se podobaly třídám. Jazyk ActionScript 2.0 přidal formální podporu tříd pomocí klíčových slov, například class a extends. Jazyk ActionScript 3.0 nejen i nadále podporuje klíčová slova zavedená v jazyce ActionScript 2.0, ale přidává také některé nové možnosti, například vylepšené ovládání přístupu s atributy protected a internal a lepší ovládání dědičnosti pomocí klíčových slov final a override. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 91 Objektově orientované programování v jazyce ActionScript Jestliže jste někdy vytvářeli třídy v programovacích jazycích jako Java, C++, nebo C#, zjistíte, že jazyk ActionScript nabízí podobnou zkušenost. Jazyk ActionScript sdílí mnoho stejných klíčových slov a názvů atributů, například class, extends a public a všechny tyto výrazy jsou uvedeny v následujících oddílech. Poznámka: V této kapitole znamená pojem vlastnost jakýkoliv člen objektu nebo třídy, včetně proměnných, konstant a metod. Dále ačkoliv jsou pojmy třída a statický často navzájem zaměňovány, v této kapitole se tyto pojmy liší. Například v této kapitole se fráze vlastnosti třídy vztahuje na všechny členy třídy, nikoliv pouze na statické členy. Definice třídy Definice třídy jazyka ActionScript 3.0 používají syntaxi, která je podobná syntaxi používané v definici tříd jazyka ActionScript 2.0. Správná syntaxe pro definici třídy vyvolá klíčové slovo class následované názvem třídy. Tělo třídy, které je obklopeno složenými závorkami ({}), následuje za názvem třídy. Například následující kód vytvoří třídu pojmenovanou Shape, která obsahuje jednu proměnnou pojmenovanou visible: public class Shape { var visible:Boolean = true; } Jedna důležitá změna syntaxe zahrnuje definice třídy, které jsou uvnitř balíku. Jestliže je v jazyce ActionScript 2.0 třída uvnitř balíku, musí být název balíku obsažen v deklaraci třídy. V jazyce ActionScript 3.0, který zahrnuje příkaz package, musí být název balíku zahrnut do deklarace balíku namísto zahrnutí v deklaraci třídy. Například následující deklarace třídy ukazuje, jak je třída BitmapData, která je součástí balíku flash.display, definována v jazycích ActionScript 2.0 a ActionScript 3.0: // ActionScript 2.0 class flash.display.BitmapData {} // ActionScript 3.0 package flash.display { public class BitmapData {} } Atributy třídy Jazyk ActionScript 3.0 vám umožňuje úpravu definicí třídy pomocí jednoho z následujících čtyř atributů: Atribut Definice dynamic Umožňuje přidávání vlastností k instancím v čase zpracování. final Nesmí být rozšířeno jinou třídou. internal (výchozí) Viditelné pro reference uvnitř aktuálního balíku. public Viditelné pro odkazy kdekoliv. Pro každý z těchto atributů, s výjimkou atributu internal, jej musíte pro získání přiřazeného chování výslovně zahrnout. Pokud například při definování třídy nezahrnete atribut dynamic, nebudete moct přidat vlastnosti do instance třídy v čase zpracování. Atribut výslovně přiřadíte jeho umístěním na začátek definice třídy, dle příkladu v následujícím kódu: dynamic class Shape {} PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 92 Objektově orientované programování v jazyce ActionScript Všimněte si, že seznam nezahrnuje atribut nazvaný abstract. Důvodem je to, že abstraktní třídy nejsou v jazyce ActionScript 3.0 podporovány. Všimněte si také, že seznam nezahrnuje atributy pojmenované private a protected. Tyto atributy mají význam pouze uvnitř definice třídy a nelze je použít na samotné třídy. Jestliže nechcete, aby byla třída mimo balík veřejně viditelná, umístěte jí dovnitř balíku a označte třídu atributem internal. Můžete také vypustit atribut internal i public a kompilátor automaticky přidá atribut internal. Jestliže nechcete, aby byla třída viditelná mimo zdrojový soubor, ve kterém je definována, umístěte třídu na konec svého zdrojového souboru, pod uzavírající složenou závorkou definice balíku. Tělo třídy Tělo třídy, které je obklopeno složenými závorkami, je používáno pro definování proměnných, konstant a metod vaší třídy. Následující příklad ukazuje deklaraci pro třídu přístupnosti v přehrávači Adobe Flash Player API: public final class Accessibility { public static function get active():Boolean; public static function updateProperties():void; } Jmenný prostor můžete definovat také uvnitř těla třídy. Následující příklad ukazuje, jak lze definovat jmenný prostor v těle třídy, a jak je použít jako atribut metody v dané třídě: public class SampleClass { public namespace sampleNamespace; sampleNamespace function doSomething():void; } Jazyk ActionScript 3.0 vám umožňuje do těla třídy zahrnout nejen definice, ale také příkazy. Příkazy, které jsou uvnitř těla třídy, ale mimo definice metody, jsou provedeny právě jednou - při první detekci definice třídy a při vytvoření přidruženého objektu třídy. Následující příklad zahrnuje volání externí funkce hello()a příkaz trace, který vytvoří hlášení o potvrzení při definování třídy: function hello():String { trace("hola"); } class SampleClass { hello(); trace("class created"); } // output when class is created hola class created V porovnání s předchozími verzemi jazyka ActionScript je v jazyce ActionScript 3.0 povoleno definovat statickou vlastnost a vlastnost instance se stejným názvem v těle stejné třídy. Například následující kód deklaruje statickou proměnnou nazvanou message a proměnnou instance stejného názvu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 93 Objektově orientované programování v jazyce ActionScript class StaticTest { static var message:String = "static variable"; var message:String = "instance variable"; } // In your script var myST:StaticTest = new StaticTest(); trace(StaticTest.message); // output: static variable trace(myST.message); // output: instance variable Atributy vlastnosti třídy Mluvíme-li o modelu objektu jazyka ActionScript, pojem vlastnost znamená cokoliv, co může být členem třídy, včetně proměnných, konstant a metod. Toto se liší od způsobu použití tohoto pojmu v referenční příručce jazyka a komponent jazyka ActionScript 3.0, kde je tento pojem požíván úžeji a zahrnuje pouze členy třídy, které jsou proměnné nebo definované pomocí metody mechanismu získání nebo nastavení. V jazyce ActionScript 3.0 existuje množina atributů, které lze použít s jakoukoliv vlastností třídy. Následující tabulka uvádí tuto množinu atributů. Atribut Definice internal (výchozí) Viditelné pro odkazy uvnitř stejného balíku. private Viditelné pro odkazy ve stejné třídě. protected Viditelné pro odkazy ve stejné a v odvozených třídách. public Viditelné pro odkazy kdekoliv. static Narozdíl od instancí třídy určuje, že vlastnost patří do příslušné třídy. UserDefinedNamespace Název vlastního jmenného prostoru definovaného uživatelem. Atributy jmenného prostoru pro ovládání přístupu Jazyk ActionScript 3.0 nabízí čtyři speciální atributy, které ovládají přístup k vlastnostem definovaných uvnitř třídy: public, private, protected a internal. Atribut public zviditelní vlastnost kdekoliv ve vašem skriptu. Například pro to, aby byla metoda dostupná pro kód mimo svůj balík, musíte deklarovat metodu s atributem public. To platí pro jakoukoliv vlastnost, ať už je deklarována pomocí klíčových slov var, const nebo function. Atribut private zviditelní vlastnost pouze pro volání v rámci třídy definující danou vlastnost. Toto chování se odlišuje od chování atributu private v jazyce ActionScript 2.0, který umožňoval přístup podtřídy k soukromé vlastnosti v nadřazené třídě. Další důležitá změna v chování se týká přístupu v čase zpracování. V jazyce ActionScript 2.0 klíčové slovo private zakazovalo přístup pouze v čase sestavování a v čase zpracování jej šlo snadno obejít. V jazyce ActionScript 3.0 toto již neplatí. Vlastnosti označené jako private jsou nedostupné v čase kompilace i v čase zpracování. Například následující kód vytvoří jednoduchou třídu pojmenovanou PrivateExample s jednou soukromou proměnnou a poté se pokusí o přístup k soukromé proměnné z vnějšku třídy. V jazyce ActionScript 2.0 byl přístup v čase kompilace zakázán, ale zákaz šlo snadno obejít pomocí operátoru přístupu k vlastnosti ([]), který provede vyhledání vlastnosti v čase zpracování, nikoliv v čase kompilace. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 94 Objektově orientované programování v jazyce ActionScript class PrivateExample { private var privVar:String = "private variable"; } var myExample:PrivateExample = new PrivateExample(); trace(myExample.privVar);// compile-time error in strict mode trace(myExample["privVar"]); // ActionScript 2.0 allows access, but in ActionScript 3.0, this is a run-time error. V jazyce ActionScript 3.0 má pokus o přístup k soukromé vlastnosti pomocí operátoru tečky (myExample.privVar) v případě použití přísného režimu za následek chybu v čase kompilace. V jiném případě je chyba nahlášena v čase zpracování, stejně jako při použití operátoru pro přístup k vlastnosti (myExample["privVar"]). Následující tabulka uvádí přehled výsledku přístupu k soukromé vlastnosti, která náleží k uzavřené (nikoliv dynamické ) třídě: Přísný režim Standardní režim operátor tečky (.) chyba v čase kompilace chyba v čase zpracování operátor závorky ([]) chyba v čase zpracování chyba v čase zpracování Ve třídách deklarovaných pomocí atributu dynamic nebudou mít pokusy o přístup k soukromé proměnné za následek chybu v čase zpracování. Namísto toho je proměnná jednoduše neviditelná, takže přehrávač Flash Player nebo Adobe® AIR™ vrátí hodnotu undefined. K chybě v čase kompilace nicméně dojde, pokud používáte operátor tečky v přísném režimu. Následující příklad je stejný jako předcházející příklad, pouze s výjimkou, že třída PrivateExample je deklarována jako dynamická: dynamic class PrivateExample { private var privVar:String = "private variable"; } var myExample:PrivateExample = new PrivateExample(); trace(myExample.privVar);// compile-time error in strict mode trace(myExample["privVar"]); // output: undefined Dynamické třídy obecně vrací hodnotu undefined namísto vygenerování chyby v případě, kdy se kód externí ke třídě pokouší o přístup k soukromé vlastnosti. Následující tabulka ukazuje, že chyba je vygenerována pouze tehdy, je-li operátor tečky používán pro přístup k soukromé vlastnosti v přísném režimu. Přísný režim Standardní režim operátor tečky (.) chyba v čase kompilace undefined operátor závorky ([]) undefined undefined Atribut protected, který je v jazyce ActionScript 3.0 nový, zviditelní vlastnost pro volající v rámci vlastní třídy nebo podtřídy. Jinými slovy, chráněná vlastnost je dostupná v rámci vlastní třídy nebo pro třídy, které leží kdekoliv pod ní v hierarchii dědičnosti. To je pravdivé pro podtřídu ve stejném i v odlišném balíku. Pro ty z vás, kteří znají jazyk ActionScript 2.0, je tato funkce podobná atributu private v jazyce ActionScript 2.0. Atribut jazyka ActionScript 3.0 protected je podobný atributu protected v aplikaci Java, ale liší se v tom, že verze Java také povoluje přístup k volajícím v rámci stejného balíku. Atribut protected je užitečný, jestliže máte proměnnou nebo metodu, kterou vaše podtřídy potřebují skrýt z kódu mimo řetězec dědičnosti. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 95 Objektově orientované programování v jazyce ActionScript Atribut internal, který je v jazyce ActionScript 3.0 nový, zviditelní vlastnost pro volající v rámci svého vlastního balíku. Jedná se o výchozí atribut pro kód uvnitř balíku a použije se na jakoukoliv vlastnost, která nemá žádný z následujících atributů: • public • private • protected • uživatelem definovaný jmenný prostor Atribut internal je podobný výchozímu ovládání přístupu v aplikaci Java, ačkoliv v Javě není pro tuto úroveň přístupu žádný explicitní název a lze jej dosáhnou pouze prostřednictvím vynechání žádného jiného modifikátoru přístupu. Atribut internal je dostupný v jazyce ActionScript 3.0 a umožňuje vám výslovně zvýraznit váš záměr zviditelnění vlastnosti pouze pro volající v rámci vlastního balíku. Atribut static Atribut static, který lze použít s vlastnostmi deklarovanými pomocí klíčových slov var, const nebo function, vám umožňuje přiřadit vlastnost ke třídě, spíše než k instancím dané třídy. Kód mimo danou třídu musí vyvolat statické vlastnosti pomocí názvu třídy namísto názvu instance. Statické vlastnosti nejsou zděděny podtřídami, ale dané vlastnosti jsou součástí řetězce rozsahu podtřídy. To znamená, že v rámci těla podtřídy lze statickou proměnnou nebo metodu použít bez odkazu na třídu, ve které byla definována. Více informací naleznete v části „Statické vlastnosti nezděděné“ na stránce 112. Atributy jmenného prostoru definované uživatelem Jako alternativu k předdefinovaným atributům ovládání přístupu můžete vytvořit vlastní jmenný prostor, který bude použit jako atribut. Na každou definici může být použit pouze jeden atribut jmenného prostoru a takový atribut nemůže být použit v kombinaci s jakýmikoliv atributy ovládání přístupu (public, private, protected, internal). Více informací o používání jmenných prostorů naleznete v části „Jmenné prostory“ na stránce 42. Proměnné Proměnné mohou být deklarovány buď pomocí klíčového slova var nebo const. U proměnných deklarovaných pomocí klíčového slova var lze jejich hodnoty několikrát změnit, a to kdykoliv při provádění skriptu. Proměnné deklarované pomocí klíčového slova const jsou vyvolané konstanty a hodnoty k nim můžete přiřadit pouze jednou. Pokus o přiřazení nové hodnoty ke konkretizované konstantě vyvolá chybu. Další informace naleznete v části „Konstanty“ na stránce 67. Statické proměnné Statické proměnné jsou deklarovány pomocí kombinace klíčového slova static a buďto příkazem var nebo const. Statické proměnné, které jsou připojeny ke třídě spíše než k instanci třídy, jsou používány pro ukládání a sdílení informací používaných na celou třídu objektů. Statická proměnná je například vhodná, jestliže si přejete zachovat čítač toho, kolikrát je třída konkretizovaná, nebo jestliže si přejete uchovat maximální počet instancí tříd, které jsou povoleny. Následující příklad vytváří proměnnou totalCount, která bude sledovat počet konkretizací třídy a konstantu MAX_NUM pro uchování maximálního počtu konkretizací. Proměnné totalCount a MAX_NUM jsou statické, protože obsahují hodnoty, které se vztahují ke třídě jako celku, spíše než k určité instanci. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 96 Objektově orientované programování v jazyce ActionScript class StaticVars { public static var totalCount:int = 0; public static const MAX_NUM:uint = 16; } Kód, který je externí ke třídě StaticVars a jakékoliv z jejích podtříd, může odkazovat vlastnosti totalCount a MAX_NUM pouze prostřednictvím samotné třídy. Správný je například následující kód: trace(StaticVars.totalCount); // output: 0 trace(StaticVars.MAX_NUM); // output: 16 Ke statickým proměnným nemáte přístup prostřednictvím instance třídy, takže následující kód vrátí chyby: var myStaticVars:StaticVars = new StaticVars(); trace(myStaticVars.totalCount); // error trace(myStaticVars.MAX_NUM); // error Proměnné, které jsou deklarovány pomocí klíčového slova static i const, musí být iniciovány v čase deklarace konstanty, jako to třída StaticVars provádí pro MAX_NUM. K MAX_NUM uvnitř konstruktoru nebo metody instance nemůžete přiřadit hodnotu. Následující kód vygeneruje chybu, protože se nejedná o platný způsob inicializace statické konstanty: // !! Error to initialize static constant this way class StaticVars2 { public static const UNIQUESORT:uint; function initializeStatic():void { UNIQUESORT = 16; } } Proměnné instance: Proměnné instance zahrnují vlastnosti deklarované pomocí klíčových slov var a const, ale bez klíčového slova static. Proměnné instance připojené k instancím třídy spíše než k celé třídě jsou užitečné pro uchovávání hodnot, které jsou specifické pro instanci. Například třída Array má vlastnost instance pojmenovanou length uchovávající počet prvků pole, které vlastní určitá instance třídy Array. Proměnné instance, ať už deklarovány jako var nebo const, nemohou být potlačeny v podtřídě. Funkce podobné potlačení proměnných můžete nicméně dosáhnout potlačením metod mechanismů získání a nastavení. Další informace, viz „Získání a nastavení metod mechanismů přístupu“ na stránce 99. Metody Metody jsou funkce, které jsou součástí definice třídy. Po vytvoření instance třídy je k dané instanci připojena metoda. Narozdíl od funkce deklarované mimo třídu nelze metodu použít mimo instance, ke které byla připojena. Metody jsou definovány pomocí klíčového slova function. Stejně jako u libovolné vlastnosti třídy můžete použít jakýkoliv z atributů vlastnosti třídy na metody, včetně osobního, chráněného, veřejného, interního, statického nebo vlastního jmenného prostoru. Použít můžete například následující příkaz funkce: public function sampleFunction():String {} Nebo můžete použít proměnnou, ke které připojíte výraz funkce, a to následovně: public var sampleFunction:Function = function () {} PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 97 Objektově orientované programování v jazyce ActionScript Ve většině případů si z následujících důvodů budete přát použít příkaz funkce namísto výrazu funkce: • Příkazy funkce jsou stručnější a snadněji se čtou. • Příkazy funkce vám umožňují použít klíčová slova override a final. Další informace naleznete v části „Potlačování metod“ na stránce 110. • Příkazy funkce vytvářejí pevnější vazby mezi identifikátorem - tj. názvem funkce - a kódem uvnitř těla metody. Protože hodnota proměnné může být změněna pomocí příkazu přiřazení, může být spojení mezi proměnnou a výrazem její funkce kdykoliv přerušeno. Ačkoliv se této problematice můžete vyhnout deklarováním proměnné pomocí const namísto var, tuto techniku nepovažujeme za nejlepší postup, protože kód je poté těžké přečíst a zabraní se použití klíčových slov override a final. Jedním případem, kdy musíte použít výraz funkce je to, jestliže si přejete připojit funkci k objektu prototypu. Více informací naleznete v části „Objekt prototypu“ na stránce 118. Metody konstruktoru Metody konstruktoru, někdy jednoduše nazývané konstruktory, jsou funkce, které sdílejí stejný název jako třídy, ve kterých jsou definovány. Každý kód, který zahrnete do metody konstruktoru je proveden, kdykoliv je instance dané třídy vytvořena pomocí klíčového slova new. Následující kód například definuje jedinou třídu nazvanou Example, která obsahuje jedinou vlastnost pojmenovanou status. Počáteční hodnota proměnné status je množina uvnitř funkce konstruktoru. class Example { public var status:String; public function Example() { status = "initialized"; } } var myExample:Example = new Example(); trace(myExample.status); // output: initialized Metody konstruktoru mohou být pouze veřejné, ale použití atributu public je volitelné. Na konstruktoru nemůžete použít žádný z jiných specifikátorů přístupu, včetně private, protected nebointernal. S metodou konstruktoru také nemůžete použít uživatelem definovaný jmenný prostor. Konstruktor může provést explicitní volání ke konstruktoru své přímé nadřazené třídy pomocí příkazu super(). Jestliže konstruktor nadřazené třídy není explicitně vyvolán, kompilátor automaticky vloží volání před první příkaz do těla konstruktoru. Metody nadřazené třídy můžete také vyvolat pomocí předpony super jako odkazu na nadřazenou třídu. Jestliže se rozhodnete použít super() i super v těle stejného konstruktoru, volejte nejprve super(). V opačném případě se odkaz super nebude chovat dle očekávání. Konstruktor super() by měl být také vyvolán před příkazem throw nebo return. Následující příklad demonstruje, co se stane, jestli se pokusíte použít odkaz super před vyvoláním konstruktoru super(). Nová třída ExampleEx rozšiřuje třídu Example. Konstruktor ExampleEx se pokusí o přístup k proměnné stavu definované ve své nadřazené třídě, ale tento pokus provede před vyvoláním super(). Příkaz trace() uvnitř konstruktoru ExampleEx vytvoří hodnotu null, protože proměnná status není dostupná, dokud není konstruktor super() proveden. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 98 Objektově orientované programování v jazyce ActionScript class ExampleEx extends Example { public function ExampleEx() { trace(super.status); super(); } } var mySample:ExampleEx = new ExampleEx(); // output: null Ačkoliv je uvnitř konstruktoru povoleno použít příkaz return, není povoleno vrátit hodnotu. Jinými slovy, příkazy return nesmí mít přiřazené výrazy nebo hodnoty. Následně pak metodám konstruktoru není povoleno vracet hodnoty, což znamená, že nelze specifikovat žádný typ návratu. Jestliže nedefinujete metodu konstruktoru ve své třídě, kompilátor automaticky vytvoří prázdný konstruktor. Jestliže vaše třída rozšiřuje jinou třídu, kompilátor zahrne volání super() do konstruktoru, kterého vytvoří. Statické metody Statické metody, označované také metody třídy , jsou metody deklarované pomocí klíčového slova static. Statické metody, které jsou připojeny ke třídě spíše než k instanci třídy, jsou užitečné pro funkci zapouzdření, která ovlivňuje něco jiného než stav jednotlivé instance. Protože jsou statické metody přiřazeny ke třídě jako celek, jsou přístupné pouze prostřednictvím třídy, ale nikoliv prostřednictvím instance třídy. Statické metody jsou užitečné pro funkci zapouzdření, která neovlivňuje pouze stav instancí třídy. Jinými slovy, metoda by měla být statická, jestliže poskytuje funkčnost, která přímo neovlivňuje hodnotu instance třídy. Například třída Date má statickou metodu pojmenovanou parse(), která přebírá řetězec a převádí jej na číslo. Metoda je statická, protože neovlivňuje jednotlivé instance třídy. Místo toho metoda parse() převezme řetězec, který představuje hodnotu dat, analyzuje jej a vrátí několik formátů kompatibilních s interní reprezentací objektu Date. Tato metoda není metoda instance, protože použití dané metody pro instanci třídy Date nedává smysl. Porovnejte statickou metodu parse() s jednou z metod instance třídy Date, například s metodou getMonth(). Metoda getMonth() je metoda instance, protože operuje přímo na hodnotě instance, a to dosazením určité komponenty (měsíce) instance Date. Protože statické metody nejsou svázány s jednotlivými instancemi, nemůžete použít klíčová slova this nebo super v rámci těla statické metody. Reference this i reference super mají význam pouze v rámci daného kontextu metody instance. V kontrastu k některým jiným programovacím jazykům založeným na třídě nejsou statické metody v jazyce ActionScript 3.0 zděděné. Více informací naleznete v části „Statické vlastnosti nezděděné“ na stránce 112. Metody instance Metody instance jsou metody, které jsou prohlášeny bez klíčového slova static. Metody instance, které jsou připojeny k instancím třídy namísto třídy jako celku, jsou užitečné pro implementaci funkčnosti, která ovlivňuje jednotlivé instance třídy. Například třídy Array obsahuje metodu instance pojmenovanou sort(), která operuje přímo na instancích Array. V rámci těla metody instance jsou jak statické tak proměnné instance v rozsahu, což znamená, že proměnné definované ve stejné třídě mohou být odkazovány pomocí jednoho identifikátoru. Například následující třída CustomArray rozšiřuje třídu Array. Třída CustomArray definuje statickou proměnnou pojmenovanou arrayCountTotal pro sledování celkového počtu instancí tříd, instanci pojmenovanou arrayNumber, která sleduje pořadí, ve kterém jsou instance vytvářeny a metodu instance pojmenovanou getPosition(), která vrátí hodnoty těchto proměnných. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 99 Objektově orientované programování v jazyce ActionScript public class CustomArray extends Array { public static var arrayCountTotal:int = 0; public var arrayNumber:int; public function CustomArray() { arrayNumber = ++arrayCountTotal; } public function getArrayPosition():String { return ("Array " + arrayNumber + " of " + arrayCountTotal); } } Ačkoliv kód mimo třídu musí odkazovat na statickou proměnnou arrayCountTotal pomocí objektu třídy používajícího kód CustomArray.arrayCountTotal, kód, který je umístěn uvnitř těla metody getPosition()může přímo odkázat k proměnné arrayCountTotal. Toto je pravda dokonce pro statické proměnné v nadřazených třídách. Ačkoliv statické vlastnosti nejsou zděděny v jazyce ActionScript 3.0, statické vlastnosti v nadřazené třídě jsou v rozsahu. Například třída Array má několik málo statických proměnných. Jednou z nich je konstanta pojmenovaná DESCENDING. Kód v nadřazené třídě může na statickou konstantu DESCENDING odkazovat pomocí jednoduchého identifikátoru: public class CustomArray extends Array { public function testStatic():void { trace(DESCENDING); // output: 2 } } Hodnota reference this uvnitř těla metody instance je odkazem na instanci, ke které je metoda připojena. Následující kód ukazuje, že odkaz this ukazuje k instanci, která obsahuje danou metodu: class ThisTest { function thisValue():ThisTest { return this; } } var myTest:ThisTest = new ThisTest(); trace(myTest.thisValue() == myTest); // output: true Dědičnost metody instance lze ovládat pomocí klíčových slov override a final. Atribut override můžete použít pro novou definici zděděné metody a atribut final zabraňuje podtřídám v potlačení metody. Další informace naleznete v části „Potlačování metod“ na stránce 110. Získání a nastavení metod mechanismů přístupu Funkce získání a nastavení mechanismů přístupu se nazývají mechanismy získání a mechanismy nastavení. Umožňují vám zachovat programovací principy skrývání informací a zapouzdření a pro vámi vytvářené třídy poskytují snadno použitelné programovací rozhraní. Funkce získání a nastavení vám umožňují zachovat vlastnosti vaší třídy pouze pro danou třídu, ale umožňují uživatelům vaší třídy přístup k těmto vlastnostem, jako v případě přístupu k proměnné třídy namísto vyvolání metody třídy. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 100 Objektově orientované programování v jazyce ActionScript Výhodou tohoto přístupu je to, že vám umožňuje vyhnout se tradičním funkcím přístupových mechanismů s nepraktickými jmény, například getPropertyName() a setPropertyName(). Další výhodou mechanismů získání a nastavení je to, že pro každou vlastnost nemusíte mít dvě veřejné funkce, které umožňují čtení a zápis. Následující příklad třídy pojmenovaný GetSet zahrnuje funkce získání a nastavení mechanismů přístupu pojmenované publicAccess(), které poskytují přístup k soukromé proměnné pojmenované privateProperty: class GetSet { private var privateProperty:String; public function get publicAccess():String { return privateProperty; } public function set publicAccess(setValue:String):void { privateProperty = setValue; } } Jestliže se pokusíte o přímý přístup k vlastnosti privateProperty, dojde k chybě: var myGetSet:GetSet = new GetSet(); trace(myGetSet.privateProperty); // error occurs Namísto toho uživatel třídy GetSet použije něco, co se jeví jako vlastnost pojmenovaná publicAccess, ale jedná se o dvojici funkcí získání a nastavení mechanismu přístupu, které operují na soukromé vlastnosti pojmenované privateProperty. Následující příkaz konkretizuje třídu GetSet a poté nastaví hodnotu privateProperty pomocí veřejného mechanismu přístupu s názvem publicAccess: var myGetSet:GetSet = new GetSet(); trace(myGetSet.publicAccess); // output: null myGetSet.publicAccess = "hello"; trace(myGetSet.publicAccess); // output: hello Funkce mechanismů získání a nastavení také umožňují potlačení vlastností, které jsou zděděny z nadřazené třídy. To není možné při použití běžných proměnných členů tříd. Proměnné členů třídy, které jsou deklarovány pomocí klíčového slova var nelze v podtřídě potlačit. Vlastnosti vytvořené pomocí funkcí mechanismů získání a nastavení toto omezení nicméně nemají. Atribut override můžete použít na funkcích mechanismů získání a nastavení, které jsou zděděny z nadřazené třídy. Metody vazeb Metoda vazby, někdy nazvaná metoda ohraničení, je jednoduše metoda vyjmutá ze své instance. Příklady metod vazby zahrnují metody, které jsou předány jako argumenty funkci nebo navráceny jako hodnoty z funkce. Nově v jazyce ActionScript 3.0 je metoda vazby podobná metodě ohraničení v tom, že zachovává své lexikální prostředí i v případě, že je vyjmuta ze své instance. Klíčovým rozdílem mezi metodou vazby a funkcí ohraničení je nicméně to, že reference this pro metodu vazby zůstává propojena s instancí, která danou metodu implementuje. Jinými slovy reference this v metodě vazby vždy poukazuje na původní objekt, který danou metodu implementoval. Pro funkci ohraničení je reference this generická, což znamená, že poukazuje na jakýkoliv objekt, ke kterému je funkce v době svého vyvolání připojena. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 101 Objektově orientované programování v jazyce ActionScript Jestliže používáte klíčové slovo this, je důležité, abyste porozuměli metodám vazeb. Vzpomeňte si, že klíčové slovo this poskytuje odkaz na nadřazený objekt metody. Většina programátorů jazyka ActionScript očekává, že klíčové slovo this vždy odkazuje na objekt nebo třídu, která obsahuje definici metody. Bez provázání metod by toto nicméně neplatilo vždy. V předchozích verzích jazyka ActionScript například reference this neodkazovala vždy k instanci, která danou metodu implementovala. Při vyjmutí metod z instance v jazyce ActionScript 2.0 je reference this nejen nepropojena s původní instancí, ale ani proměnné členů a metody třídy instance nejsou dostupné. To v jazyce ActionScript 3.0 nepředstavuje problém, protože metody provázání jsou automaticky vytvořeny při odeslání metody jako parametru. Metody vazeb zajišťují, že klíčové slovo this vždy odkazuje na objekt nebo třídu, ve které je definována metoda. Následující kód definuje třídu pojmenovanou ThisTest, která obsahuje metodu s názvem foo() definující metodu vazby a metodu pojmenovanou bar(), která metodu vazby vrátí. Kód externí ke třídě vytvoří instanci třídy ThisTest, vyvolá metodu bar() a uchová vrácenou hodnotu v proměnné pojmenované myFunc. class ThisTest { private var num:Number = 3; function foo():void // bound method defined { trace("foo's this: " + this); trace("num: " + num); } function bar():Function { return foo; // bound method returned } } var myTest:ThisTest = new ThisTest(); var myFunc:Function = myTest.bar(); trace(this); // output: [object global] myFunc(); /* output: foo's this: [object ThisTest] output: num: 3 */ Poslední dva řádky kódu ukazují, že reference this v metodě vazby foo() stále ukazuje na instanci třídy ThisTest, ačkoliv reference this v předcházejícím řádku ukazuje na globální objekt. Navíc metoda vazby uchovaná v proměnné myFunc má stále přístup k proměnným, které jsou členy třídy ThisTest. Jestliže je stejný kód spuštěn v jazyce ActionScript 2.0, reference this bude odpovídat a proměnná num bude undefined. Jedna oblast, kde je přidání metody vazby nejvíce zřejmé, je zpracovávání událostí, protože metoda addEventListener() vyžaduje, abyste funkci nebo metodu odeslali jako argument. Více informací naleznete v části Funkce poslouchače definovaná jako metoda třídy v tématu „Posluchače událostí“ na stránce 253. Výčet s třídami Výčty jsou vlastní typy dat, které vytváříte za účelem zapouzdření malé množiny hodnot. Jazyk ActionScript 3.0 nepodporuje na rozdíl od jazyka C++ s klíčovým slovem enum nebo jazyka Java s rozhraním výčtu specifické možnosti výčtu. Výčty můžete nicméně vytvořit pomocí tříd a statických konstant. Například třída PrintJob v jazyce ActionScript 3.0 používá výčet nazvaný PrintJobOrientation pro uchovávání množiny hodnot zahrnující "landscape" a "portrait", jak je uvedeno v následujícím kódu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 102 Objektově orientované programování v jazyce ActionScript public final class PrintJobOrientation { public static const LANDSCAPE:String = "landscape"; public static const PORTRAIT:String = "portrait"; } Dle úmluvy je třída výčtu deklarována s atributem final, protože není třeba danou třídu rozšířit. Třída obsahuje pouze statické členy, což znamená, že nevytváříte instance dané třídy. Namísto toho přistupujete k hodnotám výčtu přímo prostřednictvím objektu třídy, jak je ukázáno v následujícím výpise kódu. var pj:PrintJob = new PrintJob(); if(pj.start()) { if (pj.orientation == PrintJobOrientation.PORTRAIT) { ... } ... } Všechny třídy výčtu v jazyce ActionScript 3.0 obsahují pouze proměnné typu Řetězec, int nebo uint. Výhodou použití výčtu namísto řetězce literálu nebo číselných hodnot je to, že pomocí výčtu naleznete snadněji typografické chyby. Jestliže špatně zadáte název výčtu, kompilátor jazyka ActionScript vygeneruje chybu. Jestliže používáte hodnoty literálu, kompilátor nezjistí chybu, jestliže slovo špatně napíšete nebo použijete špatné číslo. V předchozím příkladu kompilátor vygeneruje chybu, jestliže je název konstanty výčtu nesprávný: if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error Nicméně kompilátor nevygeneruje chybu, jestliže špatně napíšete hodnotu řetězce literálu: if (pj.orientation == "portrai") // no compiler error Druhá technika pro vytvoření výčtů také zahrnuje vytvoření samostatné třídy se statickými vlastnostmi pro výčet. Tato technika se nicméně liší v tom, že každá ze statických vlastností obsahuje instanci dané třídy, namísto řetězce nebo celočíselné hodnoty. Například následující kód vytvoří třídu výčtu pro dny v týdnu: public final class Day { public static const public static const public static const public static const public static const public static const public static const } MONDAY:Day = new Day(); TUESDAY:Day = new Day(); WEDNESDAY:Day = new Day(); THURSDAY:Day = new Day(); FRIDAY:Day = new Day(); SATURDAY:Day = new Day(); SUNDAY:Day = new Day(); Tato technika není používána jazykem ActionScript 3.0, ale je používána mnoha vývojáři, kteří upřednostňují vylepšený typ kontroly, který tato technika nabízí. Například metoda, která vrátí hodnotu výčtu, může omezit vrácenou hodnotu na datový typ výčtu. Následující kód ukazuje nejen funkci, která vrátí den v týdnu, ale také volání funkce, které používá typ výčtu jako typ anotace: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 103 Objektově orientované programování v jazyce ActionScript function getDay():Day { var date:Date = new Date(); var retDay:Day; switch (date.day) { case 0: retDay = Day.MONDAY; break; case 1: retDay = Day.TUESDAY; break; case 2: retDay = Day.WEDNESDAY; break; case 3: retDay = Day.THURSDAY; break; case 4: retDay = Day.FRIDAY; break; case 5: retDay = Day.SATURDAY; break; case 6: retDay = Day.SUNDAY; break; } return retDay; } var dayOfWeek:Day = getDay(); Třídu Day můžete také vylepšit tak, aby propojila celek s každým dnem v týdnu a poskytla metodu toString(), která vrátí reprezentaci řetězce daného dne. Můžete si přát povýšit třídu Day na cvičení. Třídy vloženého datového zdroje Jazyk ActionScript 3.0 používá speciální třídy, nazvané třídy vloženého datového zdroje, pro reprezentaci vložených datových zdrojů. vložený datový zdroj je zdroj, jako například zvuk, obraz, nebo typ písma, který je zahrnut do souboru SWF v čase kompilace. Vkládání datového zdroje namísto jeho dynamického načtení zajišťuje, že bude dostupný v čase zpracování, ale na druhou stranu také zvýší velikost souboru SWF. Použití tříd vloženého datového zdroje v přehrávači Flash Pro vložení datového zdroje nejprve umístěte zdroj do knihovny souboru FLA. Poté pomocí vlastnosti propojení datového zdroje poskytněte název pro třídu vloženého datového zdroje. Jestliže nemůže být třída dle daného názvu nalezena v cestě třídy, je pro vás automaticky vygenerována. Poté můžete vytvořit instanci třídy vloženého datového zdroje a použít jakékoliv vlastnosti a metody definované nebo zděděné danou třídou. Například následující kód lze použít pro přehrání vloženého zvuku, který je propojen s třídou vloženého datového zdroje s názvem PianoMusic: var piano:PianoMusic = new PianoMusic(); var sndChannel:SoundChannel = piano.play(); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 104 Objektově orientované programování v jazyce ActionScript Rozhraní Rozhraní je skupinou deklarací metody, které umožňují nesouvisejícím objektům navzájem komunikovat. Například jazyk ActionScript 3.0 definuje rozhraní IEventDispatcher, které obsahuje deklarace metody, kterou třída používá pro zpracování objektů události. Rozhraní IEventDispatcher zavádí standardní způsob pro vzájemné předání objektů událostí. Následující kód ukazuje definici rozhraní IEventDispatcher interface: public interface IEventDispatcher { function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean = false):void; function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void; function dispatchEvent(event:Event):Boolean; function hasEventListener(type:String):Boolean; function willTrigger(type:String):Boolean; } Rozhraní jsou založena na rozdílu mezi rozhraním metody a její implementací. Rozhraní metody obsahuje veškeré nezbytné informace pro vyvolání dané metody, včetně názvu metody, všech její parametrů a jejího typu návratu. Implementace metody nezahrnuje pouze informace o rozhraní, ale také proveditelné příkazy, které provedou chování metody. Definice rozhraní obsahuje pouze rozhraní metody a jakákoliv třída, která implementuje dané rozhraní, je odpovědná za definici implementací metody. V jazyce ActionScript 3.0 implementuje třída EventDispatcher rozhraní IEventDispatcher definováním všech metod rozhraní IEventDispatcher a přidáním těl metod ke každé z těchto metod. Následující kód je výpisem z definice třídy EventDispatcher: public class EventDispatcher implements IEventDispatcher { function dispatchEvent(event:Event):Boolean { /* implementation statements */ } ... } Rozhraní IEventDispatcher slouží jako protokol, který instance EventDispatcher používají pro zpracování objektů události a jejich předání k jiným objektům, které také mají implementováno rozhraní IEventDispatcher. Dalším způsobem popsání rozhraní je to, že stejně jako třída definuje datový typ. Podle toho může být rozhraní použito jako typ anotace i jako třída. Jako datový typ lze rozhraní použít s operátory, jako například is a as, které vyžadují datový typ. Narozdíl od třídy nemůže být rozhraní konkretizováno. Tento rozdíl donutil mnoho programátorů přemýšlet o rozhraních jako o abstraktních datových typech a třídách jako o konkrétních datových typech. Definice rozhraní Struktura definice rozhraní je podobná struktuře definice třídy s výjimkou, že rozhraní může obsahovat pouze metody bez těl. Rozhraní nemůže zahrnovat proměnné nebo konstanty, ale může obsahovat mechanismy získání a nastavení. Pro definování rozhraní použijte klíčové slovo interface. Například následující rozhraní, IExternalizable, je součástí balíku ActionScript 3.0. Rozhraní IExternalizable definuje protokol pro serializaci objektu, což znamená jeho převedení do formátu vhodného k uložení na zařízení nebo pro přesun po síti. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 105 Objektově orientované programování v jazyce ActionScript public interface IExternalizable { function writeExternal(output:IDataOutput):void; function readExternal(input:IDataInput):void; } Upozorňujeme, že dané rozhraní IExternalizable je deklarováno pomocí modifikátoru ovládání přístupu public. Definice rozhraní lze upravit pouze pomocí specifikátorů ovládání přístupu public a internal. Deklarace metody uvnitř definice rozhraní nemohou mít žádné specifikátory ovládání přístupu. Jazyk ActionScript 3.0 se řídí ustanovením, kde názvy rozhraní začínají velkým I, ale jako název rozhraní můžete použít jakýkoliv povolený identifikátor. Definice rozhraní jsou často umístěny na nevyšší úrovni balíku. Definice rozhraní nelze umístit dovnitř definice třídy nebo dovnitř jiné definice rozhraní. Rozhraní mohou rozšířit jedno nebo více jiných rozhraní. Například následující rozhraní IExample rozšiřuje rozhraní IExternalizable: public interface IExample extends IExternalizable { function extra():void; } Jakákoliv třída, která implementuje rozhraní, musí zahrnovat implementace nejen pro metodu extra(), ale také pro metodywriteExternal() a readExternal() zděděné z rozhraní IExternalizable. Implementace rozhraní ve třídě Třída je jediným prvkem jazyka ActionScript 3.0, který může implementovat rozhraní. Pomocí klíčového slova implements v deklaraci třídy implementujete jedno nebo více rozhraní. Následující příklad definuje dvě rozhraní IAlpha a IBeta a třídu Alfa, která je obě implementuje. interface IAlpha { function foo(str:String):String; } interface IBeta { function bar():void; } class Alpha implements IAlpha, IBeta { public function foo(param:String):String {} public function bar():void {} } Ve třídě, která implementuje rozhraní, musí implementovaná metoda provést následující: • Použijte identifikátor ovládání přístupu public. • Použijte stejný název jako má metoda rozhraní. • Mají stejný počet parametrů s typy dat, které odpovídají datovým typům parametrů metody rozhraní. • Použijte stejný typ návratu. public function foo(param:String):String {} PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 106 Objektově orientované programování v jazyce ActionScript Jistou flexibilitu máte nicméně v tom, jak pojmenujete parametry metody, kterou implementujete. Ačkoliv počet parametrů a datový typ každého parametru v dané implementované metodě musí odpovídat parametru metody rozhraní, názvy parametrů odpovídat nemusí. Například v předchozím příkladě je parametr metody Alpha.foo() pojmenovaný param: Nicméně parametr je pojmenovaný str v metodě rozhraní IAlpha.foo(): function foo(str:String):String; Určitou flexibilitu máte také s výchozími hodnotami parametru. Definice rozhraní může zahrnovat deklarace funkce s výchozími hodnotami parametrů. Metoda, která implementuje takovou deklaraci funkce, musí mít výchozí hodnotu parametru, který je členem stejného datového typu, shodnou s hodnotou určenou v definici rozhraní, ale skutečná hodnota nemusí odpovídat. Například následující kód definuje rozhraní, které obsahuje metodu s výchozí hodnotou parametru 3: interface IGamma { function doSomething(param:int = 3):void; } Následující definice třídy implementuje rozhraní Igamma, ale používá odlišnou výchozí hodnotu parametru: class Gamma implements IGamma { public function doSomething(param:int = 4):void {} } Důvodem pro tuto flexibilitu je to, že pravidla pro implementování rozhraní jsou navržena specificky pro zajištění kompatibility typu dat a vyžadování identických názvů parametrů a výchozích hodnot parametrů není pro dosažení daného cíle nezbytné. Zdědění Dědičnost je formou opětovného použití kódu, které programátorům umožňuje vyvinout nové třídy, které jsou založeny na stávajících třídách. Stávající třídy jsou často označovány jako základní třídy nebo nadřazené třídy, zatímco nové třídy se obvykle nazývají podtřídy. Klíčovou výhodou dědičnosti je to, že vám umožňuje znovu použít kód ze základní třídy a přesto ponechat stávající kód bez změn. A navíc, dědičnost nevyžaduje žádné změny způsobu, kterým jiné třídy reagují se základní třídou. Spíše než úpravou stávající třídy, která mohla být řádně testována nebo může již být používána, můžete pomocí dědičnosti manipulovat s danými třídami jako s integrovaným modulem, který můžete rozšířit o dodatečné vlastnosti nebo metody. Stejně tak pomocí klíčového slova extends určíte, že třída dědí z jiné třídy. Dědičnost vám také umožňuje využít ve svém kódu polymorfismus. Polymorfismus je schopnost použít jediný název metody pro metodu, která se chová jinak při použití jiných typů dat. Jednoduchým příkladem je základní třída pojmenovaná Shape s dvěma podtřídami pojmenovanými Circle a Square. Třída Shape definuje metodu pojmenovanou area(), která vrací prostor tvaru. Jestliže je implementován polymorfismus, můžete metodu area() vyvolat na objekty typu Circle a Square a provést správné výpočty. Dědičnost aktivuje polymorfismus umožněním podtřídám zdědit, předefinovat nebo potlačit metody ze základní třídy. V následujícím příkladě je metoda area() předefinována třídami Circle a Square: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 107 Objektově orientované programování v jazyce ActionScript class Shape { public function area():Number { return NaN; } } class Circle extends Shape { private var radius:Number = 1; override public function area():Number { return (Math.PI * (radius * radius)); } } class Square extends Shape { private var side:Number = 1; override public function area():Number { return (side * side); } } var cir:Circle = new Circle(); trace(cir.area()); // output: 3.141592653589793 var sq:Square = new Square(); trace(sq.area()); // output: 1 Protože každá třída definuje typ dat, vytvoří použití dědičnosti zvláštní vztah mezi základní třídou a třídou, která jí prodlužuje. Podtřída vlastní všechny vlastnosti své základní třídy, což znamená, že instance podtřídy může být vždy nahrazena za instanci základní třídy. Například jestliže metoda definuje parametr typu Shape, je možné předat argument typu Circle, protože Circle rozšiřuje Shape, a to následovně: function draw(shapeToDraw:Shape) {} var myCircle:Circle = new Circle(); draw(myCircle); Vlastnosti a dědičnost instancí Vlastnost instance, ať už definovaná pomocí klíčových slov function, var nebo const, je děděna všemi podtřídami, pokud daná vlastnost není v základní třídě deklarována s atributem private. Například třída Event v jazyce ActionScript 3.0 má několik podtříd, které dědí vlastnosti společné pro všechny objekty události. Pro některé typy událostí třída Event obsahuje všechny vlastnosti nezbytné pro definici události. Tyto typy událostí nevyžadují vlastnosti instancí mimo těch definovaných ve třídě Event. Příklady takových událostí jsou událost complete, ke které doje při úspěšném načtení dat a událost connect, ke které dojde při navázání síťového spojení. Následující příklad je výpisem ze třídy Event, která vykazuje některé z vlastností a metod, které jsou zděděny podtřídou. Protože jsou vlastnosti zděděné, má k těmto vlastnostem přístup instance jakékoliv podtřídy. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 108 Objektově orientované programování v jazyce ActionScript public class Event { public function get type():String; public function get bubbles():Boolean; ... public public public public ... function function function function stopPropagation():void {} stopImmediatePropagation():void {} preventDefault():void {} isDefaultPrevented():Boolean {} } Jiné typy události vyžadují jedinečné vlastnosti, které nejsou dostupné ve třídě Event. Tyto události jsou definovány pomocí podtříd třídy Event, takže nové vlastnosti lze přidat k vlastnostem definovaným ve třídě Event. Příkladem takové podtřídy je třída MouseEvent, která přidává vlastnosti jedinečné k události spojené s pohybem nebo klepnutím myši, například k události mouseMove a click. Následující příklad je výpisem z třídy MouseEvent, která ukazuje definici vlastností, které existují na dané podtřídě, ale nikoliv na základní třídě: public class MouseEvent extends Event { public static const CLICK:String= "click"; public static const MOUSE_MOVE:String = "mouseMove"; ... public function get stageX():Number {} public function get stageY():Number {} ... } Specifikátory ovládání přístupu a dědičnost Jestliže je vlastnost deklarována pomocí klíčového slova public, je vlastnost pro kód viditelná kdekoliv. To znamená, že klíčové slovo public, narozdíl od klíčových slov private, protected a internalneuplatňuje na dědičnost vlastnosti žádná omezení. Jestliže je vlastnost deklarována pomocí klíčového slova private, je viditelná pouze ve třídě, která je definuje, což znamená, že není děděná žádnou podtřídou. Toto chování je odlišné od předchozích verzí jazyka ActionScript, kde se klíčové slovo private chovalo více jako klíčové slovo jazyka ActionScript protected. Klíčové slovo protected udává, že je vlastnost viditelná nejen v rámci třídy, která ji definuje, ale také pro všechny podtřídy. Narozdíl od klíčového slova protected v programovacím jazyce Java, klíčové slovo protected v jazyce ActionScript 3.0 nezviditelňuje vlastnost pro všechny jiné třídy ve stejném balíku. V jazyce ActionScript 3.0 mají k vlastnosti s klíčovým slovem protected přístup pouze podtřídy. Chráněná vlastnost je navíc viditelná pro podtřídy, ať je podtřída ve stejném balíku jako daná třída, nebo v balíku odlišném. Chcete-li omezit viditelnost vlastnosti na balík, ve kterém je definovaná, použijte klíčové slovo internal, nebo nepoužijte žádný specifikátor ovládání přístupu. Specifikátor ovládání přístupu internal je výchozím specifikátorem ovládání přístupu, který bude použit v případě, že jiný specifikátor určen není. Vlastnost označená jako internal bude zděděna pouze podtřídou, která je ve stejném balíku. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 109 Objektově orientované programování v jazyce ActionScript Pomocí následujícího příkladu zjistíte, jak každý ze specifikátorů ovládání přístupu ovlivní dědičnost napříč hranicemi balíku. Následující kód definuje hlavní třídu aplikace nazvanou AccessControl a dvě další třídy pojmenované Base a Extender. Třída Base se nachází v balíku pojmenovaném foo a třída Extender, která je podtřídou třídy Base, je umístěna v balíku pojmenovaném bar. Třída AccessControl importuje pouze třídu Extender a vytvoří instanci Extender, která se pokusí o přístup k proměnné pojmenované str definované ve třídě Base. Proměnná str je deklarovaná jako public, takže kód je sestaven a běží tak, jak je ukázáno v následujícím výpise: // Base.as in a folder named foo package foo { public class Base { public var str:String = "hello"; // change public on this line } } // Extender.as in a folder named bar package bar { import foo.Base; public class Extender extends Base { public function getString():String { return str; } } } // main application class in file named AccessControl.as package { import flash.display.MovieClip; import bar.Extender; public class AccessControl extends MovieClip { public function AccessControl() { var myExt:Extender = new Extender(); trace(myExt.str);// error if str is not public trace(myExt.getString()); // error if str is private or internal } } } Chcete-li vědět, jak jiné specifikátory ovládání přístupu ovlivňují kompilaci a provedení předchozího příkladu, změňte specifikátor ovládání přístupu proměnné str na private, protected nebo internal, a to po odstranění nebo okomentování následujícího řádku ze třídy AccessControl: trace(myExt.str);// error if str is not public PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 110 Objektově orientované programování v jazyce ActionScript Potlačení proměnných není povoleno Vlastnosti deklarované s klíčovými slovy var nebo const jsou zděděny, ale nemohou být potlačeny. Potlačit vlastnost znamená předefinovat danou vlastnost v podtřídě. Jediný typ vlastnosti, který může být potlačen, jsou metody - to znamená vlastnosti deklarované pomocí klíčového slova function. Ačkoliv nelze potlačit proměnnou instance, podobné funkce můžete dosáhnout vytvořením metod získání a nastavení pro proměnou instance a potlačením metod. Další informace naleznete v části „Potlačování metod“ na stránce 110. Potlačování metod Potlačení metody znamená nové definování chování zděděné metody. Statické metody nejsou zděděné a nelze je potlačit. Metody instance jsou nicméně zděděny podtřídami a lze je potlačit pokud jsou splněna dvě kritéria: • Metoda instance není deklarována pomocí klíčového slova final v základní třídě. Je-li používáno s metodou instance, určuje klíčové slovo final záměr programátora zabránit podtřídám potlačit danou metodu. • Metoda instance není deklarována pomocí specifikátoru ovládání private v základní třídě. Jestliže je metoda v základní třídě označena jako private, není třeba použít klíčové slovo override jestliže definujete úplně stejně pojmenovanou metodu v podtřídě, protože metoda základní třídy nebude pro podtřídu viditelná. Chcete-li potlačit metodu instance, která splňuje tato kritéria, definice metody v podtřídě musí použít klíčové slovo override a musí odpovídat verzi metody nadřazené třídy, a to následovně: • Metoda potlačení musí mít stejnou úroveň ovládání přístupu, jako metoda základní třídy. Metoda označená jako interní má stejnou úroveň ovládání přístupu jako metody, které nemají žádný specifikátor ovládání přístupu. • Metoda potlačení musí mít stejný počet parametrů jako metoda základní třídy. • Parametry metody potlačení musí mít stejné anotace typu dat, jako mají parametry v metodě základní třídy. • Metoda potlačení musí mít stejný typ vrácení jako metoda základní třídy. Názvy parametrů v dané metodě potlačení nicméně nemusí odpovídat názvům parametrů v základní třídě, jestliže počet parametrů a typ dat každého parametru souhlasí. Příkaz super Při potlačování metody si programátoři často přejí přidat k chování metody nadřazené třídy, kterou potlačují, namísto úplného nahrazení chování. To vyžaduje mechanismus, který umožňuje metodě podtřídy vyvolat vlastní verzi nadřazené třídy. Příkaz super takový mechanismus poskytuje, protože obsahuje odkaz na další nadřazenou třídu. Následující příklad definuje třídu pojmenovanou Base, která obsahuje metodu pojmenovanou thanks() a podtřídu třídy Base pojmenovanou Extender, která potlačí metodu thanks(). Metoda Extender.thanks() používá příkaz super pro vyvolání Base.thanks(). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 111 Objektově orientované programování v jazyce ActionScript package { import flash.display.MovieClip; public class SuperExample extends MovieClip { public function SuperExample() { var myExt:Extender = new Extender() trace(myExt.thanks()); // output: Mahalo nui loa } } } class Base { public function thanks():String { return "Mahalo"; } } class Extender extends Base { override public function thanks():String { return super.thanks() + " nui loa"; } } Potlačení mechanismů získání nebo nastavení Ačkoliv nemůžete potlačit proměnné definované v nadřazené třídě, můžete potlačit mechanismy získání a nastavení. Například následující kód potlačí mechanismus získání currentLabel, který je definován ve třídě MovieClip v jazyce ActionScript 3.0: package { import flash.display.MovieClip; public class OverrideExample extends MovieClip { public function OverrideExample() { trace(currentLabel) } override public function get currentLabel():String { var str:String = "Override: "; str += super.currentLabel; return str; } } } Výstup příkazu trace() v konstruktoru třídy OverrideExample je Override: null, který ukazuje, že daný příklad byl schopen potlačit zděděnou vlastnost currentLabel. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 112 Objektově orientované programování v jazyce ActionScript Statické vlastnosti nezděděné Statické vlastnosti nejsou zděděny podtřídami. To znamená, že statistické vlastnosti nejsou přístupné prostřednictvím instance nadřazené třídy. Statická vlastnost je přístupná pouze prostřednictvím objektu třídy, na které je definovaná. Například následující kód definuje základní třídu pojmenovanou Base a podtřídu, která rozšiřuje základní třídu, pojmenovanou Extender. Statická proměnná pojmenovaná test je definována ve třídě Base. Kód, jak je zapsán v následujícím výpise, není slučitelný s přísným režimem a ve standardním režimu vytvoří chybu za běhu programu. package { import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); trace(myExt.test);// error } } } class Base { public static var test:String = "static"; } class Extender extends Base { } Jediný způsob přístupu ke statické proměnné test je prostřednictvím objektu třídy, jak je ukázáno v následujícím kódu: Base.test; Nicméně je povolené definovat vlastnost instance použitím stejného názvu jako statické vlastnosti. Taková vlastnost instance může být definována ve stejné třídě jako statická vlastnost nebo v podtřídě. Například základní třída v předcházejícím příkladě by mohla mít vlastnost instance pojmenovanou test. Následující kód je sestaven a proveden, protože vlastnost instance je zděděna třídou Extender. Kód by byl také sestaven a proveden, pokud by byla definice testové proměnné instance přesunuta, ale nikoliv zkopírována, do třídy Extender. package { import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); trace(myExt.test);// output: instance } } } class Base { public static var test:String = "static"; public var test:String = "instance"; } class Extender extends Base {} PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 113 Objektově orientované programování v jazyce ActionScript Statistické vlastnosti a řetězec rozsahu Ačkoliv statické vlastnosti nejsou zděděny, existují v rámci řetězce rozsahu třídy, která definuje tyto vlastnosti a jakékoliv podtřídy dané třídy. Jako takové jsou statické vlastnosti v rozsahu třídy, ve které jsou definovány, i jakékoliv podtřídy. To znamená, že statická vlastnost je přímo přístupná v rámci těla třídy, která definuje statickou vlastnost a v jakékoliv podtřídě dané třídy. Následující příklad upravuje třídy definované v předchozím příkladě a ukazuje, že statická proměnná test definovaná v základní třídě je v rozsahu třídy Extender. Jinými slovy třída Extender má přístup k statické proměnné test bez toho, aby byla proměnná opatřena předponou s názvem třídy, která definuje test. package { import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); } } } class Base { public static var test:String = "static"; } class Extender extends Base { public function Extender() { trace(test); // output: static } } Jestliže je definovaná vlastnost instance, která používá stejný název jako statická vlastnost ve stejné třídě nebo nadřazené třídě, vlastnost instance má v řetězci rozsahu vyšší prioritu. Vlastnost instance stíní statickou vlastnost, což znamená, že hodnota vlastnosti instance je použita namísto hodnoty statické vlastnosti. Například následující kód ukazuje, že jestliže třída Extender definuje proměnnou instance pojmenovanou test, příkaz trace() používá hodnotu proměnné instance namísto hodnoty statické proměnné: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 114 Objektově orientované programování v jazyce ActionScript package { import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); } } } class Base { public static var test:String = "static"; } class Extender extends Base { public var test:String = "instance"; public function Extender() { trace(test); // output: instance } } Pokročilá témata Tato část začíná stručným přehledem historie jazyka ActionScript a OOP a dále uvádí diskuse ohledně modelu objektu jazyka ActionScript 3.0 a to, jak umožňuje novému nástroji ActionScript Virtual Machine (AVM2) pracovat výrazně rychleji, než předchozí verze přehrávače Flash Player, které obsahují starý nástroj ActionScript Virtual Machine (AVM1). Historie podpory OOP jazyka ActionScript Protože jazyk ActionScript 3.0 navazuje na předchozí verze jazyka ActionScript, může být užitečné pochopit, jak se model objektu jazyka ActionScript vyvinul. Jazyk ActionScript začal jako jednoduchý skriptovací mechanismus pro dřívější verze nástroje vytváření přehrávače Flash. Následně začali programátoři s jazykem ActionScript vytvářet komplexnější aplikace. V reakci na potřeby těchto programátorů má každá následující verze nové funkce jazyka, které umožňují vytváření složitých aplikací. ActionScript 1.0 Jazyk ActionScript 1.0 je verze jazyka použitá v přehrávači Flash Player 6 a v dřívějších verzích. I v této ranné fázi vývoje byl model objektu jazyka ActionScript založen na konceptu objektu jako základního typu dat. Objekt jazyka ActionScript je složený typ dat se skupinou vlastností. Hovoříme-li o modelu objektu, pojem vlastnosti zahrnuje vše, co je připojeno k objektu. Jedná se například o proměnné, funkce nebo metody. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 115 Objektově orientované programování v jazyce ActionScript Ačkoliv první generace jazyka ActionScript nepodporuje definici tříd pomocí klíčového slova class, můžete definovat třídu pomocí speciálního druhu objektu nazvaného objekt prototypu. Namísto použití klíčového slova class pro vytvoření definice třídy, kterou zkonkretizujete do určitých objektů, jak to děláte v jazycích založených na třídě (Java a C++), jazyky založené na prototypu (ActionScript 1.0) používají stávající objekt jako model (nebo prototyp) pro jiné objekty. Zatímco objekty v jazyce založeném na třídě mohou indikovat třídu, která slouží jako její šablona, objekty v jazyce založeném na prototypu namísto toho ukazují na jiný objekt, svůj prototyp, který slouží jako šablona. Pro vytvoření třídy v jazyce ActionScript 1.0 vytvoříte pro danou třídu funkci konstruktoru. V jazyce ActionScript jsou funkce skutečné objekty, nikoliv pouze abstraktní definice. Funkce konstruktoru, kterou vytváříte, slouží jako prototypický objekt pro instance dané třídy. Následující kód vytvoří třídu pojmenovanou Shape a definuje jednu vlastnost pojmenovanou visible, která je implicitně nastavena na hodnotu true (pravda): // base class function Shape() {} // Create a property named visible. Shape.prototype.visible = true; Tato funkce konstruktoru definuje třídu Shape, kterou můžete konkretizovat pomocí operátoru new, a to následovně: myShape = new Shape(); Stejně jako slouží objekt funkce konstruktoru Shape() jako prototyp pro instance třídy tvaru, může také sloužit jako prototyp pro podtřídy tvaru - tj. pro další třídy, které rozšiřují třídu Shape. Vytvoření třídy, která je podtřídou třídy Shape, je proces zahrnující dva kroky. Nejprve vytvořte třídu tím, že pro danou třídu definujete funkci konstruktoru: // child class function Circle(id, radius) { this.id = id; this.radius = radius; } Poté použijte operátor new za účelem deklarování, která třída Shape je prototypem třídy Circle. Každá třída, kterou vytvoříte, implicitně používá třídu Object jako prototyp, což znamená, že Circle.prototype aktuálně obsahuje generický objekt (instance třídy Object). Pro určení, že prototyp kruhu je tvar a nikoliv objekt, použijte následující kód pro změnu hodnoty Circle.prototype tak, aby obsahovala objekt tvaru namísto generického objektu: // Make Circle a subclass of Shape. Circle.prototype = new Shape(); Třídy Shape a Circle jsou nyní navzájem propojeny ve vztahu dědičnosti, který je běžně znám jako řetězec prototypu. Tento diagram ilustruje vztah v řetězci prototypu: Object.prototype Shape.prototype Circle.prototype PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 116 Objektově orientované programování v jazyce ActionScript Základní třída na konci každého řetězce prototypu je třída Object. Třída Object obsahuje statickou vlastnost pojmenovanou Object.prototype, která ukazuje na základní objekt prototypu pro všechny objekty vytvořené v jazyce ActionScript 1.0. Další objekt v řetězci prototypu našeho příkladu je objekt Shape. Důvod je ten, že vlastnost Shape.prototype nebyla nikdy explicitně nastavena, takže stále obsahuje generický objekt (instanci třídy Object). Závěrečný odkaz v tomto řetězci je třída Circle, které je propojena se svým prototypem, tedy třídou Shape (vlastnost Circle.prototype obsahuje objekt Shape). Jestliže vytvoříme instanci třídy Circle jako v následujícím příkladě, zdědí daná instance řetězec prototypu třídy Circle: // Create an instance of the Circle class. myCircle = new Circle(); Vzpomeňte si, že jsme vytvořili vlastnost pojmenovanou visible jako člen třídy Shape. V našem případě vlastnost visible neexistuje jako součást objektu myCircle, ale pouze jako člen objektu Shape. Přesto má ale následující řádek kódu výsledek true (pravda): trace(myCircle.visible); // output: true Přehrávač Flash Player může zajistit, že objekt myCircle zdědí vlastnost visible, a to procházením řetězce prototypu směrem vzhůru. Při provádění tohoto kódu přehrávač Flash Player nejprve prohledá vlastnosti objektu myCircle pro vlastnost pojmenovanou visible, ale tuto vlastnost nenalezne. Přehrávač Flash Player se dále podívá do objektu Circle.prototype, ale ani nyní vlastnost pojmenovanou visible nenalezne. Přehrávač Flash Player pokračuje dále řetězcem a nakonec nalezne vlastnost visible definovanou na objektu Shape.prototype a vyprodukuje hodnotu dané vlastnosti. V zájmu jednoduchosti vypouští tato část mnoho podrobností řetězce prototypu a namísto toho je cílem poskytnout dostatek informací, které vám pomohou pochopit model objektu jazyka ActionScript 3.0. ActionScript 2.0 Jazyk ActionScript 2.0 zavedl nová klíčová slova, například class, extends, public a private, které vám umožnily definovat třídy způsobem známým všem, kteří pracují s jazyky založenými na třídě, jako jsou Java a C++. Je důležité pochopit, že výchozí mechanismus dědičnosti se mezi jazyky ActionScript 1.0 a ActionScript 2.0 nezměnil. Jazyk ActionScript 2.0 pouze přidal novou syntaxi pro definování tříd. Řetězec prototypu funguje v obou verzích jazyka stejně. Nová syntaxe zavedená jazykem ActionScript 2.0, zobrazená v následujícím výpise, vám umožňuje definovat třídy způsobem, který je pro mnoho programátorů intuitivnější. // base class class Shape { var visible:Boolean = true; } Všimněte si, že jazyk ActionScript 2.0 také zavedl typ anotací, které budou použity pro kontrolu času kompilace. To vám umožní deklarovat, že by vlastnost visible v předchozím příkladě měla obsahovat pouze booleovskou hodnotu. Nové klíčové slovo extends také zjednodušuje proces vytváření podtřídy. V následujícím příkladě je proces se dvěma kroky v jazyce ActionScript 1.0 dokončen jedním krokem, a to pomocí klíčového slova extends: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 117 Objektově orientované programování v jazyce ActionScript // child class class Circle extends Shape { var id:Number; var radius:Number; function Circle(id, radius) { this.id = id; this.radius = radius; } } Konstruktor je nyní deklarován jako část definice třídy a vlastnosti třídy id a radius musí být také explicitně deklarovány. Jazyk ActionScript 2.0 také přidal podporu pro definici rozhraní, která vám umožňuje dále předefinovat své programy orientované na objekt s formálně definovanými protokoly pro komunikaci mezi objekty. Objekt třídy v jazyce ActionScript 3.0 Běžné paradigma programování orientované na objekt, které je nejčastěji spojené s jazyky Java a C++, používá třídy pro definici tříd objektů. Programovací jazyky, které přijímají toto paradigma, také často používají třídy pro konstrukci instancí typu dat, které třída definuje. Jazyk ActionScript používá třídy pro oba tyto způsoby, ale jeho základ jazyka založeného na prototypu přidává další zajímavé vlastnosti. Jazyk ActionScript vytváří pro každou definici třídy zvláštní objekt třídy, která umožňuje sdílení chování i stavu. Pro mnoho programátorů jazyka ActionScript nicméně tento rozdíl nemusí mít žádné praktické implikace pro kód. Jazyk ActionScript 3.0 je navržen tak, že vytváříte sofistikované aplikace jazyka ActionScript orientované na objekt bez použití, nebo dokonce pochopení, těchto zvláštních objektů tříd. Pro pokročilé programátory, kteří chtějí využít objektů tříd, se tato část věnuje danému tématu podrobně. Následující diagram ukazuje strukturu objektu třídy, který představuje jednoduchou třídu pojmenovanou A definovanou pomocí příkazu class A {}: Class.prototype T Object.prototype CA delegát typ C delegát prototyp konstruktor A vlastnost T A P A PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 118 Objektově orientované programování v jazyce ActionScript Každý obdélník v diagramu představuje objekt. Každý objekt v daném diagramu má charakter dolního indexu A, který představuje to, že náleží do třídy A. Objekt třídy (CA) obsahuje odkazy na několik jiných důležitých objektů. Objekt vlastnosti instance (TA) uchovává vlastnosti instance, které jsou definovány v rámci definice třídy. Objekt vlastnosti třídy (TCA) představuje interní typ třídy a uchovává statické vlastnosti definované danou třídou (znak dolního indexu C znamená „class” - třída). Objekt prototypu (PA) vždy odkazuje na objekt třídy, ke kterému byl původně připojen pomocí vlastnosti constructor. Objekt vlastnosti Objekt vlastnosti, který je v jazyce ActionScript 3.0 nový, byl implementován s ohledem na výkon. V předcházejících verzích jazyka ActionScript mohlo být vyhledání názvu, kdy přehrávač Flash Player prochází řetězec prototypu, časově náročným procesem. V jazyce ActionScript 3.0 je vyhledání názvu daleko účinnější a méně časově náročné, protože zděděné vlastnosti jsou kopírovány z nadřazených tříd do objektů vlastností podtříd. Objekt vlastnosti není přímo dostupný kódem programátora, ale jeho přítomnost zaznamenáte díky lepšímu výkonu a využití paměti. Objekty vlastností poskytují AVM2 detailní informace o rozvržení a obsahu třídy. Díky této znalosti může AVM2 výrazně zkrátit dobu provedení, protože může často vygenerovat přímé pokyny zařízení pro přístup k vlastnostem nebo může vyvolat metody přímo bez časově náročného vyhledávání názvu. Díky objektu vlastností může být otisk paměti objektu výrazně menší než podobný objekt v předchozích verzích jazyka ActionScript. Jestliže je například třída zapečetěna (tj. třída není deklarovaná jako dynamická), instance třídy nepotřebuje tabulku rušení pro dynamicky přidané vlastnosti a může přestavovat pouze ukazovátko na objekty vlastností a některé bloky pro pevné vlastnosti definované ve třídě. Následkem toho by objekt, který vyžaduje 100 bytů paměti v jazyce ActionScript 2.0, mohl vyžadovat pouze 20 bytů paměti v jazyce ActionScript 3.0. Poznámka: Objekt vlastnosti je interním detailem implementace a neexistuje žádná záruka, že se nezmění nebo dokonce v příštích verzích jazyka ActionScript nezmizí. Objekt prototypu Každý objekt třídy jazyka ActionScript má vlastnost pojmenovanou prototype, která je odkazem na objekt prototypu třídy. Objekt prototypu je odkazem kořenů jazyka ActionScript jako jazyka založeného na prototypu. Pro více informací viz „Historie podpory OOP jazyka ActionScript“ na stránce 114. Vlastnost prototype je určena pouze ke čtení, což znamená, že nemůže být upravena a odkazovat tak na různé objekty. To se liší od vlastnosti třídy prototype v předchozích verzích jazyka ActionScript, kdy může být prototyp znovu přiřazen tak, aby odkazoval na odlišnou třídu. Ačkoliv je vlastnost prototype určena pouze ke čtení, objekt prototypu, na který odkazuje, není. Jiným slovy, k objektu prototypu lze přidat nové vlastnosti. Vlastnosti přidané k objektu prototypu jsou sdíleny mezi všemi instancemi dané třídy. Řetězec prototypu, který byl jediným mechanismem dědičnosti v předchozích verzích jazyka ActionScript, slouží v jazyce ActionScript 3.0 pouze jako sekundární úloha. Primární mechanismus dědičnosti, dědičnost pevné vlastnosti, je zpracována interně objektem vlastnosti. Pevná vlastnost je proměnná nebo metoda definovaná jako část definice třídy. Dědičnost pevné vlastnosti se také nazývá dědičnost třídy, protože se jedná o mechanismus dědičnosti, který je spojen s klíčovými slovy jako class, extends a override. Řetězec prototypu poskytuje alternativní mechanismus dědičnosti, který je dynamičtější než dědičnost pevné vlastnosti. Vlastnosti k objektu prototypu třídy můžete přidat nejen jako součást definice třídy, ale také v čase zpracování prostřednictvím třídy vlastnosti prototype objektu. Nicméně si všimněte, že jestliže nastavíte kompilátor na přísný režim, nemusíte mít přístup k vlastnostem přidaným k objektu prototypu, pokud nedeklarujete třídu s klíčovým slovem dynamic. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 119 Objektově orientované programování v jazyce ActionScript Dobrým příkladem třídy s několika vlastnostmi připojené k objektu prototypu je třída Objekt. Metody třídy objektu toString() a valueOf() jsou vlastně funkce přiřazené k vlastnostem objektu prototypu třídy Object. Následující příklad ukazuje, jak by mohla deklarace těchto metod teoreticky vypadat (skutečná implementace se mírně liší z důvodů detailů implementace). public dynamic class Object { prototype.toString = function() { // statements }; prototype.valueOf = function() { // statements }; } Jak již bylo zmíněno dříve, můžete připojit vlastnost k objektu prototypu třídy mimo definici třídy. Například metodu toString() lze také definovat mimo definici třídy Object, a to následovně: Object.prototype.toString = function() { // statements }; Narozdíl od dědičnosti pevné vlastnosti dědičnost prototypu nevyžaduje klíčové slovo override, jestliže si přejete znovu definovat metodu v podtřídě. Například. Jestliže si přejte znovu definovat metodu valueOf() v podtřídě třídy Object, máte tři možnosti. Zaprvé definujete metodu valueOf() na objektu prototypu dílčí třídy uvnitř definice třídy. Následující kód vytvoří podtřídu objektu pojmenovanou Foo a znovu definuje metodu valueOf() na objektu prototypu Foo jako část definice třídy. Protože každá třída dědí ze třídy Object, není třeba použít klíčové slovo extends. dynamic class Foo { prototype.valueOf = function() { return "Instance of Foo"; }; } Za druhé můžete definovat metodu valueOf() na objektu prototypu Foo mimo definici třídy, dle příkladu v následujícím kódu: Foo.prototype.valueOf = function() { return "Instance of Foo"; }; Za třetí můžete definovat pevnou vlastnost pojmenovanou valueOf() jako část třídy Foo. Tato technika se liší od jiných tím, že kombinuje dědičnost pevné vlastnosti s dědičností prototypu. Jakákoliv podtřída Foo, která chce znovu definovat valueOf(), musí použít klíčové slovo override. Následující kód ukazuje valueOf() definovanou jako pevnou vlastnost v Foo: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 120 Objektově orientované programování v jazyce ActionScript class Foo { function valueOf():String { return "Instance of Foo"; } } Jmenný prostor AS3 Existence dvou oddělených mechanismů dědičnosti, dědičnosti pevné vlastnosti a dědičnosti prototypu, vytváří zajímavou otázku kompatibility s ohledem na vlastnosti a metody tříd jádra. Slučitelnost se specifikací jazyka výkresů ECMAScript, na kterých je jazyk ActionScript založen vyžaduje použití dědičnosti prototypu, což znamená, že vlastnosti a metody třídy jádra jsou definovány na objektu prototypu dané třídy. Na druhou stranu slučitelnost s jazykem ActionScript 3.0 vyžaduje použití dědičnosti pevné vlastnosti, což znamená, že vlastnosti a metody třídy jádra jsou definovány v definici třídy pomocí klíčových slov const, var a function. Navíc použití pevných vlastností namísto verzí prototypů může vést k významnému nárůstu výkonu během zpracovávání. Jazyk ActionScript 3.0 tento problém řeší použitím jak dědičnosti prototypu, tak dědičnosti pevné vlastnosti pro třídy jádra. Každá třída jádra obsahuje dvě množiny vlastností a metod. Jedna množina je definována na objektu prototypu pro slučitelnost se specifikací ECMAScript a druhá je definována pomocí pevných vlastností a jmenného prostoru AS3,0 pro slučitelnost s jazykem ActionScript 3.0. Jmenný prostor AS3 poskytuje výhodný mechanismus pro volbu mezi těmito dvěma množinami vlastností a metod. Jestliže nepoužíváte jmenný prostor AS3, instance třídy jádra dědí vlastnosti a metody definované na objektu prototypu třídy jádra. Jestliže se rozhodnete použít jmenný prostor AS3, instance třídy jádra dědí verze AS3, protože jsou pevné vlastnosti vždy upřednostněny před vlastnostmi prototypu. Jinými slovy, kdykoliv je dostupná pevná vlastnost, je vždy použita namísto stejně pojmenované vlastnosti prototypu. Můžete selektivně použít verzi jmenného prostoru AS3 vlastnosti nebo metody, a to její kvalifikací s jmenným prostorem AS3. Například následující kód používá verzi AS3 metody Array.pop(): var nums:Array = new Array(1, 2, 3); nums.AS3::pop(); trace(nums); // output: 1,2 Můžete také použít příkaz use namespace a otevřít tak jmenný prostor AS3 pro všechny definice v rámci bloku kódu. Například následující kód používá příkaz use namespace pro otevření jmenného prostoru AS3 pro metodu pop() i pro metodu push(): use namespace AS3; var nums:Array = new Array(1, 2, 3); nums.pop(); nums.push(5); trace(nums) // output: 1,2,5 Jazyk ActionScript 3.0 také poskytuje volby kompilátoru pro každou sadu vlastností, takže jmenný prostor AS3 můžete použít na celý váš program. Volba kompilátoru -as3 představuje jmenný prostor AS3 a volba -es představuje volbu dědičnosti prototypu (es znamená ECMAScript). Pro otevření jmenného prostoru AS3 pro celý váš program nastavte volbu kompilátoru -as3 na hodnotu true (pravda) a volbu -es na hodnotu false (nepravda). Pro použití verzí prototypu nastavte volby kompilátoru na opačné hodnoty. Výchozí nastavení kompilátoru pro aplikace Adobe Flex Builder 3 a Adobe Flash CS4 Professional jsou -as3 = true (pravda) a -es = false (nepravda). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 121 Objektově orientované programování v jazyce ActionScript Jestliže si přejete rozšířit jakoukoliv z tříd jádra a potlačit nějakou metodu, měli byste chápat, jak může jmenný prostor AS3 ovlivnit způsob deklarace potlačené metody. Jestliže používáte jmenný prostor AS3, jakékoliv metoda potlačení metody třídy jádra musí také používat jmenný prostor AS3, společně s atributem override. Jestliže jmenný prostor AS3 nepoužíváte a přejete si znovu definovat metodu třídy jádra v podtřídě, neměli byste používat jmenný prostor AS3 ani klíčové slovo override. Příklad: GeometricShapes Vzorová aplikace GeometricShapes ukazuje, jak lze pomocí jazyka ActionScript 3.0 použít několik konceptů a funkcí orientovaných na objekt, a to včetně: • Definování tříd • Rozšiřování tříd • Polymorfismus a klíčové slovo override • Definování, rozšiřování a implementace rozhraní Zahrnuje také „metodu rodiny”, která vytváří instanci třídy a ukazuje, jak deklarovat hodnotu vrácení jako instanci rozhraní a použít daný vrácený objekt obecným způsobem. Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace GeometricShapes naleznete ve složce Samples/GeometricShapes. Aplikace sestává z následujících souborů: Soubor Popis GeometricShapes.mxml Hlavní soubor aplikace v programu Flash (FLA) nebo Flex (MXML). nebo GeometricShapes.fla com/example/programmingas3/geometricshapes/IGeometricShape.as Základní metody definující rozhraní budou implementovány všemi třídami aplikace GeometricShapes. com/example/programmingas3/geometricshapes/IPolygon.as Metody definující rozhraní budou implementovány třídami aplikace GeometricShapes, které mají více stran. com/example/programmingas3/geometricshapes/RegularPolygon.as Typ geometrického tvaru, jehož strany mají stejnou délku a jsou rozloženy symetricky kolem středu tvaru. com/example/programmingas3/geometricshapes/Circle.as Typ geometrického tvaru, který definuje kruh. com/example/programmingas3/geometricshapes/EquilateralTriangle.as Podtřída RegularPolygon, která definuje trojúhelník, jehož strany mají stejné délky. com/example/programmingas3/geometricshapes/Square.as Podtřída RegularPolygon definující obdélník, jehož všechny strany jsou stejně dlouhé. com/example/programmingas3/geometricshapes/GeometricShapeFactory.as Třída obsahující metodu rodiny pro vytvoření tvarů s daným typem tvaru a velikostí. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 122 Objektově orientované programování v jazyce ActionScript Definice tříd GeometricShapes Aplikace GeometricShapes umožňuje uživateli specifikovat typ geometrického tvaru a jeho velikost. Tvar poté reaguje s popisem tvaru, jeho oblasti a vzdálenosti okolo jeho obvodu. Uživatelské rozhraní aplikace je triviální, včetně několika kontrol pro výběr typu tvaru, nastavení velikosti a zobrazení popisu. Nejzajímavější část této aplikace je pod povrchem, ve struktuře tříd a samotných rozhraní. Tato aplikace se zabývá geometrickými tvary, ale nezobrazuje je graficky. Poskytuje malou knihovnu tříd a rozhraní, která budou opětovně použita v druhém příkladě této kapitoly (viz „Příklad: SpriteArranger“ na stránce 308). Příklad SpriteArranger zobrazí tvary graficky a uživatel má možnost s nimi manipulovat, a to na základě rámce třídy, který je k dispozici v aplikaci GeometricShapes. Třídy a rozhraní, které definují geometrické tvary v tomto příkladě, jsou ukázány v následujícím diagramu pomocí poznámky v jednotném modelovacím jazyce (UML): << interface >> IGeometricShape +getArea (): Number +describe (): Strin Circle +diameter:Number +Circle () : Circle +getArea () : Number +describe () : String +getCircumference () : Number << interface >> IPolygon +getPerimeter (): Number +getSumOfAngles (): Number RegularPolygon +numSides : int +sideLength : Number +RegularPolygon (): RegularPolygon +getSumOfAngles (): Number +getPerimeter (): Number +getArea (): Number +describe (): String Square EquilateralTriangle +EquilateralTriangle (): EquilateralTriangle +getArea (): Number +describe (): String +Square (): Square +getArea (): Number +describe (): String Třídy příkladu GeometricShapes Definice běžného chování s rozhraními Tato aplikace GeometricShapes se zabývá třemi typy tvarů: kruhy, čtverci a rovnostrannými trojúhelníky. Struktura třídy GeometricShapes začíná s velice jednoduchým rozhraním, IGeometricShape, které uvádí metody běžné pro všechny tři typy tvarů: package com.example.programmingas3.geometricshapes { public interface IGeometricShape { function getArea():Number; function describe():String; } } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 123 Objektově orientované programování v jazyce ActionScript Rozhraní definuje dvě metody: metodu getArea(), která vypočítává a vrací oblast tvaru a metodu describe(), která sestavuje textový popis vlastností tvaru. Chceme také vědět vzdálenost okolo obvodu každého tvaru. Obvod kruhu je vypočten jedinečným způsobem, takže se chování liší od chování trojúhelníku nebo čtverce. Přesto mezi trojúhelníky, čtverci a jinými mnohoúhelníky existuje dostatečná podobnost a je tedy dobré definovat novou třídu rozhraní pouze pro ně: IPolygon. Rozhraní IPolygon je, jak je ukázáno níže, také spíše jednoduché: package com.example.programmingas3.geometricshapes { public interface IPolygon extends IGeometricShape { function getPerimeter():Number; function getSumOfAngles():Number; } } Toto rozhraní definuje dvě metody společné pro všechny mnohoúhelníky: metodu getPerimeter(), která měří kombinovanou vzdálenost všech stran a metodu getSumOfAngles(), která sčítá všechny vnitřní úhly. Rozhraní IPolygon rozšiřuje rozhraní IGeometricShape, což znamená, že jakákoliv třída, která implementuje rozhraní IPolygon, musí deklarovat všechny čtyři metody - dvě z rozhraní IGeometricShape a dvě z rozhraní IPolygon. Definice tříd tvaru Jakmile pochopíte metody společné pro každý typ tvaru, můžete definovat samotné třídy tvarů. Co se týče počtu metod, které potřebujete implementovat, je nejjednodušší třídou třída Circle: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 124 Objektově orientované programování v jazyce ActionScript package com.example.programmingas3.geometricshapes { public class Circle implements IGeometricShape { public var diameter:Number; public function Circle(diam:Number = 100):void { this.diameter = diam; } public function getArea():Number { // The formula is Pi * radius * radius. var radius:Number = diameter / 2; return Math.PI * radius * radius; } public function getCircumference():Number { // The formula is Pi * diameter. return Math.PI * diameter; } public function describe():String { var desc:String = "This shape is a Circle.\n"; desc += "Its diameter is " + diameter + " pixels.\n"; desc += "Its area is " + getArea() + ".\n"; desc += "Its circumference is " + getCircumference() + ".\n"; return desc; } } } Třída Circle implementuje rozhraní IGeometricShape, takže musí poskytnout kód pro metodu getArea() i metodu describe(). Dále definuje metodu getCircumference(), která je jedinečná pro třídu Circle. Třída Circle také deklaruje vlastnost diameter, kterou lze najít v jiných třídách mnohoúhelníků. Druhé dva typy tvarů, čtverce a jednostranné trojúhelníky, mají společné i jiné věci: oba mají stejně dlouhé strany a existují společné vzorce, které můžete použít pro výpočet obvodu a součtu vnitřních úhlů obou tvarů. Tyto společné vzorce se defacto použijí na jakékoliv jiné pravidelné mnohoúhelníky, které bude třeba definovat i v budoucnosti. Třída RegularPolygon bude nadřazenou třídou pro třídu čtverce i třídu EquilateralTriangle. Nadřazená třída vám umožňuje definovat běžné metody na stejném místě, takže je nemusíte definovat zvlášť v každé podtřídě. Zde je kód pro třídu RegularPolygon: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 125 Objektově orientované programování v jazyce ActionScript package com.example.programmingas3.geometricshapes { public class RegularPolygon implements IPolygon { public var numSides:int; public var sideLength:Number; public function RegularPolygon(len:Number = 100, sides:int = 3):void { this.sideLength = len; this.numSides = sides; } public function getArea():Number { // This method should be overridden in subclasses. return 0; } public function getPerimeter():Number { return sideLength * numSides; } public function getSumOfAngles():Number { if (numSides >= 3) { return ((numSides - 2) * 180); } else { return 0; } } public function describe():String { var desc:String = "Each side is " + sideLength + " pixels long.\n"; desc += "Its area is " + getArea() + " pixels square.\n"; desc += "Its perimeter is " + getPerimeter() + " pixels long.\n"; desc += "The sum of all interior angles in this shape is " + getSumOfAngles() + " degrees.\n"; return desc; } } } Nejprve třída RegularPolygon deklaruje dvě vlastnosti, které jsou společné pro všechny pravidelné mnohoúhelníky: délka každé strany (vlastnost sideLength) a počet stran (vlastnost numSides). Třída RegularPolygon implementuje rozhraní IPolygon a deklaruje všechny čtyři metody rozhraní IPolygon. Tato třída implementuje dvě z nich - metodu getPerimeter() a metodu getSumOfAngles() - pomocí společných vzorců. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 126 Objektově orientované programování v jazyce ActionScript Protože se vzorec pro metodu getArea() bude lišit tvar od tvaru, verze metody základní třídy nemůže zahrnovat společnou logiku, která může být zděděna metodami podtřídy. Místo toho jednoduše vrátí výchozí hodnotu 0 udávající, že daná oblast nebyla vypočtena. Pro správný výpočet oblasti každého tvaru musí podtřídy třídy RegularPolygon potlačit samotnou metodu getArea(). Následující kód pro třídu EquilateralTriangle ukazuje, jak je metoda getArea() potlačena: package com.example.programmingas3.geometricshapes { public class EquilateralTriangle extends RegularPolygon { public function EquilateralTriangle(len:Number = 100):void { super(len, 3); } public override function getArea():Number { // The formula is ((sideLength squared) * (square root of 3)) / 4. return ( (this.sideLength * this.sideLength) * Math.sqrt(3) ) / 4; } public override function describe():String { /* starts with the name of the shape, then delegates the rest of the description work to the RegularPolygon superclass */ var desc:String = "This shape is an equilateral Triangle.\n"; desc += super.describe(); return desc; } } } Klíčové slovo override udává, že metoda EquilateralTriangle.getArea() záměrně potlačí metodu getArea() z nadřazené třídy RegularPolygon. Při vyvolání metoda EquilateralTriangle.getArea() vypočte oblast pomocí vzorce v předcházejícím kódu a kód v metodě RegularPolygon.getArea() nebude nikdy proveden. Naopak třída EquilateralTriangle nedefinuje svou vlastní verzi metody getPerimeter(). Při vyvolání metody EquilateralTriangle.getPerimeter() prochází volání řetězcem dědičnosti a provede kód v metodě getPerimeter() nadřazené třídy RegularPolygon. Konstruktor EquilateralTriangle() používá příkaz super() pro explicitní vyvolání konstruktoru RegularPolygon() ze své nadřazené třídy. Pokud by konstruktory měly stejnou množinu parametrů, mohli byste úplně vypustit konstruktor EquilateralTriangle() a konstruktor RegularPolygon() by byl proveden místo něj. Nicméně konstruktor RegularPolygon() potřebuje parametr navíc, numSides. Proto konstruktor EquilateralTriangle() vyvolá super(len, 3), který projde podél vstupního parametru len a hodnotu 3, která určuje, že daný trojúhelník bude mít 3 strany. Metoda describe() také používá příkaz super(), ale jiným způsobem - pro vyvolání verze nadřazené třídy RegularPolygon metody describe(). Metoda EquilateralTriangle.describe() nejprve nastaví proměnnou řetězce desc pro příkaz ohledně typu tvaru. Poté získá výsledky metody RegularPolygon.describe() vyvoláním super.describe()a připíše výsledek k řetězci desc. Třídu Square zde nebudeme podrobně popisovat, ale je podobná třídě EquilateralTriangle a poskytuje konstruktor a své vlastní implementace metod getArea() a describe(). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 127 Objektově orientované programování v jazyce ActionScript Polymorfismus a metoda rodiny Množina třídy, která využívá rozhraní a dědičnost, může být použita mnoha zajímavými způsoby. Například všechny zatím popsané třídy tvaru buď implementují rozhraní IGeometricShape nebo rozšiřují nadřazenou třídu, která provádí implementaci. Takže pokud definujete proměnou jako instanci IGeometricShape, nemusíte vědět, zda se vlastně jedná o instanci třídy kruhu nebo čtverce pro to, aby došlo k vyvolání její metody describe(). Následující kód ukazuje způsob funkce: var myShape:IGeometricShape = new Circle(100); trace(myShape.describe()); Při vyvolání myShape.describe() dojde k provedení metody Circle.describe(), protože ačkoliv je proměnná definována jako instance rozhraní IGeometricShape, třída Circle je její základní třídou. Tento příklad ukazuje princip polymorfismu v akci: přesně to samé volání metody bude mít za následek provedení různého kódu, a to v závislosti na třídě objektu, jehož metoda je vyvolávána. Aplikace GeometricShapes použije tento typ polymorfismu založeného na rozhraní pomocí zjednodušené verze designového vzoru známé jako metoda rodiny. Pojem metoda rodiny se vztahuje k funkci, která vrátí objekt, jehož základní typ dat nebo obsah se může lišit v závislosti na kontextu. Zde uvedená třída GeometricShapeFactory definuje metodu rodiny pojmenovanou createShape(): package com.example.programmingas3.geometricshapes { public class GeometricShapeFactory { public static var currentShape:IGeometricShape; public static function createShape(shapeName:String, len:Number):IGeometricShape { switch (shapeName) { case "Triangle": return new EquilateralTriangle(len); case "Square": return new Square(len); case "Circle": return new Circle(len); } return null; } public static function describeShape(shapeType:String, shapeSize:Number):String { GeometricShapeFactory.currentShape = GeometricShapeFactory.createShape(shapeType, shapeSize); return GeometricShapeFactory.currentShape.describe(); } } } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 128 Objektově orientované programování v jazyce ActionScript Metoda rodiny createShape() umožňuje konstruktorům podtřídy tvaru definovat podrobnosti instancí, které vytvářejí, zatímco vracejí nové objekty jako instance IGeometricShape, takže je aplikace může zpracovat obecnějším způsobem. Metoda describeShape() v předcházejícím příkladě ukazuje, jak může aplikace použít metodu rodiny pro získání obecné reference ke specifičtějšímu objektu. Aplikace může získat popis pro nově vytvořený objekt Circle takto: GeometricShapeFactory.describeShape("Circle", 100); Metoda describeShape() poté vyvolá metodu rodiny createShape() se stejnými parametry a uchová nový objekt kruhu ve statické proměnné pojmenované currentShape, která je typem objektu IGeometricShape. Poté je vyvolána metoda describe() na objektu currentShape a dané volání je automaticky vyřešeno pro provedení metody Circle.describe(), která bude mít za následek podrobný popis kruhu. Vylepšení vzorové aplikace Skutečná váha rozhraní a dědičnosti bude zřejmá, jakmile vylepšíte nebo změníte svou aplikaci. Řekněme, že k této vzorové aplikaci chcete přidat nový tvar, pětiúhelník. Vytvořili byste novou třídu pětiúhelníku, která rozšiřuje třídu RegularPolygon a definuje své vlastní verze metod getArea() a describe(). Poté byste přidali novou volbu pětiúhelníku do vstupního pole v uživatelském rozhraní aplikace. Ale to je vše. Třída Pentagon by automaticky získala funkce metody getPerimeter() a metody getSumOfAngles() z třídy RegularPolygon prostřednictvím dědičnosti. Protože dědí ze třídy, která implementuje rozhraní IGeometricShape, může být s instancí Pentagon zacházeno také jako s instancí IGeometricShape. To znamená, že pro přidání nového typu tvaru nepotřebujete změnit metodu podpisu žádné z metod ve třídě GeometricShapeFactory (a následně také nemusíte změnit žádný z kódů, která třída GeometricShapeFactory používá). Můžete si přát přidat třídu Pentagon k příkladu geometrických tvarů jako cvičení a zjistit tak, jak mohou rozhraní a dědičnost ulehčit pracovní zatížení přidání nových funkcí do aplikace. 129 Kapitola 6: Práce s daty a časy Měření času nemusí být všechno, ale v softwarových aplikacích je to většinou klíčový faktor. Jazyk ActionScript 3.0 poskytuje účinné způsoby správy kalendářových dat, časů a časových intervalů. Většinu těchto časových funkcí poskytují dvě hlavní třídy: třída Date a nová třída Timer v balíčku flash.utils. Základy data a času Úvod k práci s daty a časy Data a časy jsou běžným typem informací používaných v programech ActionScript. Můžete například potřebovat znát aktuální den v týdnu nebo změřit, kolik času uživatel stráví na konkrétní obrazovce atd. V jazyku ActionScript můžete použít třídu Date k vyjádření jednoho okamžiku v čase, včetně informací o datu a čase. V instanci Date jsou hodnoty pro jednotlivé jednotky data a času, včetně roku, měsíce, dne, dne v týdnu, hodin, minut, sekund, milisekund a časového pásma. Pro pokročilejší použití obsahuje ActionScript také třídu Timer, kterou můžete použít k provádění akcí s určitým zpožděním nebo v opakovaných intervalech. Běžné úlohy s datem a časem V této kapitole jsou popsány následující běžné úlohy pro práci s informacemi o datu a čase. • Práce s objekty Date • Získání aktuálního data a času • Přístup k individuálním jednotkám data a času (dny, roky, hodiny, minuty atd.) • Provádění aritmetických operací s datem a časem • Převody mezi časovými pásmy • Provádění opakovacích akcí • Provádění akcí po nastaveném časovém intervalu Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Čas UTC: Koordinovaný světový čas – referenční časové pásmo „nulové hodiny“. Všechna ostatní časová pásma jsou definována jako počet hodin přičítaných nebo odečítaných od času UTC. Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. Protože příklady kódů uvedené v této kapitole se týkají především objektů Date, zkoušení příkladů bude zahrnovat prohlížení hodnot proměnných používaných v příkladech, buď zapsáním proměnných do instance textového pole ve vymezené ploše nebo použitím funkce trace() k vytištění hodnot do panelu Výstup. Tyto techniky jsou podrobně popsány v části „Testování příkladů kódu v této kapitole“ na stránce 34. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 130 Práce s daty a časy Správa kalendářních dat a časů Všechny funkce pro správu kalendářních dat a časů v jazyku ActionScript 3.0 jsou soustředěny v nejvyšší třídě Date. Třída Date obsahuje metody a vlastnosti, které umožňují zpracovávat data a časy buď v Koordinovaném světovém času (UTC) nebo v místním času příslušejícím k danému časovému pásmu. UTC je standardní definice času, který je v zásadě stejný jako Greenwichský čas (GMT). Vytváření objektů Date Třída Date se může pochlubit jednou z nejuniverzálnějších metod konstruktoru ze všech hlavních tříd. Můžete ji vyvolat čtyřmi různými způsoby. Za prvé, když nejsou zadány žádné parametry, konstruktor Date() vrátí objekt Date obsahující aktuální datum a čas, v místním času na základě příslušného časového pásma. Zde je příklad: var now:Date = new Date(); Za druhé, je-li zadán jeden číselný parametr, konstruktor Date() jej bude brát jako počet milisekund od 1. ledna 1970 a vrátí odpovídající objekt Date. Všimněte si, že předaná hodnota v milisekundách je brána jako počet milisekund od 1. ledna 1970 v UTC. Objekt Date však ukazuje hodnoty ve vašem místním časovém pásmu, pokud nepoužíváte k jejich vyhledání a zobrazení metody orientované na UTC. Vytvoříte-li nový objekt Date pomocí jednoho parametru milisekundy, Nezapomeňte vzít v úvahu rozdíl v časovém pásmu mezi vaším místním časem a UTC. Následující příkazy vytvoří objekt Date nastavený na půlnoc 1. ledna 1970 v UTC: var millisecondsPerDay:int = 1000 * 60 * 60 * 24; // gets a Date one day after the start date of 1/1/1970 var startTime:Date = new Date(millisecondsPerDay); Za třetí, můžete předat více číselných parametrů pro konstruktor Date(). Konstruktor bude brát tyto parametry jako rok, měsíc, den, hodinu, minutu, sekundu, resp. milisekundu a vrátí odpovídající objekt Date. Předpokládá se, že tyto vstupní parametry jsou uvedeny v místním času a ne v UTC. Následující příkazy získají objekt Date nastavený na půlnoc na začátku 1. ledna 2000 v místním času: var millenium:Date = new Date(2000, 0, 1, 0, 0, 0, 0); Za čtvrté, můžete předat jeden parametr v podobě řetězce pro konstruktor Date(). Konstruktor se pokusí analyzovat tento řetězec na složky data nebo času a vrátí odpovídající objekt Date. Použijete-li tento přístup, je dobré, když uzavřete konstruktor Date() do bloku try..catch pro zachycení případných chyb analýzy. Konstruktor Date() přijme číslo různých formátů řetězce, jak je uvedeno v Referenční příručce jazyka ActionScript 3.0 a jeho součástí. Následující příkaz inicializuje nový objekt Date pomocí hodnoty řetězce: var nextDay:Date = new Date("Mon May 1 2006 11:30:00 AM"); Nemůže-li konstruktor Date() úspěšně analyzovat parametr v podobě řetězce, nevrátí výjimku. Výsledný objekt Date však bude obsahovat neplatnou hodnotu data. Získání hodnot v jednotkách času V rámci objektu Date můžete pomocí vlastností nebo metod třídy Date vyjmout hodnoty pro různé jednotky času. Každá z následujících vlastností dává hodnotu v jednotkách času v objektu Date: • Vlastnost fullYear • Vlastnost month, která je v číselném formátu s 0 pro leden až 11 pro prosinec • Vlastnost date, která udává kalendářní pořadí dne v měsíci, v rozsahu od 1 do 31 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 131 Práce s daty a časy • Vlastnost day, která udává den v týdnu v číselném formátu, s 0 pro neděli • Vlastnost hours v rozsahu od 0 do 23 • Vlastnost minutes • Vlastnost seconds • Vlastnost milliseconds Třída Date ve skutečnosti poskytuje několik způsobů jak získat každou z uvedených hodnot. Hodnotu měsíce objektu Date můžete například získat čtyřmi různými způsoby: • Vlastnost month • Metoda getMonth() • Vlastnost monthUTC • Metoda getMonthUTC() Všechny čtyři způsoby jsou v podstatě rovnocenné ve smyslu efektivity, můžete tedy použít libovolný přístup, jaký nejlépe vyhovuje vaší aplikaci. Všechny právě vyjmenované vlastnosti představují komponenty celkové hodnoty data. Například, vlastnost milliseconds nebude nikdy větší než 999, protože když dosáhne hodnoty 1000, tak se hodnota seconds zvýší o 1 a vlastnost milliseconds se nastaví znovu na 0. Chcete-li získat hodnotu objektu Date v milisekundách od 1. ledna 1970 (UTC), můžete použít metodu getTime(). Její protějšek, metoda setTime(), umožňuje změnit hodnotu stávajícího objektu Date při použití milisekund od 1. ledna 1970 (UTC). Provádění aritmetických operací s datem a časem Pomocí třídy Date můžete u data a času provádět sčítání a odčítání. Hodnoty data jsou interně uchovávány v milisekundách, takže byste měli ostatní hodnoty nejdříve převést na milisekundy, než s nimi budete provádět sčítání nebo odčítání s objekty Date. Pokud bude vaše aplikace provádět hodně aritmetických operací s datem a časem, bude pro vás možná užitečné, když si vytvoříte konstanty, které budou udávat běžné hodnoty jednotek času v milisekundách, jako zde: public static const millisecondsPerMinute:int = 1000 * 60; public static const millisecondsPerHour:int = 1000 * 60 * 60; public static const millisecondsPerDay:int = 1000 * 60 * 60 * 24; Nyní je jednoduché provádět aritmetické operace s použitím standardních jednotek času. Následující kód nastaví hodnotu data na jednu hodinu od aktuálního času pomocí metod getTime() a setTime(). var oneHourFromNow:Date = new Date(); oneHourFromNow.setTime(oneHourFromNow.getTime() + millisecondsPerHour); Jiný způsob jak nastavit hodnotu data je vytvořit nový objekt Date s použitím parametru milliseconds. Například, následující kód přičte 30 dnů k jednomu datu, aby vypočítal jiné: // sets the invoice date to today's date var invoiceDate:Date = new Date(); // adds 30 days to get the due date var dueDate:Date = new Date(invoiceDate.getTime() + (30 * millisecondsPerDay)); Konstanta millisecondsPerDay je dále vynásobena 30, což dává čas v délce 30 dnů, a výsledek je přičten k hodnotě invoiceDate a použit k nastavení hodnoty dueDate. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 132 Práce s daty a časy Převody mezi časovými pásmy Aritmetické operace s datem a časem přijdou vhod, když chcete převést data z jednoho časového pásma na jiné. K tomu slouží metoda getTimezoneOffset(), která vrátí hodnotu v minutách, o kterou se bude časové pásmo objektu Date lišit od UTC. Tato metoda vrátí hodnotu v minutách, protože ne všechna časová pásma jsou nastavena na přírůstky v celých hodinách – některé mají půlhodinový časový posun od sousedního pásma. V následujícím příkladu je použit časový posun k převedení data z místního času na UTC. Převod se provede tak, že se nejprve vypočítá hodnota časového pásma v milisekundách a poté se o danou hodnotu upraví hodnota Date: // creates a Date in local time var nextDay:Date = new Date("Mon May 1 2006 11:30:00 AM"); // converts the Date to UTC by adding or subtracting the time zone offset var offsetMilliseconds:Number = nextDay.getTimezoneOffset() * 60 * 1000; nextDay.setTime(nextDay.getTime() + offsetMilliseconds); Kontrola časových intervalů Když vyvíjíte aplikace pomocí programu Adobe Flash CS4 Professional, máte přístup k časové ose, která poskytuje stabilní postup vaší aplikací po snímcích. V ryzích projektech ActionScript se však musíte spoléhat na jiné časovací mechanismy. Smyčky versus časovače V některých programovacích jazycích musíte navrhnout své vlastní časovací systémy pomocí smyčkových příkazů jako for nebo do..while. Smyčkové příkazy se obvykle provádějí tak rychle, jak to umožňuje místní počítač, což znamená, že aplikace běží na některých počítačích rychleji a na jiných pomaleji. Potřebuje-li vaše aplikace konzistentní interval časování, musíte ji napojit na samotný kalendář nebo hodiny. Mnohé aplikace, např. hry, animace nebo ovladače v reálném čase, potřebují pravidelné, časově řízené časovací mechanismy, které jsou na různých počítačích konzistentní. Třída Timer jazyka ActionScript 3.0 poskytuje výkonné řešení. Pomocí modelu událostí ActionScript 3.0 třída Timer odešle událost časovače vždy po uplynutí určeného časového intervalu. Třída Timer Upřednostňovaný způsob zpracování funkcí časování v jazyku ActionScript 3.0 je použití třídy Timer (flash.utils.Timer), kterou lze použít k odesílání událostí po dosažení určitého intervalu. Chcete-li spustit časovač, vytvořte nejprve instanci třídy Timer, která bude sdělovat, jak často se má generovat událost timer a kolikrát se to má opakovat, než dojde k zastavení. Například následující kód vytvoří instanci třídy Timer, která odešle událost každou sekundu a bude v tom pokračovat 60 sekund. var oneMinuteTimer:Timer = new Timer(1000, 60); Objekt Timer odešle objekt TimerEvent při každém dosažení zadaného intervalu. Typ události objektu TimerEvent je timer (definovaný konstantou TimerEvent.TIMER). Objekt TimerEvent obsahuje stejné vlastnosti jako standardní objekt Event. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 133 Práce s daty a časy Je-li instance Timer nastavena na pevný počet intervalů, odešle také událost timerComplete (definovanou konstantou TimerEvent.TIMER_COMPLETE), jakmile dosáhne konečného intervalu. Zde je malá ukázka aplikace, která ukazuje třídu Timer v činnosti: package { import flash.display.Sprite; import flash.events.TimerEvent; import flash.utils.Timer; public class ShortTimer extends Sprite { public function ShortTimer() { // creates a new five-second Timer var minuteTimer:Timer = new Timer(1000, 5); // designates listeners for the interval and completion events minuteTimer.addEventListener(TimerEvent.TIMER, onTick); minuteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete); // starts the timer ticking minuteTimer.start(); } public function onTick(event:TimerEvent):void { // displays the tick count so far // The target of this event is the Timer instance itself. trace("tick " + event.target.currentCount); } public function onTimerComplete(event:TimerEvent):void { trace("Time's Up!"); } } } Jakmile je vytvořena třída ShortTimer, vytvoří instanci třídy Timer, která bude tikat jednou za sekundu po dobu pěti sekund. Dále přidá k časovači dva posluchače událostí: jeden, který poslouchá každé tiknutí, a jeden, který poslouchá událost timerComplete. Dále spustí tikání časovače a od toho okamžiku se bude v jednosekundových intervalech provádět metoda onTick(). Metoda onTick() jednoduše zobrazuje aktuální počet tiknutí. Po uplynutí pěti sekund se provede metoda onTimerComplete(), která oznámí, že čas vypršel. Když spustíte tuto ukázku, měli byste vidět, jak se ve vaší konzole nebo sledovacím okně objevují následující řádky rychlostí jeden řádek za sekundu: tick 1 tick 2 tick 3 tick 4 tick 5 Time's Up! PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 134 Práce s daty a časy Funkce časování v balíčku flash.utils Jazyk ActionScript 3.0 obsahuje několik funkcí časování podobných těm, které byly k dispozici ve verzi ActionScript 2.0. Tyto funkce jsou poskytnuty jako funkce na úrovni balíčku v balíčku flash.utils a fungují stejně jako ve verzi ActionScript 2.0. Funkce Popis clearInterval(id:uint):void Zruší určené volání setInterval(). clearTimeout(id:uint):void Zruší určené volání setTimeout(). getTimer():int Vrátí počet milisekund, které uplynuly od spuštění přehrávače Adobe® Flash® Player nebo Adobe® AIR™. setInterval(closure:Function, delay:Number, ... arguments):uint Spouští funkci v určeném intervalu (v milisekundách). setTimeout(closure:Function, delay:Number, ... arguments):uint Spouští určenou funkci po určené prodlevě (v milisekundách). Tyto funkce zůstávají v jazyku ActionScript 3.0 kvůli zpětné kompatibilitě. Společnost Adobe nedoporučuje jejich používání v nových aplikacích ActionScript 3.0. Obecně je jednodušší a efektivnější používat ve vašich aplikacích třídu Timer. Příklad: Jednoduché analogové hodiny Příklad jednoduchých analogových hodin znázorňuje dvě koncepce data a času probrané v této kapitole: • Získání aktuálního data a času a vyjímání hodnot pro hodiny, minuty a sekundy • Použití objektu Timer k nastavení tempa aplikace Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace SimpleClock najdete ve složce Samples/SimpleClock. Aplikace sestává z následujících souborů: Soubor Popis SimpleClockApp.mxml Hlavní soubor aplikace v programu Flash (FLA) nebo Flex (MXML). nebo SimpleClockApp.fla com/example/programmingas3/simpleclock/SimpleClock.as Hlavní soubor aplikace. com/example/programmingas3/simpleclock/AnalogClockFace.as Nakreslí kruhový tvar číselníku a hodinové, minutové a sekundové ručičky podle času. Definování třídy SimpleClock Příklad hodin je jednoduchý, ale je dobré si i jednoduché aplikace dobře uspořádat, abyste je mohli v budoucnosti snadno rozšířit. K tomu účelu používá aplikace SimpleClock třídu SimpleClock pro zpracování úloh spuštění a sledování času a dále používá další třídu s názvem AnalogClockFace k vlastnímu zobrazování času. Zde je kód, který definuje a inicializuje třídu SimpleClock (všimněte si, že ve verzi Flash je třída SimpleClock rozšířením třídy Sprite): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 135 Práce s daty a časy public class SimpleClock extends UIComponent { /** * The time display component. */ private var face:AnalogClockFace; /** * The Timer that acts like a heartbeat for the application. */ private var ticker:Timer; Tato třída má dvě důležité vlastnosti: • Vlastnost face, která je instancí třídy AnalogClockFace • Vlastnost ticker, která je instancí třídy Timer Třída SimpleClock používá výchozí konstruktor. Metoda initClock() se stará o práci opravdového rozvržení a vytváří číselník a spouští instanci tikání třídy Timer. Vytvoření číselníku hodin Následující řádky kódu SimpleClock vytvoří hodinový číselník, který se používá k zobrazování času: /** * Sets up a SimpleClock instance. */ public function initClock(faceSize:Number = 200) { // creates the clock face and adds it to the display list face = new AnalogClockFace(Math.max(20, faceSize)); face.init(); addChild(face); // draws the initial clock display face.draw(); Velikost číselníku je možno předat do metody initClock(). Není-li předána žádná hodnota faceSize, použije se výchozí hodnota 200 obr. bodů. Dále aplikace inicializuje číselník a poté jej přidá na seznam zobrazení pomocí metody addChild() zděděné z třídy DisplayObject. Dále vyvolá metodu AnalogClockFace.draw() k jednomu zobrazení číselníku ukazujícího aktuální čas. Spuštění časovače Po vytvoření číselníku hodin metoda initClock() nastaví časovač: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 136 Práce s daty a časy // creates a Timer that fires an event once per second ticker = new Timer(1000); // designates the onTick() method to handle Timer events ticker.addEventListener(TimerEvent.TIMER, onTick); // starts the clock ticking ticker.start(); Nejprve tato metoda inicializuje instanci třídy Timer, která bude odesílat událost každou sekundu (každých 1000 milisekund). Protože nebyl konstruktoru Timer() předán žádný parametr repeatCount, časovač bude spuštěný do nekonečna. Metoda SimpleClock.onTick() se provede každou sekundu při obdržení události timer. public function onTick(event:TimerEvent):void { // updates the clock display face.draw(); } Metoda AnalogClockFace.draw() jednoduše nakreslí číselník a ručičky hodin. Zobrazení aktuálního času Většina kódu v třídě AnalogClockFace zajišťuje nastavení elementů zobrazení číselníku hodin. Jakmile je třída AnalogClockFace inicializována, nakreslí kruhový obrys, umístí do něj číselné popisy k jednotlivým značkám hodin a poté vytvoří tři objekty Shape, po jednom pro hodinovou ručičku, minutovou ručičku a sekundovou ručičku. Jakmile je aplikace SimpleClock spuštěná, vyvolá metodu AnalogClockFace.draw() každou sekundu, viz zde: /** * Called by the parent container when the display is being drawn. */ public override function draw():void { // stores the current date and time in an instance variable currentTime = new Date(); showTime(currentTime); } Tato metoda ukládá aktuální čas do proměnné, takže čas se nemůže během překreslování ručiček hodin změnit. Dále vyvolá metodu showTime() k zobrazení ručiček, jak můžete vidět zde: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 137 Práce s daty a časy /** * Displays the given Date/Time in that good old analog clock style. */ public function showTime(time:Date):void { // gets the time values var seconds:uint = time.getSeconds(); var minutes:uint = time.getMinutes(); var hours:uint = time.getHours(); // multiplies by 6 to get degrees this.secondHand.rotation = 180 + (seconds * 6); this.minuteHand.rotation = 180 + (minutes * 6); // Multiply by 30 to get basic degrees, then // add up to 29.5 degrees (59 * 0.5) // to account for the minutes. this.hourHand.rotation = 180 + (hours * 30) + (minutes * 0.5); } Tato metoda nejprve vyjme hodnoty pro hodiny, minuty a sekundy aktuálního času. Poté použije tyto hodnoty k výpočtu úhlu jednotlivých ručiček. Protože sekundová ručička se otočí kolem dokola každých 60 sekund, posune se každou sekundu o 6 stupňů (360/60). Minutová ručička se posune o stejný úhel každou minutu. Hodinová ručička se aktualizuje každou minutu, aby bylo během ubíhajících minut vidět, že se pohybuje. Posune se každou hodinu o 30 stupňů (360/12), ale také se posune každou minutu o půl stupně (30 stupňů děleno 60 minutami). 138 Kapitola 7: Práce s řetězci Třída String obsahuje metody, které umožňují pracovat s textovými řetězci. Řetězce jsou důležité pro práci s mnoha objekty. Metody popsané v této kapitole jsou užitečné pro práci s řetězci používanými v objektech jako TextField, StaticText, XML, ContextMenu a FileReference. Řetězce jsou posloupnosti znaků. Jazyk ActionScript 3.0 podporuje znaky ASCII a Unicode. Základy řetězců Úvod do práce s řetězci V programátorském slangu je řetězec textovou hodnotou - posloupností písmen, čísel a dalších znaků spojených do jedné hodnoty. Například tato řádka kódu vytváří proměnnou s datovým typem String a přiřazuje této proměnné hodnotu literálového řetězce: var albumName:String = "Three for the money"; Jak ukazuje tento příklad, v jazyce ActionScript můžete označit hodnotu řetězce obklopením textu dvojitými nebo jednoduchými uvozovkami. Zde jsou další příklad řetězců: "Hello" "555-7649" "http://www.adobe.com/" Při každé manipulaci s textem v jazyce ActionScript pracujete s hodnotou řetězce. Řetězec jazyka ActionScript je datovým typem, který můžete použít pro práci s textovými hodnotami. Instance String jsou často používány pro vlastnosti, parametry metod atd. v mnoha jiných třídách jazyka ActionScript. Běžné úlohy pro práci s řetězci Následující úlohy jsou běžné úlohy související s řetězci, které jsou probírány v této kapitole: • Vytváření objektů String • Práce se zvláštními znaky, například CR (návrat vozíku), Tab a znaky, které nejsou na klávesnici • Měření délky řetězce • Izolování jednotlivých znaků v řetězci • Spojování řetězců • Porovnávání řetězců • Vyhledání, extrahování a nahrazení částí řetězce • Převedení řetězce na velká nebo malá písmena Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • ASCII: systém představující textové znaky a symboly v počítačových programech. Systém ASCII podporuje 26znakovou anglickou abecedu, plus omezenou sadu dodatečných znaků. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 139 Práce s řetězci • Znak: nejmenší jednotka textových dat (jedno písmeno nebo symbol). • Zřetězení: spojení několika řetězcových hodnot přidáním jedné na konec druhé a vytvoření nové hodnoty řetězce. • Prázdný řetězec: řetězec neobsahující žádný text, prázdné znaky nebo jiné znaky, zapsaný jako "". Hodnota prázdného řetězce se odlišuje od proměnné String s hodnotou null - proměnná String s hodnotou null je proměnná, která nemá přiřazenou instanci String, zatímco prázdný řetězec má instanci s hodnotou neobsahující žádný znak. • Řetězec: textová hodnota (posloupnost znaků). • Řetězcová konstanta (nebo „literálový řetězec“): hodnota řetězce zapsaná explicitně v kódu jako textová hodnota v dvojitých nebo jednoduchých uvozovkách. • Podřetězec: řetězec, který je součástí jiného řetězce. • Unicode: standardní systém představující textové znaky a symboly v počítačových programech. Systém Unicode umožňuje použití jakéhokoliv znaku v kterémkoliv systému zápisu. Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. Protože příklady kódu v této kapitole se primárně zabývají zpracováním textu, testování příklad bude zahrnovat sledování hodnot proměnných použitých na příkladech, buď zapisováním hodnot do instancí textových polí na plochu nebo používání funkce trace() k tisku hodnot do výstupního panelu. Tyto techniky jsou podrobně popsány v části „Testování příkladů kódu v této kapitole“ na stránce 34. Vytváření řetězců Třída String se používá pro vyjádření dat řetězce (textového) v jazyce ActionScript 3.0. Jazyk ActionScript podporuje v řetězcích znaky ASCII a Unicode. Nejjednodušší způsob, jak vytvořit řetězec, je použít řetězcovou konstantu. Chcete-li deklarovat řetězcovou konstantu, použijte rovné dvojité uvozovky (") nebo jednoduché uvozovky ('). Například následující dva řetězce jsou rovnocenné: var str1:String = "hello"; var str2:String = 'hello'; Můžete také deklarovat řetězec pomocí operátoru new a to takto: var str1:String = new String("hello"); var str2:String = new String(str1); var str3:String = new String(); // str3 == "" Následující dva řetězce jsou rovnocenné: var str1:String = "hello"; var str2:String = new String("hello"); Chcete-li použít jednoduché uvozovky (') v řetězcové konstantě definované v jednoduchých uvozovkách ('), použijte únikový znak zpětné lomítko (\). Chcete-li použít dvojité uvozovky (") v řetězcové konstantě definované v dvojitých uvozovkách ("), použijte únikový znak zpětné lomítko (\). Následující dva řetězce jsou rovnocenné: var str1:String = "That's \"A-OK\""; var str2:String = 'That\'s "A-OK"'; Můžete si vybrat, zda použijete jednoduché uvozovky nebo dvojité uvozovky na základě kterýchkoliv jednoduchých nebo dvojitých uvozovek existujících v řetězcové konstantě, jako v následujícím případu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 140 Práce s řetězci var str1:String = "ActionScript <span class='heavy'>3.0</span>"; var str2:String = '<item id="155">banana</item>'; Mějte na paměti, že jazyk ActionScript rozlišuje mezi rovnými jednoduchými uvozovkami (') a levou či pravou jednoduchou uvozovkou (' nebo ' ). Totéž platí pro dvojité uvozovky. Pro vymezení řetězcových konstant použijte rovné uvozovky. Při vkládání textu z jiného zdroje do jazyka ActionScript nezapomeňte použít správné znaky. Jak ukazuje následující tabulka, můžete použít znak zpětného lomítka (\) k definování jiných znaků v řetězcové konstantě. Posloupnost pro změnu Znak \b Backspace \f Posuv formuláře \n Nový řádek \r Návrat vozíku \t Tabulátor \unnnn Znak Unicode s kódem znaku specifikovaný šestnáctkovým číslem nnnn; například \u263a je znak smajlíku. \\xnn Znak ASCII s kódem znaku specifikovaný šestnáctkovým číslemnn \' Jednoduché uvozovky \" Dvojité uvozovky \\ Znak jednoduchého zpětného lomítka Vlastnost length Každý řetězec má vlastnost length, která je rovna počtu znaků v řetězci. var str:String = "Adobe"; trace(str.length); // output: 5 Prázdný řetězec a řetězec null mají oba délku 0, jak ukazuje následující příklad: var str1:String = new String(); trace(str1.length); // output: 0 str2:String = ''; trace(str2.length); // output: 0 Práce se znaky v řetězci Každý znak v řetězci má pozici indexu v řetězci (celočíselná hodnota). Pozice indexu prvního znaku je 0. Například v následujících řetězcích má znak y polohu 0 a znak w polohu 5: "yellow" Jednotlivé znaky v různých pozicích řetězce můžete prověřit pomocí metody charAt() a charCodeAt(), jako v následujícím příkladu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 141 Práce s řetězci var str:String = "hello world!"; for (var i:int = 0; i < str.length; i++) { trace(str.charAt(i), "-", str.charCodeAt(i)); } Když tento kód spustíte, získáte následující výsledek: h e l l o w o r l d ! - 104 - 101 - 108 - 108 - 111 32 - 119 - 111 - 114 - 108 - 100 - 33 Můžete také použít kódy znaků a definovat řetězec pomocí metody fromCharCode(), jako na následujícím příkladu: var myStr:String = String.fromCharCode(104,101,108,108,111,32,119,111,114,108,100,33); // Sets myStr to "hello world!" Porovnávání řetězců K porovnávání řetězců můžete použít následující operátory: <, <=, !=, ==, => a >. Tyto operátory lze používat s podmínečnými příkazy, například if a while, jak je vidět na následujícím příkladu: var str1:String = "Apple"; var str2:String = "apple"; if (str1 < str2) { trace("A < a, B < b, C < c, ..."); } Pokud používáte tyto operátory s řetězci, jazyk ActionScript zvažuje hodnotu kódu každého znaku v řetězci, porovnává znaky zleva doprava, jako na následujícím příkladu: trace("A" < "B"); // true trace("A" < "a"); // true trace("Ab" < "az"); // true trace("abc" < "abza"); // true Použijte operátory == a != k vzájemnému porovnání řetězců a k porovnání řetězců s ostatními typy objektů, jako na následujícím příkladu: var str1:String = "1"; var str1b:String = "1"; var str2:String = "2"; trace(str1 == str1b); // true trace(str1 == str2); // false var total:uint = 1; trace(str1 == total); // true PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 142 Práce s řetězci Získání vyjádření řetězce z jiných objektů Vyjádření String můžete získat pro kterýkoliv objekt. Všechny objekty mají pro tento účel metodu toString(): var n:Number = 99.47; var str:String = n.toString(); // str == "99.47" Když použijete operátor zřetězení + s kombinací objektů String a objektů, které řetězcem nejsou, nemusíte používat metodu toString(). Podrobnosti o zřetězení, viz následující kapitola. Globální funkce String() vrací stejnou hodnotu pro daný objekt jako hodnotu vrácenou objektem volajícím metodu toString(). Zřetězení řetězců Zřetězení řetězců znamená převzetí dvou řetězců a jejich spojení za sebou do jednoho. Například můžete použít operátor + a zřetězit dva řetězce: var str1:String = "green"; var str2:String = "ish"; var str3:String = str1 + str2; // str3 == "greenish" Následující příklad ukazuje, že můžete také použít operátor += a dosáhnout stejného výsledku: var str:String = "green"; str += "ish"; // str == "greenish" Kromě toho třída String zahrnuje metodu concat(), kterou lze použít takto: var str1:String = "Bonjour"; var str2:String = "from"; var str3:String = "Paris"; var str4:String = str1.concat(" ", str2, " ", str3); // str4 == "Bonjour from Paris" Pokud použijete operátor + (nebo operátor +=) s objektem String a objektem, který není řetězec, jazyk ActionScript automaticky převede neřetězcový objekt na objekt String a vyhodnotí výraz, jak je vidět na následujícím příkladu: var str:String = "Area = "; var area:Number = Math.PI * Math.pow(3, 2); str = str + area; // str == "Area = 28.274333882308138" Následující příklad ukazuje, že však můžete použít závorky pro seskupení a poskytnout tak kontext pro operátor +: trace("Total: $" + 4.55 + 1.45); // output: Total: $4.551.45 trace("Total: $" + (4.55 + 1.45)); // output: Total: $6 Vyhledání podřetězců a vzorků v řetězci Podřetězce jsou znaky posloupnosti v řetězci: Například řetězec "abc" má následující podřetězce:"", "a", "ab", "abc", "b", "bc", "c". Můžete použít metody jazyka ActionScript a lokalizovat podřetězec řetězce. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 143 Práce s řetězci Vzorky jsou definovány v jazyce ActionScript řetězci nebo regulárními výrazy. Například následující regulární výraz definuje specifický vzorek - písmena A, B a C následovaná číslicí (dopředná lomítka jsou oddělovači regulárního výrazu): /ABC\d/ Jazyk ActionScript zahrnuje metody pro vyhledání vzorků v řetězcích a pro náhradu nalezených shod s náhradním podřetězcem. Tyto metody jsou popsané v následujících kapitolách. Regulární výrazy mohou definovat komplikované vzorky. Další informace, viz „Používání regulárních výrazů“ na stránce 202. Vyhledání podřetězce podle polohy znaku Metody substr() a substring() jsou obdobné. Obě vracejí podřetězec řetězce. Obě používají dva parametry. V obou metodách je první parametr pozicí počátečního znaku v daném řetězci. V metodě substr() je však druhý parametr délka vraceného podřetězce a v metodě substring() je druhý parametr polohou znaku na konci podřetězce (není součástí vraceného řetězce). Tento příklad ukazuje rozdíl mezi těmito dvěma metodami: var str:String = "Hello from Paris, Texas!!!"; trace(str.substr(11,15)); // output: Paris, Texas!!! trace(str.substring(11,15)); // output: Pari Metoda slice() pracuje podobně jako metoda substring(). Pokud jsou parametry vzaty dvě nezáporné celočíselné hodnoty, pracují metody shodně. Metoda slice() však může vzít jako parametry záporné celočíselné hodnoty; v tomto případě je poloha znaku vzata od konce řetězce, jak je vidět na následující příkladu: var str:String = "Hello from Paris, trace(str.slice(11,15)); // output: trace(str.slice(-3,-1)); // output: trace(str.slice(-3,26)); // output: trace(str.slice(-3,str.length)); // trace(str.slice(-8,-3)); // output: Texas!!!"; Pari !! !!! output: !!! Texas Nezáporné a záporné celočíselné hodnoty můžete zkombinovat jako parametry metody slice(). Vyhledání polohy znaku odpovídajícího podřetězce Můžete použít metody indexOf() a lastIndexOf() a lokalizovat odpovídající podřetězce v rámci řetězce, jak ukazuje následující příklad: var str:String = "The moon, the stars, the sea, the land"; trace(str.indexOf("the")); // output: 10 Povšimněte si, že metoda indexOf() rozlišuje malá a velká písmena. Můžete specifikovat druhý parametr a definovat tak pozici indexu v řetězci, ze kterého má začít hledání a to takto: var str:String = "The moon, the stars, the sea, the land" trace(str.indexOf("the", 11)); // output: 21 Metoda lastIndexOf() vyhledává poslední výskyt podřetězce v řetězci. var str:String = "The moon, the stars, the sea, the land" trace(str.lastIndexOf("the")); // output: 30 Pokud zahrnete druhý parametr do metody lastIndexOf(), hledání proběhne z této pozice indexu v řetězci směrem zpět (zprava doleva): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 144 Práce s řetězci var str:String = "The moon, the stars, the sea, the land" trace(str.lastIndexOf("the", 29)); // output: 21 Vytváření pole podřetězců rozdělené oddělovacím znakem Metodu split() můžete použít pro vytvoření pole podřetězců, které je rozděleno na základě oddělovacího znaku. Například můžete rozdělit řetězec oddělený čárkou nebo tabulátorem do několika řetězců. Následující příklad ukazuje způsob rozdělení pole do podřetězců se znakem ampersand (&) jako oddělovacím znakem: var queryStr:String = "first=joe&last=cheng&title=manager&StartDate=3/6/65"; var params:Array = queryStr.split("&", 2); // params == ["first=joe","last=cheng"] Druhý parametr metody split(), který je volitelný, definuje maximální velikost pole, které je vráceno. Jako oddělovací znak můžete použít regulární výraz: var str:String = "Give me\t5." var a:Array = str.split(/\s+/); // a == ["Give","me","5."] Další informace naleznete v kapitole „Používání regulárních výrazů“ na stránce 202 a Referenční příručce jazyka ActionScript 3.0 a jeho součástí. Vyhledání vzorků v řetězcích a nahrazení podřetězců Třída String zahrnuje následující metody pro práci se vzorky v řetězcích: • Metody match() a search() použijte k vyhledání podřetězců, které odpovídají vzorku. • Metodu replace() použijte k vyhledání podřetězce, který odpovídá vzorku a nahraďte je specifikovaným podřetězcem. Tyto metody jsou popsané v následujících kapitolách. Můžete použít řetězce nebo regulární výrazy k definování vzorků použitých v těchto metodách. Další informace o regulárních výrazech naleznete v kapitole „Používání regulárních výrazů“ na stránce 202. Vyhledání odpovídajících podřetězců Metoda search() vrací pozici indexu prvního podřetězce, který odpovídá danému vzorku, jak je vidět na tomto příkladu: var str:String = "The more the merrier."; // (This search is case-sensitive.) trace(str.search("the")); // output: 9 Můžete také použít regulární výrazy a definovat odpovídající vzorek, jako na následujícím příkladu: var pattern:RegExp = /the/i; var str:String = "The more the merrier."; trace(str.search(pattern)); // 0 Výstup z metody trace() je 0, protože první znak v řetězci má polohu indexu 0. Příznak i je nastaven v regulárním výrazu, takže hledání nerozlišuje velká a malá písmena. Metoda search() vyhledá pouze jednu shodu a vrací počáteční polohu indexu, i když je příznak g (globální) nastaven na regulární výraz. Následující příklad ukazuje komplikovanější regulární výraz a to takový, který odpovídá řetězci v dvojitých uvozovkách. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 145 Práce s řetězci var pattern:RegExp = /"[^"]*"/; var str:String = "The \"more\" the merrier."; trace(str.search(pattern)); // output: 4 str = "The \"more the merrier."; trace(str.search(pattern)); // output: -1 // (Indicates no match, since there is no closing double quotation mark.) Metoda match() pracuje podobným způsobem. Vyhledává odpovídající podřetězec. Když však použijete globální příznak ve vzorku regulárního výrazu, jako na následujícím příklad, metoda match() vrátí pole odpovídajících podřetězců: var str:String = "[email protected], [email protected]"; var pattern:RegExp = /\w*@\w*\.[org|com]+/g; var results:Array = str.match(pattern); Pole results je nastaveno následovně: ["[email protected]","[email protected]"] Další informace o regulárních výrazech naleznete v kapitole „Používání regulárních výrazů“ na stránce 202„Používání regulárních výrazů“ na stránce 202. Náhrada odpovídajících podřetězců Metodu replace() můžete použít k vyhledání specifikovaného vzorku v řetězci a nahradit shody se specifikovaným řetězcem, jak ukazuje následující příklad: var str:String = "She sells seashells by the seashore."; var pattern:RegExp = /sh/gi; trace(str.replace(pattern, "sch")); //sche sells seaschells by the seaschore. Na tomto příkladu si povšimněte, že odpovídající řetězce nerozlišují velká a malá písmena, protože příznak i (ignoreCase) je nastaven v regulárním výrazu a několik shod je nahrazeno proto, že je nastaven příznak g (global). Další informace, viz „Používání regulárních výrazů“ na stránce 202. Následující nahrazující kódy $ můžete zahrnout do nahrazujícího řetězce. Nahrazující text zobrazený v následující tabulce se vloží namísto nahrazujícího kódu $: $ Kód Nahrazující text $$ $ $& Odpovídající dílčí řetězec. $` Část řetězce, který předchází odpovídajícímu dílčímu řetězci. Tento kód používá levou jednoduchou uvozovku (`), nikoliv rovnou jednoduchou uvozovku (') nebo levou zatočenou jednoduchou uvozovku (' ). $' Část řetězce, který následuje po odpovídajícím dílčím řetězci. Tento kód používá rovnou jednoduchou uvozovku (' ). $n Zachycená, vsunutá n-tá skupina odpovídá, kde n je jednoduché číslo 1-9 a $n není následováno desetinnou číslicí. $nn Zachycená, vsunutá n-tá skupina odpovídá, kde nn je dvoumístné desetinné číslo 01-99. Pokud je nn-tý záchyt nedefinovaný, je nahrazující text prázdný řetězec. V následujícím příkladu se ukazuje použití nahrazujících kódů $1 a $2, které znázorňují první a druhou vyhovující zachycenou skupinu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 146 Práce s řetězci var str:String = "flip-flop"; var pattern:RegExp = /(\w+)-(\w+)/g; trace(str.replace(pattern, "$2-$1")); // flop-flip Jako druhý parametr metody replace() můžete také použít funkci. Odpovídající text je nahrazen vrácenou hodnotou funkce. var str:String = "Now only $9.95!"; var price:RegExp = /\$([\d,]+.\d+)+/i; trace(str.replace(price, usdToEuro)); function usdToEuro(matchedSubstring:String, capturedMatch1:String, str:String):String { var usd:String = capturedMatch1; usd = usd.replace(",", ""); var exchangeRate:Number = 0.853690; var euro:Number = parseFloat(usd) * exchangeRate; const euroSymbol:String = String.fromCharCode(8364); return euro.toFixed(2) + " " + euroSymbol; } index:int, Když funkci použijete jako druhý parametr metody replace(), jsou funkci předány následující argumenty: • Vyhovující část řetězce. • Jakákoliv zachycená vsunutá skupina odpovídá. Počet argumentů předaných tímto způsobem se bude měnit v závislosti na počtu vsunutých shod. Můžete určit počet vsunutých shod ověřením arguments.length - 3uvnitř kódu funkce. • Indexová pozice v řetězci, kde začíná shoda. • Úplný řetězec. Převod řetězců mezi velkými a malými písmeny Následující příklad ukazuje, jak metoda toLowerCase() a toUpperCase() převádějí abecední znaky v řetězci na malá, respektive na velká písma: var str:String = "Dr. Bob Roberts, #9." trace(str.toLowerCase()); // dr. bob roberts, #9. trace(str.toUpperCase()); // DR. BOB ROBERTS, #9. Po vykonání těchto metod zůstává zdrojový řetězec nezměněný. Chcete-li transformovat zdrojový řetězec, použijte následující kód: str = str.toUpperCase(); Tyto metody jsou funkční s rozšířenými znaky, nikoliv jednoduše s a–z a A–Z: var str:String = "José Barça"; trace(str.toUpperCase(), str.toLowerCase()); // JOSÉ BARÇA josé barça PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 147 Práce s řetězci Příklad: kresba ASCII Tato kresba ASCII ukazuje několik funkcí, které lze s třídou String v jazyce ActionScript 3.0 použít, včetně následujícího: • Metoda split() třídy String se používá pro extrahování hodnot z řetězce odděleného znaky (informace o obrázku v textovém souboru odděleném tabulátoru). • K změně prvního písmena každého slova v názvech souborů na velké se používá několik technik zpracování, včetně split(), zřetězení a extrahování části řetězce pomocí substring() a substr(). • Metoda getCharAt() se používá k získání jednoho znaku z řetězce (pro stanovení znaku ASCII odpovídajícího hodnotě stupnice šedé bitmapy). • Zřetězení řetězce se používá pro sestavení vyjádření kresby ASCII obrazu po jednotlivých znacích. Termín kresba ASCII popisuje textová vyjádření obrázku, ve kterém se obrázek vykreslí ve formě mřížky znaků písma se stejnou roztečí, například Courier New. Následující obrázek ukazuje příklad kresby ASCII vytvořené aplikací. Verze kresby ASCII je zobrazena vpravo. Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace ASCIIArt naleznete ve složce Samples/AsciiArt. Aplikace sestává z následujících souborů: Soubor Popis AsciiArtApp.mxml Hlavní aplikační soubor v aplikaci Flash (FLA) nebo Flex (MXML) nebo AsciiArtApp.fla com/example/programmingas3/asciiArt/AsciiArtBuilder.as Třída poskytující hlavní funkci aplikace, včetně metadat extrahování aplikace z textového soubor, načítající obrázky a řídicí proces převodu obrázku a textu. com/example/programmingas3/asciiArt/BitmapToAsciiConverter.as Třída zajišťující metodu parseBitmapData() pro převod obrazových dat do verze String. com/example/programmingas3/asciiArt/Image.as Třída zastupující načtený bitmapový obraz. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 148 Práce s řetězci Soubor Popis com/example/programmingas3/asciiArt/ImageInfo.as Třída zastupující metadata pro kresbu obrazu ASCII (například název, URL obrazového souboru atd.). obraz/ Složka obsahující obrazy používané aplikací. txt/ImageData.txt Textový soubor oddělený tabulátory, obsahující informace o obrázcích, které mají být načteny aplikací. Extrahování hodnot oddělených tabulátorem Tento příklad používá běžný postup ukládání dat aplikace odděleně od samotné aplikace; tímto způsobem není nutné soubory SWF opakovaně vytvářet, pokud se data změní (například pokud přidáte jiný obrázek nebo se změní název obrázku). V tomto případě jsou obrazová metadata, včetně názvu obrázku, URL stávajícího obrazového souboru a některé hodnoty použité pro manipulaci s obrazem, uložena v textovém souboru (soubor txt/ImageData.txt projektu). Obsahy textových souborů jsou následující: FILENAMETITLEWHITE_THRESHHOLDBLACK_THRESHHOLD FruitBasket.jpgPear, apple, orange, and bananad810 Banana.jpgA picture of a bananaC820 Orange.jpgorangeFF20 Apple.jpgpicture of an apple6E10 Soubor používá specifický formát oddělený tabulátorem. První řádek je záhlaví. Zbývající řádky obsahují následující data pro každou bitmapu, kterou je nutné načíst: • Název souboru bitmapy. • Zobrazovaný název bitmapy. • Prahová hodnota bílé a černé pro bitmapy. To jsou šestnáctkové hodnoty, nad a pod kterými obrazový bod bude považován za zcela bílý nebo zcela černý. Jakmile se aplikace spustí, třída AsciiArtBuilder se načte a analyzuje obsah textového souboru, aby mohla vytvořit „svazek“ obrázků, které zobrazí, a to pomocí následujícího kódu z metody parseImageInfo() třídy AsciiArtBuilder: var lines:Array = _imageInfoLoader.data.split("\n"); var numLines:uint = lines.length; for (var i:uint = 1; i < numLines; i++) { var imageInfoRaw:String = lines[i]; ... if (imageInfoRaw.length > 0) { // Create a new image info record and add it to the array of image info. var imageInfo:ImageInfo = new ImageInfo(); // Split the current line into values (separated by tab (\t) // characters) and extract the individual properties: var imageProperties:Array = imageInfoRaw.split("\t"); imageInfo.fileName = imageProperties[0]; imageInfo.title = normalizeTitle(imageProperties[1]); imageInfo.whiteThreshold = parseInt(imageProperties[2], 16); imageInfo.blackThreshold = parseInt(imageProperties[3], 16); result.push(imageInfo); } } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 149 Práce s řetězci Celý obsah textového souboru je obsažený v jedné instanci String, vlastnosti _imageInfoLoader.data. Pomocí metody split() se znakem nové řádky ("\n") jako parametrem je instance String rozdělena do pole Array (lines), jehož prvky jsou jednotlivé řádky textového souboru. Dále kód využívá cyklus k práci s každou řádkou (kromě první, protože ta obsahuje pouze záhlaví, spíše než stávající obsah). Uvnitř cyklu je použita metoda split() znovu k rozdělení obsahu jedné řádky do souboru hodnotu (objekt Array nazvaný imageProperties). Parametr použitý s metodou split() je v tomto případě znak tabulátoru ("\t"), protože hodnoty v každé řádce jsou rozděleny znakem tabulátoru. Použití metod String k normalizování názvů obrázků Jedním z rozhodnutí při návrhu této aplikace je to, že všechny názvy obrázků jsou zobrazeny pomocí standardního formátu, s prvním písmenem každého slova velkým (kromě několika slov, které v anglických názvech obvykle nejsou s velkými písmeny). Aplikace naformátuje názvy, když jsou extrahovány z textového souboru, spíše než aby předpokládala, že textový soubor obsahuje správně naformátované názvy. V předchozím kódu byla použita následující řádka, jako součást extrahování jednotlivých hodnot metadat obrázku: imageInfo.title = normalizeTitle(imageProperties[1]); V tomto kódu je název obrázku z textového souboru předán metodou normalizeTitle() předtím, než je uložen v objektu ImageInfo. private { var var for { function normalizeTitle(title:String):String words:Array = title.split(" "); len:uint = words.length; (var i:uint; i < len; i++) words[i] = capitalizeFirstLetter(words[i]); } return words.join(" "); } Tato metoda používá metodu split() k rozdělení názvu do jednotlivých slov (oddělené mezerou), předává každé slovo metodě capitalizeFirstLetter() a pak použije metodu join() třídy Array ke kombinování slov zpět do jednoho řetězce. Jak naznačuje název, metoda capitalizeFirstLetter() provede změnu prvního písmena každého slova na velké: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 150 Práce s řetězci /** * Capitalizes the first letter of a single word, unless it's one of * a set of words that are normally not capitalized in English. */ private function capitalizeFirstLetter(word:String):String { switch (word) { case "and": case "the": case "in": case "an": case "or": case "at": case "of": case "a": // Don't do anything to these words. break; default: // For any other word, capitalize the first character. var firstLetter:String = word.substr(0, 1); firstLetter = firstLetter.toUpperCase(); var otherLetters:String = word.substring(1); word = firstLetter + otherLetters; } return word; } U následujících slov není v angličtině počáteční znak každého slova v názvu uveden velkým písmenem: „and“, „the“, „in“, „an“, „or“, „at“, „of“, nebo „a“ (to je zjednodušená verze pravidel). Pro vykonání této logiky kód nejprve použije příkaz switch je kontrole, zda slovo je jedno ze slov, které by nemělo mít první písmeno velké. Pokud ani, kód jednoduše vyskočí z příkazu switch. Na druhou stranu, pokud slovo má mít první písmeno velké, je to provedeno několika kroky takto: 1 První písmeno slova je extrahováno pomocí metody substr(0, 1), která extrahuje podřetězec začínající znakem na indexu 0 (první písmeno v řetězci, jak je uvedeno prvním parametrem 0). Podřetězec bude jeden znak v délce (označeno druhým parametrem 1). 2 Tento znak bude převeden na velké písmeno pomocí metody toUpperCase(). 3 Zbývající znaky původního slova jsou extrahovány pomocí metody substring(1), která extrahuje podřetězec začínající na indexu 1 (druhé písmeno) až na konec řetězce (stanoveno opuštěním druhého parametru metody substring()). 4 Závěrečné slovo je vytvořeno kombinací prvního písmena nově převedeného na velké, se zbývajícími písmeny pomocí metody zřetězení: firstLetter + otherLetters. Generování textu kresby ASCII Třída BitmapToAsciiConverter poskytuje funkci převedení bitmapy do textového vyjádření ASCII. Tento proces je prováděn metodou parseBitmapData(), která je zde částečně popsána: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 151 Práce s řetězci var result:String = ""; // Loop through the rows of pixels top to bottom: for (var y:uint = 0; y < _data.height; y += verticalResolution) { // Within each row, loop through pixels left to right: for (var x:uint = 0; x < _data.width; x += horizontalResolution) { ... // Convert the gray value in the 0-255 range to a value // in the 0-64 range (since that's the number of "shades of // gray" in the set of available characters): index = Math.floor(grayVal / 4); result += palette.charAt(index); } result += "\n"; } return result; Tento kód nejprve definuje instanci String pojmenovanou result, která bude použita pro vytvoření bitmapového obrazu ve verzi kresby ASCII. Dále dojde k opakování s jednotlivými obrazovými body zdrojového bitmapového obrazu. Pomocí několika technik pro manipulaci s barvami (zde jsou pro zestručnění vynechány), převede červenou, zelenou a modrou barvu z příslušných hodnot jednotlivých obrazových bodů do jediné škály šedé (číslo od 0 do 255). Kód pak podělí tuto hodnotu 4 (jak je znázorněno) a převede ji do hodnoty stupnice 0-63, která je uložena v proměnné index. (Stupnice 0-63 se používá proto, že „paleta“ dostupných znaků ASCII použitých v aplikaci obsahuje 64 hodnot.) Paleta znaků je definována jako instance String v třídě BitmapToAsciiConverter. // The characters are in order from darkest to lightest, so that their // position (index) in the string corresponds to a relative color value // (0 = black). private static const palette:String = "@#$%&8BMW*mwqpdbkhaoQ0OZXYUJCLtfjzxnuvcr[]{}1()|/?Il!i><+_~-;,. "; Protože proměnná index definuje, který znak ASCII v paletě odpovídá stávajícímu obrazovému bodu v bitmapovém obrázku, tento znak bude načten z palette String pomocí metody charAt(). Poté dojde k připojení k result instance String pomocí operátoru přiřazení zřetězení (+=). Kromě toho na konci každé řádky obrazových bodů je znak nové řádky zřetězen na konec result String, což vynutí zalomení řádky a vytvoření nové řádky znaků „obrazových bodů“. 152 Kapitola 8: Práce s poli Pole vám umožňují ukládat více hodnot do jediné struktury dat. Můžete použít jednoduchá indexovaná pole, která uchovávají hodnoty pomocí pevných indexů s pořadovými celými čísly nebo složitá asociativní pole, která uchovávají hodnoty pomocí libovolných klíčů. Pole mohou být také vícedimenzionální, mohou obsahovat prvky, které jsou také pole. Můžete také použít Vector pro pole, jehož prvky jsou všechny instance stejného datového typu. Tato kapitola uvádí způsob vytváření a práce s různými typy polí. Základní informace o polích Úvod do práce s poli Během programovaní budete často pracovat se souborem položek více než s jediným objektem. Například v aplikaci přehrávače hudby si můžete přát vytvořit seznam písní čekajících k přehrání. Pravděpodobně si nebudete přát vytvořit samostatnou proměnnou pro každou píseň na seznamu. Oceníte všechny objekty Song společně v jednom balíku a možnost pracovat s nimi jako se skupinou. Pole je programovací element, který se chová jako kontejner pro množinu položek, například pro seznam písní. Všechny položky v poli jsou většinou instance stejné třídy. Tato shoda ale není v jazyce ActionScript požadavkem. Jednotlivé položky v poli se nazývají elementy pole. Pole si lze představit jako zásuvku pro proměnné. Proměnné lze přidat jako elementy v poli, což se podobá umístění složky do zásuvky. S polem můžete pracovat jako s jedinou proměnnou (jako byste celou zásuvku přenesli na jiné místo). S proměnnými můžete pracovat jako se skupinou (jako procházení složek a vyhledávání určité informace). K proměnným můžete také přistupovat jednotlivě (jako otevření zásuvky a vybrání jediné složky). Představte si například vytvoření aplikace přehrávače hudby, ve kterém si uživatel může vybrat více písní a přidat je do seznamu přehrávání. Ve svém kódu jazyka ActionScript máte metodu pojmenovanou addSongsToPlaylist(), která přijímá jediné pole jako parametr. Bez ohledu na počet písní, které si přejete přidat do seznamu (několik, mnoho nebo pouze jednu), voláte metodu addSongsToPlaylist() pouze jednou a předáte jí pole obsahující objekty Song. Uvnitř metody addSongsToPlaylist() můžete pomocí opakování procházet elementy pole (písně) jeden po druhým a přidat je do seznamu přehrávání. Nejběžnějším typem pole jazyka ActionScript je indexované pole. V indexovaném poli je každá položka uložena v několika slotech (nazvaných index). K položkám můžete získat přístup pomocí čísla, které slouží jako adresa. Indexovaná pole fungují dobře pro většinu programovacích potřeb. Třída Array je běžná třída, která je použita k reprezentaci indexovaného pole. Indexované pole je často použito k uložení více položek stejného typu (objekty, které jsou instancemi stejné třídy). Třída Array nemá žádné prostředky k omezení typu položek, které obsahuje. Třída Vector je typ indexovaného pole, ve kterém mají všechny položky v jednom poli stejný typ. Použitím instance Vector namísto instance Array můžete získat lepší výkon a jiné výhody. Třída Vector je dostupná od verzí Flash Player 10 a Adobe AIR 1.5. Speciální použití indexovaného pole je multidimenzionální pole. Multidimenzionální pole je indexované pole, jehož elementy jsou indexovaná pole (která obsahují další elementy). Dalším typem pole je asociativní pole, které k určení jednotlivých elementů používá řetězec key namísto numerického indexu. Jazyk ActionScript 3.0 obsahuje také třídu Dictionary, která představuje slovník. Slovník je pole, které vám umožňuje použít jakýkoliv typ objektu jako klíč k rozlišení elementů. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 153 Práce s poli Běžné úlohy polí V této kapitole jsou popsány následující běžné činnosti pro práci s poli: • Vytvoření indexovaných polí pomocí třídy Array a třídy Vector • Přidávání a odstraňování elementů polí • Třídění elementů polí • Vyjímání částí pole • Práce s asociativními poli a slovníky • Práce s multidimenzionálními poli • Kopírování elementů pole • Vytváření podtřídy pole Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Pole: objekt, který slouží jako kontejner k seskupení více objektů • Operátor přístupu k poli ([]): dvojice hranatých závorek obklopujících index nebo klíč, který jedinečně identifikuje element pole. Tato syntaxe je použita po názvu proměnné pole k určení jediného elementu pole spíše než celého pole. • Asociativní pole: pole, které používá klíče řetězců k určení jednotlivých elementů • Základní typ: datový typ daného objektu, který instance Vector může uložit • Slovník: pole, jehož položky se skládají z dvojice objektů, z klíče a hodnoty. Klíč je použit namísto numerického indexu k určení jednotlivých elementů. • Element: položka v poli • Index: numerická „adresa“ použitá k určení jednotlivých elementů v indexovaném poli • Indexované pole: standardní typ pole, které ukládá každý element v očíslované pozici a k určení jednotlivých elementů používá číslo (index) • Klíč: řetězec nebo objekt použitý k určení jednotlivých elementů v asociativním poli nebo slovníku • Multidimenzionální pole: pole obsahující položky, které jsou pole spíše než jednotlivé hodnoty • T: standardní konvence, která je použita v této dokumentaci k reprezentaci základního typu instance Vector, ať už je daným základním typem cokoliv. T konvence je použita k reprezentaci názvu třídy, viz popis parametru Type. („T” znamená „typ“, jako ve spojení „datový typ“.) • Parametr typu: syntaxe používaná s názvem třídy Vector k určení základního typu vektoru (datového typu objektů, které uchovává). Syntaxe se skládá z tečky (.), poté z názvu datového typu obklopeného lomenými závorkami (<>). Dohromady vše vypadá následovně: Vector.<T>. V této dokumentaci je třída určená v parametru typu znázorněna genericky jako T. • Vektor: typ pole jehož všechny elementy jsou instance stejného datového typu PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 154 Práce s poli Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. V podstatě všechny výpisy kódů uvedené v této kapitole zahrnují příslušné volání funkce trace(). Návod na vyzkoušení kódů uvedených v této kapitole: 1 Ve vývojovém nástroji Flash vytvořte prázdný dokument 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Spusťte program pomocí příkazu Ovládání > Testovat film. Výsledky funkcetrace() se zobrazí v panelu Výstup. Tyto a další postupy pro testování vzorových výpisů kódů jsou podrobněji popsány v sekci „Testování příkladů kódu v této kapitole“ na stránce 34. Indexovaná pole Indexovaná pole uchovávají sérii jedné nebo více hodnot seřazených tak, aby každá hodnota byla přístupná pomocí celého čísla bez znaménka. První index je vždy číslo 0 a pro každý následující prvek přidaný do pole se hodnota indexu zvýší o 1. V jazyce ActionScript 3.0 jsou jako indexovaná pole použity dvě třídy: třída Array a třída Vector. Indexovaná pole používají pro číslo indexu 32-bitové celé číslo bez znaménka. Maximální velikost indexovaného pole je 232 - 1 nebo 4,294,967,295. Pokus o vytvoření pole většího než je maximální velikost vyvolá chybu v době běhu. Pro přístup k jednotlivým elementům indexovaného pole použijte operátor přístupu k poli ([]) k určení pozice indexu elementu, ke kterému si přejete získat přístup. Například následující kód představuje první element (element v indexu 0) v indexovaném poli nazvaném songTitles: songTitles[0] Kombinace názvu proměnné pole následovaná indexem v hranatých závorkách má funkci identifikátoru. (Jinak řečeno, může být použita jakýmkoliv způsobem, kterým bývá proměnná obvykle použita.) Elementu indexovaného pole můžete přiřadit hodnotu pomocí názvu a indexu na levé straně příkazu přiřazení: songTitles[1] = "Symphony No. 5 in D minor"; Podobně můžete načíst hodnotu elementu indexovaného pole pomocí názvu a indexu na pravé straně příkazu přiřazení: var nextSong:String = songTitles[2]; Můžete také použít proměnnou v hranatých závorkách a nemusíte zadat explicitní hodnotu. (Proměnná musí obsahovat nezápornou hodnotu celého čísla, např. uint, kladný int nebo kladnou instanci celého čísla Number.) Tato technika je běžně používána k „vytvoření smyčky“ přes elementy v indexovaném poli a provedení operace na některých nebo na všech elementech. Toto technika je ukázána v následujícím výpise kódu. Kód používá opakování k přístupu ke každé hodnotě v objektu Array nazvaném oddNumbers. Používá příkaz trace() k vytištění každé hodnoty ve formuláři „oddNumber[index] = value“: var oddNumbers:Array = [1, 3, 5, 7, 9, 11]; var len:uint = oddNumbers.length; for (var i:uint = 0; i < len; i++) { trace("oddNumbers[" + i.toString() + "] = " + oddNumbers[i].toString()); } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 155 Práce s poli Třída Array Prvním typem indexovaného pole je třída Array. Instance Array může obsahovat hodnotu libovolného datového typu. Stejný objekt Array může obsahovat objekty, které mají odlišný datový typ. Každá instance Array může mít například hodnotu String v indexu 0, instanci Number v indexu 1 a objekt XML v indexu 2. Třída Vector Dalším typem indexovaného pole, které je v jazyce ActionScript 3.0 dostupné, je třída Vector. Instance Vector je typované pole, což znamená, že všechny elementy v instanci Vector mají vždy stejný datový typ. Poznámka: Třída Vector je dostupná od verzí Flash Player 10 a Adobe AIR 1.5. Jestliže deklarujete proměnnou Vector nebo konkretizujete objekt Vector, explicitně určíte datový typ daného objektu, který může daný vektor obsahovat. Určený datový typ je známý jako základní typ Vektoru. V době běhu a v době kompilace (v přísném režimu) je zkontrolován jakýkoliv kód, který nastaví hodnotu elementu Vector nebo načte hodnotu z Vektoru. Jestliže přidávaný nebo načítaný datový typ objektu neodpovídá základnímu typu Vektoru, vygeneruje se chyba. Kromě omezení typu dat má třída Vector i další omezení, která ji odlišují od třídy Array: • Vektor je husté pole. Objekt Array může mít hodnoty v indexu 0 a 7, i když nemá žádné hodnoty v pozicích 1 až 6. Nicméně Vektor musí mít v každém indexu hodnotu (nebo null). • Vektor může mít volitelně pevně stanovenou délku. To znamená, že počet elementů, které vektor obsahuje, se nezmění. • Přístup k prvkům Vektoru je kontrolován s ohledem na meze. Nelze číst hodnotu z indexu většího než poslední prvek (length- 1). Nelze nastavit hodnotu s indexem více než jedna za aktuálním konečným indexem (jinými slovy, můžete nastavit hodnotu pouze na stávajícím indexu nebo na indexu [length]). V důsledku těchto omezení má Vektor dvě hlavní výhody před instancí Array, jejíž prvky jsou všechny instance jediné třídy: • Výkon: přístup k prvkům pole a iterace jsou mnohem rychlejší při použití instance Vector než při použití instance Array. • Typ zabezpečení: v přísném režimu může kompilátor identifikovat chyby datového typu. Příklady takových chyb zahrnují přiřazení hodnoty k nesprávnému datovému typu k Vektoru nebo očekávání špatného datového typu při čtení hodnoty z Vektoru. V době běhu jsou datové typy také zkontrolovány při přidávání dat nebo načítání dat z objektu Vector. Upozorňujeme však, že pomocí metody push() nebo unshift() pro přidání hodnot do Vektoru nebudou typy dat argumentů kontrolovány během kompilace. Při používání těchto metod jsou hodnoty stále kontrolovány v době běhu. Mimo dodatečných omezení a výhod se třída Vector velice podobá třídě Array. Vlastnosti a metody objektu Vector jsou podobné – ve většině případů totožné – vlastnostem a metodám Array. V každé situaci tam, kde byste použili pole, ve kterém mají všechny prvky stejný datový typ, je výhodnější použít instanci Vector. Vytváření polí K vytvoření instance Array nebo Vector můžete použít několik technik. Nicméně techniky k vytvoření každého typu pole se trochu liší. Vytváření instance Array Objekt Array vytvoříte voláním konstruktoru Array() nebo použitím syntaxe literálu Array. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 156 Práce s poli Funkci konstruktoru třídyArray() lze použít třemi způsoby. Zaprvé, jestliže voláte konstruktor bez argumentů, získáte prázdné pole. Pro ověření, zda pole nemá žádné prvky, můžete použít vlastnost třídy Array length. Následující kód například vyvolá konstruktor třídy Array() bez argumentů: var names:Array = new Array(); trace(names.length); // output: 0 Za druhé, jestliže použijete jako jediný parametr konstruktoru třídy Array() číslo, vytvoří se pole o dané délce a každá hodnota prvku bude nastavena na undefined. Argument musí být celé číslo bez znaménka o hodnotě od 0 do 4,294,967,295. Následující kód například volá konstruktor třídy Array() pomocí jediného číselného argumentu: var names:Array = new Array(3); trace(names.length); // output: 3 trace(names[0]); // output: undefined trace(names[1]); // output: undefined trace(names[2]); // output: undefined Zatřetí, jestliže voláte konstruktor a předáte seznam prvků jako parametry, vytvoří se pole a jeho prvky budou odpovídat každému parametru. Následující kód předá do konstruktoru třídy Array() tři argumenty: var names:Array = new Array("John", "Jane", "David"); trace(names.length); // output: 3 trace(names[0]); // output: John trace(names[1]); // output: Jane trace(names[2]); // output: David Můžete také vytvořit pole s literály Array. Literál pole může být přiřazen přímo k proměnné pole, viz následující příklad: var names:Array = ["John", "Jane", "David"]; Vytváření instance Vector Instanci Vector vytvoříte voláním konstruktoru Vector.<T>(). Vector můžete také vytvořit voláním globální funkce Vector.<T>(). Daná funkce převede určený objekt na instanci Vector. Jazyk ActionScript nemá žádný ekvivalent vektoru k syntaxi literálu Array. Kdykoliv deklarujete proměnnou Vector (nebo podobně parametr metody Vector nebo typ návratové metody), určujete základní typ proměnné Vector. Základní typ také určíte, když vytvoříte instanci Vector, voláním konstruktoruVector.<T>(). Jinak řečeno, kdykoliv použijete v jazyce ActionScript termín Vector, je tento termín doplněn základním typem. Základní typ vektoru určíte pomocí syntaxe parametru typu. Parametr typu v kódu ihned následuje za slovem Vector. Skládá se z tečky .), poté z názvu základní třídy obklopené lomenými závorkami (<>), viz následující příklad: var v:Vector.<String>; v = new Vector.<String>(); Na prvním řádku příkladu je proměnná v deklarována jako instance Vector.<String>. Jinými slovy, představuje indexované pole, které může obsahovat pouze instance String. Druhý řádek volá konstruktor Vector() k vytvoření instance stejného typu Vector (tj. Vektor, jehož elementy jsou všechny objekty String). Přiřadí daný objekt k v. Používání konstruktoru Vector.<T>() Jestliže používáte konstruktor Vector.<T>() bez argumentů, vytvoří se prázdná instance Vector. Prázdný vektor otestujete zkontrolováním jeho vlastnosti length. Například následující kód volá konstruktorVector.<T>() bez argumentů: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 157 Práce s poli var names:Vector.<String> = new Vector.<String>(); trace(names.length); // output: 0 Jestliže již předem víte, kolik elementů bude vektor na začátku potřebovat, můžete předem definovat počet elementů v daném Vektoru. Pro vytvoření Vektoru s určitým počtem elementů předejte počet elementů jako první parametr (parametr length). Protože elementy Vector nemohou být prázdné, jsou vyplněny instancemi základního typu. Jestliže je základní typ referenčním typem, který umožňuje hodnoty null, všechny elementy obsahují null. V opačném případě všechny elementy obsahují výchozí hodnotu pro danou třídu. Například proměnná uint nemůže být null. V následujícím kódu je Vektor nazvaný ages vytvořen se sedmi elementy, kde každý obsahuje hodnotu 0: var ages:Vector.<uint> = new Vector.<uint>(7); trace(ages); // output: 0,0,0,0,0,0,0 Nakonec pomocí konstruktoruVector.<T>() můžete vytvořit Vektor s pevnou délkou true pro druhý parametr (parametr fixed). V daném příkladě je Vektor vytvořený s určitým počtem elementů a daný počet elementů nelze změnit. Nicméně upozorňujeme, že hodnoty elementů Vektoru s pevnou délkou stále můžete změnit. Narozdíl od třídy Array nemůžete předat seznam hodnot ke konstruktoru Vector.<T>() k určení počátečních hodnot Vektoru. Používání globální funkce Vector.<T>() Mimo konstruktor Vector.<T>() můžete také k vytvoření objektu Vector použít globální funkci Vector.<T>(). Globální funkce Vector.<T>() je funkcí konverze. Když voláte globální funkci Vector.<T>(), určíte základní typ Vektoru, který daná metoda vrátí. Předáte jednotlivé indexované pole (instance Array nebo Vector) jako argument. Metoda poté vrátí Vektor s určitým datovým typem obsahujícím hodnoty v argumentu zdrojového pole. Následující výpis kódu ukazuje syntaxi pro volání globální funkce Vector.<T>(): var friends:Vector.<String> = Vector.<String>(["Bob", "Larry", "Sarah"]); Globální funkce Vector.<T>() provádí konverzi datového typu na dvou úrovních. Zaprvé, při předání instance Array k funkci bude vrácena instance Vector. Zadruhé, ať je zdrojové pole instance Array nebo Vector, funkce se pokusí převést elementy zdrojového pole na hodnoty základního typu. Převod používá standardní pravidla převodu datového typu jazyka ActionScript. Například následující výpis kódu převede hodnoty String ve zdrojovém poli na celá čísla ve výsledném Vektoru. Desetinná část prví hodnoty ("1.5") je zkrácená a nečíselná třetí hodnota ("Waffles") je ve výsledku převedena na 0: var numbers:Vector.<int> = Vector.<int>("1.5", "17", "Waffles"]); trace(numbers); // output: 1,17,0 Jestliže jakýkoliv ze zdrojových elementů nelze převést, vygeneruje se chyba. Jestliže kód volá globální funkci Vector.<T>() a element ve zdrojovém poli je instancí podtřídy určeného základního typu, je daný element přidán k výslednému Vektoru (nevygeneruje se chyba). Používání globální funkce Vector.<T>() je ve skutečnosti jediný způsob, jak převést Vektor se základním typem T na Vektor se základním typem, který je supertřídou T. Vkládání prvků pole Nejzákladnějším způsobem přidání elementu k indexovanému poli je použití operátoru přístupu k poli ([]). K nastavení hodnoty elementu indexovaného pole použijte název objektu Array nebo Vector a číslo indexu na levé straně přiřazeného příkazu: songTitles[5] = "Happy Birthday"; Jestliže Array nebo Vector ještě nemá na daném indexu element, index se vytvoří a hodnota se uloží tam. Jestliže v daném indexu hodnota existuje, nová hodnota nahradí tu stávající. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 158 Práce s poli Objekt Array vám umožňuje vytvořit element v daném indexu. Nicméně u objektu Vector můžete hodnotu přiřadit pouze ke stávajícímu indexu nebo k dalšímu dostupnému indexu. Další dostupný index odpovídá vlastnosti objektu Vectorlength. Nejbezpečnějším způsobem přidání nového elementu k objektu Vector je použít kód podobný tomuto výpisu kódu: myVector[myVector.length] = valueToAdd; Tři z metod třídy Array a Vector - push(), unshift() a splice() - vám umožňují vkládat prvky do indexovaného pole. Metoda push() přidá jeden nebo více prvků na konec pole. Jinak řečeno, poslední prvek vložený do daného pole pomocí metody push() bude mít nejvyšší číslo indexu. Metoda unshift() vloží jeden nebo více prvků na začátek pole, a to vždy do umístění čísla indexu 0. Metoda splice() vloží libovolný počet položek do určeného indexu v poli. Následující příklad ukazuje všechny tři metody. Pole pojmenované planets je vytvořeno pro uložení názvů planet v pořadí jejich blízkosti ke Slunci. Zaprvé, metoda push() je volána za účelem přidání první položky Mars. Zadruhé, metoda unshift() je volána pro vložení položky, která patří do přední části pole, Mercury. Nakonec je volána metoda splice() pro vložení položek Venus a Earth za Mercury, ale před Mars. První argument odeslán do splice(), celé číslo 1, řídí vkládání tak, aby začalo na indexu 1. Druhý argument odeslaný do splice(), celé číslo 0, určuje, že by neměly být vymazány žádné položky. Nakonec třetí a čtvrté argumenty odeslané dosplice(), Venus a Earth jsou položky, které mají být vloženy. var planets:Array = new Array(); planets.push("Mars"); // array contents: Mars planets.unshift("Mercury"); // array contents: Mercury,Mars planets.splice(1, 0, "Venus", "Earth"); trace(planets); // array contents: Mercury,Venus,Earth,Mars Metody push() a unshift() vrátí celé číslo bez znaménka, které představuje délku upraveného pole. Metoda splice() vrátí prázdné pole, je-li použita pro vložení prvků. To se může zdát divné, ale vezmeme-li v úvahu pružnost metody splice(), je to již jasnější. Metodu splice() můžete použít nejen k vkládání prvků do pole, ale také k odstraňování prvků z pole. Je-li používána k odstraňování prvků, vrátí metoda splice()pole obsahující odstraněné prvky. Poznámka: Jestliže vlastnost objektu Vector fixed je true, celkový počet elementů ve Vektoru se nemůže změnit. Jestliže se snažíte přidat nový element k Vektoru s pevnou délkou pomocí zde popsaných technik, vygeneruje se chyba. Načítání hodnot a odstraňování elementů pole Nejjednodušší způsob načtení hodnoty elementu z indexovaného pole je použít operátor přístupu k poli ([]). K načtení hodnoty elementu indexovaného pole použijte název objektu Array nebo Vector a číslo indexu na levé straně přiřazeného příkazu: var myFavoriteSong:String = songTitles[3]; Můžete se pokusit načíst hodnotu z pole nebo vektoru pomocí indexu, kde neexistují žádné elementy. V daném případě vrátí objekt Array hodnotu nedefinovanou a vektor vygeneruje výjimku RangeError. Tři metody tříd Array a Vector - pop(), shift(), a splice() - vám umožňují odstranit elementy. Metoda pop() odstraní prvek z konce pole. Jinak řečeno, odstraní prvek na nejvyšším čísle indexu. Metoda shift() odstraní prvek ze začátku pole, což znamená, že vždy odstraní prvek v čísle indexu 0. Metoda splice(), kterou lze také použít pro vkládání prvků, odstraní libovolný počet prvků, které začínají na čísle indexu určeném prvním argumentem odeslaném na metodu. Následující příklad používá všechny tři metody pro odstranění prvků z instance Array. Pole pojmenované oceans je vytvořeno za účelem uložení názvů větších vodních ploch. Některé názvy v poli jsou jezera, nikoliv oceány, takže je třeba je vyjmout. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 159 Práce s poli Zaprvé, metoda splice() se použije pro odstranění položek Aral a Superior a vložení položek Atlantic a Indian. První argument odeslaný na splice(), celé číslo 2, určuje, že by operace měla začínat třetí položkou v seznamu, která se nachází na indexu 2. Druhý argument, 2, určuje, že by měly být odstraněny dvě položky. Zbývající argumenty, Atlantic a Indian, jsou hodnoty, které budou vloženy na místo indexu 2. Zadruhé, metoda pop() se použije k odstranění posledního prvku v poli, Huron. A zatřetí, metoda shift() se použije k odstranění první položky v poli, Victoria. var oceans:Array = ["Victoria", "Pacific", "Aral", "Superior", "Indian", "Huron"]; oceans.splice(2, 2, "Arctic", "Atlantic"); // replaces Aral and Superior oceans.pop(); // removes Huron oceans.shift(); // removes Victoria trace(oceans);// output: Pacific,Arctic,Atlantic,Indian Metody pop() a shift() obě vrátí položku, která byla odstraněna. Pro instanci Array je datový typ návratové hodnoty Object, protože pole mohou obsahovat hodnoty jakéhokoliv datového typu. Pro instanci Vector je datový typ návratové hodnoty základním typem Vektoru. Metoda splice() vrátí Pole nebo Vektor obsahující odstraněné hodnoty. Pole oceans můžete například změnit tak, že volání splice() přiradí Pole k nové proměnné Pole, viz následující příklad: var lakes:Array = oceans.splice(2, 2, "Arctic", "Atlantic"); trace(lakes); // output: Aral,Superior Kód, který používá operátor delete, můžete najít na elementu objektu Array. Operátor delete nastaví hodnotu elementu Pole na undefined, ale neodstraní element z Pole. Například následující kód používá operátor delete na třetím elementu v Poli oceans, ale délka Pole zůstává 5. var oceans:Array = ["Arctic", "Pacific", "Victoria", "Indian", "Atlantic"]; delete oceans[2]; trace(oceans);// output: Arctic,Pacific,,Indian,Atlantic trace(oceans[2]); // output: undefined trace(oceans.length); // output: 5 Pole nebo vektor můžete oříznout pomocí vlastností polelength. Jestliže nastavíte vlastnost lengthindexovaného pole na délku, která je menší než aktuální délka pole, pole je oříznuto a odstraní se všechny uložené prvky na indexových číslech vyšších než je nová hodnota Length mínus 1. Jestliže pole oceans bylo například roztříděno tak, aby všechny platné záznamy byly na začátku pole, můžete vlastnost length použít pro odstranění záznamů na konci pole, viz následující kód: var oceans:Array = ["Arctic", "Pacific", "Victoria", "Aral", "Superior"]; oceans.length = 2; trace(oceans); // output: Arctic,Pacific Poznámka: Jestliže vlastnost objektu Vector fixed je true, celkový počet elementů ve Vektoru se nemůže změnit. Jestliže se snažíte odstranit element nebo seříznout Vektor s pevnou délkou pomocí zde popsaných technik, vygeneruje se chyba. Třídění pole Existují tři metody - reverse(), sort() a sortOn() - které vám umožňují změnit pořadí indexovaného pole, a to buď tříděním nebo obrácením pořadí. Všechny tyto metody upravují stávající pole. Následující tabulka nabízí souhrn těchto metod a jejich chování pro objekty Array a Vector: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 160 Práce s poli Metoda Chování pole Chování vektoru reverse() Změní pořadí elementů tak, aby se poslední element stal elementem prvním, předposlední element se stal elementem druhým, atd. Identické s chováním Pole sort() Umožňuje vám třídit elementy Array různými předem definovanými způsoby, například v alfabetickém nebo číselném pořadí. Můžete také určit vlastní algoritmus třídění. Třídí elementy podle vlastního algoritmu třídění, který zadáte. sortOn() Umožňuje vám třídit objekty, které mají jednu nebo více společných vlastností a určuje vlastnost nebo vlastnosti, které budou použity jako klíče třídění Ve třídě Vector není dostupná Metoda reverse() Metoda reverse() nepřebírá žádné parametry a nevrací hodnotu. Nicméně vám umožňuje přepínat pořadí svého pole z jeho aktuálního stavu do opačného pořadí. Následující příklad obrací pořadí oceánů uvedených v poli oceans: var oceans:Array = ["Arctic", "Atlantic", "Indian", "Pacific"]; oceans.reverse(); trace(oceans); // output: Pacific,Indian,Atlantic,Arctic Základní třídění pomocí metody sort() (pouze třída Array) Pro instance Array změní metoda sort() pořadí prvků v poli pomocí výchozího pořadí třídění. Výchozí pořadí třídění má následující charakteristiky: • Třídění je citlivé na velká a malá písmena, což znamená, že velká písmena předcházejí malá písmena. Například písmeno D předchází písmenu b. • Třídění je vzestupné, což znamená, že kódy malých písmen (například A) předcházejí kódům velkých písmen (například B). • Třídění umístí stejné hodnoty tak, aby navzájem sousedily, ale bez zvláštního pořadí. • Třídění je založeno na řetězci, což znamená, že prvky jsou před porovnáním převedeny na řetězce (například 10 předchází 3, protože řetězec "1" má nižší kód znaku než řetězec "3"). Můžete zjistit, že svá pole potřebujete roztřídit bez ohledu na velká a malá písmena, v sestupném pořadí, nebo vaše pole možná obsahuje čísla, která si přejete třídit číselně namísto abecedně. Metoda třídy Array sort() má parametr options, který vám umožňuje změnit každou charakteristiku výchozího pořadí třídění. Volby jsou definovány sadou statických konstant ve třídě Array, viz následující seznam: • Array.CASEINSENSITIVE: Po vybrání této možnosti nebude třídění zohledňovat velikost písmen. Například malé písmeno b předchází velkému písmenu D. • • Array.DESCENDING: Obrátí výchozí vzestupné třídění. Například písmeno B předchází písmenu A. Array.UNIQUESORT: Vybráním této možnosti bude třídění přerušeno v případě, že budou nalezeny dvě stejné hodnoty. • Array.NUMERIC: Vyvolá číselné třídění, takže 3 předchází 10. Následující příklad zdůrazňuje některé z těchto voleb. Vytvořeno je pole pojmenované poets, které je tříděno pomocí několika různých možností. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 161 Práce s poli var poets:Array = ["Blake", "cummings", "Angelou", "Dante"]; poets.sort(); // default sort trace(poets); // output: Angelou,Blake,Dante,cummings poets.sort(Array.CASEINSENSITIVE); trace(poets); // output: Angelou,Blake,cummings,Dante poets.sort(Array.DESCENDING); trace(poets); // output: cummings,Dante,Blake,Angelou poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // use two options trace(poets); // output: Dante,cummings,Blake,Angelou Vlastní třídění pomocí metody sort() (třídy Array a Vector) Vedle základního třídění, které je dostupné pro objekt Array, můžete také definovat vlastní pravidla třídění. Tato technika je jediným formátem metody sort(), který je dostupný pro třídu Vector. K definování vlastního třídění zapište vlastní funkci třídění a předejte ji jako argument k metodě sort(). Jestliže máte například seznam jmen, kde každý prvek seznamu obsahuje celé jméno osoby, ale přejete si seznam třídit podle příjmení, musíte použít vlastní funkci třídění pro analyzování každého prvku a použití příjmení ve funkci třídění. Následující kód ukazuje způsob třídění pomocí vlastní funkce, která je použita jako parametr metody Array.sort(): var names:Array = new Array("John Q. Smith", "Jane Doe", "Mike Jones"); function orderLastName(a, b):int { var lastName:RegExp = /\b\S+$/; var name1 = a.match(lastName); var name2 = b.match(lastName); if (name1 < name2) { return -1; } else if (name1 > name2) { return 1; } else { return 0; } } trace(names); // output: John Q. Smith,Jane Doe,Mike Jones names.sort(orderLastName); trace(names); // output: Jane Doe,Mike Jones,John Q. Smith Vlastní funkce třídění orderLastName() používá běžný výraz k vyjmutí příjmení z každého prvku a jeho použití pro operaci porovnání. Identifikátor funkce orderLastName se používá jako výhradní parametr při volání metody sort() na poli names. Funkce třídění přijímá dva parametry, a a b, protože pracuje najednou na dvou prvcích pole. Návratová hodnota funkce třídění udává, jak by měly být prvky tříděny: • Návratová hodnota -1 určuje, že první parametr a předchází druhému parametru b. • Návratová hodnota 1 určuje, že druhý parametr b předchází prvnímu a. • Návratová hodnota 0 určuje, že prvky mají při třídění stejnou přednost. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 162 Práce s poli Metoda sortOn() (pouze třída Array) Metoda sortOn() je určena pro objekty Array s elementy, které obsahují objekty. Očekává se, že tyto objekty mají minimálně jednu společnou vlastnost, která může být použita jako klíč třídění. Použití metody sortOn() pro pole jakéhokoliv jiného typu vygeneruje neočekávané výsledky. Poznámka: Třída Vector nezahrnuje metodu sortOn(). Tato metoda je dostupná pouze pro objekty Array. Následující příklad reviduje pole poets tak, že každý prvek je objekt namísto řetězec. Každý objekt obsahuje jak příjmení básníka, tak datum jeho narození. var poets:Array = new Array(); poets.push({name:"Angelou", born:"1928"}); poets.push({name:"Blake", born:"1757"}); poets.push({name:"cummings", born:"1894"}); poets.push({name:"Dante", born:"1265"}); poets.push({name:"Wang", born:"701"}); Metodu sortOn() můžete použít pro třídění pole dle vlastnosti born. Metoda sortOn() definuje dva parametry, fieldName a options. Argument fieldName musí být určen jako řetězec. V následujícím příkladě je metoda sortOn() volána se dvěma argumenty "born" a Array.NUMERIC. Argument Array.NUMERIC se používá pro zajištění, že třídění je provedeno číselně a nikoliv abecedně. Toto je dobrou praxí i v případě, kdy všechna čísla mají stejný počet číslic, protože argument zajistí, že jestliže je později k poli přidáno číslo s méně nebo více číslicemi, bude se třídění i nadále chovat dle očekávání. poets.sortOn("born", Array.NUMERIC); for (var i:int = 0; i < poets.length; ++i) { trace(poets[i].name, poets[i].born); } /* output: Wang 701 Dante 1265 Blake 1757 cummings 1894 Angelou 1928 */ Třídění bez úpravy původního pole (pouze třída Array) Metody sort() a sortOn() obecně upravují Pole. Jestliže si přejete třídit Pole bez úpravy stávajícího pole, odešlete konstantu Array.RETURNINDEXEDARRAY jako součást parametru options. Tato možnost nařídí metodě vrátit nové pole, které odráží třídění a ponechá původní Pole beze změn. Pole vrácené metodami je jednoduché pole čísel indexu, které odráží nové pořadí třídění a neobsahuje žádné prvky z původního Pole. Například pro třídění pole poets dle data narození bez úpravy Pole začleňte konstantu Array.RETURNINDEXEDARRAY do argumentu odeslaného pro parametr options. Následující příklad uchovává vrácenou informaci indexu v Poli pojmenovaném indices a používá pole indices ve spojení s nezměněným polem poets pro dosazení básníků v pořadí dle roku narození: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 163 Práce s poli var indices:Array; indices = poets.sortOn("born", Array.NUMERIC | Array.RETURNINDEXEDARRAY); for (var i:int = 0; i < indices.length; ++i) { var index:int = indices[i]; trace(poets[index].name, poets[index].born); } /* output: Wang 701 Dante 1265 Blake 1757 cummings 1894 Angelou 1928 */ Dotazování pole Čtyři metody třídy Array a Vector - concat(), join(), slice()a toString() - všechny dotazují pole pro informaci, ale pole nemění. Metody concat() a slice() vrátí nová pole, zatímco metody join() a toString() vrátí řetězce. Metoda concat() vezme nové pole nebo seznam prvků jako argumenty, zkombinuje je se stávajícím polem a vytvoří tak pole nové. Metoda slice() má dva parametry, vhodně pojmenované startIndex a endIndex a vrátí nové pole obsahující kopii prvků „odříznutých“ ze stávajícího pole. Řez začíná u prvku na startIndex a končí u prvku před endIndex. To přivodí opakování: prvek na endIndex není zahrnut do návratové hodnoty. Následující příklad používá concat() a slice() pro vytvoření nových polí pomocí prvků jiných polí. var array1:Array = ["alpha", "beta"]; var array2:Array = array1.concat("gamma", "delta"); trace(array2); // output: alpha,beta,gamma,delta var array3:Array = array1.concat(array2); trace(array3); // output: alpha,beta,alpha,beta,gamma,delta var array4:Array = array3.slice(2,5); trace(array4); // output: alpha,beta,gamma Metody join() a toString() můžete použít pro dotazování pole a vrácení svého obsahu jako řetězce. Jestliže pro metodu join() nejsou použity žádné parametry, chovají se obě dvě metody stejně - vrátí řetězec obsahující čárkou rozdělený seznam všech prvků v poli. Metoda join() narozdíl od metody toString() přijímá parametr pojmenovaný delimiter, který vám umožní zvolit symbol, který bude použit jako oddělovač mezi každým parametrem ve vráceném řetězci. Následující příklad vytvoří pole nazvané rivers a volá jak metodu join() tak toString() pro vrácení hodnoty v Poli jako řetězec. Metoda toString() je použita pro vrácení hodnot oddělených čárkou (riverCSV), zatímco metoda join() se používá pro vrácení hodnot oddělených znakem +. var rivers:Array = ["Nile", "Amazon", "Yangtze", "Mississippi"]; var riverCSV:String = rivers.toString(); trace(riverCSV); // output: Nile,Amazon,Yangtze,Mississippi var riverPSV:String = rivers.join("+"); trace(riverPSV); // output: Nile+Amazon+Yangtze+Mississippi V případě metody join() je třeba upozornit na jeden možný problém a to ten, že jakékoliv vnořené instance Array nebo Vector jsou vždy vráceny s hodnotami oddělenými čárkami, bez ohledu na to, jaký oddělovač určíte pro hlavní prvky pole. Viz následující příklad: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 164 Práce s poli var nested:Array = ["b","c","d"]; var letters:Array = ["a",nested,"e"]; var joined:String = letters.join("+"); trace(joined); // output: a+b,c,d+e Asociativní pole Asociativní pole, někdy nazvané křížek nebo mapa, používá pro seřazení uchovaných hodnot namísto číselného indexu klíče. Každý klíč v asociativním poli je jedinečným řetězcem, který se používá k získání přístupu k uložené hodnotě. Asociativní pole je instancí třídy Object, což znamená, že každý klíč odpovídá názvu vlastnosti. Asociativní pole jsou sbírkou párů klíčů a hodnot bez pořadí. Váš kód by neměl předpokládat klíče asociativního pole v určitém pořadí. Jazyk ActionScript 3.0 obsahuje také pokročilý typ asociativního pole nazvaný slovník. Slovníky, které jsou instancemi třídy Dictionary v balíku flash.utils, používají klíče, které mohou mít jakýkoliv datový typ. Jinak řečeno, klíče slovníku nejsou omezeny na hodnoty typu String. Asociativní pole s klíči řetězce Existují dva způsoby k vytvoření asociativních polí v jazyce ActionScript 3.0. Prvním způsobem je použití instance Object. Pomocí instance Object můžete konkretizovat své pole s literálem objektu. Instance třídy Object, nazvaná také generický objekt, je co do funkce totožná s asociativním polem. Každý název vlastnosti generického objektu slouží jako klíč, který poskytuje přístup k uložené hodnotě. Následující příklad vytvoří asociativní pole nazvané monitorInfo, pomocí literálu objektu inicializuje pole se dvěma dvojicemi klíče a hodnoty: var monitorInfo:Object = {type:"Flat Panel", resolution:"1600 x 1200"}; trace(monitorInfo["type"], monitorInfo["resolution"]); // output: Flat Panel 1600 x 1200 Jestliže nepotřebujete inicializovat pole v čase deklarace, můžete pro vytvoření pole použít konstruktor třídy Object, viz níže: var monitorInfo:Object = new Object(); Po vytvoření objektu pomocí buď literálu objektu nebo konstruktoru třídy Object můžete do pole přidat nové hodnoty pomocí operátoru přístupu k poli ([]) nebo operátoru tečky (.). Následující příklad přidá dvě nové hodnoty domonitorArray: monitorInfo["aspect ratio"] = "16:10"; // bad form, do not use spaces monitorInfo.colors = "16.7 million"; trace(monitorInfo["aspect ratio"], monitorInfo.colors); // output: 16:10 16.7 million Všimněte si, že klíč pojmenovaný aspect ratio obsahuje znak mezery. To je možné s operátorem přístupu k poli ([]), ale jestliže pokus provedete s operátorem tečky, dojde k vygenerování chyby. Použití mezer v názvech klíčů se doporučuje. Druhý způsob vytvoření asociativního pole je použít konstruktor třídy Array (nebo konstruktor libovolné dynamické třídy) a poté použít buď operátor přístupu k poli ([]) nebo operátor tečky (.) pro přidání dvojic klíče a hodnoty k poli. Jestliže své asociativní pole prohlásíte za typ Array, nemůžete použít objekt literálu k inicializaci pole. Následující příklad vytvoří asociativní pole nazvané monitorInfo pomocí konstruktoru Array a přidá klíč nazvaný type a klíč nazvaný resolution, spolu s jejich hodnotami: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 165 Práce s poli var monitorInfo:Array = new Array(); monitorInfo["type"] = "Flat Panel"; monitorInfo["resolution"] = "1600 x 1200"; trace(monitorInfo["type"], monitorInfo["resolution"]); // output: Flat Panel 1600 x 1200 Použití konstruktoru třídy Array pro vytvoření asociativního pole neposkytuje žádnou výhodu. Vlastnost Array.length nebo žádnou z metod třídy Array nemůžete použít s asociativními poli, i v případě, že použijete konstruktor Array nebo datový typ Array. Použití konstruktoru třídy Array je lépe ponechat pro vytváření indexovaných polí. Asociativní pole s klíči objektu (Slovníky) Třídu Dictionary můžete použít pro vytvoření asociativního pole, které používá objekty pro klíče spíše než pro řetězce. Taková pole se někdy nazývají slovníky, křížky nebo mapy. Zvažte například aplikaci, která určuje umístění objektu Sprite na základě jeho asociace s určitým kontejnerem. Objekt Dictionary můžete použít pro mapování každého objektu Sprite ke kontejneru. Následující kód vytvoří tři instance třídy Sprite, které slouží jako klíče pro objekt Dictionary. Každému klíči je přiřazena hodnota buď GroupA nebo GroupB. Hodnota může mít jakýkoliv datový typ, ale v tomto příkladě jsou GroupA i GroupB instancemi třídy Object. Následně můžete získat přístup k hodnotě přiřazené ke každému klíči s operátorem přístupu k poli ([]), viz následující kód: import flash.display.Sprite; import flash.utils.Dictionary; var groupMap:Dictionary = new Dictionary(); // objects to use var spr1:Sprite = var spr2:Sprite = var spr3:Sprite = as keys new Sprite(); new Sprite(); new Sprite(); // objects to use as values var groupA:Object = new Object(); var groupB:Object = new Object(); // Create new key-value pairs in dictionary. groupMap[spr1] = groupA; groupMap[spr2] = groupB; groupMap[spr3] = groupB; if (groupMap[spr1] { trace("spr1 is } if (groupMap[spr2] { trace("spr2 is } if (groupMap[spr3] { trace("spr3 is } == groupA) in groupA"); == groupB) in groupB"); == groupB) in groupB"); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 166 Práce s poli Iterace s klíči objektu Obsahem objektu Dictionary můžete iterovat buď pomocí smyčkyfor..in nebo smyčky for each..in smyčka. Smyčka for..in vám umožňuje iteraci na základě klíčů, zatímco smyčkafor each..in umožňuje iteraci na základě hodnot přiřazených ke každému klíči. Použijte smyčku for..in pro přímý přístup ke klíčům objektu Dictionary. K hodnotám objektu Dictionary lze také získat přístup pomocí operátora přístupu k poli ([]). Následující kód používá předchozí příklad slovníku groupMap a ukazuje tak, jak iterovat skrze objekt Dictionary se smyčkou for..in: for (var key:Object in groupMap) { trace(key, groupMap[key]); } /* output: [object Sprite] [object Object] [object Sprite] [object Object] [object Sprite] [object Object] */ Použijte smyčku for each..in pro přímý přístup k hodnotám objektu Dictionary. Následující kód také používá slovník groupMap a ukazuje tak, jak iterovat skrze objekt Dictionary se smyčkou for each..in: for each (var item:Object in groupMap) { trace(item); } /* output: [object Object] [object Object] [object Object] */ Klíče objektu a správa paměti Adobe® Flash® Player a Adobe® AIR™ používají systém pro čištění volnění paměti pro obnovení paměti, která již není používaná. Jestliže objekt nemá žádné reference, které by k němu ukazovaly, stává se objekt vhodným pro čištění uvolněné paměti a paměť je obnovena při příštím provedení čištění uvolněné paměti. Následující kód například vytvoří nový objekt a přiřadí referenci objektu k proměnné myObject: var myObject:Object = new Object(); Jestliže na daný objekt existuje reference, systém čištění uvolněné paměti neobnoví paměť, kterou objekt zabírá. Jestliže je hodnota myObject změněna tak, že ukazuje na odlišný objekt nebo je nastavena na hodnotu null, paměť využívaná původním objektem se stává vhodnou pro čištění uvolněné paměti, ale pouze pokud na původní objekt neexistují žádné reference. Jestliže používáte myObject jako klíč v objektu Dictionary, vytváříte na původní objekt jinou referenci. Například následující kód vytvoří dvě reference na objektu - proměnnou myObject a klíč v objektu myMap: import flash.utils.Dictionary; var myObject:Object = new Object(); var myMap:Dictionary = new Dictionary(); myMap[myObject] = "foo"; Aby byl objekt odkazovaný myObject vhodný pro čištění uvolněné paměti, musíte odstranit všechny reference, které jsou s ním spojené. V tomto případě musíte změnit hodnotu myObject a odstranit klíč myObjectz myMap, viz následující kód: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 167 Práce s poli myObject = null; delete myMap[myObject]; Alternativně můžete použít parametr useWeakReference konstruktoru Dictionary pro označení všech klíčů slovníku jako slabé reference. Systém pro čištění uvolněné paměti ignoruje slabé reference, což znamená, že objekt, který má pouze slabé reference je vhodný pro čištění uvolněné paměti. V následujícím kódu například není třeba odstranit klíč myObject z myMap, aby byl objekt označen jako vhodný pro čištění uvolněné paměti: import flash.utils.Dictionary; var myObject:Object = new Object(); var myMap:Dictionary = new Dictionary(true); myMap[myObject] = "foo"; myObject = null; // Make object eligible for garbage collection. Vícedimenzionální pole Vícedimenzionální pole obsahují jiná pole jako prvky. Představte si například seznam úloh, který je uložený jako indexované pole řetězců: var tasks:Array = ["wash dishes", "take out trash"]; Jestliže si přejete uložit samostatný seznam úloh pro každý den v týdnu, můžete vytvořit vícedimenzionální pole s jedním prvkem pro každý den v týdnu. Každý prvek obsahuje indexované pole, podobné poli tasks, které ukládá seznam úloh. Ve vícedimenzionálních polích můžete použít libovolnou kombinaci indexovaných nebo asociovaných polí. Příklady v následující části používají buď dvě indexovaná pole nebo asociativní pole indexovaných polí. Další kombinace můžete zkusit jako cvičení. Dvě indexovaná pole Jestliže používáte dvě indexovaná pole, můžete výsledek zobrazit jako tabulku nebo pracovní formulář. Prvky prvního pole reprezentují řádky tabulky, zatímco prvky druhého pole reprezentují sloupce. Například následující vícedimenzionální pole používá dvě indexovaná pole pro sledování seznamů stop pro každý den v týdnu. První pole, masterTaskList, je vytvořeno pomocí konstruktoru třídy Array. Každý prvek pole představuje den v týdnu, kde index 0 představuje pondělí a index 6 představuje neděli. Tyto prvky si můžete představit jako řádky v tabulce. Seznam úloh pro každý den můžete vytvořit přiřazením literálu pole ke každému ze sedmi prvků, které vytvoříte v poli masterTaskList. Literál pole představuje sloupce v tabulce. var masterTaskList:Array = new Array(); masterTaskList[0] = ["wash dishes", "take out trash"]; masterTaskList[1] = ["wash dishes", "pay bills"]; masterTaskList[2] = ["wash dishes", "dentist", "wash dog"]; masterTaskList[3] = ["wash dishes"]; masterTaskList[4] = ["wash dishes", "clean house"]; masterTaskList[5] = ["wash dishes", "wash car", "pay rent"]; masterTaskList[6] = ["mow lawn", "fix chair"]; K jednotlivým položkám na jakémkoliv seznamu úloh můžete získat přístup pomocí operátoru přístupu k poli ([]). První sada závorek představuje den v týdnu a druhá sada závorek představuje seznam úloh pro daný den. Například pro získání druhé úlohy ze seznamu středy nejprve použijte index 2 pro středu a poté použijte index 1 pro druhou úlohu v seznamu. trace(masterTaskList[2][1]); // output: dentist PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 168 Práce s poli Pro získání první úlohy ze seznamu neděle použijte index 6 pro neděli a index 0 pro první úlohu na seznamu. trace(masterTaskList[6][0]); // output: mow lawn Asociativní pole s indexovaným polem Aby bylo získání přístupu k jednotlivým polím snadnější, můžete asociativní pole použít pro dny v týdny a indexovaná pole pro seznamy úloh. Použití asociativního pole vám umožňuje použít syntaxi tečky při odkazování na určitý den v týdnu, ale to za cenu vyššího zpracovávání v době běhu pro přístup ke každému prvku asociativního pole. Následující příklad používá asociativní pole jako základ seznamu úloh, s dvojicí klíče a hodnoty pro každý den v týdnu: var masterTaskList:Object = new Object(); masterTaskList["Monday"] = ["wash dishes", "take out trash"]; masterTaskList["Tuesday"] = ["wash dishes", "pay bills"]; masterTaskList["Wednesday"] = ["wash dishes", "dentist", "wash dog"]; masterTaskList["Thursday"] = ["wash dishes"]; masterTaskList["Friday"] = ["wash dishes", "clean house"]; masterTaskList["Saturday"] = ["wash dishes", "wash car", "pay rent"]; masterTaskList["Sunday"] = ["mow lawn", "fix chair"]; Díky syntaxi tečky bude kód snáze čten a budete se tak moct vyhnout více sadám závorek. trace(masterTaskList.Wednesday[1]); // output: dentist trace(masterTaskList.Sunday[0]);// output: mow lawn Seznamem úloh můžete iterovat pomocí smyčky for..in, ale pro přístup k hodnotě přiřazené každému klíči musíte použít operátor přístupu k poli ([]) namísto syntaxe tečky. Protože masterTaskList je asociativní pole, prvky nejsou nezbytně získány v pořadí, které můžete očekávat, viz následující příklad: for (var day:String in masterTaskList) { trace(day + ": " + masterTaskList[day]) } /* output: Sunday: mow lawn,fix chair Wednesday: wash dishes,dentist,wash dog Friday: wash dishes,clean house Thursday: wash dishes Monday: wash dishes,take out trash Saturday: wash dishes,wash car,pay rent Tuesday: wash dishes,pay bills */ Klonování polí Třída Array nemá žádnou zabudovanou metodu pro kopírování polí. Mělkoukopii pole můžete vytvořit voláním metody concat() nebo slice() bez argumentů. V mělké kopii, jestliže má původní pole prvky, které jsou objekty, jsou zkopírovány pouze reference na objekty, nikoliv samotné objekty. Kopie ukazuje na stejné objekty jako původní pole. Jakékoliv změny provedené v objektech se odrazí v obou polích. V hluboké kopii jsou jakékoliv objekty nalezené v původním poli také zkopírovány, takže nové pole neukazuje na stejné objekty jako pole původní. Hluboké kopírování vyžaduje více než jeden řádek kódu, což obvykle volá po vytvoření funkce. Taková funkce by měla být vytvořena jako globální funkce utility nebo jako metoda podtřídy Array. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 169 Práce s poli Následující příklad definuje funkci pojmenovanou clone(), která provádí hluboké kopírování. Algoritmus je vypůjčen z běžné programovací techniky jazyka Java. Funkce vytvoří hlubokou kopii serializací pole do instance třídy ByteArray a poté načte pole zpět do nového pole. Tato funkce přijímá objekt a může být použita s indexovanými poli i asociativními poli, viz následující kód: import flash.utils.ByteArray; function clone(source:Object):* { var myBA:ByteArray = new ByteArray(); myBA.writeObject(source); myBA.position = 0; return(myBA.readObject()); } Pokročilá témata Rozšíření třídy Array Třída Array je jednou z mála základních tříd, která není koncová. To znamená, že můžete vytvořit svoji vlastní podtřídu třídy Array. Tato část poskytuje příklad způsobu vytvoření podtřídy třídy Array a uvádí některé z problémů, které mohou během procesu vzniknout. Jak již bylo zmíněno dříve, pole v jazyku ActionScript nejsou typová, ale můžete vytvořit podtřídu třídy Array, která přijímá prvky pouze určitého datového typu. Příklad v následujících částech definuje podtřídy třídy Array pojmenované TypedArray, které omezují její prvky na hodnoty datového typu určeného v prvním parametru. Třída TypedArray je uvedena pouze jako příklad rozšíření třídy Array a nemusí být vhodná pro účely produkování, a to z několika důvodů. Zaprvé, kontrola typu probíhá v době běhu spíše než v době kompilace. Zadruhé, jestliže metoda TypedArray nalezne nesoulad, bude nesoulad ignorován a nebude vygenerována žádná výjimka, ačkoliv mohou být metody snadno upraveny tak, aby výjimky vygenerovaly. Zatřetí, třída nemůže zabránit použití operátoru přístupu k poli ve vložení hodnot libovolného typu do pole. Začtvrté, styl kódování upřednostňuje jednoduchost před optimalizací výkonu. Poznámka: Zde popsanou techniku můžete použít k vytvoření typovaného pole. Lepším přístupem je nicméně použít objekt Vector. Instance Vector je pravé typované pole a na rozdíl od třídy Array nebo jakékoliv podtřídy poskytuje lepší výkon a jiné výhody. Účelem této diskuse je ukázat způsob vytvoření podtřídy Array. Deklarování podtřídy Pomocí klíčového slova extends určíte, že třída je podtřídou třídy Array. Podtřída třídy Array by měla použít atribut dynamic, stejně jako třída Array. V opačném případě nebude vaše podtřída pracovat správně. Následující kód ukazuje definici třídy TypedArray obsahující konstantu, která bude obsahovat datový typ, metodu konstruktoru a čtyři metody, které jsou schopné přidat prvky do pole. V tomto příkladě je u každé metody vynechán kód, ale je vymezen a plně vysvětlen v částech uvedených níže: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 170 Práce s poli public dynamic class TypedArray extends Array { private const dataType:Class; public function TypedArray(...args) {} AS3 override function concat(...args):Array {} AS3 override function push(...args):uint {} AS3 override function splice(...args) {} AS3 override function unshift(...args):uint {} } Všechny čtyři potlačené metody používají jmenný prostor AS3 namísto atributu public, protože tento příklad předpokládá, že je volba kompilátoru -as3nastavena na hodnotu true a volba kompilace -es je nastavena na false. Jedná se o výchozí nastavení produktu Adobe Flex Builder 3 a Adobe® Flash® CS4 Professional. Více informací naleznete v části „Jmenný prostor AS3“ na stránce 120. Jste-li pokročilý vývojář, který upřednostňuje použití dědičnosti prototypu, můžete provést dvě menší změny třídy TypedArray a přikázat jí kompilovat s volbou kompilace -es nastavenou na true. Nejprve odstraňte všechny výskyty atributu override a nahraďte jmenný prostor AS3 atributem public. Zadruhé, nahraďte Array.prototype pro všechny čtyři výskyty super. Konstruktor TypedArray Konstruktor podtřídy představuje zajímavou otázku, protože musí přijmout seznam argumentů libovolné délky. Otázka se týká způsobu odeslání argumentů na superkonstruktor pro vytvoření pole. Jestliže předáte seznam argumentů jako pole, superkonstruktor jej bude považovat za jediný argument typu Array a výsledné pole je vždy o 1 prvek delší. Tradičním způsobem zpracovávání procházení seznamů argumentů je použití metody Function.apply(), která bere pole argumentů jako svůj druhý parametr, ale převádí jej na seznam argumentů při provádění funkce. Metodu Function.apply() nelze bohužel použít s konstruktory. Jedinou zbývající možností je znovu vytvořit logiku konstruktoru Array v konstruktoru TypedArray. Následující kód ukazuje algoritmus použitý v konstruktoru třídy Array, který můžete znovu použít v konstruktoru podtřídy Array: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 171 Práce s poli public dynamic class Array { public function Array(...args) { var n:uint = args.length if (n == 1 && (args[0] is Number)) { var dlen:Number = args[0]; var ulen:uint = dlen; if (ulen != dlen) { throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")"); } length = ulen; } else { length = n; for (var i:int=0; i < n; i++) { this[i] = args[i] } } } } Konstruktor TypedArray sdílí většinu kódu z konstruktoru Array, pouze se čtyřmi změnami kódu. Zaprvé, seznam parametrů zahrnuje nový vyžadovaný parametr typu Class, který umožňuje specifikaci datového typu pole. Zadruhé, datový typ předaný konstruktoru je přiřazen proměnné dataType. Zatřetí, v příkazu else je hodnota vlastnosti length přiřazena po smyčce for, takže length zahrnuje pouze argumenty, které mají správný typ. Začtvrté, tělo smyčky for používá potlačenou verzi metody push(), takže jsou do pole přidány pouze argumenty správného datového typu. Následující příklad ukazuje funkci TypedArray. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 172 Práce s poli public dynamic class TypedArray extends Array { private var dataType:Class; public function TypedArray(typeParam:Class, ...args) { dataType = typeParam; var n:uint = args.length if (n == 1 && (args[0] is Number)) { var dlen:Number = args[0]; var ulen:uint = dlen if (ulen != dlen) { throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")") } length = ulen; } else { for (var i:int=0; i < n; i++) { // type check done in push() this.push(args[i]) } length = this.length; } } } Potlačené metody TypedArray Třída TypedArray potlačí čtyři metody třídy Array, které mohou přidat prvky do pole. V každém případě přidá potlačená metoda kontrolu typu, která zabrání předání prvků bez správného datového typu. Následně každá metoda volá verzi nadřazené třídy sebe sama. Metoda push() iteruje skrze seznam argumentů se smyčkou for..in a na každém argumentu provádí kontrolu typu. Jakýkoliv argument, který nemá správný typ, je odstraněn z pole args pomocí metody splice(). Po ukončení smyčky for..in obsahuje pole args pouze hodnoty typudataType. Verze nadřazené třídy push()je poté volána s aktualizovaným polem args, viz následující příklad: AS3 override function push(...args):uint { for (var i:* in args) { if (!(args[i] is dataType)) { args.splice(i,1); } } return (super.push.apply(this, args)); } Metoda concat() vytvoří přechodnou třídu TypedArray pojmenovanou passArgs pro uložení argumentů, které projdou kontrolou typu. To umožní opětovné použití kódu kontroly typu, který existuje v metodě push(). Smyčka for..in iteruje skrze pole args a na každém argumentu volá metodu push(). Protože je passArgs typováno jako TypedArray, bude provedena verze TypedArray metody push(). Metoda concat() poté volá verzi své vlastní nadřazené třídy, viz následující příklad: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 173 Práce s poli AS3 override function concat(...args):Array { var passArgs:TypedArray = new TypedArray(dataType); for (var i:* in args) { // type check done in push() passArgs.push(args[i]); } return (super.concat.apply(this, passArgs)); } Metoda splice() vezme libovolný seznam argumentů, ale první dva argumenty se vždy vztahují k číslu indexu a počtu prvků, které mají být odstraněny. To je důvod, proč potlačená metoda splice() provádí kontrolu typu pouze pro prvky pole args v poloze indexu 2 nebo vyšší. Jedním bodem zájmu je kód, který se zdá být rekurzivním voláním splice() uvnitř smyčky for, ale nejedná se o rekurzivní volání, protože args je typem třídy Array, nikoliv TypedArray, což znamená, že volání args.splice() je voláním verze nadřazené třídy metody. Po ukončení smyčky for..in obsahuje pole args pouze hodnoty se správným typem v poloze indexu 2 nebo vyšší a metoda splice() volá verzi své vlastní nadřazené třídy, viz.následující kód: AS3 override function splice(...args):* { if (args.length > 2) { for (var i:int=2; i< args.length; i++) { if (!(args[i] is dataType)) { args.splice(i,1); } } } return (super.splice.apply(this, args)); } Metoda unshift(), která přidává prvky na začátek pole, také přijímá libovolný seznam argumentů. Potlačená metoda unshift() používá algoritmus velice podobný algoritmu používaného metodou push(), viz následující příklad kódu: AS3 override function unshift(...args):uint { for (var i:* in args) { if (!(args[i] is dataType)) { args.splice(i,1); } } return (super.unshift.apply(this, args)); } } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 174 Práce s poli Příklad: PlayList Příklad PlayList ukazuje techniky pro práci s poli v kontextu aplikace seznamu přehrávání hudby, která spravuje seznam písní. Tyto techniky jsou následující: • Vytvoření indexovaného pole • Přidávání položek do indexovaného pole • Třídění pole objektů podle odlišných vlastností, pomocí odlišných voleb třídění • Převádění pole na řetězec oddělený znakem. Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace PlayList lze nalézt ve složce Samples/PlayList. Aplikace sestává z následujících souborů: Soubor Popis PlayList.mxml Hlavní soubor aplikace v programu Flash (FLA) nebo Flex (MXML). nebo PlayList.fla com/example/programmingas3/playlist/PlayList.as Třída, která zastupuje seznam skladeb. K uložení seznamu používá pole a spravuje pořadí položek tohoto seznamu. com/example/programmingas3/playlist/Song.as Objekt hodnoty představující informaci o jediné písni. Položky, které jsou spravovány třídou PlayList, jsou instancemi třídy Song. com/example/programmingas3/playlist/SortProperty.as Pseudo-vyčíslení, jehož dostupné hodnoty představují vlastnosti třídy Song, dle kterých lze třídit seznam objektů Song. Přehled třídy PlayList Třída PlayList spravuje sadu objektů Song. Má veřejné metody s funkcemi pro přidání písně do seznamu přehrávání (metoda addSong()) a třídění písní v seznamu (metody sortList()). Daná třída také zahrnuje vlastnost přístupového mechanismu určenou pouze ke čtení songList, která poskytuje přístup k vlastnímu seznamu písní v seznamu přehrávání. Třída PlayList interně uchovává záznamy svých písní pomocí soukromé proměnné Array: public class PlayList { private var _songs:Array; private var _currentSort:SortProperty = null; private var _needToSort:Boolean = false; ... } Vedle proměnné třídy Array _songs, která je používána třídou PlayList pro uchovávání záznamů svého seznamu písní, uchovávají dvě další soukromé proměnné záznam toho, zda je třeba seznam třídit (_needToSort) a podle které vlastnosti je seznam písní v daný čas tříděn (_currentSort). Jako u všech objektů je prohlášení instance třídy Array pouze polovinou procesu vytváření třídy Array. Před získáním přístupu k vlastnostem nebo metodám instance třídy Array musí být konkretizováno, která z nich je provedena v konstruktoru třídy PlayList. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 175 Práce s poli public function PlayList() { this._songs = new Array(); // Set the initial sorting. this.sortList(SortProperty.TITLE); } První řádek konstruktoru konkretizuje proměnnou _songs a ta je poté připravena k použití. Dále je volána metoda sortList() pro nastavení počáteční metody, podle které má být provedeno třídění. Přidání písně do seznamu Jestliže uživatel přidá do aplikace novou píseň, kód v záznamu dat vytvoří volání metody třídy PlayList addSong(). /** * Adds a song to the playlist. */ public function addSong(song:Song):void { this._songs.push(song); this._needToSort = true; } Uvnitř addSong() je volána metoda pole _songs nazvaná push() přidávající objekt Song, který byl předán do addSong() jako nový prvek v daném poli. V případě metody push() je nový prvek přidán na konec pole, bez ohledu na třídění, které mohlo být použito již dříve. To znamená, že po volání metody push() již seznam písní pravděpodobně nebude tříděn správně, takže proměnná _needToSort je nastavena na hodnotu true. Teoreticky by mohla být metoda sortList() volána okamžitě a nebylo by tak třeba uchovávat záznam toho, zda je seznam tříděn či nikoliv. V praxi nicméně není třeba třídit seznam písní až do okamžiku těsně před jeho získáním. Rozlišením operací třídění aplikace neprovede třídění, které není nutné, jestliže je například několik tříd přidáno do seznamu před jeho získáním. Třídění seznamu písní Protože jsou instance třídy Song spravované seznamem přehrávání složitými objekty, mohou si uživatelé aplikace přát třídit seznam přehrávání podle různých vlastností, například názvu písně nebo roku vydání. V aplikaci PlayList má úloha třídění seznamu písní tři části: identifikace vlastnosti, podle které by měl být seznam tříděn, určení voleb třídění, které je třeba použít při třídění dané vlastnosti a samotné provedení operace třídění. Vlastnosti pro třídění Objekt Song uchovává záznam o několika vlastnostech, včetně názvu písně, interpreta, roku vydání, názvu souboru a uživatelem vybraných skupiny žánrů, do které daná třída patří. Z výše uvedených vlastností mají pouze první tři praktické využití při třídění. Pro usnadnění práce vývojářů obsahuje daný příklad třídu SortProperty, která se chová jako vyčíslení s hodnotami představujícími vlastnosti dostupné pro třídění. public static const TITLE:SortProperty = new SortProperty("title"); public static const ARTIST:SortProperty = new SortProperty("artist"); public static const YEAR:SortProperty = new SortProperty("year"); Třída SortProperty obsahuje tři konstanty TITLE, ARTIST a YEAR a každá z nich uchovává String obsahující skutečný název vlastnosti přidružené třídy Song, kterou lze použít pro třídění. Ve zbytku kódu, kdykoliv je určena vlastnost třídění, je třídění provedeno pomocí člena vyčíslení. Například v konstruktoru PlayList je seznam zpočátku tříděn voláním metody sortList(), a to následovně: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 176 Práce s poli // Set the initial sorting. this.sortList(SortProperty.TITLE); Protože je vlastnost pro třídění určena jako SortProperty.TITLE, jsou písně tříděny pole svého názvu. Třídění dle vlastnosti a určení voleb třídění Práce vlastního třídění seznamu písní je provedena třídou PlayList v metodě sortList(), a to následovně: /** * Sorts the list of songs according to the specified property. */ public function sortList(sortProperty:SortProperty):void { ... var sortOptions:uint; switch (sortProperty) { case SortProperty.TITLE: sortOptions = Array.CASEINSENSITIVE; break; case SortProperty.ARTIST: sortOptions = Array.CASEINSENSITIVE; break; case SortProperty.YEAR: sortOptions = Array.NUMERIC; break; } // Perform the actual sorting of the data. this._songs.sortOn(sortProperty.propertyName, sortOptions); // Save the current sort property. this._currentSort = sortProperty; // Record that the list is sorted. this._needToSort = false; } Během třídění podle názvu nebo interpreta je vhodné třídit abecedně, ale při třídění na základě roku je logičtější provést číselné třídění. Příkaz switch se používá pro definování vhodné volby třídění, uložené v proměnné sortOptions, podle hodnoty určené v parametru sortProperty. Zde jsou opět pojmenované členy vyčíslení použity pro rozlišení mezi vlastnostmi, spíše než pevně kódované hodnoty. S určenou vlastností třídění a volbami třídění je pole _songs vlastně tříděno voláním své metody sortOn()a předáním těchto dvou hodnot jako parametrů. Aktuální vlastnost třídění je zaznamenána stejně jako fakt, že daná píseň je aktuálně tříděna. Kombinování prvků pole do řetězce odděleného znakem Vedle používání pole k uchovávání seznamu písní ve třídě PlayList, jsou v tomto příkladě pole také použita ve třídě Song pro usnadnění správy seznamu žánrů, do kterého daná píseň patří. Věnujte pozornost tomuto výstřižku z definice třídy Song: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 177 Práce s poli private var _genres:String; public function Song(title:String, artist:String, year:uint, filename:String, genres:Array) { ... // Genres are passed in as an array // but stored as a semicolon-separated string. this._genres = genres.join(";"); } Při vytváření nové instance Song je parametr genres používaný pro učení žánru (nebo žánrů), do kterého daná píseň patří, definován jako instance třída Array. Je proto výhodné seskupit více žánrů dohromady do jediné proměnné, kterou lze předat konstruktoru. Nicméně třída Song interně uchovává žánry v soukromé proměnné _genres jako instanci řetězce odděleného středníkem. Parametr Array je převeden do řetězce odděleného středníkem voláním své metody join() s hodnotou řetězce literálu ";" jako určeného oddělovače. Dle stejného důkazu mechanismy přístupu genres umožňují nastavení nebo dosazení žánrů jako třídu Array: public function get genres():Array { // Genres are stored as a semicolon-separated String, // so they need to be transformed into an Array to pass them back out. return this._genres.split(";"); } public function set genres(value:Array):void { // Genres are passed in as an array, // but stored as a semicolon-separated string. this._genres = value.join(";"); } Mechanismus přístupu genresset se chová stejně jako konstruktor; přijímá pole, volá metodu join() a převádí jej na řetězec oddělený středníkem. Mechanismus přístupu get provede opačnou operaci: volána je metoda proměnné _genres s názvem split() a rozdělí String do pole hodnot pomocí určeného oddělovače (hodnoty řetězce literálu ";" jako dříve). 178 Kapitola 9: Zpracování chyb Zpracování chyb znamená, že se do aplikace začlení logika, která zpracuje neboli opraví chybu vygenerovanou buďto během kompilování aplikace nebo za běhu již zkompilované aplikace. Když aplikace zpracovává chyby, něco se stane jako odezva na zjištění chyby, na rozdíl od tichého selhání procesu, při němž k této chybě došlo, bez jakékoliv odezvy. Při správném použití pomáhá zpracování chyb chránit příslušnou aplikaci a její uživatele proti jinak neočekávanému chování. Zpracování chyb je však velmi obsáhlá kategorie zahrnující odezvy na různé druhy chyb vyvolaných během kompilování nebo za běhu. Tato kapitola je zaměřena na zpracování chyb vzniklých za běhu (různých druhů chyb, které mohou být vygenerovány) a na výhody nového systému zpracování chyb v jazyce ActionScript 3.0. Dále je v této kapitole vysvětlen postup při implementaci vlastních strategií pro zpracování chyb v příslušné aplikaci. Základy zpracování chyb Úvod do zpracování chyb Chyba chodu programu je porucha, která nastane v kódu jazyka ActionScript a zastaví provádění jeho obsahu v aplikaci Adobe® Flash® Player nebo Adobe® AIR™. Chcete-li uživatelům zajistit hladké provádění kódu jazyka ActionScript, musíte ve vlastní aplikaci napsat kód, který chybu zpracuje – opraví ji, obejde ji nebo alespoň uživatele upozorní, že k ní došlo. Tento proces se nazývá zpracování chyb. Zpracování chyb je velmi obsáhlá kategorie zahrnující odezvy na různé druhy chyb vyvolaných během kompilování nebo za běhu. Chyby, k nimž dojde během kompilování, se obvykle snáze identifikují – je nezbytné je opravit, aby bylo možné dokončit proces vytváření souboru SWF. Tato kapitola se nezabývá chybami kompilace. Další informace o psaní kódu, který neobsahuje chyby kompilace naleznete v sekcích „Jazyk ActionScript a jeho syntaxe“ na stránce 37a „Objektově orientované programování v jazyce ActionScript“ na stránce 89. Tato kapitola je zaměřena na chyby chodu programu. Chyby chodu programu může být obtížnější zjistit, protože aby k nim vůbec došlo, musí se provádět chybný kód. Máli segment programu několik větví kódu, např. příkaz if..then..else, je zapotřebí otestovat všechny možné podmínky se všemi možnými vstupními hodnotami, které mohou použít skuteční uživatelé, aby bylo možné potvrdit, že se v příslušném kódu nevyskytují chyby. Chyby chodu programu lze rozdělit do dvou kategorií: chyby programu jsou chyby v kódu jazyka ActionScript, např. určení nesprávného datového typu u parametru metody; logické chyby jsou chyby v logice (kontrola dat a manipulace s hodnotami) programu, např. použití nesprávného vzorce k výpočtu výše úroků v bankovní aplikaci. Opět platí, že tyto typy chyb lze často odhalit a opravit předem důkladným otestováním aplikace. V ideálním případě budou všechny chyby odhaleny a odstraněny z aplikace ještě před jejím vydáním koncovým uživatelům. Ne všechny chyby je však možné předvídat nebo jim zamezit. Předpokládejme například, že aplikace jazyka ActionScript načte informace z určitého webového místa, které nemáte pod kontrolou. Pokud se stane, že toto webové místo nebude k dispozici, nebude se ta část aplikace, která je závislá na těchto externích datech, chovat správně. K nejdůležitějším aspektům zpracování chyb patří příprava na tyto neznámé případy a jejich postupné zpracování, aby uživatelé mohli i nadále příslušnou aplikaci používat, nebo alespoň obdrželi přátelskou chybovou zprávu s vysvětlením, proč aplikace nefunguje. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 179 Zpracování chyb Chyby chodu programu jsou v jazyce ActionScript vyjádřeny dvěma způsoby: • Třídy chyb: K celé řadě chyb je přiřazena třída chyb. Když dojde k chybě, aplikace Flash Player nebo Adobe AIR vytvoří instanci určité třídy chyb, která je přiřazena k této konkrétní chybě. Příslušný kód může použít informace obsažené v tomto objektu chyby k zajištění vhodné odezvy na chybu. • Události chyb: Někdy dojde k chybě ve chvíli, kdy by aplikace Flash Player nebo Adobe AIR normálně spustila událost. V takových případech spustí aplikace Flash Player a Adobe AIR místo toho událost chyby. Stejně jako ostatní události má i každá událost chyby přiřazenu třídu a aplikace Flash Player a Adobe AIR předávají instanci této třídy do metod, které jsou přihlášeny k této události chyby. Chcete-li určit, zda může určitá metoda spustit chybu nebo událost chyby, přečtěte si zadání této metody v Referenční příručce jazyka ActionScript 3.0 a jeho součástí. Běžné úlohy zpracování chyb Zde jsou uvedeny nejběžnější úlohy týkající se chyb, které může být zapotřebí provést u příslušného kódu: • Psaní kódu pro zpracování chyb • Testování výskytu, zachycení a opětné vyvolání chyb • Definování vlastní třídy chyb • Reagování na události chyb a stavů Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Asynchronní: Příkaz programu, např. volání metody, který nezajistí okamžitý výsledek. Místo toho poskytne výsledek (nebo chybu) ve formě události. • Zachycení: Když dojde k výjimce (nebo k chybě chodu programu) a příslušný kód si výjimku uvědomí, říká se, že kód výjimku zachytí. Jakmile je výjimka zachycena, přestanou aplikace Flash Player a Adobe AIR upozorňovat zbývající kód jazyka ActionScript na tuto výjimku. • Ladicí verze: Speciální verze aplikace Flash Player nebo Adobe AIR (ADL) obsahující kód pro upozornění uživatelů na chyby chodu programu. Ve standardní verzi aplikace Flash Player nebo Adobe AIR (kterou má většina uživatelů) se chyby, jež nejsou zpracovány kódem jazyka ActionScript, ignorují. V ladicích verzích (které jsou součástí aplikací Adobe Flash CS4 Professional a Adobe Flex) se zobrazí výstražná zpráva, když dojde k výskytu nezpracovávané chyby. • Výjimka: Chyba, k níž dojde za běhu programu, nebo kterou prostředí běhu programu (tj. Flash Player nebo Adobe AIR) nedokáže samostatně vyřešit. • Opětné vyvolání: Když kód výjimku zachytí, aplikace Flash Player nebo Adobe AIR již neupozorňuje ostatní objekty na tuto výjimku. Pokud je důležité, aby byly ostatní objekty na výjimku upozorněny, musí ji kód znovu vyvolat a tím znovu spustit proces upozornění. • Synchronní: Příkaz programu, např. volání metody, který zajistí okamžitý výsledek (neboli okamžitě vyvolá chybu), což znamená, že tuto odezvu je možné použít ve stejném bloku kódu. • Vyvolání: Upozornění aplikace Flash Player nebo Adobe AIR (a následkem toho i upozornění ostatních objektů a kódu jazyka ActionScript), že došlo k chybě, se nazývá vyvolání chyby. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 180 Zpracování chyb Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. V podstatě všechny výpisy kódů uvedené v této kapitole zahrnují příslušné volání funkce trace(). Návod na vyzkoušení kódů uvedených v této kapitole: 1 Vytvořte prázdný dokument Flash. 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Spusťte program pomocí příkazu Ovládání > Testovat film. Výsledky funkcí trace() uvedených kódů uvidíte v panelu Výstup. Některé výpisy kódů uvedené dále jsou složitější a jsou napsány jako třída. Postup při testování těchto příkladů: 1 Vytvořte prázdný dokument Flash a uložte ho ve svém počítači. 2 Vytvořte nový soubor ActionScript a uložte ho do stejného adresáře jako dokument Flash. Název souboru by měl být stejný jako název třídy ve výpisu kódu. Jestliže například výpis kódu definuje třídu s názvem ErrorTest, použijte k uložení souboru ActionScript název ErrorTest.as. 3 Zkopírujte výpis kódu do souboru ActionScript a soubor uložte. 4 V dokumentu Flash klepněte na prázdnou část Plochy nebo pracovní oblasti a aktivujte Inspektor vlastností dokumentu. 5 V Inspektoru vlastností zadejte do pole Třída dokumentu název třídy ActionScript vykopírovaný z textu. 6 Spusťte program pomocí volby Ovládání > Testovat film. Výsledky příkladu se zobrazí v panelu Výstup (pokud je v příkladu použita funkce trace()) nebo v textovém poli vytvořeném kódem příkladu. Tyto postupy pro testování vzorových výpisů kódů jsou podrobněji popsány v sekci „Testování příkladů kódu v této kapitole“ na stránce 34. Typy chyb Při vyvíjení a spouštění aplikací narazíte na různé typy chyb a na terminologii související s chybami. V následujícím soupise jsou vysvětleny hlavní typy chyb a termíny: • Chyby kompilace vyvolává kompilátor ActionScript během kompilování kódu. K chybám kompilace dochází, když potíže se syntaxí v příslušném kódu zamezí vytvoření aplikace. • Chyby chodu programu vznikají při spuštění aplikace po jejím zkompilování. Chyby chodu programu jsou chyby, k nimž dochází během přehrávání souboru SWF v aplikaci Adobe Flash Player nebo Adobe AIR. Ve většině případů je možné chyby chodu programu zpracovat hned při jejich výskytu, nahlásit je uživateli a podniknout kroky pro zajištění nepřetržitého chodu aplikace. Jestliže se jedná o závažnou chybu, např. nelze navázat připojení ke vzdálenému webovému místu nebo načíst požadovaná data, je možné prostřednictvím zpracování chyb umožnit aplikaci postupné dokončení operace. • Synchronní chyby jsou chyby chodu programu, k nimž dochází při zavolání funkce – když například zkusíte použít určitou metodu a argument předaný metodě je neplatný, takže aplikace Flash Player nebo Adobe AIR vyvolá výjimku. Většina chyb vzniká synchronně – při vykonávání příkazu – a postup řízení ihned přejde k nejvhodnějšímu příkazu catch. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 181 Zpracování chyb Následující výpis kódu například vyvolá chybu chodu programu, protože metoda browse() není zavolána před tím, než se program pokusí odeslat soubor: var fileRef:FileReference = new FileReference(); try { fileRef.upload("http://www.yourdomain.com/fileupload.cfm"); } catch (error:IllegalOperationError) { trace(error); // Error #2037: Functions called in incorrect sequence, or earlier // call was unsuccessful. } V tomto případě vznikne chyba chodu programu synchronně, neboť aplikace Flash Player zjistila, že metoda browse() nebyla zavolána před tím, než proběhl pokus o odeslání souboru. Podrobné informace týkající se zpracování synchronních chyb naleznete v sekci „Zpracování synchronních chyb v aplikaci“ na stránce 184. • Asynchronní chyby jsou chyby chodu programu, k nimž dochází na různých místech během chodu programu. Generují události a zachycují je posluchači událostí. Asynchronní operace je taková, při níž funkce spustí operaci, ale nečeká na její dokončení. Lze vytvořit posluchače událostí chyb, který počká, až aplikace nebo uživatel zkusí provést nějakou operaci, a pokud tato operace selže, lze zachytit chybu pomocí posluchače událostí a reagovat na událost chyby. Posluchač událostí pak zavolá funkci zpracování události, aby vhodným způsobem reagovala na událost chyby. Zpracování události může například spustit dialogový rámeček, který uživatele vyzve k vyřešení chyby. Posuďte výše uvedený příklad synchronní chyby při odesílání souboru. Jestliže před zahájením odesílání souboru úspěšně zavoláte metodu browse(), aplikace Flash Player odešle několik událostí. Při zahájení odesílání se například odešle událost open. Po úspěšném dokončení odeslání souboru bude odeslána událost complete. Vzhledem k tomu, že zpracování chyb je asynchronní (tj. neprobíhá v určitou, známou, předem definovanou dobu), je třeba poslouchat tyto specifické události pomocí metody addEventListener(), jak je znázorněno v následujícím kódu: var fileRef:FileReference = new FileReference(); fileRef.addEventListener(Event.SELECT, selectHandler); fileRef.addEventListener(Event.OPEN, openHandler); fileRef.addEventListener(Event.COMPLETE, completeHandler); fileRef.browse(); function selectHandler(event:Event):void { trace("...select..."); var request:URLRequest = new URLRequest("http://www.yourdomain.com/fileupload.cfm"); request.method = URLRequestMethod.POST; event.target.upload(request.url); } function openHandler(event:Event):void { trace("...open..."); } function completeHandler(event:Event):void { trace("...complete..."); } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 182 Zpracování chyb Podrobné informace týkající se zpracování asynchronních chyb naleznete v sekci „Reakce na chybové události a stavy“ na stránce 189. • Nezachycené výjimky jsou chyby vyvolané bez odpovídající logiky (např. příkazu catch), která by na ně reagovala. Pokud aplikace vyvolá chybu a na aktuální nebo vyšší úrovni se nenachází žádný příkaz catch nebo metoda zpracování události vhodná ke zpracování této chyby, je chyba považována za nezachycenou výjimku. Aplikace Flash Player nezachycené výjimky za běhu standardně ignoruje a zkouší pokračovat v přehrávání, pokud chyba nezastaví aktuální soubor SWF, protože uživatelé nemusí být nutně schopni chybu sami vyřešit. Proces ignorování nezachycené chyby se nazývá „tiché selhání“ a může zkomplikovat ladění aplikací. Ladicí verze aplikace Flash Player reaguje na nezachycenou chybu ukončením aktuálního skriptu a zobrazením nezachycené chyby ve výstupu příkazu trace nebo zapsáním chybové zprávy do souboru záznamu. Jestliže je objekt výjimky instance třídy Error nebo některé z jejích podtříd, vyvolá se metoda getStackTrace() a informace sledování zásobníku se rovněž zobrazí ve výstupu příkazu trace nebo v souboru záznamu. Další informace týkající se použití ladicí verze aplikace Flash Player naleznete v sekci „Práce s ladicími verzemi aplikací Flash Player a AIR“ na stránce 183. Zpracování chyb v jazyce ActionScript 3.0 Vzhledem k tomu, že řada aplikací může běžet i bez začlenění logiky pro zpracování chyb, mají vývojáři tendenci odkládat začlenění zpracování chyb do svých aplikací. Bez zpracování chyb se však může aplikace snadno zastavit nebo může uživateli zmařit plány, pokud něco nebude fungovat tak, jak má. Jazyk ActionScript 2.0 má třídu Error, ve které lze do vlastních funkcí začlenit logiku k vyvolání výjimky s určitou zprávou. Jelikož je zpracování chyb velmi důležité pro vytvoření uživatelsky přívětivé aplikace, zahrnuje jazyk ActionScript 3.0 rozšířenou architekturu k zachycení chyb. Poznámka: Přestože Referenční příručka jazyka ActionScript 3.0 a jeho komponent dokumentuje výjimky vyvolané celou řadou metod, nemusí zahrnovat všechny výjimky, které u jednotlivých metod přicházejí v úvahu. Metoda může vyvolat výjimku kvůli syntaktickým chybám či jiným potížím, jež nejsou v popisu metody explicitně uvedeny, a to i v případě, že popis zahrnuje výčet některých výjimek, které může metoda vyvolat. Elementy zpracování událostí v jazyce ActionScript 3.0 Jazyk ActionScript 3.0 obsahuje celou řadu nástrojů pro zpracování chyb, včetně: • Třídy chyb. Jazyk ActionScript 3.0 zahrnuje široké rozpětí tříd Error k rozšíření rozsahu situací, které mohou vyprodukovat objekty chyb. Každá třída Error pomáhá aplikaci zpracovat a reagovat na určité chyby, ať už se jedná o systémové chyby (např. stav MemoryError), chyby v kódování (např. stav ArgumentError), chyby v síťovém propojení nebo v komunikaci (např. stav URIError) či jiné situace. Další informace o jednotlivých třídách naleznete v sekci „Porovnání tříd Error“ na stránce 192. • Méně tichých selhání. V dřívějších verzích aplikace Flash Player se chyby generovaly a hlásily pouze při explicitním použití příkazu throw. U přehrávače Flash Player verze 9 a pozdější a programu Adobe AIR nativní metody a vlastnosti jazyka ActionScript vyvolávají chyby chodu programu, díky nimž lze tyto výjimky zpracovat mnohem efektivněji hned při jejich výskytu a následně na jednotlivé výjimky individuálně reagovat. • Zobrazení jasných chybových zpráv během ladění. Při použití ladicí verze aplikace Flash Player nebo Adobe AIR se při potížích s kódem nebo v problematických situacích vygenerují robustní chybové zprávy, pomocí nichž lze snadno odhalit příčinu selhání určitého bloku kódu. Tím se opravování chyb značně zefektivní. Další informace naleznete v sekci „Práce s ladicími verzemi aplikací Flash Player a AIR“ na stránce 183. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 183 Zpracování chyb • Díky přesným chybám se mohou uživatelům za běhu zobrazovat jasné chybové zprávy. V předchozích verzích aplikace Flash Player vracela metoda FileReference.upload() Booleovskou hodnotu false, pokud bylo volání metody upload() neúspěšné, což značilo jednu z pěti možných chyb. Jestliže dojde k chybě při volání metody upload() v jazyce ActionScript 3.0, lze vyvolat jednu ze čtyř specifických chyb, takže se uživatelům mohou zobrazovat přesnější chybové zprávy. • Přesnější zpracování chyb. V řadě běžných situací se zobrazují odlišné chyby. V jazyce ActionScript 2.0 má například před vyplněním objektu FileReference vlastnost name hodnotu null (takže před tím, než bude možné vlastnost name použít nebo zobrazit, je třeba zajistit její nastavení na jinou hodnotu než null). Pokud se v jazyce ActionScript 3.0 pokusíte vstoupit do vlastnosti name dříve, než bude vyplněna, vyvolá aplikace Flash Player nebo AIR chybu IllegalOperationError, která značí, že nebyla nastavena hodnota. Ke zpracování chyby lze použít bloky try..catch..finally. Další informace naleznete v sekci „Použití příkazů try..catch..finally“ na stránce 184. • Žádné výrazné zhoršení výkonnosti. Zpracování chyb pomocí bloků try..catch..finally nevyžaduje oproti předchozím verzím jazyka ActionScript žádné nebo jen minimální zdroje navíc. • Třída ErrorEvent umožňující vytvoření posluchačů pro specifické události asynchronních chyb. Další informace naleznete v sekci „Reakce na chybové události a stavy“ na stránce 189. Strategie zpracování chyb Dokud aplikace nenarazí na problematický stav, může úspěšně fungovat i v případě, že do příslušného kódu nebude začleněna logika zpracování chyb. Jestliže však nebudou chyby aktivně zpracovány a v aplikaci dojde k potížím, uživatelé se nedozví důvod selhání aplikace. Zpracování chyb je možné v aplikaci řešit několika způsoby. V následujícím výčtu jsou shrnuty tři základní možnosti zpracování chyb: • Použití příkazů try..catch..finally . Ty zachytí synchronní chyby hned při jejich výskytu. Příkazy lze vnořit do hierarchie za účelem zachycení výjimek na různých úrovních provádění kódu. Další informace naleznete v sekci „Použití příkazů try..catch..finally“ na stránce 184. • Vytvoření vlastních objektů chyb. Pomocí třídy Error lze vytvořit vlastní objekty chyb sloužící ke sledování specifických operací v aplikaci, jež nejsou pokryty vestavěnými typy chyb. Potom lze u vlastních objektů chyb použít příkazy try..catch..finally. Další informace naleznete v sekci „Vytvoření vlastních tříd chyb“ na stránce 188. • Vytvoření posluchačů a zpracování událostí k zajištění odezvy na události chyb. Pomocí této strategie lze vytvořit globální zpracování chyb, které umožní zpracování podobných událostí bez duplikování příliš velké části kódu v blocích try..catch..finally. U tohoto přístupu je rovněž vyšší pravděpodobnost zachycení asynchronních chyb. Další informace naleznete v sekci „Reakce na chybové události a stavy“ na stránce 189. Práce s ladicími verzemi aplikací Flash Player a AIR Aplikace Adobe poskytuje vývojářům speciální verze aplikací Flash Player a Adobe AIR usnadňující ladění. Kopii ladicí verze aplikace Flash Player získáte při instalaci softwaru Adobe Flash CS4 Professional nebo Adobe Flex Builder 3. Verzi ladiče také získáte z verze aplikace Adobe AIR, která se nazývá ADL, když nainstalujete některý z těchto nástrojů nebo jako součást sady SDK aplikace Adobe AIR. Mezi tím, jakým způsobem označují chyby ladicí verze a standardní verze aplikací Flash Player a Adobe AIR, je velký rozdíl. Ladicí verze zobrazují typ chyby (např. obecná chyba Error, IOError nebo EOFError), číslo chyby a lidmi čitelnou chybovou zprávu. Standardní verze zobrazují pouze typ a číslo chyby. Posuďte například následující kód: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 184 Zpracování chyb try { tf.text = myByteArray.readBoolean(); } catch (error:EOFError) { tf.text = error.toString(); } Kdyby metoda readBoolean() vyvolala v ladicí verzi aplikace Flash Player chybu EOFError, zobrazila by se v textovém poli tf následující zpráva: „EOFError: Error #2030: End of file was encountered.“ Stejný kód by ve standardní verzi aplikace Flash Player nebo Adobe AIR zobrazil následující text: „EOFError: Error #2030“. Za účelem omezení zdrojů informací a velikosti ve standardních verzích na minimum nejsou k dispozici řetězce chybových zpráv. Číslo chyby lze vyhledat v dokumentaci (přílohy Referenční příručky jazyka ActionScript 3.0 a jeho komponent) a dát je do vzájemného vztahu s chybovou zprávou. Případně je možné chybu reprodukovat pomocí ladicí verze aplikace Flash Player nebo AIR a zobrazit celou zprávu. Zpracování synchronních chyb v aplikaci Nejběžnějším zpracováním chyb je logika synchronního zpracování chyb, kde se do kódu vkládají příkazy pro zachycení synchronních chyb za běhu. Při tomto typu zpracování chyb dokáže aplikace zaregistrovat chyby chodu programu a obnovit svoji činnost, když dojde k selhání funkcí. Logika pro zachycení synchronní chyby zahrnuje příkazy try..catch..finally, které doslova vyzkouší operaci, zachytí odpověď aplikace Flash Player nebo Adobe AIR na chybu a nakonec provedou jinou operaci za účelem zpracování neúspěšné operace. Použití příkazů try..catch..finally Při práci se synchronními chybami chodu programu použijte příkazy try..catch..finally k zachycení chyb. Když dojde k chybě chodu programu, aplikace Flash Player nebo Adobe AIR vyvolá výjimku, což znamená, že přeruší normální provádění kódu a vytvoří speciální objekt typu Error. Objekt Error se pak vyvolá do prvního dostupného bloku catch. Příkaz try ohraničuje příkazy, u nichž může docházet k chybám. Příkaz catch se vždy používá s příkazem try. Budeli v některém příkazu v bloku příkazů try zjištěna chyba, provedou se příkazy catch připojené k tomuto příkazu try. Příkaz finally ohraničuje příkazy, které se provedou bez ohledu na to, zda v bloku try dojde k chybě či nikoliv. Pokud k žádné chybě nedojde, příkazy uvnitř bloku finally se provedou, jakmile budou dokončeny příkazy bloku try. V případě výskytu chyby se nejprve provede příslušný příkaz catch, po němž budou následovat příkazy v bloku finally. Následující kód ilustruje syntaxi pro použití příkazů try..catch..finally: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 185 Zpracování chyb try { // some code that could throw an error } catch (err:Error) { // code to react to the error } finally { // Code that runs whether or not an error was thrown. This code can clean // up after the error, or take steps to keep the application running. } Jednotlivé příkazy catch identifikují určité typy výjimek, který zpracovávají. Příkaz catch může určovat jen třídy chyb, která jsou podtřídami třídy Error. Jednotlivé příkazy catch se postupně zkontrolují. Provede se pouze první příkaz catch, který odpovídá vyvolanému typu chyby. Jinými slovy, jestliže se nejprve zkontroluje třída Error vyšší úrovně a pak podtřída třídy Error, bude odpovídat jen třída Error vyšší úrovně. Tato skutečnost je znázorněna v následujícím kódu: try { throw new ArgumentError("I am an ArgumentError"); } catch (error:Error) { trace("<Error> " + error.message); } catch (error:ArgumentError) { trace("<ArgumentError> " + error.message); } Předchozí kód zobrazí následující výstup: <Error> I am an ArgumentError Aby byla správně zachycena chyba ArgumentError, musí být nejprve uvedeny nejběžnější typy chyb a teprve potom obecnější typy chyb, jak znázorňuje následující kód: try { throw new ArgumentError("I am an ArgumentError"); } catch (error:ArgumentError) { trace("<ArgumentError> " + error.message); } catch (error:Error) { trace("<Error> " + error.message); } Řada metod a vlastností v rozhraní API aplikace Flash Player vyvolává chyby chodu programu v případě, že během provádění narazí na chybu. Například metoda close() ve třídě Sound vyvolá chybu IOError, pokud není schopna zavřít zvukový stream, jak ilustruje následující kód: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 186 Zpracování chyb var mySound:Sound = new Sound(); try { mySound.close(); } catch (error:IOError) { // Error #2029: This URLStream object does not have an open stream. } Až se blíže seznámíte s Referenční příručkou jazyka ActionScript 3.0 a jeho komponent, zjistíte, které metody vyvolávají výjimky, jak je podrobně uvedeno v popisu jednotlivých metod. Příkaz throw Aplikace Flash Player a Adobe AIR vyvolávají výjimky, když za běhu narazí na chyby v příslušné aplikaci. Kromě toho lze výjimky vyvolat explicitně pomocí příkazu throw. Při explicitním vyvolávání chyb Adobe doporučuje vyvolávat instance třídy Error nebo jejích podtříd. Následující kód znázorňuje příkaz throw, který vyvolá instanci třídy Error MyErr a případně vyvolá funkci myFunction() jako reakci na vyvolání chyby: var MyError:Error = new Error("Encountered an error with the numUsers value", 99); var numUsers:uint = 0; try { if (numUsers == 0) { trace("numUsers equals 0"); } } catch (error:uint) { throw MyError; // Catch unsigned integer errors. } catch (error:int) { throw MyError; // Catch integer errors. } catch (error:Number) { throw MyError; // Catch number errors. } catch (error:*) { throw MyError; // Catch any other error. } finally { myFunction(); // Perform any necessary cleanup here. } Všimněte si, že příkazy catch jsou uspořádány tak, aby nejpřesnější datové typy byly uvedeny jako první. Kdyby by byl nejprve uveden příkaz catch pro datový typ Number, nebyl by nikdy proveden příkaz catch pro datový typ uint ani příkaz catch pro datový typ int. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 187 Zpracování chyb Poznámka: V programovacím jazyce Java musí každá funkce, která může vyvolat výjimku, tuto skutečnost deklarovat, s uvedením tříd výjimek, jež dokáže vyvolat, v klauzuli throws připojené k deklaraci této funkce. V jazyce ActionScript není zapotřebí deklarovat výjimky, které může funkce vyvolat. Zobrazení jednoduché chybové zprávy Jedním z největších přínosů nového modelu událostí výjimek a chyb je, že lze uživatelům sdělit, kdy a proč akce selhala. Vaším úkolem je napsat kód pro zobrazení této zprávy a nabídnutí možných reakcí. Následující kód znázorňuje jednoduchý příkaz try..catch k zobrazení chyby v textovém poli: package { import flash.display.Sprite; import flash.text.TextField; public class SimpleError extends Sprite { public var employee:XML = <EmpCode> <costCenter>1234</costCenter> <costCenter>1-234</costCenter> </EmpCode>; public function SimpleError() { try { if (employee.costCenter.length() != 1) { throw new Error("Error, employee must have exactly one cost center assigned."); } } catch (error:Error) { var errorMessage:TextField = new TextField(); errorMessage.autoSize = TextFieldAutoSize.LEFT; errorMessage.textColor = 0xFF0000; errorMessage.text = error.message; addChild(errorMessage); } } } } Pomocí pestré škály tříd chyb a vestavěných chyb kompilátoru nabízí jazyk ActionScript 3.0 více informací o příčinách selhání činnosti než předchozí verze jazyka ActionScript. Díky tomu lze vytvářet stabilnější aplikace s lepším zpracováním chyb. Opětné vyvolání chyb Při vytváření aplikací může nastat několik případů, kdy je zapotřebí znovu vyvolat chybu, pokud nejste schopni tuto chybu řádně zpracovat. Následující kód například znázorňuje vnořený blok try..catch, který znovu vyvolá vlastní chybu ApplicationError, pokud vnořený blok catch není schopen tuto chybu zpracovat: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 188 Zpracování chyb try { try { trace("<< try >>"); throw new ArgumentError("some error which will be rethrown"); } catch (error:ApplicationError) { trace("<< catch >> " + error); trace("<< throw >>"); throw error; } catch (error:Error) { trace("<< Error >> " + error); } } catch (error:ApplicationError) { trace("<< catch >> " + error); } Výstup předcházejícího zlomku kódu by byl následující: << << << << try >> catch >> ApplicationError: some error which will be rethrown throw >> catch >> ApplicationError: some error which will be rethrown Vnořený blok try vyvolá vlastní chybu ApplicationError, která bude zachycena následujícím blokem catch. Tento vnořený blok catch může zkusit chybu zpracovat a pokud se mu to nepodaří, může vyvolat objekt ApplicationError do uzavírajícího bloku try..catch. Vytvoření vlastních tříd chyb V jazyce ActionScript je možné rozšířit jednu ze standardních tříd Error a vytvořit vlastní specializované třídy chyb. K vytvoření vlastních tříd chyb existuje řada důvodů: • Určení specifických chyb nebo skupin chyb, které jsou jedinečné pro příslušnou aplikaci. Například můžete chtít provést různé akce u chyb vyvolaných vlastním kódem, kromě těch, které zachytí aplikace Flash Player nebo Adobe AIR. Můžete vytvořit podtřídu třídy Error pro sledování nového datového typu chyb v blocích try..catch. • Zajištění jedinečných schopností zobrazení chyb vygenerovaných příslušnou aplikací. Například je možné vytvořit novou metodu toString(), která zformátuje chybové zprávy určitým způsobem. Rovněž lze definovat metodu lookupErrorString(), která na základě jazykových preferencí uživatele načte pro chybový kód správnou zprávu. Specializovaná třída chyb musí rozšiřovat základní třídu Error jazyka ActionScript. Zde je příklad specializované třídy AppError, která rozšiřuje třídu Error: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 189 Zpracování chyb public class AppError extends Error { public function AppError(message:String, errorID:int) { super(message, errorID); } } Následující příklad ilustruje použití třídy AppError ve vlastním projektu: try { throw new AppError("Encountered Custom AppError", 29); } catch (error:AppError) { trace(error.errorID + ": " + error.message) } Poznámka: Chcete-li ve vlastní podtřídě nahradit metodu Error.toString(), musíte jí přiřadit jeden z parametrů ...(zbytek). Specifikace jazyka ECMAScript, na které je jazyk ActionScript 3.0 založen, definuje metodu Error.toString() a jazyk ActionScript 3.0 ji definuje stejně pro zpětnou kompatibilitu. Při nahrazení metody Error.toString() je proto zapotřebí přesně sladit parametry. Není žádoucí předávat jakékoliv parametry do metody toString() za běhu, neboť tyto parametry se ignorují. Reakce na chybové události a stavy Jedním z nejnápadnějších vylepšení zpracování chyb v jazyce ActionScript 3.0 je podpora zpracování událostí chyb, díky němuž lze reagovat na asynchronní chyby chodu programu. (Definici asynchronních chyb naleznete v sekci „Typy chyb“ na stránce 180.) Lze vytvářet posluchače a zpracování událostí k zajištění odezvy na události chyb. Řada tříd odesílá události chyb stejným způsobem jako ostatní události. Instance třídy XMLSocket například obvykle odesílá tři typy událostí: Event.CLOSE, Event.CONNECT a DataEvent.DATA. Pokud však nastanou potíže, může třída XMLSocket odeslat chybu IOErrorEvent.IOError nebo SecurityErrorEvent.SECURITY_ERROR. Další informace týkající se posluchačů a zpracování událostí naleznete v sekci „Zpracování událostí“ na stránce 243. Události chyb spadají do jedné z následujících kategorií: • Události chyb rozšiřující třídu ErrorEvent Třída flash.events.ErrorEvent obsahuje vlastnosti a metody pro řízení chyb chodu programu týkajících se operací síťového propojení nebo komunikace. Třídy AsyncErrorEvent, IOErrorEvent a SecurityErrorEvent rozšiřují třídu ErrorEvent. Při použití ladicí verze aplikace Flash Player nebo Adobe AIR bude dialogový rámeček za běhu informovat o všech událostech chyb bez funkcí posluchače, na něž přehrávač narazí. • Události chyb založené na stavu Události chyb založené na stavu se vztahují k vlastnostem netStatus a status u síťových a komunikačních tříd. Když v aplikaci Flash Player nebo Adobe AIR nastanou potíže při čtení či zápisu dat, nastaví se vlastnosti netStatus.info.level nebo status.level (v závislosti na použitém objektu třídy) na hodnotu "error". Na tuto chybu reagujete tím, že zkontrolujete, zda vlastnost level ve funkci zpracování událostí obsahuje hodnotu "error". PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 190 Zpracování chyb Práce s událostmi chyb Třída ErrorEvent a její podtřídy obsahují typy chyb pro zpracování chyb odeslaných aplikací Flash Player nebo Adobe AIR při pokusu o čtení nebo zapisování dat. V následujícím příkladu se použije příkaz try..catch i zpracování událostí chyb k zobrazení všech chyb zjištěných při pokusu o čtení lokálního souboru. Na místech označených komentářem „your error-handling code here“ lze přidat kód pro složitější zpracování a poskytnout tak uživateli různé možnosti, nebo zpracovat chyby automaticky. package { import import import import import import import import import flash.display.Sprite; flash.errors.IOError; flash.events.IOErrorEvent; flash.events.TextEvent; flash.media.Sound; flash.media.SoundChannel; flash.net.URLRequest; flash.text.TextField; flash.text.TextFieldAutoSize; public class LinkEventExample extends Sprite { private var myMP3:Sound; public function LinkEventExample() { myMP3 = new Sound(); var list:TextField = new TextField(); list.autoSize = TextFieldAutoSize.LEFT; list.multiline = true; list.htmlText = "<a href=\"event:track1.mp3\">Track 1</a><br>"; list.htmlText += "<a href=\"event:track2.mp3\">Track 2</a><br>"; addEventListener(TextEvent.LINK, linkHandler); addChild(list); } private function playMP3(mp3:String):void { try { myMP3.load(new URLRequest(mp3)); myMP3.play(); } catch (err:Error) PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 191 Zpracování chyb { trace(err.message); // your error-handling code here } myMP3.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); } private function linkHandler(linkEvent:TextEvent):void { playMP3(linkEvent.text); // your error-handling code here } private function errorHandler(errorEvent:IOErrorEvent):void { trace(errorEvent.text); // your error-handling code here } } } Práce s událostmi změny stavu Aplikace Flash Player a Adobe AIR dynamicky mění hodnotu vlastností netStatus.info.level nebo status.level u tříd, jež podporují vlastnost level. Třídy, které mají vlastnost netStatus.info.level, jsou NetConnection, NetStream a SharedObject. Třídy, jež mají vlastnost status.level jsou HTTPStatusEvent, Camera, Microphone a LocalConnection. Je možné napsat funkci zpracování za účelem reagování na změnu hodnoty level a sledování chyb komunikace. V následujícím příkladu slouží funkce netStatusHandler() k testování hodnoty vlastnosti level. Pokud vlastnost level značí, že byla nalezena chyba, kód sleduje zprávu „Video stream failed“. package { import import import import import import flash.display.Sprite; flash.events.NetStatusEvent; flash.events.SecurityErrorEvent; flash.media.Video; flash.net.NetConnection; flash.net.NetStream; public class VideoExample extends Sprite { private var videoUrl:String = "Video.flv"; private var connection:NetConnection; private var stream:NetStream; public function VideoExample() { connection = new NetConnection(); connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); connection.connect(null); } private function netStatusHandler(event:NetStatusEvent):void PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 192 Zpracování chyb { if (event.info.level == "error") { trace("Video stream failed") } else { connectStream(); } } private function securityErrorHandler(event:SecurityErrorEvent):void { trace("securityErrorHandler: " + event); } private function connectStream():void { var stream:NetStream = new NetStream(connection); var video:Video = new Video(); video.attachNetStream(stream); stream.play(videoUrl); addChild(video); } } } Porovnání tříd Error Jazyk ActionScript poskytuje několik předdefinovaných tříd Error. Řadu těchto tříd používají aplikace Flash Player a Adobe AIR, stejné třídy Error je však rovněž možné použít ve vlastním kódu. V jazyce ActionScript 3.0 jsou k dispozici dva hlavní typy tříd Error: základní třídy Error jazyka ActionScript a třídy Error balíčku flash.error. Základní třídy Error předepisuje Specifikace jazyka ECMAScript (ECMA-262), vydání 3. Balíček flash.error obsahuje další třídy zavedené pro usnadnění vývoje a ladění aplikací v jazyce ActionScript 3.0. Základní třídy Error v jazyce ECMAScript Mezi základní třídy chyb v jazyce ECMAScript patří třídy Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError a URIError. Každá z těchto tříd je umístěna v jmenném prostoru na nejvyšší úrovni. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 193 Zpracování chyb Název třídy Popis Poznámky Error Třídu Error lze použít k vyvolání výjimek. Jedná se o základní třídu pro ostatní třídy výjimek definované v jazyce ECMAScript: EvalError, RangeError, ReferenceError, SyntaxError, TypeError a URIError. Třída Error slouží jako základní třída pro všechny chyby chodu programu vyvolané aplikacemi Flash® Player a Adobe® AIR®, a jde o doporučenou základní třídu pro vlastní třídy chyb. EvalError Výjimka EvalError se vyvolá v případě předání parametrů do konstruktoru třídy Function, nebo pokud kód uživatele volá funkci eval(). V jazyce ActionScript 3.0 byla podpora funkce eval() odstraněna a při pokusu o použití této funkce se vyvolá chyba. RangeError Výjimka RangeError se vyvolá, jestliže číselná hodnota leží mimo přijatelný rozsah. Výjimku RangeError by například vyvolala třída Timer, pokud by prodleva byla negativní nebo by nebyla konečná. Výjimka RangeError může být rovněž vyvolána při pokusu o přidání objektu zobrazení v neplatné hloubce. ReferenceError Výjimka ReferenceError se vyvolá při pokusu o provedení odkazu na nedefinovanou vlastnost u uzavřeného (nedynamického) objektu. Verze kompilátoru jazyka ActionScript starší než ActionScript 3.0 nevyvolaly chybu při pokusu o přístup do vlastnosti s hodnotou undefined. Nicméně v této situaci jazyk ActionScript 3.0 vygeneruje výjimku ReferenceError. Výjimky pro nedefinované proměnné ukazují na možné chyby, což pomáhá zlepšit kvalitu softwaru. Pokud však nejste zvyklí, že je zapotřebí proměnné inicializovat, může toto nové chování jazyka ActionScript vyžadovat změnu obvyklých postupů při kódování. Dřívější verze aplikace Flash Player používaly funkci eval() k zajištění přístupu do proměnných, vlastností, objektů či filmových klipů podle názvu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 194 Zpracování chyb Název třídy Popis Poznámky SyntaxError Výjimka SyntaxError se vyvolá, když v kódu jazyka ActionScript dojde k chybě analýzy. Chyba SyntaxError může být vyvolána za následujících okolností: Další informace naleznete v sekci 15.11.6.4 specifikace jazyka ECMAScript (ECMA-262), vydání 3 na adrese www.ecmainternational.org/publications/standards/Ecma262.htm, jakož i v sekci 10.3.1 specifikace jazyka ECMAScript pro XML (E4X) (ECMA-357, vydání 2) na adrese www.ecmainternational.org/publications/standards/Ecma357.htm. • Skript jazyka ActionScript vyvolá výjimku SyntaxError, když je neplatný regulární výraz analyzovaný třídou RegExp. • Skript jazyka ActionScript vyvolá výjimku SyntaxError, když je neplatný XML analyzovaný třídou XMLDocument. Výjimka TypeError se vyvolá, když je skutečný typ operandu odlišný od očekávaného typu. Chyba TypeError může být vyvolána za následujících okolností: TypeError Další informace naleznete v sekci 15.11.6.5 specifikace jazyka ECMAScript na adrese www.ecmainternational.org/publications/standards/Ecma262.htm, jakož i v sekci 10.3 specifikace jazyka E4X na adrese www.ecmainternational.org/publications/standards/Ecma357.htm. URIError • Aktuální parametr funkce nebo metody nemůže být vnucen určitému typu parametru. • Proměnné je přiřazena hodnota, která nemůže být vnucena typu proměnné. • Pravá strana operátoru is nebo instanceof není platného typu. • Klíčové slovo super je nesprávně použito. • Vyhledávání vlastnosti má za výsledek více než jedno spojení a proto je nejednoznačné. • Metoda je uplatňována na nekompatibilní objekt. Výjimka TypeError se například vyvolá, když je metoda třídy RegExp připojena na nechráněný objekt a pak uplatněna. Výjimka URIError se vyvolá, když je jedna z funkcí pro Chyba URIError může být vyvolána za následujících okolností: zpracování globálního URI použita způsobem, který Pro funkci rozhraní API v aplikaci Flash Player je zadán neplatný není kompatibilní s její definicí. URI místo očekávaného platného URI, např. Socket.connect(). Další informace naleznete v sekci 15.11.6.6 specifikace jazyka ECMAScript na adrese www.ecmainternational.org/publications/standards/Ecma262.htm. Základní třídy Error v jazyce ActionScript Kromě základních tříd Error v jazyce ECMAScript přidává jazyk ActionScript řadu vlastních tříd pro chyby specifické pro jazyk ActionScript a funkčnost zpracování chyb. Vzhledem k tomu, že tyto třídy v jazyce ActionScript jsou rozšířením specifikace jazyka ECMAScript, vydání 3, a mohou být zajímavým doplňkem specifikace, jsou uchovávány na nejvyšší úrovni místo toho, aby byly umístěny v balíčku jako flash.error. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 195 Zpracování chyb Název třídy Popis Poznámky ArgumentError Třída ArgumentError představuje chybu, která se Příklady chyb argumentů mohou být následující: objeví, když hodnoty parametrů použité během volání • Pro metodu bylo zadáno příliš málo nebo příliš mnoho funkce neodpovídají parametrům definovaným pro argumentů. tuto funkci. • SecurityError VerifyError Výjimka SecurityError se vyvolá, když dojde k narušení bezpečnosti a přístup je zamítnut. Výjimka VerifyError se vyvolá, když je nalezen chybný nebo poškozený soubor SWF. Argument měl být podle očekávání členem výčtu a nebyl. Příklady chyb zabezpečení mohou být následující: • Neoprávněný přístup k vlastnosti nebo je volání metody provedeno přes hranice rozsahu zabezpečení. • Byl učiněn pokus přístupu k URL, nedovolený rozsahem zabezpečení • Došlo k pokusu připojení soketu na port, ale nezbytný soubor zásad nebyl k dispozici. • Byl učiněn pokus přístupu k uživatelově kameře nebo mikrofonu, žádost o přístup k zařízení byla odmítnuta uživatelem. Když soubor SWF načítá jiný soubor SWF, může nadřazený soubor SWF zachytit výjimku VerifyError vygenerovanou načteným souborem SWF. Třídy Error v balíčku flash.error Balíček flash.error obsahuje třídy Error, které jsou považovány za součást rozhraní API aplikace Flash Player. Na rozdíl od tříd Error, jež byly právě popsány, balíček flash.error oznamuje chyby specifické pro aplikaci Flash Player nebo Adobe AIR. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 196 Zpracování chyb Název třídy Popis Poznámky EOFError Výjimka EOFError se vyvolá, když se uživatel pokouší číst přes konec dostupných dat. Například chyba EOFError je vrácena v případě, že je zavolána jedna z metod čtení v rozhraní IDataInput a nejsou k dispozici dostatečná data, která by požadavek na čtení uspokojila. IllegalOperationError Výjimka IllegalOperationError se vyvolá, když není Příklady chyb neplatných operací zahrnují: implementována některá metoda nebo příslušná • Základní třída, například DisplayObjectContainer, implementace nepokrývá aktuální použití. poskytuje více funkcí, než kolik jich může podporovat třída Stage. Když se například pokusíte získat nebo nastavit masku na ploše (pomocí metody stage.mask), vyvolá aplikace Flash Player nebo Adobe AIR výjimku IllegalOperationError se zprávou „The Stage class does not implement this property or method“. • Podtřída zdědí metodu, kterou nepotřebuje a nechce podporovat. • Jisté metody přístupnosti jsou volány v okamžiku, když je aplikace Flash Player sestavena bez možnosti přístupu. • Funkce jen pro vytváření se vyvolávají z běhových verzí aplikace Flash Player. • Snažíte se nastavit název objektu umístěného na časové ose. IOError Výjimka IOError se vyvolá, když nastane určitý typ výjimky V/V. Tato chyba se zobrazí například při pokusu o čtení a zápis na socketu, který není připojen nebo byl odpojen. MemoryError Výjimka MemoryError bude vyvolána, když je požadavek na alokování paměti neúspěšný. Verze ActionScript Virtual Machine 2 implicitně nestanoví limit velikosti paměti, kterou může program jazyka ActionScript přiřazovat. U stolních počítačů se chyby přidělení paměti vyskytují jen zřídka. K chybě dojde, když systém není schopen přidělit paměť potřebnou pro danou operaci. Proto u stolního počítače tato výjimka nastane jen výjimečně, pokud není požadavek na přidělení paměti extrémně velký. Například požadavek na 3 miliardy bytů je nesplnitelný, neboť 32bitový program Microsoft® Windows® má přístup jen k 2 GB adresového prostoru. ScriptTimeoutError Výjimka ScriptTimeoutError se vyvolá po uplynutí 15 sekundového intervalu časového limitu skriptu. Zachycením výjimky ScriptTimeoutError lze zpracovat časový limit skriptu elegantněji. Není-li k dispozici zpracování výjimek, funkce zpracování nezachycených výjimek zobrazí dialogové okno s chybovou zprávou. Aby nemohl zlomyslný vývojář výjimku zachytit a zůstat v nekonečné smyčce, může být zachycena pouze první výjimka ScriptTimeoutError vyvolaná v průběhu určitého skriptu. Následující výjimku ScriptTimeoutError nemůže příslušný kód zachytit, proto ihned přejde ke zpracování nezachycené výjimky. StackOverflowError Výjimka StackOverflowError se vyvolá po vyčerpání zásobníku, který je k dispozici pro daný skript. Výjimka StackOverflowError může značit, že nastala nekonečná rekurze. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 197 Zpracování chyb Příklad: použití třídy CustomErrors V použití třídy CustomErrors jsou znázorněny techniky práce s vlastními chybami při vytváření aplikace. Tyto techniky jsou následující: • Ověření paketu XML • Zápis vlastní chyby • Vyvolání vlastních chyb • Upozornění uživatelů při vyvolání chyby Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Aplikační soubory CustomErrors se nacházejí ve složce Samples/CustomError. Aplikace sestává z následujících souborů: Soubor Popis CustomErrors.mxml Hlavní aplikační soubor v aplikaci Flash (FLA) nebo Flex (MXML) nebo CustomErrors.fla com/example/programmingas3/errors/ApplicationError.as Třída, která slouží jako základní třída chyb pro třídu FatalError i WarningError. com/example/programmingas3/errors/FatalError.as Třída definující chybu FatalError, jež může být vyvolána aplikací. Tato třída rozšiřuje vlastní třídu ApplicationError. com/example/programmingas3/errors/Validator.as Třída definující jedinou metodu, která ověří paket XML zaměstnance zadaný uživatelem. com/example/programmingas3/errors/WarningError.as Třída definující chybu WarningError, jež může být vyvolána aplikací. Tato třída rozšiřuje vlastní třídu ApplicationError. Přehled použití třídy CustomErrors Po načtení aplikace se vyvolá metoda initApp() v programu Flex nebo se provede kód v časové ose (není funkcí) v aplikaci Flash. Tento kód definuje vzorový paket XML, který bude ověřen třídou Validator. Spustí se následující kód: employeeXML = <employee id="12345"> <firstName>John</firstName> <lastName>Doe</lastName> <costCenter>12345</costCenter> <costCenter>67890</costCenter> </employee>; } Paket XML se pak zobrazí v instanci komponenty TextArea na ploše. To umožní úpravu paketu XML před tím, než proběhne pokus o obnovení jeho platnosti. Po klepnutí na tlačítko Ověřit se zavolá metoda validateData(). Tato metoda ověří platnost paketu XML zaměstnance pomocí metody validateEmployeeXML() ve třídě Validator. Následující kód znázorňuje metodu validateData(): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 198 Zpracování chyb function validateData():void { try { var tempXML:XML = XML(xmlText.text); Validator.validateEmployeeXML(tempXML); status.text = "The XML was successfully validated."; } catch (error:FatalError) { showFatalError(error); } catch (error:WarningError) { showWarningError(error); } catch (error:Error) { showGenericError(error); } } Nejprve se vytvoří dočasný objekt XML pomocí obsahu instance komponenty TextArea xmlText. Potom se vyvolá metoda validateEmployeeXML() ve vlastní třídě Validator (com.example.programmingas3/errors/Validator.as) a odešle dočasný objekt XML jako parametr. Jestliže je paket XML platný, zobrazí instance komponenty Label status úspěšnou zprávu a aplikace se ukončí. Pokud metoda validateEmployeeXML() vyvolá vlastní chybu (tzn. dojde k chybě FatalError, WarningError nebo k obecné chybě Error), provede se odpovídající příkaz catch , který zavolá metodu showFatalError(), showWarningError() nebo showGenericError(). Každá z těchto metod zobrazí příslušnou zprávu v textové oblasti s názvem statusText a upozorní uživatele na konkrétní vzniklou chybu. Každá metoda rovněž aktualizuje instanci komponenty Label status specifickou zprávou. Jestliže během pokusu o ověření paketu XML zaměstnance dojde k závažné chybě, deaktivuje se chybová zpráva zobrazená v textové oblasti statusText, instance komponenty TextArea xmlText a instance komponenty Button validateBtn, jak je znázorněno v následujícím kódu: function showFatalError(error:FatalError):void { var message:String = error.message + "\n\n"; var title:String = error.getTitle(); statusText.text = message + " " + title + "\n\nThis application has ended."; this.xmlText.enabled = false; this.validateBtn.enabled = false; hideButtons(); } Pokud místo závažné chyby dojde k chybě upozornění, zobrazí se chybová zpráva v instanci objektu TextArea statusText, ale instance komponent TextField a Button xmlText nebudou deaktivovány. Metoda showWarningError() zobrazuje vlastní chybovou zprávu v textové oblasti statusText. Zpráva se rovněž uživatele dotáže, zda má pokračovat ověřování XML nebo zda má být skript ukončen. Následující výpisek znázorňuje metodu showWarningError(): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 199 Zpracování chyb function showWarningError(error:WarningError):void { var message:String = error.message + "\n\n" + "Do you want to exit this application?"; showButtons(); var title:String = error.getTitle(); statusText.text = message; } Po klepnutí na tlačítko Ano nebo Ne se vyvolá metoda closeHandler(). Následující výpisek znázorňuje metodu closeHandler(): function closeHandler(event:CloseEvent):void { switch (event.detail) { case yesButton: showFatalError(new FatalError(9999)); break; case noButton: statusText.text = ""; hideButtons(); break; } } Jestliže se uživatel rozhodne skript ukončit klepnutím na tlačítko Ano, vyvolá se chyba FatalError, která způsobí ukončení aplikace. Vytvoření vlastního validátoru Vlastní třída Validator obsahuje jedinou metodu, validateEmployeeXML(). Metoda validateEmployeeXML() převezme jediný argument employee, což je paket XML, který se má ověřit. Metoda validateEmployeeXML() je následující: public static function validateEmployeeXML(employee:XML):void { // checks for the integrity of items in the XML if (employee.costCenter.length() < 1) { throw new FatalError(9000); } if (employee.costCenter.length() > 1) { throw new WarningError(9001); } if (employee.ssn.length() != 1) { throw new FatalError(9002); } } Aby bylo možné provést ověření, musí zaměstnanec patřit do jednoho (a pouze jednoho) nákladového střediska. Pokud zaměstnanec do žádného nákladového střediska nepatří, vyvolá metoda chybu FatalError, která probublá až do metody validateData() v hlavním aplikačním souboru. Patří-li zaměstnanec do více než jednoho nákladového střediska, vyvolá se chyba WarningError. Konečná kontrola ve validátoru XML ověří, zda má uživatele definováno právě jedno číslo sociálního pojištění (uzel ssn v paketu XML). Jestliže není k dispozici právě jeden uzel ssn, vyvolá se chyba FatalError. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 200 Zpracování chyb Do metody validateEmployeeXML() lze přidat další kontroly, např. pro zajištění, aby uzel ssn obsahoval platné číslo nebo aby měl zaměstnanec definováno alespoň jedno telefonní číslo a e-mailovou adresu a aby obě hodnoty byly platné. Rovněž je možné upravit XML, aby každý zaměstnanec měl jedinečné ID a určoval ID svého správce. Definice třídy ApplicationError Třída ApplicationError slouží jako základní třída pro třídu FatalError i WarningError. Třída ApplicationError rozšiřuje třídu Error a definuje vlastní metody a vlastnosti, včetně ID chyby, závažnosti chyby a objektu XML, který obsahuje vlastní kódy chyb a chybové zprávy. Tato třída rovněž definuje dvě statické konstanty, které slouží k definování závažnosti jednotlivých typů chyb. Metoda konstruktoru třídy ApplicationError je následující: public function ApplicationError() { messages = <errors> <error code="9000"> <![CDATA[Employee must be assigned to a cost center.]]> </error> <error code="9001"> <![CDATA[Employee must be assigned to only one cost center.]]> </error> <error code="9002"> <![CDATA[Employee must have one and only one SSN.]]> </error> <error code="9999"> <![CDATA[The application has been stopped.]]> </error> </errors>; } Každý uzel chyby v objektu XML obsahuje jedinečný číselný kód a chybovou zprávu. Chybové zprávy lze snadno vyhledat podle jejich chybových kódů pomocí jazyka E4X, jak je znázorněno v následující metodě getMessageText(): public function getMessageText(id:int):String { var message:XMLList = messages.error.(@code == id); return message[0].text(); } Metoda getMessageText() převezme jediný argument celého čísla, id, a vrátí řetězec. Argument id je chybový kód pro chybu, která se má vyhledat. Například při odeslání id 9001 se načte chyba, která říká, že zaměstnanci musí být přiřazeni pouze k jednomu nákladovému středisku. Má-li více chyb stejný chybový kód, vrátí ActionScript chybovou zprávu pouze pro první nalezený výsledek (message[0] v načteném objektu XMLList). Následující metoda v této třídě, getTitle(), nepřebírá žádné parametry a vrací řetězcovou hodnotu obsahující ID chyby pro tuto konkrétní chybu. Tato hodnota slouží pro snadnou identifikaci přesné chyby, k níž došlo při ověřování platnosti paketu XML. Následující výpisek znázorňuje metodu getTitle(): public function getTitle():String { return "Error #" + id; } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 201 Zpracování chyb Poslední metodou ve třídě ApplicationError je toString(). Tatometoda nahradí funkci definovanou ve třídě Error, aby bylo možné přizpůsobit vzhled chybové zprávy. Metoda vrací řetězec, který identifikuje specifické číslo chyby a chybovou zprávu, jež byla zobrazena. public override function toString():String { return "[APPLICATION ERROR #" + id + "] " + message; } Definice třídy FatalError Třída FatalError rozšiřuje vlastní třídu ApplicationError a definuje tři metody: konstruktor FatalError, getTitle() a toString(). První metoda, konstruktor FatalError, převezme jediný argument celého čísla, errorID, nastaví závažnost chyby pomocí statických konstantních hodnot definovaných ve třídě ApplicationError a získá chybovou zprávu určité chyby zavoláním metody getMessageText() ve třídě ApplicationError. Konstruktor FatalError je následující: public function FatalError(errorID:int) { id = errorID; severity = ApplicationError.FATAL; message = getMessageText(errorID); } Další metoda ve třídě FatalError, getTitle(), nahradí metodu getTitle() definovanou dříve ve třídě ApplicationError a k názvu připojí text „-- FATAL“, který uživatele informuje, že došlo k závažné chybě. Metoda getTitle() je následující: public override function getTitle():String { return "Error #" + id + " -- FATAL"; } Poslední metoda v této třídě, toString(), nahradí metodu toString() definovanou ve třídě ApplicationError. Metoda toString() je následující: public override function toString():String { return "[FATAL ERROR #" + id + "] " + message; } Definice třídy WarningError Třída WarningError rozšiřuje třídu ApplicationError a je téměř stejná jako třída FatalError až na to, že obsahuje dvě drobné změny v řetězci a nastavuje závažnost chyby na ApplicationError.WARNING místo ApplicationError.FATAL, jak je znázorněno v následujícím kódu: public function WarningError(errorID:int) { id = errorID; severity = ApplicationError.WARNING; message = super.getMessageText(errorID); } 202 Kapitola 10: Používání regulárních výrazů Regulární výraz popisuje vzorec, který se používá k vyhledání a manipulaci se shodným textem v řetězcích. Regulární výrazy se podobají řetězcům, ale mohou zahrnovat speciální kódy pro popis vzorců a opakování. Například následující regulární výraz se shoduje s řetězcem, který začíná znakem A a následuje jedna nebo více sekvenčních číslic: /A\d+/ Tato kapitola popisuje základní syntaxi pro konstruování regulárních výrazů. Regulární výrazy mohou být nicméně velice složité a mohou zahrnovat mnoho malých detailů. Podrobné zdroje o regulárních výrazech naleznete na webu a v knihkupectvích. Mějte na paměti, že odlišná programovací rozhraní implementují regulární výrazy různým způsobem. Jazyk ActionScript 3.0 implementuje regulární výrazy dle definice v specifikaci jazyka ECMAScript, vydání 3. (ECMA-262). Základní informace o regulárních výrazech Úvod do použití regulárních výrazů Regulární výraz popisuje vzorec znaků. Regulární výrazy se obvykle používají k ověření, zda textové hodnoty odpovídají zvláštnímu vzorci (například ověření, zda uživatelem zadané telefonní číslo má správný počet číslic) nebo pro nahrazení částí hodnoty textu, která odpovídá zvláštnímu vzorci. Regulární výrazy mohou být jednoduché. Například předpokládejme, že si přejete potvrdit, zda určitý řetězec odpovídá „ABC“, nebo si přejete nahradit každý výskyt „ABC“ v řetězci jiným textem. V takovém případě byste mohli použít následující regulární výraz, který definuje vzorec skládající se z písmen A, B a C v sekvenci: /ABC/ Všimněte si, že literál regulárního výrazu je vymezen pomocí znaku lomítka (/). Vzorce regulárních výrazů mohou být také složité a jejich vzhled může být někdy kryptický, jako například následující výraz, který odpovídá platné e-mailové adrese: /([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}/ Regulární výrazy nejběžněji použijete pro vyhledání vzorců z řetězců a pro nahrazení znaků. V těchto případech vytvoříte objekt regulárního výrazu a použijete jej jako parametr pro jednu z několika metod třídy String. Následující metody třídy String přebírají regulární výrazy jako parametry: match(), replace(), search() a split(). Více informací o těchto metodách naleznete v části „Vyhledání vzorků v řetězcích a nahrazení podřetězců“ na stránce 144. Třída RegExp zahrnuje následující metody: test() a exec(). Více informací naleznete v části „Metody pro použití regulárních výrazů s řetězci“ na stránce 217. Běžné úlohy regulárních výrazů. Pro regulární výrazy existuje několik běžných použití, které jsou v této kapitole podrobně popsány: • Vytvoření vzorce regulárního výrazu • Používání zvláštních znaků ve vzorcích PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 203 Používání regulárních výrazů • Identifikace pořadí více znaků (například „dvoumístné číslo“ nebo „mezi sedmi a pěti písmeny“) • Identifikace libovolných znaků v rozpětí písmen nebo čísel (například „libovolné písmeno od a do m“) • Identifikace znaku v množině možných znaků • Identifikace dílčích sekvencí (segmenty v rámci vzorce) • Propojování a nahrazování textu na základě vzorců Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny používané v této kapitole: • Znak escape: Znak určující, že následující znak by měl být zpracován jako metaznak spíše než znak literálu. V syntaxi regulárních výrazů je znakem escape znak zpětného lomítka (\), takže zpětné lomítko následované dalších znakem je speciální kód spíše než kód samotný. • Příznak: Znak, který určuje některé možnosti použití vzorce regulárního výrazu, například zda rozlišit mezi velkými a malými znaky. • Metaznak: Znak, který má zvláštní význam ve vzorci regulárního výrazu, oproti literální reprezentaci daného znaku ve vzorci. • Kvantifikátor: Znak (nebo několik znaků) určující, kolikrát je třeba část daného vzorce zopakovat. Kvantifikátor lze například použít pro určení, že poštovní směrovací číslo Spojených států by mělo obsahovat pět nebo devět čísel. • Regulární výraz: Příkaz programu definující vzorec znaků, které lze použít pro potvrzení, zda se jiné řetězce shodují s daných vzorcem nebo pro nahrazení částí řetězce. Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. Protože se ukázky kódu v této kapitole primárně skládají ze vzorců regulárních výrazů, zahrnuje testování příkladů několik kroků: 1 Vytvořte nový dokument Flash. 2 Zvolte klíčový snímek a otevřete panel Akce. 3 Vytvořte proměnnou RegExp (regulární výraz), například následující: var pattern:RegExp = /ABC/; 4 Zkopírujte vzorec z příkladu a přiřaďte jej jako hodnotu proměnné RegExp. Například v předcházejícím řádku kódu je vzorec součástí kódu napravo od znaménka rovnosti a neobsahuje středník (/ABC/). 5 Vytvořte jednu nebo více proměnných řetězce, které obsahují řetězce vhodné pro testování vašich regulárních výrazů. Jestliže například vytváříte regulární výraz pro textování platných e-mailových adres, vytvořte nové proměnné řetězce, které obsahují platné a špatné e-mailové adresy: var goodEmail:String = "[email protected]"; var badEmail:String = "5@$2.99"; 6 Přidejte řádky kódu pro testování proměnných řetězce a určete, zda se shodují se vzorcem regulárních výrazů. Tyto budou hodnotami, který budete chtít získat jako výstup na obrazovce pomocí funkce trace() nebo jejich zapsáním do textového pole na ploše. trace(goodEmail, " is valid:", pattern.test(goodEmail)); trace(badEmail, " is valid:", pattern.test(badEmail)); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 204 Používání regulárních výrazů Předpokládejme například, že pattern definuje vzorec regulárního výrazu pro platnou e-mailovou adresu, předcházející řádky kódu zapisují tento text do panelu Výstup: [email protected] is valid: true 5@$2.99 is valid: false Více informací o testování hodnot zapsáním hodnot do instance textového pole na ploše nebo použitím funkce trace() pro vytištění hodnot na panel Výstup naleznete v části „Testování příkladů kódu v této kapitole“ na stránce 34. Syntaxe regulárního výrazu Tato část popisuje všechny prvky syntaxe regulárního výrazu jazyka ActionScript. Jak zjistíte, regulární výrazy mohou být složité a mohou obsahovat mnoho malých detailů. Podrobné zdroje o regulárních výrazech naleznete na webu a v knihkupectvích. Mějte na paměti, že odlišná programovací rozhraní implementují regulární výrazy různým způsobem. Jazyk ActionScript 3.0 implementuje regulární výrazy dle definice v specifikaci jazyka ECMAScript, vydání 3. (ECMA-262). Obecně používáte regulární výrazy, které se shodují se složitými vzorci více než s jednoduchým řetězcem znaků. Například následující regulární výraz definuje vzorec skládající se z písmen A, B a C v sekvenci následované libovolnou číslicí: /ABC\d/ Kód \d představuje „libovolnou číslici“. Znak zpětného lomítka (\) se nazývá znak escape a v kombinaci se znakem, který za ním následuje (v tomto případě písmeno d), má v regulárním výrazu zvláštní význam. Tato kapitola popisuje tyto sekvence znaků escape a jiných prvků syntaxe regulárního výrazu. Následující regulární výraz definuje vzorec písmen ABC následovaný libovolným počtem číslic (všimněte si hvězdičky): /ABC\d*/ Znak hvězdičky (*) je metaznak. Metaznak je znak, který má v regulárním výrazu speciální význam. Hvězdička je speciální typ metaznaku nazvanýkvantifikátor, který se používá ke kvantifikaci množství opakování znaku nebo skupiny znaků. Další informace naleznete v části „Kvantifikátory“ na stránce 209. Vedle tohoto vzorce může regulární výraz obsahovat příznaky, které specifikují, jak má být regulární výraz přiřazen. Například následující regulární výraz používá příznak i, který specifikuje, že regulární výraz ignoruje rozlišení velkých a malých písmen v odpovídajících řetězcích: /ABC\d*/i Více informací naleznete v části „Příznaky a vlastnosti“ na stránce 214. Regulární výrazy můžete použít s následujícími metodami třídy String: match(), replace() a search(). Více informací o těchto metodách naleznete v části „Vyhledání vzorků v řetězcích a nahrazení podřetězců“ na stránce 144. Vytvoření instance regulárního výrazu Pro vytvoření instance regulárního výrazu existují dva způsoby. Jedním způsobem je použití znaků lomítka /) k vymezení regulárního výrazu; dalším způsobem je použití konstruktoru new. Například následující regulární výrazy jsou rovnocenné: var pattern1:RegExp = /bob/i; var pattern2:RegExp = new RegExp("bob", "i"); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 205 Používání regulárních výrazů Lomítka vymezí literál regulárního výrazu stejným způsobem jako uvozovky vymezují literál řetězce. Část regulárního výrazu mezi lomítky definuje vzorec. Regulární výraz může také po závěrečném vymezujícím lomítku zahrnovat příznaky. Tyto příznaky jsou považovány za součást regulárního výrazu, ale jsou odděleny od jeho vzorce. Při používání konstruktoru new použijete k definování regulárního výrazu dva řetězce. První řetězec definuje vzorec a druhý řetězec definuje příznaky, viz následující příklad: var pattern2:RegExp = new RegExp("bob", "i"); Při zahrnutí lomítka do regulárního výrazu, který je definován pomocí vymezovačů lomítka, musíte před lomítko nejprve umístit znak escape(\) zpětného lomítka. Například následující regulární výraz odpovídá vzorci 1/2: var pattern:RegExp = /1\/2/; Chcete-li zahrnout uvozovky do regulárního výrazu, který je definován s konstruktorem new, musíte před uvozovky přidat znak escape zpětného lomítka (\) (jako při definování libovolného literálu String). Například následující regulární výrazy odpovídají vzorci eat at "joe's": var pattern1:RegExp = new RegExp("eat at \"joe's\"", ""); var pattern2:RegExp = new RegExp('eat at "joe\'s"', ""); Znak escape zpětného lomítka nepoužívejte s uvozovkami v regulárních výrazech, které jsou definovány pomocí vymezovačů obyčejného lomítka. Obdobně nepoužívejte znaky escape s lomítkem v regulárních výrazech, které jsou definovány konstruktorem new. Následující regulární výrazy jsou ekvivalentní a definují vzorec 1/2 "joe's": var pattern1:RegExp = /1\/2 "joe's"/; var pattern2:RegExp = new RegExp("1/2 \"joe's\"", ""); var pattern3:RegExp = new RegExp('1/2 "joe\'s"', ''); Také v regulárním výrazu, který je definován konstruktoremnew, napište při použití metasekvence začínající zpětným lomítkem (\ ) znak zpětného lomítka dvakrát, jako třeba u metasekvence \d (která odpovídá každému číslu): var pattern:RegExp = new RegExp("\\d+", ""); // matches one or more digits Znak zpětného lomítka musíte napsat dvakrát, protože první parametr metody konstruktora RegExp() je řetězec a v řetězcovém literálu musíte napsat znak zpětného lomítka dvakrát, aby byl rozeznatelný jako jediný znak zpětného lomítka. Následující části popisují syntaxi pro definování vzorců regulárních výrazů. Více informací o příznacích naleznete v části „Příznaky a vlastnosti“ na stránce 214. Znaky, metaznaky a metasekvence Nejjednodušší regulární výraz je ten, který odpovídá sekvenci znaků, viz následující příklad: var pattern:RegExp = /hello/; Nicméně následující znaky, známé jako metaznaky, mají v regulárních výrazech speciální význam: ^ $ \ . * + ? ( ) [ ] { } | Například následující regulární výraz se shoduje s písmenem A následovaným nulou nebo více instancemi písmene B (metaznak hvězdičky označuje opakování) následovanými písmenem C: /AB*C/ Chcete-li zahrnout metaznak do vzorce regulárního výrazu bez jeho speciálního významu, musíte použít znak escape zpětného lomítka (\). Například následující regulární výraz se shoduje s písmenem A následovaným písmenem B, následovaným hvězdičkou a písmenem C: var pattern:RegExp = /AB\*C/; PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 206 Používání regulárních výrazů Metasekvence, podobně jako metaznak, má v regulárním výrazu speciální význam. Metasekvence se skládá s více než jednoho znaku. V následujících částech jsou uvedeny podrobnosti o používání metaznaků a metasekvencí. O metaznacích Následující tabulka poskytuje souhrn metaznaků, které lze použít v regulárních výrazech: Metaznak Popis ^ (stříška) Souhlasné hodnoty na začátku řetězce. Je-li nastaven příznak m (multiline), shoduje se stříška také se začátkem řádku (viz „Příznaky a vlastnosti“ na stránce 214). Všimněte si, že pokud je stříška použita na začátku třídy znaků, určuje negaci, nikoliv začátek řetězce. Pro více informací viz „Třídy znaků“ na stránce 208. $ (znak dolaru) Souhlasné hodnoty na konci řetězce. Je-li nastaven příznak m (multiline), znak $ se shoduje také s pozicí před znakem nového řádku (\n). Více informací naleznete v části „Příznaky a vlastnosti“ na stránce 214. \ (zpětné lomítko) Ukončí speciální význam metaznaku speciálních znaků Znak zpětného lomítka můžete také použít, jestliže si přejete použít znak lomítka v literálu regulárního výrazu, viz /1\/2/ (pro shodu se znakem 1 následovaným znakem lomítka, následovaným znakem 2). . (tečka) Shoduje se s jakýmkoliv jediným znakem. Tečka odpovídá znaku nového řádku (\n) pouze je-li nastavený příznak s (dotall). Více informací naleznete v části „Příznaky a vlastnosti“ na stránce 214. * (hvězda) Spáruje se s předcházející položkou neopakovanou nebo opakovanou. Další informace naleznete v části „Kvantifikátory“ na stránce 209. + (plus) Spáruje se s předcházející položkou opakovanou jednou nebo vícekrát. Další informace naleznete v části „Kvantifikátory“ na stránce 209. ? (otazník) Spáruje se s předcházející položku neopakovanou nebo opakovanou jednou. Další informace naleznete v části „Kvantifikátory“ na stránce 209. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 207 Používání regulárních výrazů Metaznak Popis (a) Definuje skupiny v rámci regulárního výrazu. Skupiny lze použít k následujícím akcím: • Pro ohraničení rozsahu znaku alternace |: /(a|b|c)d/ • Pro definování rozsahu kvantifikátoru: /(walla.){1,2}/ • Ve zpětných referencích. Například \1 v následujícím regulárním výrazu se shoduje s čímkoliv, co se shoduje s první skupinou závorek daného vzorce: • /(\w*) is repeated: \1/ Další informace viz „Skupiny“ na stránce 211. [a] Definuje třídu znaku, která definuje možné shody pro jediný znak: /[aeiou]/ spáruje se s libovolným ze specifikovaných znaků. V rámci tříd znaků můžete pomocí pomlčky (-) určit rozsah znaků: /[A-Z0-9]/ se shoduje s velkým písmenem A až Z nebo s číslem 0 až 9. V rámci třídy znaků vložte zpětné lomítko pro ukončení znaků ] a - znaky: /[+\-]\d+/ se shoduje buď s + nebo - před jednou nebo více číslicemi. V rámci tříd znaků jsou jiné znaky, které jsou běžně metaznaky, zpracovávány jako běžné znaky (nikoliv metaznaky), bez nutnosti zpětného lomítka: /[$]/£ se shoduje buď s $ nebo £. Pro více informací viz „Třídy znaků“ na stránce 208. | (spojovací znak) Používá se pro alternaci, pro souhlas buď s částí levé strany nebo s částí pravé strany: /abc|xyz/ se shoduje buď s abc nebo xyz. O metasekvencích Metasekvence jsou sekvence znaků, které mají ve vzorci regulárních výrazů speciální význam. Následující tabulka tyto znaky popisuje: Metasekvence Popis {n} Určuje numerický kvantifikátor nebo rozsah kvantifikátoru pro předchozí položku: {n,} /A{27}/ se shoduje se znakem A, který je opakován 27x. a /A{3,}/ se shoduje se znakem A, který je opakován 3x. {n,n} /A{3,5}/ se shoduje se znakem A, který je opakován 3x až 5x. Další informace naleznete v části „Kvantifikátory“ na stránce 209. \b Shoduje se s pozicí mezi znakem sova a znakem jiným než znakem slova. Jestliže je první nebo poslední znak v řetězci znak slova, shoduje se také se začátkem nebo koncem řetězce. \B Shoduje se s pozicí mezi dvěma znaky slova. Shoduje se také s pozicí mezi dvěma znaky, které nejsou znaky slova. \d Shoduje se s desítkovou číslicí. \D Shoduje se s jakýmkoliv znakem jiným než číslice. \f Shoduje se se znakem kanálu formuláře. \n Shoduje se se znakem nového řádku. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 208 Používání regulárních výrazů Metasekvence Popis \r Shoduje se s návratovým znakem. \s Shoduje se s libovolným znakem bílého místa (mezera, tabulátor, nový řádek nebo návratový znak). \S Shoduje se s jakýmkoliv znakem jiným než znakem bílého místa \t Shoduje se se znakem tabulátoru. \unnnn Spáruje znak Unicode s kódem znaku určeným hexadecimálním číslem nnnn. Například \u263a je znak smajlíka. \v Shoduje se se znakem vertikálního kanálu. \w Shoduje se se znakem slova (AZ–, az–, 0-9 nebo _). Všimněte si, že \w se neshoduje s neanglickými znaky, například s é , ñ neboç. \W Shoduje se s jakýmkoliv znakem jiným než znakem slova. \\xnn Spáruje znak s určenou hodnotou ASCII, dle definice hexadecimálního čísla nn. Třídy znaků Třídy znaků můžete použít pro určení seznamu znaků, které odpovídají jedné poloze v regulárním výrazu. Třídy znaků lze definovat pomocí hranatých závorek ( [ a ] ). Například následující regulární výraz definuje třídu znaků, která se shoduje s bag, beg, big, bognebo bug: /b[aeiou]g/ Escape sekvence v třídách znaků Většina metaznaků a metasekvencí, které mají v regulárních výrazech běžně speciální význam, nemají tyto stejné významy uvnitř třídy znaků. Například v regulárním výrazu je hvězdička použita pro opakování, ale to neplatí pro hvězdičku ve třídě znaků. Následující třída znaků se literálově shoduje s hvězdičkou, společně s libovolným jiným uvedeným znakem: /[abc*123]/ Nicméně tři znaky uvedené v následující tabulce fungují jako metaznaky, se speciálním významem ve třídách znaků: Metaznak Metaznaky ve třídách znaků ] Definuje konec třídy znaku. - Definuje rozmezí znaků (viz následující část „Rozmezí znaků ve třídách znaků“). \ Definuje metasekvence a ruší speciální význam metaznaků. Aby mohly být jakékoliv z těchto znaků rozpoznány jako znaky literálu (bez speciálního významu metaznaku), musíte před tyto znaky umístit znak escape zpětného lomítka. Například následující regulární výraz zahrnuje třídu znaku, která se shoduje s jakýmkoliv ze čtyř symbolů ($, \, ]nebo -): /[$\\\]\-]/ Vedle metaznaků, které si zachovávají své speciální významy, fungují ve třídách znaků následující metasekvence: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 209 Používání regulárních výrazů Metasekvence Metaznaky ve třídách znaků \n Shoduje se se znakem nového řádku. \r Shoduje se se znakem vrácení. \t Shoduje se se znakem tabulátoru. \unnnn Spáruje znak s určenou hodnotou bodu kódu Unicode (dle definice hexadecimálního čísla nnnn). \\xnn Spáruje znak s určenou hodnotou ASCII (dle definice hexadecimálního čísla nn). Jiné metasekvence a metaznaky regulárního výrazu jsou ve třídě znaku zpracovávány jako běžné znaky. Rozmezí znaků ve třídách znaků Pro určení rozmezí znaků, například A-Z, a-z nebo0-9, použijte pomlčku. Tyto znaky musí představovat platné rozmezí znakové sady. Například následující třída znaků se shoduje s jakýmkoliv znakem v rozmezí a-z nebo s jakoukoliv číslicí: /[a-z0-9]/ Pro určení rozmezí dle hodnoty ASCII můžete také použít kód znaku ASCII \\xnn. Například následující třída znaků se shoduje s jakýmkoliv znakem ze sady rozšířených znaků ASCII (například é a ê ): \\x Negované třídy znaků Jestliže na začátku třídy znaku použijete znak stříšky (^), bude daná třída negována - jakýkoliv neuvedený znak bude považován za shodu. Následující třída znaků se shoduje s jakýmkoliv znakem, s výjimkou malého písmena (az–) nebo číslice: /[^a-z0-9]/ Pro určení negace musíte znak stříšky (^) zapsat na začátek třídy znaků. V opačném případě jednoduše přidáte znak stříšky ke znakům ve třídě znaků. Například následující třída znaků se shoduje s jakýmkoliv ze znaků symbolů, včetně stříšky: /[!.,#+*%$&^]/ Kvantifikátory Kvantifikátory se používají pro určení opakování znaků nebo sekvencí ve vzorcích, a to následovně: Metaznak kvantifikátoru Popis * (hvězda) Spáruje se s předcházející položkou neopakovanou nebo opakovanou. + (plus) Spáruje se s předcházející položkou opakovanou jednou nebo vícekrát. ? (otazník) Spáruje se s předcházející položku neopakovanou nebo opakovanou jednou. {n} Určuje numerický kvantifikátor nebo rozsah kvantifikátoru pro předchozí položku: {n,} /A{27}/ se shoduje se znakem A, který je opakován 27x. a /A{3,}/ se shoduje se znakem A, který je opakován 3x nebo vícekrát. {n,n} /A{3,5}/ se shoduje se znakem A, který je opakován 3x až 5x. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 210 Používání regulárních výrazů Kvantifikátor můžete použít na jediný znak, na třídu znaků nebo na skupinu: • /a+/ se shoduje se znakem a, který je opakován jednou nebo vícekrát. • /\d+/ odpovídá dvou nebo více číslicím. • /[abc]+/ odpovídá opakování jednoho nebo více znaků a každý z těchto znaku je buď a, b nebo c. • /(very, )*/ se shoduje s very následovaným čárkou a mezerou, které nejsou opakovány nebo jsou opakovány vícekrát. Kvantifikátory lze použít uvnitř seskupení kulatých závorek, na které jsou použity kvantifikátory. Například následující kvantifikátor se shoduje s řetězci, například word a word-word-word: /\w+(-\w+)*/ Regulární výrazy implicitně provádějí to, co se označuje za chamtivé srovnávání. Jakýkoliv dílčí vzorec v regulárním výrazu (například .*) se snaží přiřadit se k co nejvíce znakům v řetězci před tím, než přejde k další části regulárního výrazu. Zvažte například následující regulární výraz a řetězec: var pattern:RegExp = /<p>.*<\/p>/; str:String = "<p>Paragraph 1</p> <p>Paragraph 2</p>"; Regulární výraz se shoduje s celým řetězcem: <p>Paragraph 1</p> <p>Paragraph 2</p> Nicméně předpokládejme, že si přejete přiřadit pouze jedno seskupení <p>...</p>. Použít k tomu můžete následující: <p>Paragraph 1</p> Přidáním otazníku (?) za libovolný kvantifikátor jej změníte na to, čemu se říká líný kvantifikátor. Například následující regulární výraz, který používá líný *? kvantifikátor, se shoduje s <p> následovaným minimálním možným počtem znaků (líným), následovaným </p>: /<p>.*?<\/p>/ O kvantifikátorech je třeba si zapamatovat následující body: • Kvantifikátory {0} a {0,0} nevyřazují ze shody položku. • Nekombinujte více kvantifikátorů, např. /abc+*/. • znak tečka (.) nerozdělí řádky, pokud není nastaven příznak s (dotall), i v případě, že následuje kvantifikátor *. Posuďte například následující kód: var str:String = "<p>Test\n"; str += "Multiline</p>"; var re:RegExp = /<p>.*<\/p>/; trace(str.match(re)); // null; re = /<p>.*<\/p>/s; trace(str.match(re)); // output: <p>Test // Multiline</p> Více informací naleznete v části „Příznaky a vlastnosti“ na stránce 214. Alternace Spojovací znak | použijte v regulárním výrazu pro to, aby vyhledávač regulárního výrazu zvážil alternativy pro shodu. Například následující regulární výraz odpovídá jakémukoliv ze slov cat, dog, pig, rat: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 211 Používání regulárních výrazů var pattern:RegExp = /cat|dog|pig|rat/; Pro definici skupin za účelem omezení rozsahu měniče | můžete použít kulaté závorky. Následující regulární výraz se shoduje s cat a následně nap nebo nip: var pattern:RegExp = /cat(nap|nip)/; Další informace viz „Skupiny“ na stránce 211. Následující dva regulární výrazy, jeden používající měnič |, druhý používající třídu znaků (definovanou pomocí [ a ] ), jsou ekvivalentní: /1|3|5|7|9/ /[13579]/ Pro více informací viz „Třídy znaků“ na stránce 208. Skupiny Skupinu můžete v regulárním výraze určit pomocí kulatých závorek, viz dále: /class-(\d*)/ Skupina je dílčí částí vzorce. Skupiny můžete použít k následujícím akcím: • Pro použití kvantifikátoru na více než jeden znak. • Pro načrtnutí dílčích vzorců, které budou použity s alternací (pomocí znaku |). • Zachycení shod dílčích řetězců (například použitím \1 v regulárním výrazu pro přiřazení předešle přiřazené skupiny nebo pomocí $1 obdobně v metodě replace() třídy String). V následujících částech jsou uvedeny podrobnosti k těmto použitím skupin. Používání skupin s kvantifikátory Jestliže nepoužijete skupinu, kvantifikátor se použije na znak nebo třídu znaků, která mu předchází, viz následující ukázka: var pattern:RegExp = /ab*/ ; // matches the character a followed by // zero or more occurrences of the character b pattern = /a\d+/; // matches the character a followed by // one or more digits pattern = /a[123]{1,3}/; // matches the character a followed by // one to three occurrences of either 1, 2, or 3 Skupinu můžete nicméně použít k aplikaci kvantifikátoru na více než jeden znak nebo třídu znaků: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 212 Používání regulárních výrazů var pattern:RegExp = /(ab)*/; // matches zero or more occurrences of the character a // followed by the character b, such as ababab pattern = /(a\d)+/; // matches one or more occurrences of the character a followed by // a digit, such as a1a5a8a3 pattern = /(spam ){1,3}/; // matches 1 to 3 occurrences of the word spam followed by a space Více informací o kvantifikátorech naleznete v části „Kvantifikátory“ na stránce 209. Použití skupin se znakem měniče (|) Skupiny můžete použít k definici skupin znaků, na které si přejete použít znak měniče (|), a to následovně: var pattern:RegExp = /cat|dog/; // matches cat or dog pattern = /ca(t|d)og/; // matches catog or cadog Používání skupin pro zachycení shod dílčího řetězce Když ve vzorci definujete standardní skupinu kulatých závorek, můžete se na ni později odkázat v regulárním výrazu. Tomu se říká zpětná referencea takové typy skupin jsou známé jako skupiny se zachycením. Například v následujícím regulárním výrazu se sekvence \1 shoduje s čímkoliv, co dílčí řetězec přiřadil skupině kulatých závorek zachycení: var pattern:RegExp = /(\d+)-by-\1/; // matches the following: 48-by-48 V regulárním výrazu můžete určit až 99 takových zpětných referencí, a to zadáním \1, \2, ... , \99. Obdobně můžete v metodě replace() třídy String použít $1$99– pro vložení zachycených shod dílčího řetězce skupiny do nahrazujícího řetězce: var pattern:RegExp = /Hi, (\w+)\./; var str:String = "Hi, Bob."; trace(str.replace(pattern, "$1, hello.")); // output: Bob, hello. Jestliže používáte skupiny zachycení, vrátí metodaexec() třídy RegExp a metoda match() třídy String dílčí řetězce, které odpovídají skupinám zachycení. var pattern:RegExp = /(\w+)@(\w+).(\w+)/; var str:String = "[email protected]"; trace(pattern.exec(str)); // [email protected],bob,example,com Používání skupin bez zachycení a skupin dopředného vyhledávání Skupina bez zachycení je skupina, která se používá pouze pro seskupování; není „shromažďována“ a neshoduje se s očíslovanými zpětnými referencemi. Pro definici skupin bez zachycení použijte (?: a ), následovně: var pattern = /(?:com|org|net); Všimněte si například rozdílu mezi umístěním (com|org) ve skupině zachycení oproti skupině bez zachycení (metoda exec() uvádí skupiny zachycení po kompletní shodě): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 213 Používání regulárních výrazů var pattern:RegExp = /(\w+)@(\w+).(com|org)/; var str:String = "[email protected]"; trace(pattern.exec(str)); // [email protected],bob,example,com //noncapturing: var pattern:RegExp = /(\w+)@(\w+).(?:com|org)/; var str:String = "[email protected]"; trace(pattern.exec(str)); // [email protected],bob,example Zvláštním typem skupiny bez zachycení je skupina dopředného vyhledávání, která má dva typy: pozitivní skupina dopředného vyhledávání a negativní skupina dopředného vyhledávání. Pro definici pozitivní skupiny dopředného vyhledávání použijte (?= a ), což určuje, že dílčí vzorec ve skupině musí odpovídat poloze. Nicméně část řetězce, která odpovídá pozitivní skupině dopředného vyhledávání, se může shodovat se zbylými vzorci v regulárním výrazu. Například protože (?=e) je pozitivní skupina dopředného vyhledávání, znak e, který se s ní shoduje, může být ve shodě s následnou částí regulárního výrazu - v tomto případě se skupinou zachycení, \w*): var pattern:RegExp = /sh(?=e)(\w*)/i; var str:String = "Shelly sells seashells by the seashore"; trace(pattern.exec(str)); // Shelly,elly Pro definici negativní skupiny dopředného vyhledávání použijte (?! a ), což určuje, že dílčí vzorec ve skupině nesmíodpovídat poloze. Například: var pattern:RegExp = /sh(?!e)(\w*)/i; var str:String = "She sells seashells by the seashore"; trace(pattern.exec(str)); // shore,ore Používání pojmenovaných skupin Pojmenovaná skupina je typ skupiny v regulárním výrazu, které je udělen pojmenovaný identifikátor. Pro definici pojmenované skupiny použijte (?P<name> a ). Například následující regulární výraz zahrnuje pojmenovanou skupinu s identifikátorem nazvaným digits: var pattern = /[a-z]+(?P<digits>\d+)[a-z]+/; Při použití metody exec() je shodná pojmenovaná skupina přidána jako vlastnost pole result: var myPattern:RegExp = /([a-z]+)(?P<digits>\d+)[a-z]+/; var str:String = "a123bcd"; var result:Array = myPattern.exec(str); trace(result.digits); // 123 Zde je další příklad, který používá dvě pojmenované skupiny, s identifikátory name a dom: var emailPattern:RegExp = /(?P<name>(\w|[_.\-])+)@(?P<dom>((\w|-)+))+\.\w{2,4}+/; var address:String = "[email protected]"; var result:Array = emailPattern.exec(address); trace(result.name); // bob trace(result.dom); // example Poznámka: Pojmenované skupiny nejsou součástí specifikací jazyka ECMAScript. Jedná se o funkci přidanou do jazyka ActionScript 3.0. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 214 Používání regulárních výrazů Příznaky a vlastnosti Následující tabulka uvádí pět příznaků, které lze nastavit pro regulární výrazy. Ke každému příznaku lze získat přístup jako k vlastnosti objektu regulárního výrazu. Příznak Vlastnost Popis g global Odpovídá více než jedné shodě. i ignoreCase Shody citlivé na velikost písma Platí pro znaky A - Z a a - z, ale nikoliv pro rozšířené znaky, například É a é . m multiline Je-li tento příznak nastaven, mohou se $ a ^ shodovat se začátkem řádku, respektive s koncem řádku. s dotall Je-li tento příznak nastaven, může . (tečka) odpovídat znaku nového řádku (\n). x extended Povoluje rozšířené regulární výrazy. Do regulárního výrazu můžete zadat mezery, které jsou jako součást vzorce ignorovány. Tím můžete zapsat kód regulárního výrazu čitelněji. Upozorňujeme, že tyto vlastnosti jsou určené pouze ke čtení. Příznaky (g, i, m, s, x) můžete nastavit při nastavování proměnné regulárního výrazu, a to následovně: var re:RegExp = /abc/gimsx; Pojmenované vlastnosti nemůžete nicméně nastavit přímo. Následující kód například vygeneruje chybu: var re:RegExp = /abc/; re.global = true; // This generates an error. Pokud jste příznaky neurčili v deklaraci regulárního výrazu, příznaky nejsou implicitně nastaveny a odpovídající vlastnosti jsou také nataveny na hodnotu false. Dále existují dvě další vlastnosti regulárního výrazu: • Vlastnost lastIndex určuje pozici indexu v řetězci, která bude použita pro další volání metody exec() nebo test() regulárního výrazu. • Vlastnost source určuje řetězec, který definuje část vzorce regulárního výrazu. Příznak g (global) Jestliže příznak g (global) není obsažen, regulární výraz nebude odpovídat více než jedné shodě. Například pokud příznak g není zahrnut do regulárního výrazu, metoda String.match() vrátí pouze jeden shodný dílčí řetězec: var str:String = "she sells seashells by the seashore."; var pattern:RegExp = /sh\w*/; trace(str.match(pattern)) // output: she Je-li příznak g nastaven, metoda Sting.match() vrátí více shod, viz níže: var str:String = "she sells seashells by the seashore."; var pattern:RegExp = /sh\w*/g; // The same pattern, but this time the g flag IS set. trace(str.match(pattern)); // output: she,shells,shore Příznak i (ignoreCase) Shody regulárních výrazů implicitně zohledňují velká a malá písmena. Jestliže nastavíte příznak i (ignoreCase), bude zohlednění malých a velkých písmen ignorováno. Například malé písmeno s v regulárním výrazu se neshoduje s velkým písmenem S, prvním znakem řetězce: var str:String = "She sells seashells by the seashore."; trace(str.search(/sh/)); // output: 13 -- Not the first character PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 215 Používání regulárních výrazů Je-li příznak i nastaven, regulární výraz se neshoduje s velkým písmenem S: var str:String = "She sells seashells by the seashore."; trace(str.search(/sh/i)); // output: 0 Příznak i ignoruje zohlednění velkých a malých písmen pouze pro znaky A–Z a a–z, ale nikoliv pro rozšířené znaky, například É a é . Příznak m (multiline) Jestliže příznak m (multiline) není nastaven, znak ^ se shoduje se začátkem řetězce a znak $ se shoduje s koncem řetězce. Je-li příznak m nastaven, shodují se tyto znaky se začátkem řádku, respektive s koncem řádku. Zvažte následující řetězec, který zahrnuje znak nového řádku: var str:String = "Test\n"; str += "Multiline"; trace(str.match(/^\w*/g)); // Match a word at the beginning of the string. Ačkoliv je příznak g (global) v regulárním výrazu nastaven, metoda match() se shoduje pouze s jedním dílčím řetězcem, protože pro znak ^existuje pouze jedna shoda - začátek řetězce. Výstup je následující: Test Zde je stejný kód s nastaveným příznakem m: var str:String = "Test\n"; str += "Multiline"; trace(str.match(/^\w*/gm)); // Match a word at the beginning of lines. Výstup tentokrát zahrnuje slova na začátku obou řádků: Test,Multiline Všimněte si, že pouze znak \n označuje konec řádku. Následující znaky konec řádku neoznačují: • Znak vrácení (\r) • Znak oddělovače řádku Unicode(\u2028) • Znak oddělovače odstavce Unicode (\u2029) Příznak s (dotall) Jestliže příznak s (dotall nebo „dot all“) není nastaven, tečka (.) ve vzorci regulárního výrazu neodpovídá znaku nového řádku (\n). Pro následující příklad tedy neexistuje žádná shoda: var str:String = "<p>Test\n"; str += "Multiline</p>"; var re:RegExp = /<p>.*?<\/p>/; trace(str.match(re)); Je-li příznak s nicméně nastaven, tečka se shoduje se znakem nového řádku: var str:String = "<p>Test\n"; str += "Multiline</p>"; var re:RegExp = /<p>.*?<\/p>/s; trace(str.match(re)); V tomto případě je shodou celý řetězec v rámci tagu <p>, včetně znaku nového řádku: <p>Test Multiline</p> PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 216 Používání regulárních výrazů Příznak x (extended) Regulární výrazy mohou být obtížné pro čtení, zvláště pokud obsahují mnoho metasymbolů a metasekvencí. Například: /<p(>|(\s*[^>]*>)).*?<\/p>/gi Jestliže příznak x (extended) použijete v regulárním výrazu, budou jakákoliv prázdná místa, která zadáte do vzorce, ignorována. Například následující regulární výraz je identický s předcházejícím příkladem: / <p (> | (\s* [^>]* >)) .*? <\/p> /gix Jestliže jste příznak x nastavili a přejete si jej přiřadit znaku prázdného místa, umístěte před prázdné místo zpětné lomítko. Například následující dva regulární výrazy jsou rovnocenné: /foo bar/ /foo \ bar/x Vlastnost lastIndex Vlastnost lastIndex určuje indexovou polohu v řetězci, ve které se má zahájit další hledání. Tato vlastnost ovlivňuje metody exec() a test() volané na regulárním výrazu, který má příznak g nastaven na true. Posuďte například následující kód: var pattern:RegExp = /p\w*/gi; var str:String = "Pedro Piper picked a peck of pickled peppers."; trace(pattern.lastIndex); var result:Object = pattern.exec(str); while (result != null) { trace(pattern.lastIndex); result = pattern.exec(str); } Vlastnost lastIndex je implicitně nastavena na hodnotu 0 (pro zahájení vyhledávání na začátku řetězce). Po každé shodě je tato vlastnost nastavena na indexovou pozici za shodou. Proto je výstup pro předešlý kód následující: 0 5 11 18 25 36 44 Jestliže je příznak global nastaven na false, metody exec() a test() nepoužijí nebo nenastaví vlastnost lastIndex. Metody match(), replace()a search() třídy String zahájí veškerá vyhledávání na začátku řetězce, bez ohledu na nastavení vlastnosti lastIndex regulárního výrazu použitého ve volání dané metody. (Nicméně metoda match() nenastaví vlastnost lastIndex na hodnotu 0.) Můžete nastavit vlastnost lastIndex tak, aby přizpůsobila počáteční pozici v řetězci pro porovnávání regulárního výrazu. Vlastnost zdroje Vlastnost source určuje řetězec, který definuje část vzorce regulárního výrazu. Například: var pattern:RegExp = /foo/gi; trace(pattern.source); // foo PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 217 Používání regulárních výrazů Metody pro použití regulárních výrazů s řetězci Třída RegExp zahrnuje dvě metody: exec() a test(). Vedle metod exec() a test() třídy RegExp zahrnuje třída String následující metody, které vám umožňují přiřadit regulární výrazy v řetězcích: match(), replace(), search() a splice(). Metoda test() Metoda test() třídy RegExp jednoduše zkontroluje dodaný řetězec, zda obsahuje shodu pro daný regulární výraz. Viz. následující kód: var pattern:RegExp = /Class-\w/; var str = "Class-A"; trace(pattern.test(str)); // output: true Metoda exec() Metoda exec() třídy RegExp zkontroluje dodaný řetězec, zda obsahuje shodu regulárního výrazu, a vrátí pole s následujícími hodnotami: • Odpovídajícím dílčím řetězcem • Shody dílčího řetězce pro jakékoliv skupiny kulatých závorek v regulárním výrazu Pole obsahuje také vlastnost index, která určuje indexovou pozici začátku shody dílčího řetězce. Posuďte například následující kód: var pattern:RegExp = /\d{3}\-\d{3}-\d{4}/; //U.S phone number var str:String = "phone: 415-555-1212"; var result:Array = pattern.exec(str); trace(result.index, " - ", result); // 7-415-555-1212 Použijte několikrát hodnotu exec() pro přiřazení několika dílčích řetězců, je-li pro daný regulární výraz nastaven příznak g (global): var pattern:RegExp = /\w*sh\w*/gi; var str:String = "She sells seashells by the seashore"; var result:Array = pattern.exec(str); while (result != null) { trace(result.index, "\t", pattern.lastIndex, "\t", result); result = pattern.exec(str); } //output: // 0 3 She // 10 19 seashells // 27 35 seashore Metody řetězců, které používají parametry RegExp Následující metody třídy String přebírají regulární výrazy jako parametry: match(), replace(), search() a split(). Více informací o těchto metodách naleznete v části „Vyhledání vzorků v řetězcích a nahrazení podřetězců“ na stránce 144. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 218 Používání regulárních výrazů Příklad: analyzátor Wiki Tento jednoduchý příklad konverze textu Wiki ukazuje několik využití regulárních výrazů: • Převedení řádků textu, které odpovídají zdrojovému vzorci Wiki na příslušné výstupní řetězce HTML. • Použití regulárního výrazu pro převedení vzorců URL na hyperlinkové tagy HTML <a>. • Použití regulárního výrazu pro převedení řetězců amerického dolaru (například "$9.95") na řetězce Euro (například "8.24 €"). Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace WikiEditor lze nalézt ve složce Samples/WikiEditor. Aplikace sestává z následujících souborů: Soubor Popis WikiEditor.mxml Hlavní soubor aplikace v programu Flash (FLA) nebo Flex (MXML). nebo WikiEditor.fla com/example/programmingas3/regExpExamples/WikiParser.as Třída, která zahrnuje metody používající regulární výrazy pro převedení vzorců vstupního textu Wiki na ekvivalentní výstup HTML. com/example/programmingas3/regExpExamples/URLParser.as Třída obsahující metody používající regulární výrazy pro převedení řetězců URL na hyperlinkové tagy HTML <a>. com/example/programmingas3/regExpExamples/CurrencyConverter.as Třída obsahující metody používající regulární výrazy pro převedení řetězců amerického dolaru na Euro. Definice třídy WikiParser Třída WikiParser zahrnuje metody, které převádějí vstupní text Wiki na ekvivalentní výstup HTML. Nejedná se o masivní aplikaci převodu Wiki, ale ukazuje některá dobrá využití regulárních výrazů pro párování vzorců a převod řetězců. Funkce konstruktoru, společně s metodousetWikiData(), jednoduše inicializuje ukázkový řetězec vstupního textu Wiki, a to následovně: public function WikiParser() { wikiData = setWikiData(); } Když uživatel ve vzorové aplikaci klepne na tlačítko Test, aplikace iniciuje metodu parseWikiString() objektu WikiParser. Tato metoda volá několik jiných metod, které zase sestaví výsledný řetězec HTML. public function parseWikiString(wikiString:String):String { var result:String = parseBold(wikiString); result = parseItalic(result); result = linesToParagraphs(result); result = parseBullets(result); return result; } Každá z volaných metod - parseBold(), parseItalic(), linesToParagraphs() a parseBullets() - používají metodu replace() řetězce pro nahrazení shodných vzorců, definovaných regulárním výrazem, pro převedení vstupu textu Wiki do textu formátovaného v HTML. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 219 Používání regulárních výrazů Převedení vzorců tučného písma a kurzívy Metoda parseBold() vyhledá textový vzorec Wiki tučného textu (například '''foo''') a převede jej do ekvivalentu HTML (například <b>foo</b>), následovně: private function parseBold(input:String):String { var pattern:RegExp = /'''(.*?)'''/g; return input.replace(pattern, "<b>$1</b>"); } Všimněte si, že část regulárního výrazu (.?*) odpovídá libovolnému počtu znaků (*) mezi dvěma definujícími ''' vzorci. Kvantifikátor ? provede přiřazení nechamtivě, takže například pro řetězec '''aaa''' bbb '''ccc''' bude první souhlasný řetězec'''aaa''' a nikoliv celý řetězec (který začíná a končí vzorcem '''). Kulaté závorky v regulárním výrazu definují skupinu zachycení a metoda replace() odkazuje na tuto skupinu pomocí kódu $1 v náhradním řetězci. Příznak g (global) v regulárním výrazu zajistí, že metoda replace() nahradí všechny shody v řetězci (ne pouze první shodu). Metoda parseItalic() pracuje podobně jako metoda parseBold() s výjimkou, že jako oddělovač pro text kurzívy vyhledá dva apostrofy ('') (nikoliv tři): private function parseItalic(input:String):String { var pattern:RegExp = /''(.*?)''/g; return input.replace(pattern, "<i>$1</i>"); } Převádění vzorků odrážek Jak ukazuje následující příklad, metoda parseBullet() vyhledá vzorec řádku odrážky Wiki (například * foo) a převede jej do ekvivalentu HTML (například <li>foo</li>): private function parseBullets(input:String):String { var pattern:RegExp = /^\*(.*)/gm; return input.replace(pattern, "<li>$1</li>"); } Symbol ^ na začátku regulárního výrazu se shoduje se začátkem řádku. Příznak m (multiline) v regulárním výrazu způsobí, že se bude regulární výraz shodovat se symbolem ^ oproti začátku řádku, ne pouze jednoduše se začátkem řetězce. Vzorec \* se shoduje se znakem hvězdičky (zpětné lomítko je použito pro označení hvězdičky literálu namísto * kvantifikátoru). Kulaté závorky v regulárním výrazu definují skupinu zachycení a metoda replace() odkazuje na tuto skupinu pomocí kódu $1 v náhradním řetězci. Příznak g (global) v regulárním výrazu zajistí, že metoda replace() nahradí všechny shody v řetězci (ne pouze první shodu). Převádění vzorců odstavce Wiki Metoda linesToParagraphs() převede každý řádek ve vstupním řetězci Wiki na tag odstavce HTML <p>. Tyto řádky v metodě vyskriptují prázdné řádky ze vstupního řetězce Wiki: var pattern:RegExp = /^$/gm; var result:String = input.replace(pattern, ""); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 220 Používání regulárních výrazů Symboly ^ a $ regulárního výrazu se shodují se začátkem a koncem řádku. Příznak m (multiline) v regulárním výrazu způsobí, že se bude regulární výraz shodovat se symbolem ^ oproti začátku řádku, ne pouze jednoduše se začátkem řetězce. Metoda replace() nahradí všechny shodující se dílčí řetězce (prázdné řádky) prázdným řetězcem (""). Příznak g (global) v regulárním výrazu zajistí, že metoda replace() nahradí všechny shody v řetězci (ne pouze první shodu). Převádění URL na tagy HTML <a> Když uživatel klepne v ukázkové aplikaci na tlačítko Test, jestliže zaškrtl políčko urlToATag, aplikace volá statickou metodu URLParser.urlToATag() pro převedení řetězců URL ze vstupního řetězce Wiki na tagy HTML <a>. var var var var var protocol:String = "((?:http|ftp)://)"; urlPart:String = "([a-z0-9_-]+\.[a-z0-9_-]+)"; optionalUrlPart:String = "(\.[a-z0-9_-]*)"; urlPattern:RegExp = new RegExp(protocol + urlPart + optionalUrlPart, "ig"); result:String = input.replace(urlPattern, "<a href='$1$2$3'><u>$1$2$3</u></a>"); Funkce konstruktoru RegExp() se používá pro sestavení regulárního výrazu (urlPattern) z několika složkových částí. Tyto složkové části jsou každá řetězcem, který definuje část vzorce regulárního výrazu. První část vzorce regulárního výrazu, definovaná řetězcem protocol, definuje protokol URL: buď http:// nebo ftp://. Kulaté závorky definují skupinu bez zachycení, označenou symbolem ? symbol. To znamená, že kulaté závorky jsou jednoduše použity k definování skupiny pro vzorec alternace |; skupina se nebude shodovat s kódy zpětné reference ($1, $2, $3) v náhradním řetězci metody replace(). Každá z dalších složkových částí regulárního výrazu používá skupiny zachycení (označené ve vzorci kulatými závorkami), které jsou poté použity v kódech zpětné reference ($1, $2, $3) v náhradním řetězci metody replace(). Část vzorce definovaná řetězcem urlPart se shoduje minimálně s jedním z následujících znaků: a-z, 0-9, _ nebo -. Kvantifikátor + označuje, že byl přiřazen minimálně jeden znak. \. označuje požadovaný znak tečky (.). A zbytek se shoduje s dalším řetězcem minimálně s jedním z těchto znaků: a-z, 0-9, _ nebo -. Část vzorce definovaná řetězcem optionalUrlPart se shoduje s nulou nebo více následujících prvků: tečka (.) znak následovaný libovolným počtem alfanumerických znaků (včetně _ a -). Kvantifikátor * označuje, že bylo přiřazeno nula nebo více znaků. Volání metody replace() použije regulární výraz a pomocí zpětných referencí sestaví náhradní řetězec HTML. Metoda urlToATag() poté volá metodu emailToATag(), která používá podobné techniky pro nahrazení vzorců emailu hyperlinkovými řetězci HTML <a>. Regulární výrazy použité pro přiřazení HTTP, FTP a URL e-mailu v tomto ukázkovém souboru jsou za účelem znázornění jednoduché; pro přesnější přiřazení takových URL existují o mnoho komplikovanější regulované výrazy. Převedení řetězců amerického dolaru na řetězce Euro. Když uživatel klepne v ukázkové aplikaci na tlačítko Test, jestliže zaškrtl políčko dollarToEuro , aplikace volá statickou metodu CurrencyConverter.usdToEuro() pro převedení řetězců amerického dolaru (například "$9.95") na řetězce Euro (například "8.24 €"), a to následovně: var usdPrice:RegExp = /\$([\d,]+.\d+)+/g; return input.replace(usdPrice, usdStrToEuroStr); První řádek definuje jednoduchý vzorec pro přiřazení řetězců amerického dolaru. Všimněte si, že znaku $ předchází znak escape zpětného lomítka (\). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 221 Používání regulárních výrazů Metoda replace() používá regulární výraz jako objekt přiřazení vzorce a volá funkci usdStrToEuroStr() pro stanovení náhradního řetězce (hodnota v Eur). Je-li jako druhý parametr metody replace() použit název funkce, jsou následující hodnoty předány jako parametry volané funkci: • Vyhovující část řetězce. • Libovolná zachycená skupina kulatých závorek se shoduje. Počet argumentů předaných tímto způsobem se bude měnit v závislosti na počtu zachycených shod skupiny kulatých závorek. Počet zachycených shod skupiny kulatých závorek můžete určit ověřením arguments.length - 3 uvnitř kódu funkce. • Indexová pozice v řetězci, kde začíná shoda. • Úplný řetězec. Metoda usdStrToEuroStr() převede vzorce řetězce amerického dolaru na řetězce Euro, a to následovně: private function usdToEuro(...args):String { var usd:String = args[1]; usd = usd.replace(",", ""); var exchangeRate:Number = 0.828017; var euro:Number = Number(usd) * exchangeRate; trace(usd, Number(usd), euro); const euroSymbol:String = String.fromCharCode(8364); // € return euro.toFixed(2) + " " + euroSymbol; } Všimněte si, že args[1] představuje zachycenou skupinu přiřazenou pomocí regulárního výrazu usdPrice. Jedná se o numerickou část řetězce amerického dolaru: tj. částku v dolarech se znakem $. Metoda použije převod směnného kurzu a vrátí výsledný řetězec (s koncovým symbolem € namísto vedoucího symbolu $). 222 Kapitola 11: Práce s jazykem XML ActionScript 3.0 obsahuje skupinu tříd založených na specifikaci ECMAScript pro XML (E4X) (ECMA-357, vydání 2). Tyto třídy zahrnují výkonné a snadno použitelné funkce pro práci s daty XML. Pomocí E4X budete schopni vytvořit kód s daty XML rychleji než s předchozími programovacími postupy. Další výhodou je to, že vytvořený kód bude snáze čitelný. Tato kapitola popisuje způsob použití specifikace E4X ke zpracování dat XML. Základy jazyka XML Úvod do práce s jazykem XML Jazyk XML představuje standardní způsob vyjádření strukturovaných informací, aby byly snadno zpracovatelné pro počítače a poměrně snadno zapisovatelné a pochopitelné pro lidi. XML je zkratka pro eXtensible Markup Language (rozšiřitelný značkovací jazyk). Standard XML je dostupný na adrese www.w3.org/XML/. XML nabízí standardní a pohodlný způsob kategorizace dat, aby byla snáze čitelná, přístupná a zpracovatelná. XML používá podobnou stromovou strukturu a strukturu tagů jako jazyk HTML. Zde je jednoduchá ukázka dat XML: <song> <title>What you know?</title> <artist>Steve and the flubberblubs</artist> <year>1989</year> <lastplayed>2006-10-17-08:31</lastplayed> </song> Data XML mohou být také mnohem složitější, s tagy vnořenými do jiných tagů, jakož i atributy a dalšími strukturními komponentami. Zde je složitější ukázka dat XML: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 223 Práce s jazykem XML <album> <title>Questions, unanswered</title> <artist>Steve and the flubberblubs</artist> <year>1989</year> <tracks> <song tracknumber="1" length="4:05"> <title>What do you know?</title> <artist>Steve and the flubberblubs</artist> <lastplayed>2006-10-17-08:31</lastplayed> </song> <song tracknumber="2" length="3:45"> <title>Who do you know?</title> <artist>Steve and the flubberblubs</artist> <lastplayed>2006-10-17-08:35</lastplayed> </song> <song tracknumber="3" length="5:14"> <title>When do you know?</title> <artist>Steve and the flubberblubs</artist> <lastplayed>2006-10-17-08:39</lastplayed> </song> <song tracknumber="4" length="4:19"> <title>Do you know?</title> <artist>Steve and the flubberblubs</artist> <lastplayed>2006-10-17-08:44</lastplayed> </song> </tracks> </album> Všimněte si, že tento dokument XML v sobě zahrnuje další kompletní struktury XML (např. tagy song s jejich podřízenými objekty). Znázorňuje také další struktury XML, jako jsou atributy (tracknumber a length uvnitř tagů song) a tagy, jež obsahují další tagy spíše než data (např. tag tracks). Začínáme s jazykem XML Nemáte-li s jazykem XML žádné nebo máte jen malé zkušenosti, zde je stručný popis nejčastějších aspektů dat XML. Data XML jsou napsána jako prostý text, se specifickou syntaxí pro uspořádání informací do strukturovaného formátu. Jediná sada dat XML se obecně označuje jako dokument XML. Ve formátu XML jsou data uspořádána do elementů (což mohou být jednotlivé datové položky nebo kontejnery pro další elementy) za použití hierarchické struktury. Každý dokument XML má jediný element jako položku nejvyšší úrovně nebo hlavní položku. Uvnitř tohoto kořenového elementu může být jediná informace, ale pravděpodobněji v něm budou další elementy, které zase obsahují jiné elementy atd. Tento dokument XML například obsahuje informace o hudebním albu: <song tracknumber="1" length="4:05"> <title>What do you know?</title> <artist>Steve and the flubberblubs</artist> <mood>Happy</mood> <lastplayed>2006-10-17-08:31</lastplayed> </song> Jednotlivé elementy jsou odlišeny sadou tagů – název elementu uzavřený v lomených závorkách (znaménka méně než a více než). Počáteční tag, který označuje začátek elementu, má název elementu: <title> Koncový tag, jenž označuje konec elementu, má před názvem elementu lomítko: </title> PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 224 Práce s jazykem XML Jestliže element nemá žádný obsah, může být zapsán jako prázdný element (někdy zvaný samouzavírací element). V jazyce XML je tento element: <lastplayed/> stejný jako tento element: <lastplayed></lastplayed> Kromě obsahu elementu umístěného mezi počátečním a koncovým tagem může element zahrnovat také další hodnoty, označované jako atributy, které jsou definovány v počátečním tagu elementu. Tento element XML například definuje jediný atribut s názvem length, jehož hodnota je "4:19": <song length="4:19"></song> Každý element XML má obsah, což je buďto jediná hodnota, jeden či více elementů XML nebo nic (u prázdného elementu). Další informace o jazyce XML Jestliže chcete získat více informací o práci s jazykem XML, je k dispozici celá řada dalších publikací a zdrojů obsahujících další podrobnosti o jazyce XML, včetně následujících webových míst: • Výuková lekce XML W3Schools: http://w3schools.com/xml/ • XML.com: http://www.xml.com/ • Výukové lekce XMLpitstop, seznamy diskusí a další zdroje: http://xmlpitstop.com/ Třídy ActionScript pro práci s jazykem XML ActionScript 3.0 obsahuje několik tříd, které slouží pro práci s informacemi strukturovanými pomocí jazyka XML. Dvě hlavní třídy jsou následující: • XML: Představuje jediný element XML, což může být dokument XML s několika podřízenými dokumenty, nebo element s jedinou hodnotou uvnitř dokumentu. • XMLList: Představuje sadu elementů XML. Objekt XMLList se používá v případě, že existuje více elementů XML na stejné úrovni (obsažených stejným nadřízeným objektem v hierarchii dokumentů XML). Instance objektu XMLList například představuje nejsnazší způsob zpracování následující sady elementů XML (pravděpodobně obsažených v dokumentu XML): <artist type="composer">Fred Wilson</artist> <artist type="conductor">James Schmidt</artist> <artist type="soloist">Susan Harriet Thurndon</artist> Pro pokročilejší použití zahrnující jmenné prostory XML obsahuje ActionScript také třídy Namespace a QName. Další informace naleznete v sekci „Použití jmenných prostorů XML“ na stránce 237. Kromě těchto vestavěných tříd pro práci s jazykem XML zahrnuje ActionScript 3.0 také několik operátorů poskytujících specifickou funkčnost pro přístup k datům XML a jejich zpracování. Tento přístup k práci s jazykem XML pomocí těchto tříd a operátorů se nazývá ECMAScript pro XML (E4X) podle definice ve specifikaci ECMA-357, vydání 2. Běžné úlohy XML Při práci s jazykem XML v jazyce ActionScript se budou pravděpodobně provádět následující úlohy: • Tvorba dokumentu XML (přidání elementů a hodnot) • Přístup k elementům XML, hodnotám a atributům PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 225 Práce s jazykem XML • Filtrování (vyhledávání) elementů XML • Opakování sady elementů XML • Převádění dat mezi třídami XML a třídou String • Práce s jmennými prostory XML • Načtení externích souborů XML Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny používané v této kapitole: • Element: Jediná položka v dokumentu XML, identifikovaná jako obsah umístěný mezi počátečním tagem a koncovým tagem (včetně samotných tagů). Elementy XML mohou obsahovat textová data či jiné elementy, nebo mohou být prázdné. • Prázdný element: Element XML, který neobsahuje žádné podřízené elementy. Prázdné elementy jsou často napsány jako samouzavírací tagy (např. <element/>). • Dokument: Jediná struktury XML. Dokument XML může obsahovat libovolný počet elementů (nebo jej může tvořit pouze jediný prázdný element), ale musí mít jeden element nejvyšší úrovně, který bude obsahovat všechny ostatní elementy v tomto dokumentu. • Uzel: Jiný název pro element XML. • Atribut: Pojmenovaná hodnota přiřazená k elementu, která je zapsána do počátečního tagu elementu ve formátu attributename="value" místo toho, aby byla zapsána jako samostatný podřízený element vnořený v elementu. Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. V podstatě všechny výpisy kódů uvedené v této kapitole již zahrnují příslušné volání funkce trace(). Návod na vyzkoušení kódů uvedených v této kapitole: 1 Vytvořte prázdný dokument Flash. 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Spusťte program pomocí příkazu Ovládání > Testovat film. Výsledky funkcetrace() se zobrazí v panelu Výstup. Tyto a další postupy pro testování vzorových výpisů kódů jsou podrobněji popsány v sekci „Testování příkladů kódu v této kapitole“ na stránce 34. Přístup E4X ke zpracování XML Specifikace ECMAScript pro XML definuje sadu tříd a funkce pro práci s daty XML. Tyto třídy a funkce se společně nazývají E4X.ActionScript 3.0 zahrnuje následující třídy E4X: XML, XMLList, QName a Namespace. Při navrhování metod, vlastností a operátorů tříd E4X byly sledovány následující cíle: • Jednoduchost – Tam, kde je to možné, E4X usnadňuje zápis a pochopení kódu pro práci s daty XML. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 226 Práce s jazykem XML • Jednotnost – Metody a argumenty v pozadí E4X jsou vnitřně jednotné a jsou v souladu s ostatními částmi jazyka ActionScript. • Povědomost – Data XML se zpracovávají pomocí dobře známých operátorů, jako je např. operátor tečka (.) operátor. Poznámka: V jazyce ActionScript 2.0 byla k dispozici třída XML. V jazyce ActionScript 3.0 byla tato třída přejmenována na XMLDocument, aby nedocházelo ke konfliktům s třídou XML jazyka ActionScript 3.0, která je součástí E4X. Starší třídy – XMLDocument, XMLNode, XMLParser a XMLTag – jsou v jazyce ActionScript 3.0 obsaženy v balíčku flash.xml, a to zejména kvůli podpoře starších verzí. Nové třídy E4X jsou základní třídy, takže k jejich použití není zapotřebí provádět import balíčku. Tato kapitola se nezabývá podrobnostmi o starších třídách XML verze ActionScript 2.0. Podrobnosti o nich naleznete v sekci věnované balíčku balík flash.xml v Referenční příručce jazyka ActionScript 3.0 a jeho komponent. Zde je příklad zpracování dat pomocí E4X: var myXML:XML = <order> <item id='1'> <menuName>burger</menuName> <price>3.95</price> </item> <item id='2'> <menuName>fries</menuName> <price>1.45</price> </item> </order> Aplikace bude často načítat data XML z externího zdroje, např. z webové služby nebo kanálu RSS. Kvůli větší srozumitelnosti však příklady v této kapitole přiřazují data XML jako literály. Jak je znázorněno v následujícím kódu, E4X zahrnuje několik intuitivních operátorů, např. operátory tečka (.) a identifikátor atributu (@), pro přístup k vlastnostem a atributům v jazyce XML: trace(myXML.item[0].menuName); // Output: burger trace(myXML.item.(@id==2).menuName); // Output: fries trace(myXML.item.(menuName=="burger").price); // Output: 3.95 Metoda appendChild() slouží k přiřazení nového podřízeného uzlu k objektu XML, jak ilustruje následující výstřižek: var newItem:XML = <item id="3"> <menuName>medium cola</menuName> <price>1.25</price> </item> myXML.appendChild(newItem); Operátory @ a .slouží nejen ke čtení dat, ale také k přiřazování dat, jako v následujícím příkladu: myXML.item[0].menuName="regular burger"; myXML.item[1].menuName="small fries"; myXML.item[2].menuName="medium cola"; myXML.item.(menuName=="regular burger").@quantity = "2"; myXML.item.(menuName=="small fries").@quantity = "2"; myXML.item.(menuName=="medium cola").@quantity = "2"; Pomocí smyčky for lze iterovat uzly XML následujícím způsobem: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 227 Práce s jazykem XML var total:Number = 0; for each (var property:XML in myXML.item) { var q:int = Number(property.@quantity); var p:Number = Number(property.price); var itemTotal:Number = q * p; total += itemTotal; trace(q + " " + property.menuName + " $" + itemTotal.toFixed(2)) } trace("Total: $", total.toFixed(2)); Objekty XML Objekt XML může představovat element XML, atribut, komentář, příkaz zpracování nebo textový element. Objekt XML je klasifikován jako objekt s jednoduchým obsahem nebo komplexním obsahem. Objekt XML, který má podřízené uzly, je klasifikován jako objekt s komplexním obsahem. O objekt s jednoduchým obsahem se jedná v případě, že jde o jeden z následujících objektů XML: atribut, komentář, příkaz zpracování nebo textový uzel. Následující objekt XML má například komplexní obsah, včetně komentáře a příkazu zpracování: XML.ignoreComments = false; XML.ignoreProcessingInstructions = false; var x1:XML = <order> <!--This is a comment. --> <?PROC_INSTR sample ?> <item id='1'> <menuName>burger</menuName> <price>3.95</price> </item> <item id='2'> <menuName>fries</menuName> <price>1.45</price> </item> </order> Jak je znázorněno v následujícím příkladu, pomocí metod comments() a processingInstructions() lze vytvářet nové objekty XML, komentář a příkaz zpracování: var x2:XML = x1.comments()[0]; var x3:XML = x1.processingInstructions()[0]; Vlastnosti XML Třída XML má pět statických vlastností: • Vlastnosti ignoreComments a ignoreProcessingInstructions určují, zda jsou při analýze objektu XML ignorovány komentáře nebo příkazy zpracování. • Vlastnost ignoreWhitespace určuje, zda budou ignorovány znaky prázdných míst uvnitř tagů elementů a vnořené výrazy, které jsou odděleny pouze znaky prázdných míst. • Vlastnosti prettyIndentaprettyPrinting slouží k formátování textu vráceného metodami toString() a toXMLString() třídy XML. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 228 Práce s jazykem XML Pro podrobnosti o těchto vlastnostech viz Referenční příručka jazyka ActionScript 3.0 a jeho komponent. Metody XML Následující metody umožňují práci s hierarchickou strukturou objektů XML: • appendChild() • child() • childIndex() • children() • descendants() • elements() • insertChildAfter() • insertChildBefore() • parent() • prependChild() Následující metody umožňují práci s atributy objektu XML: • attribute() • attributes() Následující metody umožňují práci s vlastnostmi objektu XML: • hasOwnProperty() • propertyIsEnumerable() • replace() • setChildren() Následující metody jsou určeny pro práci s kvalifikovanými názvy a jmennými prostory: • addNamespace() • inScopeNamespaces() • localName() • name() • namespace() • namespaceDeclarations() • removeNamespace() • setLocalName() • setName() • setNamespace() Následující metody umožňují zpracování a stanovení určitých typů obsahu XML: • comments() • hasComplexContent() PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 229 Práce s jazykem XML • hasSimpleContent() • nodeKind() • processingInstructions() • text() Následující metody slouží k převádění na řetězce a k formátování objektů XML: • defaultSettings() • setSettings() • settings() • normalize() • toString() • toXMLString() K dispozici je i několik dalších metod: • contains() • copy() • valueOf() • length() Pro podrobnosti o těchto metodách viz Referenční příručka jazyka ActionScript 3.0 a jeho komponent. Objekty XMLList Instance XMLList představuje libovolnou kolekci objektů XML. Může obsahovat úplné dokumenty XML, fragmenty XML nebo výsledky dotazu XML. Následující metody umožňují práci s hierarchickou strukturou objektů XMLList: • child() • children() • descendants() • elements() • parent() Následující metody umožňují práci s atributy objektu XMLList: • attribute() • attributes() Následující metody umožňují práci s vlastnostmi objektu XMLList: • hasOwnProperty() • propertyIsEnumerable() Následující metody umožňují zpracování a stanovení určitých typů obsahu XML: • comments() PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 230 Práce s jazykem XML • hasComplexContent() • hasSimpleContent() • processingInstructions() • text() Následující metody slouží k převádění na řetězce a k formátování objektu XMLList: • normalize() • toString() • toXMLString() K dispozici je i několik dalších metod: • contains() • copy() • length() • valueOf() Pro podrobnosti o těchto metodách viz Referenční příručka jazyka ActionScript 3.0 a jeho komponent. Pro objekt XMLList obsahující přesně jeden element XML lze použít všechny vlastnosti a metody třídy XML, neboť objekt XMLList s jedním elementem XML je považován za objekt XML. Například v následujícím kódu, jelikož doc.div je objekt XMLList obsahující jeden element, lze použít metodu appendChild() ze třídy XML: var doc:XML = <body> <div> <p>Hello</p> </div> </body>; doc.div.appendChild(<p>World</p>); Seznam vlastností a metod XML naleznete v sekci „Objekty XML“ na stránce 227. Inicializace proměnných XML Objektu XML lze přiřadit literál XML následujícím způsobem: var myXML:XML = <order> <item id='1'> <menuName>burger</menuName> <price>3.95</price> </item> <item id='2'> <menuName>fries</menuName> <price>1.45</price> </item> </order> Jak ilustruje následující výstřižek, pomocí konstruktoru new lze vytvořit instanci objektu XML z řetězce obsahujícího data XML: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 231 Práce s jazykem XML var str:String = "<order><item id='1'><menuName>burger</menuName>" + "<price>3.95</price></item></order>"; var myXML:XML = new XML(str); Nejsou-li data XML v řetězci správně zformovaná (např. pokud chybí koncový tag), dojde k chybě chodu programu. Data lze do objektu XML rovněž předávat podle odkazu (z jiných proměnných), jak znázorňuje následující příklad: var tagname:String = "item"; var attributename:String = "id"; var attributevalue:String = "5"; var content:String = "Chicken"; var x:XML = <{tagname} {attributename}={attributevalue}>{content}</{tagname}>; trace(x.toXMLString()) // Output: <item id="5">Chicken</item> K načítání dat XML z URL slouží třída URLLoader, jak ilustruje následující příklad: import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; var externalXML:XML; var loader:URLLoader = new URLLoader(); var request:URLRequest = new URLRequest("xmlFile.xml"); loader.load(request); loader.addEventListener(Event.COMPLETE, onComplete); function onComplete(event:Event):void { var loader:URLLoader = event.target as URLLoader; if (loader != null) { externalXML = new XML(loader.data); trace(externalXML.toXMLString()); } else { trace("loader is not a URLLoader!"); } } Ke čtení dat XML ze soketového připojení použijte třídu XMLSocket. Další informace naleznete u třídy třída XMLSocket v Referenční příručce jazyka ActionScript 3.0 a jeho komponent. Sestavování a transformace objektů XML Pomocí metody prependChild() nebo appendChild() lze přidat vlastnost na začátek nebo na konec seznamu vlastností objektu XML, jak znázorňuje následující příklad: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 232 Práce s jazykem XML var var var x = x = x = x1:XML = <p>Line 1</p> x2:XML = <p>Line 2</p> x:XML = <body></body> x.appendChild(x1); x.appendChild(x2); x.prependChild(<p>Line 0</p>); // x == <body><p>Line 0</p><p>Line 1</p><p>Line 2</p></body> Pomocí metody insertChildBefore() nebo insertChildAfter() lze přidat vlastnost před nebo za určenou vlastnost následujícím způsobem: var x:XML = <body> <p>Paragraph 1</p> <p>Paragraph 2</p> </body> var newNode:XML = <p>Paragraph 1.5</p> x = x.insertChildAfter(x.p[0], newNode) x = x.insertChildBefore(x.p[2], <p>Paragraph 1.75</p>) Jak je znázorněno v následujícím příkladu, při sestavování objektů XML je rovněž možné použít operátory složené závorky ( { a } ) k předávání dat podle odkazu (z jiných proměnných): var ids:Array = [121, 122, 123]; var names:Array = [["Murphy","Pat"], ["Thibaut","Jean"], ["Smith","Vijay"]] var x:XML = new XML("<employeeList></employeeList>"); for (var i:int = 0; i < 3; i++) { var newnode:XML = new XML(); newnode = <employee id={ids[i]}> <last>{names[i][0]}</last> <first>{names[i][1]}</first> </employee>; x = x.appendChild(newnode) } Pomocí operátoru = lze objektu XML přiřadit vlastnosti a atributy, jako v následujícím příkladu: var x:XML = <employee> <lastname>Smith</lastname> </employee> x.firstname = "Jean"; x.@id = "239"; To nastaví objekt XMLx následujícím způsobem: <employee id="239"> <lastname>Smith</lastname> <firstname>Jean</firstname> </employee> Operátory + a += slouží k zřetězení objektů XMLList: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 233 Práce s jazykem XML var x1:XML = <a>test1</a> var x2:XML = <b>test2</b> var xList:XMLList = x1 + x2; xList += <c>test3</c> To nastaví objekt XMLList xList následujícím způsobem: <a>test1</a> <b>test2</b> <c>test3</c> Procházení struktur XML Jednou z výkonných funkcí jazyka XML je jeho schopnost poskytovat složitá, vnořená data pomocí lineárního řetězce textových znaků. Po načtení dat do objektu XML ActionScript tato data analyzuje a načte jejich hierarchickou strukturu do paměti (nebo vyvolá chybu chodu programu, pokud nejsou data XML správně zformovaná). Operátory a metody objektů XML a XMLList usnadňují procházení struktury dat XML. Operátor tečka (.) a operátor dceřiného mechanismu přístupu (..) slouží pro přístup k podřízeným vlastnostem objektu XML. Zvažte následující objekt XML: var myXML:XML = <order> <book ISBN="0942407296"> <title>Baking Extravagant Pastries with Kumquats</title> <author> <lastName>Contino</lastName> <firstName>Chuck</firstName> </author> <pageCount>238</pageCount> </book> <book ISBN="0865436401"> <title>Emu Care and Breeding</title> <editor> <lastName>Case</lastName> <firstName>Justin</firstName> </editor> <pageCount>115</pageCount> </book> </order> Objekt myXML.book je objekt XMLList obsahující podřízené vlastnosti objektu myXML s názvem book. Jedná se o dva objekty XML odpovídající dvěma vlastnostem book objektu myXML. Objekt myXML..lastName je objekt XMLList obsahující všechny podřízené vlastnosti s názvem lastName. Jedná se o dva objekty XML odpovídající dvěma vlastnostem lastName objektu myXML. Objekt myXML.book.editor.lastName je objekt XMLList obsahující všechny podřízené objekty s názvem lastName podřízených objektů s názvem editor podřízených objektů s názvembook objektu myXML: v tomto případě se jedná o objekt XMLList obsahující pouze jeden objekt XML (vlastnost lastName s hodnotou „Case“). Přístup k nadřízeným a podřízeným uzlům Metoda parent() vrátí nadřízený objekt objektu XML. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 234 Práce s jazykem XML Pomocí ordinálních hodnot indexu podřízeného seznamu lze získat přístup k určitým podřízeným objektům. Zvažte například objekt XML myXML, který má dvě podřízené vlastnosti s názvem book. Každá podřízená vlastnost s názvem book má přiřazeno pořadové číslo: myXML.book[0] myXML.book[1] Chcete-li získat přístup k určitému prapotomkovi, můžete určit pořadová čísla pro název podřízeného objektu i prapotomka: myXML.book[0].title[0] Jestliže však existuje jen jeden podřízený objekt objektu x.book[0] s názvem title, lze odkaz na index vynechat: myXML.book[0].title Stejně tak, pokud existuje jen jeden podřízený objekt „book“ objektu x a pokud má tento podřízený objekt jen jeden objekt „title“, lze vynechat oba odkazy na index takto: myXML.book.title Metodu child() lze použít pro přechod k podřízeným objektům, jejichž názvy jsou založeny na proměnné nebo výrazu, jak znázorňuje následující příklad: var myXML:XML = <order> <book> <title>Dictionary</title> </book> </order>; var childName:String = "book"; trace(myXML.child(childName).title) // output: Dictionary Přístup k atributům Symbol @ (operátor identifikátor atributu) slouží pro přístup k atributům v objektu XML nebo XMLList, jak ilustruje následující kód: var employee:XML = <employee id="6401" code="233"> <lastName>Wu</lastName> <firstName>Erin</firstName> </employee>; trace(employee.@id); // 6401 Zástupný znak * lze použít se symbolem @ pro přístup ke všem atributům objektu XML nebo XMLList, jako v následujícím kódu: var employee:XML = <employee id="6401" code="233"> <lastName>Wu</lastName> <firstName>Erin</firstName> </employee>; trace(employee.@*.toXMLString()); // 6401 // 233 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 235 Práce s jazykem XML Pomocí metody attribute() nebo attributes() lze získat přístup k určitému atributu nebo ke všem atributům objektu XML nebo XMLList, jako v následujícím kódu: var employee:XML = <employee id="6401" code="233"> <lastName>Wu</lastName> <firstName>Erin</firstName> </employee>; trace(employee.attribute("id")); // 6401 trace(employee.attribute("*").toXMLString()); // 6401 // 233 trace(employee.attributes().toXMLString()); // 6401 // 233 Všimněte si, že pro přístup k atributům je rovněž možné použít syntaxi znázorněnou v následujícím příkladu: employee.attribute("id") employee["@id"] employee.@["id"] Každý z nich se rovná employee.@id. Použití syntaxe employee.@id je však vhodnější. Filtrování podle hodnoty atributu nebo elementu Pomocí operátorů závorky – ( a ) – lze filtrovat elementy s určitým názvem elementu nebo s určitou hodnotou atributu. Zvažte následující objekt XML: var x:XML = <employeeList> <employee id="347"> <lastName>Zmed</lastName> <firstName>Sue</firstName> <position>Data analyst</position> </employee> <employee id="348"> <lastName>McGee</lastName> <firstName>Chuck</firstName> <position>Jr. data analyst</position> </employee> </employeeList> Platné jsou všechny následující výrazy: • x.employee.(lastName == "McGee") – Toto je druhý uzel employee. • x.employee.(lastName == "McGee").firstName – Toto je vlastnost firstName druhého uzlu employee. • x.employee.(lastName == "McGee").@id – Toto je hodnota atributu id druhého uzlu employee. • x.employee.(@id == 347) – První uzel employee. • x.employee.(@id == 347).lastName – Toto je vlastnost lastName prvního uzlu employee. • x.employee.(@id > 300) – Toto je objekt XMLList s oběma vlastnostmi employee. • x.employee.(position.toString().search("analyst") > -1) – Toto je objekt XMLList s oběma vlastnostmi position. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 236 Práce s jazykem XML Jestliže se pokusíte filtrovat atributy nebo elementy, které neexistují, aplikace Flash® Player a Adobe® AIR™ vyvolají výjimku. Například poslední řádek následujícího kódu vygeneruje chybu, protože ve druhém elementu p neexistuje žádný atribut id: var doc:XML = <body> <p id='123'>Hello, <b>Bob</b>.</p> <p>Hello.</p> </body>; trace(doc.p.(@id == '123')); Stejně tak vygeneruje chybu i poslední řádek následujícího kódu, neboť neexistuje žádná vlastnost b druhého elementu p: var doc:XML = <body> <p id='123'>Hello, <b>Bob</b>.</p> <p>Hello.</p> </body>; trace(doc.p.(b == 'Bob')); Aby k těmto chybám nedošlo, lze identifikovat vlastnosti, jež mají odpovídající atributy nebo elementy, pomocí metod attribute() a elements(), jako v následujícím kódu: var doc:XML = <body> <p id='123'>Hello, <b>Bob</b>.</p> <p>Hello.</p> </body>; trace(doc.p.(attribute('id') == '123')); trace(doc.p.(elements('b') == 'Bob')); Rovněž lze použít metodu hasOwnProperty(), jako v následujícím kódu: var doc:XML = <body> <p id='123'>Hello, <b>Bob</b>.</p> <p>Hello.</p> </body>; trace(doc.p.(hasOwnProperty('@id') && @id == '123')); trace(doc.p.(hasOwnProperty('b') && b == 'Bob')); Použití příkazů for..in a for each..in ActionScript 3.0 zahrnuje příkaz for..in a příkaz for each..in umožňující iteraci objektů XMLList. Zvažte například následující objekt XML myXML a objekt XMLList myXML.item. Objekt XMLList myXML.item tvoří dva uzly item objektu XML. var myXML:XML = <order> <item id='1' quantity='2'> <menuName>burger</menuName> <price>3.95</price> </item> <item id='2' quantity='2'> <menuName>fries</menuName> <price>1.45</price> </item> </order>; PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 237 Práce s jazykem XML Příkaz for..in umožňuje iteraci přes sadu názvů vlastností v objektu XMLList: var total:Number = 0; for (var pname:String in myXML.item) { total += myXML.item.@quantity[pname] * myXML.item.price[pname]; } Příkaz for each..inumožňuje iteraci vlastností v objektu XMLList: var total2:Number = 0; for each (var prop:XML in myXML.item) { total2 += prop.@quantity * prop.price; } Použití jmenných prostorů XML Jmenné prostory v objektu XML (nebo v dokumentu) označují typ dat, která tento objekt obsahuje. Například při odesílání dat XML do webové služby používající protokol zpráv SOAP se deklaruje jmenný prostor v počátečním tagu objektu XML: var message:XML = <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body xmlns:w="http://www.test.com/weather/"> <w:getWeatherResponse> <w:tempurature >78</w:tempurature> </w:getWeatherResponse> </soap:Body> </soap:Envelope>; Jmenný prostor má předponu soap a URI definující jmenný prostor http://schemas.xmlsoap.org/soap/envelope/. ActionScript 3.0 obsahuje třídu Namespace pro práci s jmennými prostory XML. Pro objekt XML v předchozím příkladu lze třídu Namespace použít následujícím způsobem: var soapNS:Namespace = message.namespace("soap"); trace(soapNS); // Output: http://schemas.xmlsoap.org/soap/envelope/ var wNS:Namespace = new Namespace("w", "http://www.test.com/weather/"); message.addNamespace(wNS); var encodingStyle:XMLList = message.@soapNS::encodingStyle; var body:XMLList = message.soapNS::Body; message.soapNS::Body.wNS::GetWeatherResponse.wNS::tempurature = "78"; Třída XML zahrnuje následující metody pro práci s jmennými prostory: addNamespace(), inScopeNamespaces(), localName(), name(), namespace(), namespaceDeclarations(), removeNamespace(), setLocalName(), setName() a setNamespace(). Instrukce default xml namespace umožňuje přiřazení výchozího jmenného prostoru pro objekty XML. Například v následujícím kódu mají oba objekty x1 i x2 stejný výchozí jmenný prostor: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 238 Práce s jazykem XML var ns1:Namespace = new Namespace("http://www.example.com/namespaces/"); default xml namespace = ns1; var x1:XML = <test1 />; var x2:XML = <test2 />; Převod typu XML Objekty XML a objekty XMLList lze převádět na hodnoty String. Stejně tak je možné převádět řetězce na objekty XML a XMLList. Rovněž je třeba mít na paměti, že všechny hodnoty atributů XML, názvy a textové hodnoty jsou řetězce. Následující sekce pojednávají o všech těchto formách převodu typu XML. Převádění objektů XML a XMLList na řetězce Třídy XML a XMLList zahrnují metodu toString() a metodu toXMLString(). Metoda toXMLString() vrátí řetězec zahrnující všechny tagy, atributy, deklarace jmenných prostorů a obsah objektu XML. U objektů XML s komplexním obsahem (podřízené elementy) má metoda toString() stejný efekt jako metoda toXMLString() . U objektů XML s jednoduchým obsahem (ty obsahují pouze jeden textový element) vrátí metoda toString() jen textový obsah elementu, jak je znázorněno v následujícím příkladu: var myXML:XML = <order> <item id='1' quantity='2'> <menuName>burger</menuName> <price>3.95</price> </item> <order>; trace(myXML.item[0].menuName.toXMLString()); // <menuName>burger</menuName> trace(myXML.item[0].menuName.toString()); // burger Pokud použijete metodu trace() bez určení metody toString() nebo toXMLString(), budou data standardně převedena pomocí metody toString(), jak ilustruje tento kód: var myXML:XML = <order> <item id='1' quantity='2'> <menuName>burger</menuName> <price>3.95</price> </item> <order>; trace(myXML.item[0].menuName); // burger Při použití metody trace() k ladění kódu je často vhodné použít metodu toXMLString(), protože metoda trace() tak vygeneruje kompletnější data. Převádění řetězců na objekty XML Pomocí konstruktoru new XML() lze z řetězce vytvořit objekt XML následujícím způsobem: var x:XML = new XML("<a>test</a>"); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 239 Práce s jazykem XML Jestliže se pokusíte převést řetězec na XML z řetězce představujícího neplatný nebo nesprávně zformovaný objekt XML, bude vyvolána výjimka: var x:XML = new XML("<a>test"); // throws an error Převádění hodnot atributů, názvů a textových hodnot z řetězců Všechny hodnoty atributů XML, názvy a textové hodnoty jsou datové typy String a může být zapotřebí je převést na jiné datové typy. Následující kód například převádí textové hodnoty na čísla pomocí funkce Number(): var myXML:XML = <order> <item> <price>3.95</price> </item> <item> <price>1.00</price> </item> </order>; var total:XML = <total>0</total>; myXML.appendChild(total); for each (var item:XML in myXML.item) { myXML.total.children()[0] = Number(myXML.total.children()[0]) + Number(item.price.children()[0]); } trace(myXML.total); // 4.35; Kdyby nebyla v tomto kódu použita funkce Number(), kód by interpretoval operátor + jako operátor zřetězení řetězců a metoda trace() v posledním řádku by pak vygenerovala následující výsledek: 01.003.95 Čtení externích dokumentů XML Pomocí třídy URLLoader lze načíst data XML z URL. Chcete-li použít následující kód ve vlastní aplikaci, nahraďte hodnotu XML_URL v tomto příkladu platnou adresou URL: var myXML:XML = new XML(); var XML_URL:String = "http://www.example.com/Sample3.xml"; var myXMLURL:URLRequest = new URLRequest(XML_URL); var myLoader:URLLoader = new URLLoader(myXMLURL); myLoader.addEventListener("complete", xmlLoaded); function xmlLoaded(event:Event):void { myXML = XML(myLoader.data); trace("Data loaded."); } Pomocí třídy XMLSocket lze rovněž vytvořit asynchronní soketové připojení XML k serveru. Pro více informací viz Referenční příručka jazyka ActionScript 3.0 a jeho komponent. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 240 Práce s jazykem XML Příklad: Načtení dat RSS z Internetu Vzorová aplikace RSSViewer znázorňuje několik funkcí pro práci s daty XML v jazyce ActionScript, včetně následujících: • Použití metod XML k procházení dat XML ve formě kanálu RSS. • Použití metod XML k sestavování dat XML ve formě HTML pro jejich použití v textovém poli. Formát RSS se obecně používá k publikování zpráv pomocí XML. Jednoduchý datový soubor RSS může vypadat například takto: <?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel> <title>Alaska - Weather</title> <link>http://www.nws.noaa.gov/alerts/ak.html</link> <description>Alaska - Watches, Warnings and Advisories</description> <item> <title> Short Term Forecast - Taiya Inlet, Klondike Highway (Alaska) </title> <link> http://www.nws.noaa.gov/alerts/ak.html#A18.AJKNK.1900 </link> <description> Short Term Forecast Issued At: 2005-04-11T19:00:00 Expired At: 2005-04-12T01:00:00 Issuing Weather Forecast Office Homepage: http://pajk.arh.noaa.gov </description> </item> <item> <title> Short Term Forecast - Haines Borough (Alaska) </title> <link> http://www.nws.noaa.gov/alerts/ak.html#AKZ019.AJKNOWAJK.190000 </link> <description> Short Term Forecast Issued At: 2005-04-11T19:00:00 Expired At: 2005-04-12T01:00:00 Issuing Weather Forecast Office Homepage: http://pajk.arh.noaa.gov </description> </item> </channel> </rss> Aplikace SimpleRSS čte data RSS z Internetu, analyzuje data pro titulky (nadpisy), odkazy a popisy a potom tato data vrátí. Třída SimpleRSSUI poskytuje uživatelské rozhraní a volá třídu SimpleRSS, která provede veškeré zpracování XML. Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Aplikační soubory RSSViewer jsou umístěny ve složce Samples/RSSViewer. Aplikace sestává z následujících souborů: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 241 Práce s jazykem XML Soubor Popis RSSViewer.mxml Hlavní soubor aplikace v programu Flash (FLA) nebo Flex (MXML). nebo RSSViewer.fla com/example/programmingas3/rssViewer/RSSParser.as Třída obsahující metody, které pomocí E4X procházejí data RSS (XML) a generují odpovídající HTML představující tato data. RSSData/ak.rss Vzorový soubor RSS. Tato aplikace je vytvořena tak, aby četla data RSS z webu, na kanálu Flex RSS hostovaném aplikací Adobe. Aplikaci je však možné snadno změnit, aby četla data RSS z tohoto dokumentu, který používá poněkud odlišné schéma než kanál Flex RSS. Čtení a analýza dat XML Třída RSSParser zahrnuje metodu xmlLoaded(), která převádí vstupní data RSS uložená v proměnné rssXML na řetězec obsahující výstup rssOutput zformátovaný pomocí HTML. Kód nastaví na začátku této metody výchozí jmenný prostor XML, pokud zdrojová data RSS zahrnují výchozí jmenný prostor: if (rssXML.namespace("") != undefined) { default xml namespace = rssXML.namespace(""); } Následující řádky pak vytvoří smyčku z obsahu zdrojových dat XML, přičemž zkoumají každou podřízenou vlastnost s názvem item. for each (var item:XML in rssXML..item) { var itemTitle:String = item.title.toString(); var itemDescription:String = item.description.toString(); var itemLink:String = item.link.toString(); outXML += buildItemHTML(itemTitle, itemDescription, itemLink); } První tři řádky jednoduše nastaví proměnné řetězce, aby představovaly vlastnosti titul, popis a odkaz vlastnosti item dat XML. Následující řádek pak zavolá metodu buildItemHTML(), která vygeneruje data HTML ve formě objektu XMLList, přičemž tři nové proměnné řetězce budou použity jako parametry. Sestavování dat objektu XMLList Data HTML (objekt XMLList) mají následující formu: <b>itemTitle</b> <p> itemDescription <br /> <a href="link"> <font color="#008000">More...</font> </a> </p> První řádky metody vymažou výchozí jmenný prostor XML (default xml namespace): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 242 Práce s jazykem XML default xml namespace = new Namespace(); Instrukce default xml namespace má rozsah funkce na úrovni bloku. To znamená, že rozsahem této deklarace je metoda buildItemHTML(). Řádky, které následují, sestaví objekt XMLList na základě argumentů řetězce předaných do funkce: var body:XMLList = new XMLList(); body += new XML("<b>" + itemTitle + "</b>"); var p:XML = new XML("<p>" + itemDescription + "</p>"); var link:XML = <a></a>; link.@href = itemLink; // <link href="itemLinkString"></link> link.font.@color = "#008000"; // <font color="#008000"></font></a> // 0x008000 = green link.font = "More..."; p.appendChild(<br/>); p.appendChild(link); body += p; Tento objekt XMLList představuje data řetězce vhodná pro textové pole HTML jazyka ActionScript. Metoda xmlLoaded() používá vrácené hodnoty metody buildItemHTML() a převádí je na řetězec: XML.prettyPrinting = false; rssOutput = outXML.toXMLString(); Vyjmutí titulu kanálu RSS a odeslání vlastní události Metoda xmlLoaded() nastaví proměnnou řetězce rssTitle na základě informací ve zdrojových datech RSS XML: rssTitle = rssXML.channel.title.toString(); Nakonec metoda xmlLoaded() vygeneruje událost, která aplikaci upozorní, že data byla analyzována a jsou k dispozici: dataWritten = new Event("dataWritten", true); 243 Kapitola 12: Zpracování událostí Systém zpracování událostí umožňuje programátorům reagovat na vstupy uživatele a události systému pohodlným způsobem. Model událostí jazyka ActionScript 3.0 není jenom pohodlný, ale splňuje také standardy, je dobře integrován do seznamů zobrazení aplikace Adobe® Flash® Player a Adobe® AIR™. Na základě specifikace události DOM (objektového modelu dokumentu) úrovně 3, což je architektura zpracování událostí průmyslového standardu, poskytuje programátorům jazyka ActionScript nový model událostí výkonný, ale přesto intuitivní nástroj pro zpracování událostí. Tato kapitola je organizována do pěti sekcí. První dvě sekce poskytují vedlejší informace o zpracování události v jazyce ActionScript. Poslední tři části popisují hlavní koncepty, které stojí za modelem událostí: tok událostí, objekt událostí a posluchače událostí. Systém zpracování událostí v jazyce ActionScript 3.0 úzce spolupracuje se seznamem zobrazení a tato kapitola předpokládá, že máte základní znalosti tohoto seznamu zobrazení. Další informace naleznete v části „Programování zobrazení“ na stránce 265. Základy zpracování událostí Úvod do zpracování událostí Na události můžete nahlížet jako na výskyty čehokoliv v souborech SWF, která vás jako programátora zajímají. Například většina souborů SWF podporuje nějakou interakci s uživatelem - například jednoduchá forma, jako je klepnutí myší, nebo složitější forma, například příjem a zpracování dat zadaných do formuláře. Každá taková interakce uživatele s vaším souborem SWF je považována za událost. Události mohou nastat také bez přímé interakce uživatele, například když je dokončeno načítání dat ze serveru nebo když se aktivuje připojena kamera. V jazyce ActionScript 3.0 je každá událost zastoupena objektem události, což je instance třídy Event nebo jedné z jejích podtříd. Objekt události nejenom, že ukládá informace o specifické události, ale obsahuje také metody, které usnadňují manipulaci s objektem události. Když například aplikace Flash Player nebo AIR detekuje klepnutí myší, vytvoří objekt události (instance třídy MouseEvent), který reprezentuje tuto specifickou události klepnutí myši. Po vytvoření objektu události jej aplikace Flash Player nebo AIR odešle, což znamená, že objekt události je předán objektu, která je cílem této události. Objekt sloužící jako cíl odeslaného objektu události se nazývá cíl události. Když se například aktivuje připojená kamera, aplikace Flash Player odešle objekt události přímo do cíle události, což je v tomto případě objekt představující kameru. V případě, že cíl události je na seznamu zobrazení, objekt události je předán dolů hierarchií seznamu zobrazení, dokud nedosáhne cíle události. V některých případech pak objekt události "probublává" zpět v hierarchii seznamu zobrazení, po stejné trase. Tento průchod hierarchií seznamu zobrazení se nazývá tok událostí. Ve svém kódu můžete objektům událostí "naslouchat" pomocí posluchačů události. Posluchače událostí jsou funkce nebo metody, které zapisujete v odezvě na specifické události. Pro zajištění, aby vaše programy na události odpovídaly, musíte přidat posluchače událostí do cíle události nebo do objektu seznamu zobrazení, který je součástí toku objektu událostí. Vždy, když píšete kód posluchače události, je nutné dodržovat tuto základní strukturu (prvky tučným písmem jsou rezervovaná místa, které vyplníte svým specifickým případem): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 244 Zpracování událostí function eventResponse(eventObject:EventType):void { // Actions performed in response to the event go here. } eventTarget.addEventListener(EventType.EVENT_NAME, eventResponse); Tento kód provádí dvě věci. Nejprve definuje funkci, která je způsobem specifikace činností, které budou provedeny v odezvě na událost. Dále je zavolána metoda addEventListener() zdrojového objektu, v podstatě “odběr” specifikované události funkcí tak, že když k události dojde, jsou provedeny činnosti funkce. Když dojde ke specifické události, cíl události zkontrolujte seznam všech funkcí a metod, které jsou zaregistrovány jako posluchače událostí. Poté postupně každou zavolá a předá objekt události jako parametr. Chcete-li vytvořit vlastní posluchač událostí, musíte změnit v tomto kódu čtyři věci. Nejprve musíte změnit název funkce na název, který chcete používat (musíte jej změnit na dvou místech, kde kód definuje eventResponse). Za druhé musíte specifikovat vhodný název třídy objektu události, který je odeslán událostí, které chcete naslouchat (v kódu EventType) a musíte specifikovat příslušnou konstantu pro specifickou událost (v seznamu EVENT_NAME). Za třetí musíte zavolat metodu addEventListener() pro objekt, která odešle události (v tomto kódu eventTarget). Volitelně můžete změnit názve proměnné použité jako parametr funkce (v tomto kódu eventObject). Společné úlohy zpracování událostí Následující úlohy jsou společné úlohy zpracování událostí, z nichž každá je v této kapitole popsána. • Zápis kódu reagujícího na události • Zastavení reakce kódu na události • Práce s objekty událostí • Práce s tokem událostí • Identifikování informací toku událostí • Zastavení toku událostí • Zabránění výchozího chování • Odeslání události z vašich tříd • Vytváření vlastních typů událostí Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Výchozí chování: některé události zahrnují chování, ke kterému normálně dochází společně s událostí, známou jako výchozí chování. Například když uživatel zadá text do textového pole, je aktivována události zadávání textu. Výchozí chování pro tuto událost je v podstatě zobrazení znaku, který byl do textového pole zadán - výchozí chování však můžete potlačit (pokud z nějakého důvodu nechcete zadaný text zobrazit). • Odeslání: vyrozumění posluchačů událostí o tom, že došlo k události. • Událost: něco, co se stane objektu, o čem tento objekt může říci objektům ostatním. • Tok událostí: když se objektu na seznamu zobrazení stane nějaká událost (objekt zobrazený na obrazovce), všechny objekty obsahující tento objekt jsou o události vyrozuměny a ty zase vyrozumí své posluchače událostí. Tento proces začíná na ploše a pokračuje seznamem zobrazení ke stávajícímu objektu, kde k události došlo, pak pokračuje znovu na plochu. Tento proces je znám jako tok událostí. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 245 Zpracování událostí • Objekt události: objekt obsahující informace o specifickém výskytu události, které jsou odeslány všem posluchačům, když je objekt odeslán. • Cíl události: objekt, který událost ve skutečnosti odeslal. Pokud například uživatel klepne na tlačítko, které se nachází uvnitř pohyblivého symbolu, který se opět nachází na ploše, všechny tyto objekty odešlou události, ale cíl události je ten, ke k události ve skutečnosti došlo - v tomto případě se jedná o tlačítko, na které bylo klepnuto. • Posluchač: objekt nebo funkce, které se zaregistrovaly u objektu a které označují, že by měly být informovány v případě, že ke specifické události dojde. Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. Všechny příklady kódu v této kapitole zahrnují volání funkce trace() pro testování výsledků kódu. Návod na vyzkoušení kódů uvedených v této kapitole: 1 Pomocí vývojového nástroje Flash vytvořte prázdný dokument. 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Spusťte program pomocí příkazu Ovládání > Testovat film. Výsledky funkcí trace() uvedených kódů uvidíte v panelu Výstup. Některé příklady kódu jsou složitější a zapsány jako třída. Postup při testování těchto příkladů: 1 Pomocí vývojového nástroje Flash vytvořte prázdný dokument a uložte jej na svůj počítač. 2 Vytvořte nový soubor ActionScript a uložte ho do stejného adresáře jako dokument vytvořený v 1. kroku. Název souboru by měl být stejný jako název třídy ve výpisu kódu. Pokud příklad kódu například definuje třídu pojmenovanou EventTest, použijte k uložení souboru jazyka ActionScript název EventTest.as. 3 Zkopírujte výpis kódu do souboru ActionScript a soubor uložte. 4 V dokumentu klepněte na prázdnou část Plochy nebo pracovní oblasti a aktivujte Inspektor vlastností dokumentu. 5 V Inspektoru vlastností zadejte do pole Třída dokumentu název třídy ActionScript vykopírovaný z textu. 6 Spusťte program pomocí volby Ovládání > Testovat film. Výsledky příkladu se zobrazí v panelu Výstup. Tyto techniky testování příkladu kódu jsou vysvětleny podrobněji v kapitole „Testování příkladů kódu v této kapitole“ na stránce 34. Jak se zpracování událostí v jazyce ActionScript 3.0 liší od předchozích verzí Nejvýraznější rozdíl mezi zpracováním události v jazyce ActionScript 3.0 a předchozích verzích tohoto jazyka je to, že ActionScript 3.0 je jediným systémem pro zpracování událostí, zatímco předchozí verze jazyka ActionScript umožňovaly existenci několika různých systémů pro zpracování událostí. Tato kapitola začíná přehledem, jak zpracování událostí pracovalo v předchozích verzích jazyka ActionScript a pak popisuje, jak se jazyce ActionScript 3.0 zpracování událostí změnilo. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 246 Zpracování událostí Zpracování událostí v předchozích verzích jazyka ActionScript Verze jazyka ActionScript před verzí ActionScript 3.0 poskytovaly několik různých způsobů zpracování událostí: • manipulační programy on(), které lze umístit přímo na instance Button a MovieClip • manipulační programy onClipEvent(), které lze umístit přímo na instance MovieClip • Vlastnosti funkce zpětného volání, například XML.onload a Camera.onActivity • Posluchače událostí, které zaregistrujete pomocí metody addListener() • Třída UIEventDispatcher, která částečně implementuje model událostí DOM. Každý z těchto mechanismů představuje svou vlastní sadu výhod a omezení. Manipulační programy událostí on() a onClipEvent() se snadno používají, ale činí následnou údržbu projektu obtížnější, protože kód je vložen přímo na tlačítka a filmové klipy a lze jej tak obtížně nalézt. Funkce zpětného volání se také jednoduše implementují, ale omezují vás pouze na jednu funkci zpětného volání na danou událost. Posluchače událostí se implementují obtížně - vyžadují nejenom vytvoření objektu a funkce posluchače, ale také registrace posluchače u objektu, který událost generuje. Tyto zvýšené nároky však umožňují vytvořit několik posluchačů událostí a registrovat je všechny pro stejnou událost. Vývoj součástí jazyka ActionScript 2.0 vedl k vytvoření ještě dalšího modelu události. Tento nový model, implementovaný ve třídě UIEventDispatcher, byl založen na podřízené sadě specifikace událostí DOM. Vývojáři, kteří jsou seznámeni se zpracováním událostí součástí, shledají nový model událostí v jazyce ActionScript 3.0 relativně bezproblémový. Syntaxe použitá různými modely událostí se různými způsoby překrývá a jinými se odlišuje. Například v jazyce ActionScript 2.0 mohou být některé vlastnosti, jako například TextField.onChanged, použity jako funkce zpětného volání nebo posluchač události. Syntax pro registrování objektů posluchače se liší v závislosti na tom, zda používáte jednu ze šesti tříd, která podporuje posluchače nebo třídy UIEventDispatcher. Pro třídy Key, Mouse, MovieClipLoader, Selection, Stage a TextField používejte metodu addListener(), avšak pro zpracování událostí součástí používejte metodu nazvanou addEventListener(). Další složitost zavedená různými modely zpracování událostí spočívá v tom, že rozsah funkce manipulačního programu událostí se velmi liší v závislosti na použitém mechanismu. Jinými slovy, význam klíčového slova this nebyl mezi různými systémy zpracování událostí konzistentní. Zpracování událostí v jazyce ActionScript 3.0 Jazyk ActionScript 3.0 zavádí jednotlivý model zpracování událostí, který nahrazuje mnoho různých mechanismů, které se vyskytovaly v předchozích verzích jazyka. Nový model událostí je založen na Specifikaci události DOM (objektového modelu dokumentu) úrovně 3. I když formát souboru SWF nedodržuje specificky standard DOM, mezi seznamem zobrazení a strukturou DOM existuje dostatečná podobnost, aby implementace modelu událostí DOM byla možná. Objekt na seznamu zobrazení je analogií uzlu v hierarchické struktuře DOM a termíny objekt seznamu zobrazení a uzel jsou v této diskusi používány záměnným způsobem. Implementace modelu událostí DOM v aplikaci Flash Player a AIR zahrnuje koncept pojmenovaný výchozí chování. Výchozí chování je činností, kterou aplikace Flash Player nebo AIR vykonává jako normální následek některých událostí. Výchozí chování Vývojáři jsou obvykle odpovědní za zápis kódu, který odpovídá na události. V některých případech je chování však natolik běžně spojeno s událostí, že aplikace Flash Player nebo AIR vykonává dané chování automaticky, pokud vývojář nepřidá kód, který toto chování zruší. Protože Flash Player nebo AIR automaticky vykazují chování, je toto chování nazýváno výchozí chování. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 247 Zpracování událostí Když například uživatel zadá do objektu TextField text, je očekávání, že se text se zobrazí v tomto objektu TextField natolik běžné, že toto chování je do aplikace Flash Player a AIR přímo integrováno. Pokud nechcete, aby k tomuto výchozímu chování docházelo, můžete jej zrušit pomocí nového systému zpracování událostí. Když uživatel zadá do objektu TextField text, aplikace Flash Player nebo AIR vytvoří instanci třídy TextEvent reprezentující tento vstup uživatele. Chcete-li aplikaci Flash Player nebo AIR zabránit v zobrazení objektu TextField, musíte zpřístupnit tuto specifickou instanci TextEvent a zavolat metodu preventDefault() této instance. Nelze však zabránit všemi výchozím chováním. Aplikace Flash Player a AIR například vygenerují objekt MouseEvent v případě poklepání na slovo v objektu TextField. Výchozí chování, kterému nelze zabránit, je zvýraznění slova pod kurzorem. Mnoho typů objektů událostí nemá připojené výchozí chování. Například aplikace Flash Player odešle objekt události připojení, když je vytvořeno připojení k sítu, ale s není s tím spojeno žádné výchozí chování. Dokumentace rozhraní API pro třídu Event a její podtřídy uvádí každý typ události a popisuje všechna související výchozí chování a zad lze tomuto chování zabránit. je důležité porozumět tomu, že výchozí chování jsou spojena pouze s událostmi odeslanými aplikacemi Flash Player nebo AIR, a neexistují pro objekty událostí odeslané programově prostřednictvím jazyka ActionScript. Například můžete použít metody třídy EventDispatcher k odeslání objektu události typu textInput, ale tento objekt události nebude mít připojené výchozí chování. Jinými slovy aplikace Flash Player a AIR nezobrazí znak v objektu TextField v důsledku události textInput, kterou jste odeslali programově. Co je nového s posluchači událostí v jazyce ActionScript 3.0 Pro vývojáře se zkušeností z používání jazyka ActionScript 2.0 a jeho metody addListener() může být vhodné poukázat na rozdíly mezi modelem posluchače události ActionScript 2.0 a modelem události ActionScript 3.0. Následující seznam popisuje několik hlavních rozdílů mezi dvěma modely událostí. • Chcete-li přidat posluchače událostí v jazyce ActionScript 2.0, použijete v některých případech addListener() a v jiných addEventListener(), zatímco v jazyce ActionScript 3.0 použijete ve všech situacích addEventListener(). • V jazyce ActionScript 2.0 neexistuje žádný tok události, což znamená, že metoda addListener() může být zavolána pouze pro objekt, který vysílá události, zatímco v jazyce ActionScript 3.0 může být metoda addEventListener() zavolána pro kterýkoliv objekt, který je součástí toku událostí. • V jazyce ActionScript 2.0 mohou být posluchače události buď funkcemi, metodami nebo objekty, zatímco v jazyce ActionScript 3.0 mohou být pouze funkcemi nebo metodami. Tok událostí Aplikace Flash Player nebo AIR odesílá objekty událostí kdykoliv k nějaké události dojde. Pokud cíl události není na seznamu zobrazení, aplikace Flash Player nebo AIR odešle událost přímo do cíle události. Například aplikace Flash Player odešle objekt události průběhu přímo do objektu URLStream. V případě, že cílová událost se nachází na seznamu zobrazení, aplikace Flash Player odešle objekt události do seznamu zobrazení a objekt události se poté pohybuje seznamem zobrazení do cíle události. Tok událostí popisuje, jak se objekt události pohybuje seznamem zobrazení. Seznam zobrazení je organizován hierarchicky, což lze popsat jako strom. Nahoře seznamu zobrazení je plocha, což je speciální kontejner objektů zobrazení, který slouží jako kořen seznamu zobrazení. Plocha je reprezentována třídou flash.display.Stage a lze ji zpřístupnit pouze prostřednictvím objektu zobrazení. Každý objekt zobrazení má vlastnost pojmenovanou stage, která odkazuje na plochu pro danou aplikaci. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 248 Zpracování událostí Když aplikace Flash Player nebo AIR odešle objekt události pro událost související se seznamem zobrazení, tento objekt události se pohybuje z plochy do cíle uzlu. Specifikace událostí DOM definuje uzel cíle jako uzel představující cíl události. Jinými slovy uzel cíle je objektem seznamu zobrazení, kde k události došlo. Pokud například uživatel klepne na objekt seznamu zobrazení nazvaný child1, aplikace Flash Player nebo AIR odešle objekt události nazvaný child1 jako cílový uzel. Tok událostí je koncepčně rozdělen na tři části. První část se nazývá fáze zachycení: tato fáze obsahuje všechny uzly z plochy až po zdroj uzlu cíle. Druhá část je nazvaná cílová fáze a je tvořena výhradně uzlem cíle. Třetí fáze se nazývá fází probublávání. Fáze probublávání je tvořena uzly ze zpáteční cesty od zdroj uzlu cíle na plochu. Názvy fází dávají větší smysl, pokud pojmete seznam zobrazení jako svislou hierarchii s plochou jako horní částí, jak je znázorněno na následujícím schématu. Vymezená plocha Nadřazený uzel Podřízený uzel2 Podřízený uzel1 Pokud uživatel klepne na Uzel Child1, aplikace Flash Player nebo AIR odešlou objekt události do toku události. Jak ukazuje následující obrázek, cesta objektu začíná na Stage, dále pokračuje do Parent Node, pak do uzlu Child1 a nakonec „probublává” zpět na Stage, přičemž prochází znovu Parent Node při své cestě na plochu Stage. Vymezená plocha Fáze zachycení Bublinová fáze Nadřazený uzel Podřízený uzel1 Podřízený uzel2 Cílová fáze V tomto příkladu fáze zachycení obsahuje Stage a Parent Node během počáteční cesty směrem dolů. Cílová fáze je tvořena časem stráveným v uzlu Child1. Fáze probublávání obsahuje Parent Node a Stage při cestě směrem nahoru zpět do kořenového uzlu. Tok událostí přispívá k výkonnějšímu systému zpracování událostí, než který byl programátorům ActionScript dostupný dříve. V předchozích verzích jazyka ActionScript tok událostí neexistoval, což znamená posluchače událostí mohou být přidány pouze k objektu, který událost generuje. V jazyce ActionScript 3.0 můžete přidat posluchače událostí nejenom do cílového uzlu, ale také do kteréhokoliv uzlu podél toku událostí. Schopnost přidat posluchače událostí během toku události je užitečný, když součást uživatelského rozhraní obsahuje více než jeden objekt. Například objekt tlačítka často obsahuje objekt testu, který slouží jako jmenovka tlačítka. Bez schopnosti přidat posluchače události do toku události budete muset posluchače přidat k objektu tlačítka i k objektu textu a zajistit tak, že obdržíte oznámení o událostech klepnutí, ke kterým dojde kdekoliv na tlačítku. Existence toku událostí však umožňuje umístit jednotlivé posluchače událostí na objekt tlačítka, který zpracovává události klepnutí, ke kterým dojde buď na objektu textu nebo na objektu tlačítka, které nejsou zablokovány objektem textu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 249 Zpracování událostí Každý objekt události se však nemusí účastnit všech tří fází toku událostí. Některé typy událostí, například enterFrame a init, jsou odesílány přímo do uzlu cíle a neúčastní se ani fáze zachycení, ani fáze probublávání. Jiné události mohou zacílit objekty, které nejsou na seznamu zobrazení, například události odeslané do instance třídy Socket. Tyto objekty události budou také procházet přímo do objektu cíle, aniž by se účastnily fází zachycení nebo probublávání. Chcete-li zjistit, jak se specifický typ události chová, můžete se buď informovat v dokumentaci k rozhraní API nebo zkontrolovat vlastnosti objektu události. Prověření vlastností objektu události je popsáno v následující kapitole. Objekty událostí V novém systému zpracování událostí slouží objekty událostí dvěma hlavním účelům. První, objekty událostí představuje skutečné události ukládáním informací o specifických událostech do souboru vlastností. Druhý, objekty událostí obsahují soubor metod, které umožňují manipulovat s objekty událostí a ovlivňovat chování systém zpracování událostí. Pro usnadnění přístup k těmto vlastnostem a metodám definuje rozhraní API aplikace Flash Player třídu Event, která slouží jako základní třída pro všechny objekty událostí. Třída Event definuje základní soubor vlastností a metod, které jsou společné pro všechny objekty událostí. Tato kapitola začíná diskusí o vlastnostech třídy Event, pokračuje popisem metod třídy Event a končí vysvětlením, proč existují podtřídy třídy Event. Porozumění vlastnostem třídy Event Třída Event definuje počet vlastností určených pouze ke čtení a konstant, které poskytují důležité informace o objektu události. Obzvláště důležité jsou následující: • Objekt události jsou představovány konstantami a ukládání ve vlastnosti Event.type. • Booleovská hodnota uložená ve vlastnosti Event.cancelable stanoví, zda lze zabránit výchozímu chování události. • Informace o toku událost je obsažena ve zbývajících vlastnostech. Typy objektu události Každý objekt událost má připojen typ události. Typy události jsou uloženy ve vlastnosti Event.type jako řetězcové hodnoty. Je vhodné znát typ objektu události, aby váš kód mohl odlišit objekty různých typů navzájem mezi sebou. Například následující kód specifikuje, že posluchače funkce clickHandler() by měl reagovat na kterýkoliv objekt klepnutí myší, který je předán do myDisplayObject: myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler); Asi dvanáct typů událostí je spojeno se samotnou třídou Event a zastupováno konstantami třídy Event, některé z nich jsou zobrazeny v následujícím výňatku z definice třídy Event: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 250 Zpracování událostí package flash.events { public class Event { // class constants public static const ACTIVATE:String = "activate"; public static const ADDED:String= "added"; // remaining constants omitted for brevity } } Tyto konstanty poskytují snadný způsob odkazován na specifické typy událostí. Tyto konstanty byste měli používat namísto řetězců, které zastupují. Pokud nesprávně uvedete název konstanty v kódu, kompilátor chybu zachytí, ale pokud namísto toho použijete řetězce, typografická chyba se nemusí v době kompilace projevit a může vést k neočekávanému chování, které může být obtížné ladit. Například když přidáváte posluchače události, použijte následující kód: myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler); spíše než: myDisplayObject.addEventListener("click", clickHandler); Informace o výchozím chování Kód může kontrolovat, zda lze zabránit výchozímu chování pro kterýkoliv daný objekt události a to přístupem k vlastnosti cancelable. Vlastnost cancelable uchovává booleovskou hodnotu, která signalizuje, zda může být výchozímu chování zabráněno, nebo nikoliv. Můžete zabránit výchozímu chování spojenému s malým počtem událostí nebo jej zrušit a to pomocí metody preventDefault(). Více informací viz Zrušení výchozího chování události v části „Porozumění metodám třídy Event“ na stránce 251. Informace toku události Zbývající vlastnosti třídy Event obsahují důležité informace o objektu události a jeho vztahu s tokem události, jak je popsáno v následujícím seznamu: • Vlastnost bubbles obsahuje informace o částech toku události, na kterých se účastní objekt události. • Vlastnost eventPhase signalizuje stávající fázi v toku události. • Vlastnost target ukládá odkaz na cíl události. • Vlastnost currentTarget ukládá odkaz na objekt seznamu zobrazení, který právě zpracovává objekt události. Vlastnost bubbles O události říkáme, že probublává v případě, že objekt události se účastní fáze probublávání toku události, což znamená, že objekt události je předán z uzlu cíle přes jeho následníky, až dosáhne plochy. Vlastnost Event.bubbles ukládá booleovskou hodnotu signalizující, zda se objekt události účastní fáze probublávání. Protože všechny události, které probublávají se také účastní fází zachycení a cílové fáze, kterákoliv událost, která probublává, se účastní všech tří fází toku události. Pokud je hodnota true, objekt události se účastní všech tří fází. Pokud je hodnota false, objekt události se neúčastní fáze probublávání. Vlastnost eventPhase Můžete stanovit fázi události pro kterýkoliv objekt události a to vyšetřením jeho vlastnosti eventPhase. Vlastnost eventPhase obsahuje celočíselnou hodnotu bez znaménka, která zastupuje jednu ze tří fází toku události. Rozhraní API aplikace Flash Player definuje samostatnou třídu EventPhase, která obsahuje tři konstanty odpovídající třem celočíselným hodnotám bez znaménka, jak je znázorněno v následujícím výňatku kódu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 251 Zpracování událostí package flash.events { public final class EventPhase { public static const CAPTURING_PHASE:uint = 1; public static const AT_TARGET:uint = 2; public static const BUBBLING_PHASE:uint= 3; } } Tyto konstanty odpovídají třem platným hodnotám vlastnosti eventPhase. Tyto konstanty můžete použít ke zpřehlednění kódu a zvýšení jeho čitelnosti. Pokud chcete například zajistit, aby funkce pojmenovaná myFunc() byla volána pouze v případě, že cíl události je v cílové fázi, můžete k otestování tohoto stavu použít následující kód: if (event.eventPhase == EventPhase.AT_TARGET) { myFunc(); } Vlastnost target Vlastnost target uchovává odkaz na objekt, který je cílem události. V některých případech je toto přímočaré, například když se aktivuje mikrofon, je cílem objektu události objekt Microphone. Pokud je cíl na seznamu zobrazení, musíte vzít v úvahu hierarchii seznamu zobrazení. Pokud například uživatel klepne myší na důležité místi, které obsahuje překrývající se objekty seznamu zobrazení, aplikace Flash Player a AIR jako cíl události vždy zvolí objekt, který je nejdále od plochy. V případě složitých souborů SWF, obzvláště těch, jejichž tlačítka jsou běžně zdobena malými podřízenými objekty, nemusí být vlastnost target použita často, protože může obvykle ukazovat na podřízený objekt tlačítka, namísto na samotné tlačítko. V této situaci je běžným postupem přidání posluchačů událostí k tlačítku a použití vlastnosti currentTarget, protože ukazuje na tlačítko, zatímco vlastnost target může ukazovat na podřízený objekt tlačítka. Vlastnost currentTarget Vlastnost currentTarget obsahuje odkaz na objekt, který právě zpracovává objekt události. I když se může zdát neobvyklé nevědět, který uzel právě zpracovává objekt události, který prověřujete, mějte na paměti, že můžete přidat funkci objektu události ke kterémukoliv objektu zobrazení, v daném toku události tohoto objektu a funkci posluchače lze umístit do libovolného umístění. Kromě toho lze přidat stejnou funkci posluchače k jiným objektům zobrazení. Se zvětšování velikosti projektu a jeho složitosti se vlastnost currentTarget stává stále více užitečnější. Porozumění metodám třídy Event Existují tři kategorie metod třídy event. • Metody pomocné, které mohou vytvářet kopie objektu nebo jej převádět na řetězec • Metody toku události, které odebírají objekty události z toku události • Výchozí chování metod, které brání výchozímu chování nebo kontrolují, zda mu bylo zabráněno Pomocné metody třídy Event Ve třídě Event existují dvě pomocné metody. Metoda clone() umožňuje vytvářet kopie objektu události. Metoda toString() umožňuje generovat znázornění řetězce vlastnosti pro objekt události, společně s jejich hodnotami. Obě tyto metody jsou požívány vnitřně systémem modelu události, ale jsou zpřístupněny vývojářům pro obecné použití. Pokročilí vývojáři, kteří vytvářejí podtřídy třídy Event, musí potlačit a implementovat verze obou pomocných metod a zajistit tak, že podtřída události bude řádně funkční. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 252 Zpracování událostí Zastavení toku událostí Můžete zavolat metodu Event.stopPropagation() nebo Event.stopImmediatePropagation() a zabránit tak objektu události v pokračování pohybu skrze tok událostí. Dvě metody jsou téměř identické a liší se pouze v tom, zda mohou být vykonány ostatní posluchače události stávajícího uzlu: • Metoda Event.stopPropagation() zabraňuje objektu události v pohybu k následujícímu uzlu, ale pouze poté, co je povoleno vykonání všech ostatních posluchačů události ve stávajícím uzlu. • Metoda Event.stopImmediatePropagation() také zabraňuje objektu události v pohybu k následujícímu uzlu, ale neumožňuje vykonání všech ostatních posluchačů události ve stávajícím uzlu. Zavolání některé z těchto metod nemá žádný účinek na to, zda dojde k výchozímu chování souvisejícímu s danou událostí. Metody výchozího chování třídy Event použijte k tomu, abyste zabránili výchozímu chování. Zrušení výchozího chování události Dvě metody, které se týkají zrušení výchozího chování, jsou preventDefault() a isDefaultPrevented(). Zavolejte metodu preventDefault() a zrušte výchozí chování související s událostí. Chcete-li zkontrolovat, zda metoda preventDefault() byla již zavolána pro objekt události, zavolejte metodu isDefaultPrevented(), která vrátí hodnotu true, pokud již byla metoda zavolána, jinak vrátí hodnotu false. Metoda preventDefault() bude funkční pouze v případě, že je zrušeno výchozí chování události. V dokumentaci rozhraní API můžete zkontrolovat, zda se jedná o tento případ, případně můžete použít jazyk ActionScript k prověření vlastnosti cancelable objektu události. Zrušení výchozího chování nemá žádný účinek na průběh pohybu objektu události skrze tok události. Metody toku události pro třídu Event použijte pro odstranění objektu události z toku události. Podtřídy třídy Event Pro mnoho událostí postačuje běžná sada vlastností, která je definována v třídě Event. Ostatní události však mají unikátní charakteristiku, kterou nelze zachytit vlastnostmi dostupnými ve třídě Event. Pro tyto události definuje jazyk ActionScript 3.0 několik podtříd třídy Event. Každá podtřída poskytuje dodatečné vlastnosti a typy události, které jsou unikátní pro danou kategorii událostí. Například, události související se vstupem myši mají několik unikátních vlastností, které nelze zachytit vlastnostmi definovanými ve třídě Event. Třída MouseEvent rozšiřuje třídu Event přidáním deseti vlastností, které obsahují informace, jako je například umístění události mouse a zda jsou stisknuty během události mouse specifická tlačítka. Podtřída Event rovněž obsahuje konstanty, které zastupují typy událostí související s podtřídami. Například třída MouseEvent definuje konstanty pro několik typů události mouse, včetně typů události click, doubleClick, mouseDown a mouseUp. Jak je popsáno v kapitole Pomocné metody třídy Event v tématu „Objekty událostí“ na stránce 249, při vytváření podtřídy Event musíte potlačit metody clone() a toString() a poskytnout tak funkčnost specifickou pro podtřídu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 253 Zpracování událostí Posluchače událostí Posluchače událostí, které se také nazývají manipulační programy událostí, jsou funkce, které aplikace Flash Player a AIR vykonávají v odezvě na specifické události. Přidání posluchače události je dvoukrokový proces. Nejprve vytvoříte funkci nebo metodu třídy pro aplikaci Flash Player nebo AIR, která se vykoná v odezvě na událost. Toto se někdy nazývá funkce posluchače nebo funkce manipulačního programu událostí. Za druhé použijete metodu addEventListener() k zaregistrování funkce posluchače v cíli události nebo v kterémkoliv objektu seznamu zobrazení, který leží v příslušném toku události. Vytváření funkce posluchače Vytvoření funkce posluchače je jednou z oblastí, kde se model události jazyka ActionScript 3.0 odchyluje od modelu události DOM. V modelu události DOM je zřetelné rozlišení mezi posluchačem události a funkcí posluchače: posluchač události je instancí třídy, která implementuje rozhraní EventListener, zatímco funkce posluchače je metodou této třídy, pojmenovanou handleEvent(). V modelu události DOM registrujete instanci třídy, která obsahuje funkci posluchače, spíše než skutečnou funkci posluchače. V modelu události jazyka ActionScript 3.0 neexistuje žádné odlišené mezi posluchačem události a funkcí posluchače. Jazyk ActionScript 3.0 nemá žádné rozhraní EventListener a funkce posluchače, které mohou být definované mimo třídu nebo jako součást třídy. Kromě toho funkce posluchače nemusí být pojmenovány handleEvent() - mohou být pojmenovány libovolným platným identifikátorem. V jazyce ActionScript 3.0 registrujete název skutečné funkce posluchače. Funkce posluchače definovaná mimo třídu Následující kód vytváří jednoduchý soubor SWF, který zobrazuje červený čtvercový obrazec. Funkce posluchače pojmenovaná clickHandler(), která není součástí třídy, naslouchá událostem klepnutí myši na červený čtverec. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 254 Zpracování událostí package { import flash.display.Sprite; public class ClickExample extends Sprite { public function ClickExample() { var child:ChildSprite = new ChildSprite(); addChild(child); } } } import flash.display.Sprite; import flash.events.MouseEvent; class ChildSprite extends Sprite { public function ChildSprite() { graphics.beginFill(0xFF0000); graphics.drawRect(0,0,100,100); graphics.endFill(); addEventListener(MouseEvent.CLICK, clickHandler); } } function clickHandler(event:MouseEvent):void { trace("clickHandler detected an event of type: " + event.type); trace("the this keyword refers to: " + this); } Když uživatel pracuje s výsledným souborem SWF klepnutím na čtverec, aplikace Flash Player nebo AIR generují následující výstup: clickHandler detected an event of type: click the this keyword refers to: [object global] Povšimněte si, že objekt události je předán jako argument do clickHandler(). To umožní funkci posluchače prověřit objekt události. V tomto příkladu použijte vlastnost objektu události type a ujistěte se, že událost je událostí klepnutí. Příklad také kontroluje hodnotu klíčového slova this. V tomto případě this zastupuje globální objekt, což dává smysl, protože funkce je definována mimo kteroukoliv uživatelskou třídu nebo objekt. Funkce posluchače definované jako metoda třídy Následující příklad je shodný s předchozím, který definoval třídu ClickExample kromě toho, že funkce clickHandler() je definována jako metoda třídy ChildSprite: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 255 Zpracování událostí package { import flash.display.Sprite; public class ClickExample extends Sprite { public function ClickExample() { var child:ChildSprite = new ChildSprite(); addChild(child); } } } import flash.display.Sprite; import flash.events.MouseEvent; class ChildSprite extends Sprite { public function ChildSprite() { graphics.beginFill(0xFF0000); graphics.drawRect(0,0,100,100); graphics.endFill(); addEventListener(MouseEvent.CLICK, clickHandler); } private function clickHandler(event:MouseEvent):void { trace("clickHandler detected an event of type: " + event.type); trace("the this keyword refers to: " + this); } } Když uživatel pracuje s výsledným souborem SWF klepnutím na červený čtverec, aplikace Flash Player nebo AIR generují následující výstup: clickHandler detected an event of type: click the this keyword refers to: [object ChildSprite] Povšimněte si, že klíčové slovo this odkazuje na instanci ChildSprite pojmenovanou child. To je změna chování od verze ActionScript 2.0. Pokud jste používali součásti v jazyce ActionScript 2.0, můžete si zapamatovat, že když byly třídy metody předány do UIEventDispatcher.addEventListener(), rozsah metod byl vázán na součást, která vysílal událost, namísto třídy, ve které byla metoda posluchače definována. Jinými slovy, pokud jste používali tuto techniku v jazyce ActionScript 2.0, klíčové slovo this by odkazovalo na součást vysílající událost, namísto instance ChildSprite. To byl významný problém pro některé programátory, protože to znamenalo, že nemohou přistupovat k jiným metodám a vlastnostem třídy, obsahující metodu posluchače. Jako opravný prostředek mohli programátoři jazyka ActionScript 2.0 používat třídu mx.util.Delegate ke změně rozsahu metody posluchače. To již není nutné, protože jazyk ActionScript 3.0 vytváří vázanou metodu, když je zavolána metoda addEventListener(). V důsledku toho klíčové slovo this odkazuje na instanci ChildSprite pojmenovanou child a programátor má přístup k jiným metodám a vlastnostem třídy ChildSprite. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 256 Zpracování událostí Posluchač události, který by neměl být používán Existuje třetí technika, kterou vytváříte generický objekt s vlastností, která ukazuje na dynamicky přiřazené funkce posluchače, ale její použití se nedoporučuje. Je zde popisována pouze proto, že byla běžně používána v jazyce ActionScript 2.0, ale ve verzi ActionScript 3.0 by používána být neměla. Tato technika se nedoporučuje proto, že klíčové slovo this bude odkazovat na globální objekt, namísto objektu posluchače. Následující příklad je shodný s předchozím příkladem třídy ClickExample, kromě toho, že funkce posluchače je definována jako součást druhového objektu nazvaného myListenerObj: package { import flash.display.Sprite; public class ClickExample extends Sprite { public function ClickExample() { var child:ChildSprite = new ChildSprite(); addChild(child); } } } import flash.display.Sprite; import flash.events.MouseEvent; class ChildSprite extends Sprite { public function ChildSprite() { graphics.beginFill(0xFF0000); graphics.drawRect(0,0,100,100); graphics.endFill(); addEventListener(MouseEvent.CLICK, myListenerObj.clickHandler); } } var myListenerObj:Object = new Object(); myListenerObj.clickHandler = function (event:MouseEvent):void { trace("clickHandler detected an event of type: " + event.type); trace("the this keyword refers to: " + this); } Výsledky sledování budou vypadat takto: clickHandler detected an event of type: click the this keyword refers to: [object global] Bylo by možné očekávat, že klíčové slovo this bude odkazovat na myListenerObj a že výstup sledování bude [object Object], ale namísto toho odkazuje na globální objekt. Když předáte název dynamické vlastnosti jako argument metodě addEventListener(), aplikace Flash Player nebo AIR nedokáží vytvořit vázanou metodu. Tak tomu je proto, že to, co předáváte jako parametr listener není ničím jiným, než paměťovou adresou funkce posluchače, a aplikace Flash Player a AIR nemá žádný způsob, jak spojit tuto paměťovou adresu s instancí myListenerObj. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 257 Zpracování událostí Správa posluchačů událostí Pomocí metod rozhraní IEventDispatcher můžete spravovat funkce posluchače. Rozhraní IEventDispatcher je verzí jazyka ActionScript 3.0 rozhraní EventTarget modelu události DOM. Ačkoliv může IEventDispatcher implikovat, že hlavním účelem je odesílat (nebo předávat) objekty události, metody této třídy jsou ve skutečnosti používány mnohem častěji k registrování posluchačů událostí, jejich kontrole a odebrání. Rozhraní IEventDispatcher definuje pět metod, jako je zobrazeno v následujícím kódu: package flash.events { public interface IEventDispatcher { function addEventListener(eventName:String, listener:Object, useCapture:Boolean=false, priority:Integer=0, useWeakReference:Boolean=false):Boolean; function removeEventListener(eventName:String, listener:Object, useCapture:Boolean=false):Boolean; function dispatchEvent(eventObject:Event):Boolean; function hasEventListener(eventName:String):Boolean; function willTrigger(eventName:String):Boolean; } } Aplikace Flash Player API implementuje rozhraní IEventDispatcher s třídou EventDispatcher, která slouží jako základní třída pro všechny třídy, které mohou být cíli událostí nebo částí toku události. Například třída DisplayObject dědí z třídy EventDispatcher. To znamená, že kterýkoliv objekt na seznamu zobrazení má přístup k metodám rozhraní IEventDispatcher. Přidávání posluchačů událostí Metoda addEventListener() je hlavní tažnou silou rozhraní IEventDispatcher. Použijte ji k registrování funkcí posluchače. Dva vyžadované parametry jsou type a listener. Parametr type použijte pro specifikování typu události. Parametr listener použijte pro specifikování funkce posluchače, která se spustí, když dojde k události. Parametr listener může být referenci na kteroukoliv funkci nebo metodu třídy. Poznámka: Při specifikování parametru listener nepoužívejte závorky. Například funkce clickHandler() je specifikována bez závorek v následujícím volání metody addEventListener(): Poznámka: addEventListener(MouseEvent.CLICK, clickHandler). Parametr useCapture metody addEventListener() umožňuje ovládat toku události od fáze, ve které bude váš posluchač aktivní. Pokud useCapture nastavíte na hodnotu true, posluchač bude aktivní během fáze toku události. Pokud useCapture nastavíte na hodnotu false, posluchač bude aktivní během cílové fáze a fáze probublávání toku události. Chcete-li naslouchat události během všech fází toku události, musíte zavolat dvakrát addEventListener(), jednou s parametrem useCapture nastaveným na hodnotu true a pak znovu s parametrem useCapture nastaveným na hodnotu false. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 258 Zpracování událostí Parametr priority metody addEventListener() není oficiální součástí modelu objektu události DOM úrovně 3. Je součástí jazyka ActionScript 3.0 proto, aby vám umožnil vyšší flexibilitu organizování posluchačů událostí. Když zavoláte addEventListener(), můžete nastavit prioritu pro daný posluchač události předáním celočíselné hodnoty jako parametru priority. Výchozí hodnota je 0, ale můžete ji nastavit na zápornou nebo kladnou celočíselnou hodnotu. Čím vyšší je číslo, tím dříve bude posluchač události vykonán. Posluchače událostí se stejnou prioritou jsou vykonány v pořadí, ve kterém jsou přidány, takže čím dříve je posluchač přidán, tím dříve je vykonán. Parametr useWeakReference umožňuje specifikovat, zda je odkaz na funkci posluchače slabý nebo normální. Nastavením tohoto parametru na hodnotu true umožňuje se vyhnout situacím, ve kterých funkce posluchače setrvává v paměti, i když již není potřebná. Aplikace Flash Player a AIR používají techniku nazvanou čištění uvolněné paměti k odstranění objektů z paměti, které již nejsou používány. Objekt je považován za dále nepoužitý, pokud k němu nejsou žádné odkazy. Funkce čištění uvolněné paměti se neohlíží na slabé odkazy, což znamená, že funkce posluchače mající pouze slabé odkazy ukazující ni, je vhodná pro čištění paměti. Odstranění posluchačů události Metodu removeEventListener() můžete použít pro odstranění posluchače události, který již dále nepotřebujete. Je vhodné odstranit všechny posluchače, které již nebudou používány. Vyžadované parametry zahrnují parametry eventName a listener, které jsou shodné, jako požadované parametry metody addEventListener(). Nezapomeňte, že můžete naslouchat událostem během všech fází dvojím zavoláním addEventListener(), jednou s parametrem useCapture nastaveným na hodnotu true a pak znovu se stejným parametrem nastaveným na hodnotu false. Chcete-li odstranit oba posluchače událostí, měli byste zavolat dvakrát removeEventListener(), jednou s parametrem useCapture nastaveným na hodnotu true a pak znovu se stejným parametrem nastaveným na hodnotu false. odesílání události Metoda dispatchEvent() může být použita pokročilými programátory k odeslání objektu uživatelské události do toku události. Jediným parametrem přijatým touto metodou je odkaz na objekt události, což musí být instance třídy Event nebo podtřídy třídy Event. Po odeslání je vlastnost target objektu události nastavena na objekt, pro který byla zavolána událost dispatchEvent(). Kontrola stávajících posluchačů událostí Závěrečné dvě metody rozhraní IEventDispatcher poskytují užitečné informace o existenci posluchačů události. Metoda hasEventListener() vrací hodnotu true v případě, že je nalezen posluchač události pro specifický typ události na specifickém objektu seznamu zobrazení. Metoda willTrigger() rovněž vrací hodnotu true v případě, že je nalezen posluchač události pro specifický objekt seznamu zobrazení, ale willTrigger() kontroluje posluchače nejenom na daném objektu zobrazení, ale také na všech předchůdcích objektu seznamu zobrazení pro všechny fáze toku události. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 259 Zpracování událostí Události chyb bez posluchačů Výjimky, spíše než události, jsou primárním mechanismem pro zpracování chyb v jazyce ActionScript 3.0, ale zpracování výjimek není funkční pro asynchronní provoz, například pro načítání souborů. Pokud chyba nastane během takového asynchronního provozu, aplikace Flash Player a AIR odešle objekt události chyby. Pokud nevytvoříte posluchače pro událost chyby, verze ladicího programu aplikace Flash Player a AIR vyvolá dialogové okno s informacemi o chybě. Například verze ladiče přehrávače Flash Player vyvolá následující dialogové okno popisující chybu vygenerovanou, když se aplikace pokusí načíst soubor z neplatné adresy URL: Většina událostí chyby je založena na třídě ErrorEvent a jako takové budou mít vlastnost pojmenovanou text, která je uložena v chybovém hlášení zobrazeném aplikací Flash Player nebo AIR. Dvě výjimky jsou třídy StatusEvent a NetStatusEvent. Obě tyto třídy mají vlastnost level (StatusEvent.level a NetStatusEvent.info.level). Když je vlastnost level nastavena na hodnou "error", tyto typy událostí jsou považovány za události chyby. Událost chyby nezpůsobí zastavení chodu souboru SWF. Projeví se pouze jako dialogové okno ve verzích ladicího programu zásuvných modulů prohlížeče a samostatných přehrávačů, jako hlášení na výstupním panelu v přehrávači a jako záznam v souboru protokolu pro vývojové prostředí Adobe Flex Builder 3. Neprojeví se ve všech vydaných verzích aplikace Flash Player nebo AIR. Příklad: budík Příklad budíku je tvořen budíkem, který umožňuje uživateli specifikovat čas, ve kterém se budík vypne, stejně jako hlášení, které se v daný čas zobrazí. Příklad budíku je postaven na aplikaci SimpleClock z kapitoly „Práce s daty a časy“ na stránce 129 Budík ukazuje několik aspektů práce s událostmi v jazyce ActionScript 3.0, včetně: • Poslech a odpovídání na události • Vyrozumění posluchačů o události • Vytváření vlastních typů událostí Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace Budík naleznete ve složce Samples/AlarmClock. Aplikace zahrnuje následující soubory: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 260 Zpracování událostí Soubor Popis AlarmClockApp.mxml Hlavní soubor aplikace v programu Flash (FLA) nebo Flex (MXML). nebo AlarmClockApp.fla com/example/programmingas3/clock/AlarmClock.as Třída, která rozšiřuje třídu SimpleClock přidáním funkce budíku. com/example/programmingas3/clock/AlarmEvent.as Třída uživatelské události (podtřída flash.events.Event), která slouží jako objekt události pro událost alarm třídy AlarmClock. com/example/programmingas3/clock/AnalogClockFace.as Vykreslí kruhové hodiny s hodinovou, minutovou a sekundovou ručičkou na základě času (popsáno v příkladu SimpleClock). com/example/programmingas3/clock/SimpleClock.as Rozhraní součásti hodin s jednoduchou funkcí stopek (popsáno v příkladu SimpleClock). Přehled Budíku Hlavní funkce budíku v tomto příkladu, včetně sledování času a zobrazení hodin, opětovně používá kód aplikace SimpleClock, který je popsán v kapitole „Příklad: Jednoduché analogové hodiny“ na stránce 134. Třída AlarmClock rozšiřuje třídu SimpleClock z příkladu přidáním funkce pro budík, včetně nastavení času buzení a informování o tom, kdy bude budík vypnutý. Poskytnutí informace o tom, kdy dojde k nějaké události, je úlohou pro kterou jsou události stvořeny. Třída AlarmClock zpřístupňuje událost Alarm, které mohou jiné objekty naslouchat s cílem provedení různých činností. Kromě toho třída AlarmClock používá instanci třídy Timer ke stanovení, kdy má spustit alarm. Podobně jako třída AlarmClock, také třída Timer poskytuje událost a informuje ostatní objekty (v tomto případě instance AlarmClock), když uplynul jistý čas. Podobně jako u většiny aplikací v jazyce ActionScript, události tvoří důležitou část funkce vzorové aplikace Budík. Spuštění budíku Jak bylo uvedeno dříve, jedinou funkcí, kterou třída AlarmClock ve skutečnosti poskytuje, je nastavení a spuštění budíku. Vestavěná třída Timer (flash.utils.Timer) poskytuje způsob, jak může vývojář definovat kód, který bude spuštěn po specifikované době. Třída AlarmClock využívá instanci Timer pro stanovení, kdy má budík vypnout. import flash.events.TimerEvent; import flash.utils.Timer; /** * The Timer that will be used for the alarm. */ public var alarmTimer:Timer; ... /** * Instantiates a new AlarmClock of a given size. */ public override function initClock(faceSize:Number = 200):void { super.initClock(faceSize); alarmTimer = new Timer(0, 1); alarmTimer.addEventListener(TimerEvent.TIMER, onAlarm); } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 261 Zpracování událostí Instance Timer definovaná v třídě AlarmClock je pojmenovaná alarmTimer. Metoda initClock(), která provádí potřebná nastavení pro instanci AlarmClock, provádí s proměnnou alarmTimer dvě věci. Nejprve je proměnná konkretizována s parametry, které poskytují instrukce instanci Timer, aby vyčkala 0 milisekund a spustí událost budíku pouze jednou. Po konkretizaci alarmTimer kód zavolá metodu proměnné addEventListener() a signalizuje tak, že chce naslouchat události timer této proměnné. Instance Timer pracuje odesláním události timer po uplynutí stanovené doby. Třída AlarmClock bude muset znát, kdy je událost timer odeslána a nastaví tak vlastní budík. Zavoláním addEventListener() se kód AlarmClock sám zaregistruje jako posluchač s alarmTimer. Dva parametry signalizují, že třída AlarmClock chce poslouchat události timer (indikovaná konstantou TimerEvent.TIMER) a když k události dojde, metoda onAlarm() třídy AlarmClock by měla být zavolána v odezvě na danou událost. Chcete-li nastavit alarm, třída AlarmClock setAlarm() je zavolána následujícím způsobem: /** * Sets the time at which the alarm should go off. * @param hour The hour portion of the alarm time. * @param minutes The minutes portion of the alarm time. * @param message The message to display when the alarm goes off. * @return The time at which the alarm will go off. */ public function setAlarm(hour:Number = 0, minutes:Number = 0, message:String = "Alarm!"):Date { this.alarmMessage = message; var now:Date = new Date(); // Create this time on today's date. alarmTime = new Date(now.fullYear, now.month, now.date, hour, minutes); // Determine if the specified time has already passed today. if (alarmTime <= now) { alarmTime.setTime(alarmTime.time + MILLISECONDS_PER_DAY); } // Stop the alarm timer if it's currently set. alarmTimer.reset(); // Calculate how many milliseconds should pass before the alarm should // go off (the difference between the alarm time and now) and set that // value as the delay for the alarm timer. alarmTimer.delay = Math.max(1000, alarmTime.time - now.time); alarmTimer.start(); return alarmTime; } Tato metoda provádí několik věcí, včetně uložení zprávy budíku a vytvoření objektu Date (alarmTime), který zastupuje skutečný časový okamžik, kdy byl budík vypnutý. S největším významem pro stávající diskusi, v několika posledních řádcích metody, je časovač proměnné alarmTimer nastaven a aktivován. Nejprve je zavolána jeho metoda reset(), časovač se zastaví a resetuje se v případě, že je již spuštěn. Dále, stávající čas (zastoupen proměnou now) je odečten od hodnoty proměnné alarmTime s cílem stanovit, kolik milisekund musí uplynout, než se budík vypne. Třída Timer neaktivuje událost timer v absolutním čase, takže je to tento rozdíl relativního času, který je přiřazen vlastnosti delay pro alarmTimer. Nakonec je zavolána metoda start() a časovač se ve skutečnosti spustí. Jakmile uplynul specifický čas, alarmTimer odešle událost timer. protože třída AlarmClock registruje svou metodu onAlarm() jako posluchače pro tuto událost, když dojde k události timer, je zavolána metoda onAlarm(). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 262 Zpracování událostí /** * Called when the timer event is dispatched. */ public function onAlarm(event:TimerEvent):void { trace("Alarm!"); var alarm:AlarmEvent = new AlarmEvent(this.alarmMessage); this.dispatchEvent(alarm); } Metoda, která je registrována jako posluchač události musí být definovaná vhodným podpisem (tj. soubor parametrů a zpětný typ metody). Má-li být metoda posluchačem pro událost timer třídy Timer, musí metoda definovat jeden parametr, jehož datový typ je TimerEvent (flash.events.TimerEvent), podtřída třídy Event. Když instance Timer zavolá své posluchače událost, předá instanci TimerEvent jako objekt události. Informování ostatních o budíku Podobně jako třída Timer, také třída AlarmClock poskytuje událost, která umožňuje ostatnímu kódu přijímat oznámení, když je budík vypnut. Má-li třída používat rámec zpracování událostí vestavěných do jazyka ActionScript, musí tato třída implementovat rozhraní flash.events.IEventDispatcher. To je nejběžnější provedeno rozšířením třídy flash.events.EventDispatcher, která poskytuje standardní implementaci IEventDispatcher (nebo rozšířením jedné z podtříd EventDispatcher). Jak bylo popsáno výše, třída AlarmClock rozšiřuje třídu SimpleClock, která zase rozšiřuje třídu Sprite, která (prostřednictvím řetězce dědičnosti) rozšiřuje třídu EventDispatcher. To vše znamená, že třída AlarmClock má již vestavěnou funkci poskytování vlastních událostí. Jiný kód může registrovat oznámení události alarm třídy AlarmClock zavoláním metody addEventListener(), kterou AlarmClock dědí z EventDispatcher. Když je instance AlarmClock připraven k oznámení jiné části kódu, že její událost alarm byla aktivována, učiní tak zavoláním metody dispatchEvent(), která je také zděděna z EventDispatcher. var alarm:AlarmEvent = new AlarmEvent(this.alarmMessage); this.dispatchEvent(alarm); Tyto řádky kódu jsou převzaty z metody onAlarm() třídy AlarmClock (dříve zobrazena celá). Je zavolána metoda dispatchEvent() instance AlarmClock, která vyrozumí všechny registrované posluchače, že byla spuštěna událost alarm instance AlarmClock. Parametr předaný do dispatchEvent() je objektem události, který bude předán společně s metodami posluchače. V tomto případě se jedná o instanci třídy AlarmEvent, podtřídu Event, vytvořenou specificky pro tento příklad. Poskytnutí uživatelské události budíku Všechny posluchače událostí získají parametr objektu události s informací o aktivaci specifické události. V mnoha případech je objekt události instancí třídy Event. Nicméně v některých případech je užitečné posluchačům události poskytnout další informace. Jak bylo popsáno výše v této kapitole, běžným způsobem jak toto uskutečnit je definování nové třídy, podtřídy třídy Event, a použití instance této třídy jako objektu události. Na tomto příkladu je instance AlarmEvent použita jako objekt události, když je odeslána událost alarm třídy AlarmClock. Třída AlarmEvent zde zobrazená poskytuje další informace o události alarm, specificky hlášení budíku: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 263 Zpracování událostí import flash.events.Event; /** * This custom Event class adds a message property to a basic Event. */ public class AlarmEvent extends Event { /** * The name of the new AlarmEvent type. */ public static const ALARM:String = "alarm"; /** * A text message that can be passed to an event handler * with this event object. */ public var message:String; /** *Constructor. *@param message The text to display when the alarm goes off. */ public function AlarmEvent(message:String = "ALARM!") { super(ALARM); this.message = message; } ... } Nejlepší způsob, jak vytvořit vlastní objekt události, je definovat třídu, která rozšiřuje třídu Event, jak je znázorněno v předchozím příkladu. Chcete-li doplnit zděděnou funkčnost, musí třída AlarmEvent definovat vlastnost message obsahující text hlášení budíku souvisejícího s událostí; hodnota message je předána jako parametr do konstruktoru AlarmEvent. Třída AlarmEvent také definuje konstantu ALARM, kterou lze použít k odkazování na specifickou událost (alarm) při zavolání metody addEventListener() třídy AlarmClock. Kromě přidání vlastní funkčnosti musí každá podtřída Event potlačit zděděnou metodu clone() jako součást rámce zpracování události jazyka ActionScript. Podtřídy Event mohou také volitelně potlačit zděděnou metodu toString() a zahrnout vlastnosti vlastní události do hodnoty vrácené, když je zavolaná metoda toString(). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 264 Zpracování událostí /** * Creates and returns a copy of the current instance. * @return A copy of the current instance. */ public override function clone():Event { return new AlarmEvent(message); } /** * Returns a String containing all the properties of the current * instance. * @return A string representation of the current instance. */ public override function toString():String { return formatToString("AlarmEvent", "type", "bubbles", "cancelable", "eventPhase", "message"); } Potlačená metoda clone() musí vrátit novou instanci podtřídy Event, se všemi uživatelskými vlastnostmi nastavenými tak, aby odpovídaly stávající instanci. V potlačené metodě toString() se použije pomocná metoda formatToString() (zděděná od Event) pro poskytnutí řetězce s názvem vlastního typu, stejně jako názvů a hodnoty všech svých vlastností. 265 Kapitola 13: Programování zobrazení Programování zobrazení v Adobe® ActionScript® 3.0 vám umožňuje pracovat s prvky, které se objeví na ploše přehrávače Adobe® Flash® Player nebo Adobe® AIR™. Tato kapitola popisuje základní koncepty pro práci s prvky na obrazovce. Zjistíte podrobnosti o programatickém uspořádání vizuálních prvků. Naučíte se také vytvářet své vlastní třídy pro objekty zobrazení. Základy programování zobrazení Úvod do programování zobrazení Každá aplikace vytvořená pomocí jazyka ActionScript 3.0 má hierarchii objektů zobrazení, která se nazývá seznam zobrazení. Viz níže. Seznam zobrazení obsahuje všechny viditelné prvky v aplikaci. Vymezená Stageplocha Instance hlavní třídy souboru SWF Objekt zobrazení Kontejner objektu zobrazení Kontejner objektu zobrazení Objekt zobrazení Kontejner objektu zobrazení Objekt zobrazení Kontejner objektu zobrazení PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 266 Programování zobrazení Jak ukazuje obrázek, elementy zobrazení lze rozdělit do jedné nebo více následujících skupin: • Vymezená plocha Plocha je základní kontejner pro objekty zobrazení. Každá aplikace má jeden objekt plochy, který obsahuje všechny objekty zobrazení na obrazovce. Plocha je kontejner nejvyšší úrovně a je na prvním místě hierarchie seznamu zobrazení: Každý soubor SWF má přirazenou třídu jazyka ActionScript, která se nazývá hlavní třída souboru SWF. Když se v aplikaci Flash Player nebo prostředí Adobe AIR otevře soubor SWF, vyvolá pro danou třídu funkci konstruktora a vytvořená instance (jedná se vždy o typ objektu zobrazení) je přidána jako podřízený objekt plochy. Hlavní třída souboru SWF vždy rozšiřuje třídu Sprite (pro více informací viz „Výhody přístupu seznamu zobrazení“ na stránce 270). Na plochu se dostanete pomocí vlastnosti stage jakékoliv instance třídy DisplayObject. Více informací naleznete v části „Nastavení vlastností plochy“ na stránce 278. • Objekty zobrazení V jazyce ActionScript 3.0 jsou všechny prvky, které se zobrazí na obrazovce v aplikaci typy objektů zobrazení. Balík flash.display zahrnuje třídu DisplayObject, která je základní třídou rozšířenou o několik dalších tříd. Tyto různé třídy představují různé typy objektů zobrazení, jako jsou například vektorové tvary, filmové klipy a textová pole. Přehled těchto tříd naleznete v části „Výhody přístupu seznamu zobrazení“ na stránce 270. • Kontejnery objektů zobrazení Kontejnery objektů zobrazení jsou zvláštní typy objektů zobrazení, které mají svou vlastní vizuální reprezentaci, a mohou také obsahovat podřízené objekty, které jsou také objekty zobrazení. Třída DisplayObjectContainer je podtřídou třídy DisplayObject. Objekt DisplayObjectContainer může obsahovat více objektů zobrazení ve svém podřízenémseznamu. Například následující ilustrace ukazuje typ objektu DisplayObjectContainer, známý jako Sprite, který obsahuje různé objekty zobrazení: A B C D A. Objekt SimpleButton. Tento typ objektu zobrazení má různé stavy „nahoru”, „dolů” a „přes”. B. Objekt Bitmap. V tomto případě byl objekt Bitmap načten z externího formátu JPEG pomocí objektu Loader. C. Objekt Shape. „Rámeček snímku” obsahuje zaoblený obdélník, který je nakreslen v jazyce ActionScript. Na tento objekt Shape je použit filtr vrženého stínu. D. Objekt TextField. V tomto kontextu objektů zobrazení jsou objekty DisplayObjectContainer známé také jako kontejnery objektů zobrazení nebo jednodušekontejnery. Jak již bylo uvedeno dříve, plocha je kontejner objektů zobrazení. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 267 Programování zobrazení Ačkoliv všechny viditelné objekty zobrazení dědí ze třídy DisplayObject, typ každého z nich je určitou podtřídou třídy DisplayObject. Například funkce konstruktora existuje pro třídu Shape nebo Video, ale pro třídu DisplayObject neexistuje žádná funkce konstruktora. Běžné úlohy programování zobrazení Protože mnoho programování v jazyce ActionScript zahrnuje vytvoření a manipulaci vizuálními prvky, existuje několik úloh, které souvisí s programováním zobrazení. Tato kapitola popisuje běžné úlohy, které se vztahují na všechny objekty zobrazení, včetně: • Práce se seznamem zobrazení a kontejnery objektů zobrazení • Přidávání objektů zobrazení do seznamu zobrazení • Odstranění objektů ze seznamu zobrazení • Přesouvání objektů mezi kontejnery zobrazení • Přesouvání objektů před nebo za jiné objekty • Práce s plochou • Nastavení kmitočtu snímků • Ovládání měřítka plochy • Práce v režimu celé obrazovky • Zpracování událostí objektů zobrazení • Umístění objektů zobrazení, včetně vytvoření interakce přetažení • Změna velikosti nebo měřítka a otáčení s objekty zobrazení • Použití režimů prolnutí, transformací barev a průhlednosti na objekty zobrazení • Maskování objektů zobrazení • Animace objektů zobrazení • Nahrání externího obsahu zobrazení (obrazů nebo souborů SWF) Kapitoly dále v této příručce popisují další úlohy pro práci s objekty zobrazení. Mezi tyto úlohy patří ty, které se vztahují na jakýkoliv objekt zobrazení, a úlohy přiřazené k určitým typům objektů zobrazení: • Kreslení vektorové grafiky pomocí jazyka ActionScript na objektech zobrazení, viz část „Používání kreslicího rozhraní API“ na stránce 314 • Použití geometrických transformací na objekty zobrazení, popsáno v části „Práce s geometrií“ na stránce 334 • Použítí efektů grafických filtrů, jako rozostření, záře, vržený stín a další, pro objekty zobrazení, viz části „Filtrování objektů zobrazení“ na stránce 346 • Práce s vlastnostmi specifickými pro MovieClip, popsaná v části „Práce s filmovými klipy“ na stránce 398 • Práce s objekty TextField, popsaná v části „Práce s textem“ na stránce 423 • Práce s grafikou bitmapy, popsaná v části „Práce s bitmapami“ na stránce 473 • Práce s video prvky, popsaná v části „Práce s videem“ na stránce 515 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 268 Programování zobrazení Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Alfa: Hodnota barvy představující množství průhlednosti (nebo přesněji, množství neprůhlednosti) v barvě. Například barva s hodnotou kanálu alfa 60 % ukazuje 60 % z plné intenzity a ze 40 % je průhledná. • Bitmapová Grafika: Grafika, která je v počítači definována jako mřížka (řádky a sloupce) barevných obrazových bodů. Běžné bitmapové grafiky zahrnují digitální fotografie a podobné obrazy. • Režim prolnutí: Určuje, jak by měly obsahy dvou překrývajících se obrazů vzájemně reagovat. Neprůhledný obraz nacházející se nad jiným obrazem obvykle blokuje spodní obraz, který tak není vůbec viditelný. Různé režimy prolnutí však způsobí, že se barvy snímků navzájem prolnou různými způsoby, takže výsledný obsah je určitou kombinací daných dvou obrazů • Seznam zobrazení: Hierarchie objektů zobrazení, které budou vykreslovány jako viditelný obsah obrazovky přehrávačem Flash Player a aplikací AIR. Plocha je kořen seznamu zobrazení a všechny objekty zobrazení, které jsou připojeny k ploše nebo k některé z podřízených ploch, vytvářejí seznam zobrazení (i v případě, že objekt není ve skutečnosti vykreslován, například pokud je mimo hranice plochy). • Objekt zobrazení: Objekt, který představuje nějaký typ vizuálního obsahu v přehrávači Flash Player nebo aplikaci AIR. Do seznamu zobrazení lze zahrnout pouze objekty zobrazení a všechny třídy objektů zobrazení jsou podtřídami třídy DisplayObject. • Kontejner objektu zobrazení: Zvláštní typ objektu zobrazení, který může obsahovat podřízené objekty zobrazení. Kromě toho má obvykle vlastní vizuální znázornění. • Hlavní třída souboru SWF: Třída, která definuje chování nejkrajnějšího objektu zobrazení v souboru SWF, který je koncepčně třídou pro vlastní soubor SWF. Například soubor SWF vytvořený ve vývojovém prostředí Flash má „hlavní časovou osu“, která obsahuje všechny ostatní časové osy; hlavní třída souboru SWF je třída, pro kterou je časová osa instancí. • Maskování: Technika, kdy jsou určité části obrazu skryty z pohledu (nebo opačně, kdy jsou určité části obrazu zobrazeny). Části obrazu maskování budou průhledné, takže lze vidět obsah pod nimi. Tento termín souvisí s krycí páskou, která při malování zabraňuje použití nátěru na určité oblasti. • Plocha: Vizuální kontejner, který je základem nebo pozadím všech vizuálních obsahů v SWF. • Transformace: Úprava vizuálních vlastností grafiky, jako je otočení objektu, změna velikosti, zkosení nebo deformace tvaru či změna barvy. • Grafika vektoru: Grafika, která je definována v počítači jako čáry a tvary nakreslené se zvláštními vlastnostmi (například tloušťka, délka, velikost, úhel a poloha). Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. Protože se tato kapitola týká vytváření a manipulace s vizuálním obsahem, všechny kódy v této kapitole vytvářejí vizuální objekty a zobrazení na obrazovce; testování vzorku zahrnuje zobrazení výsledku v přehrávači Flash Player nebo v aplikaci AIR, nikoli zobrazení hodnot proměnných jako v předchozích kapitolách. Návod na vyzkoušení kódů uvedených v této kapitole: 1 Pomocí vývojového nástroje Flash vytvořte prázdný dokument 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Spusťte program pomocí příkazu Ovládání > Testovat film. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 269 Programování zobrazení Zobrazíte výsledky kódu zobrazeného na obrazovce a na panelu Výstup se zobrazí všechna volání funkce trace(). Techniky pro zkoušení uvedených příkladů kódů jsou podrobněji vysvětleny v části „Testování příkladů kódu v této kapitole“ na stránce 34. Základní třídy zobrazení Balíček flash.display v jazyce ActionScript 3.0 obsahuje třídy pro vizuální objekty, které lze zobrazit v přehrávači Flash Player nebo v aplikaci AIR. Následující ilustrace ukazuje vztahy podtříd těchto tříd objektů základních zobrazení. DisplayObject AVM1Movie Bitmap InteractiveObject DisplayObjectContainer SimpleButton Loader Sprite MorphShape Shape StaticText Video TextField Stage MovieClip Ilustrace zobrazuje dědění tříd objektů zobrazení. Všimněte si, že některé z těchto tříd, zvláště StaticText, TextField a Video, nejsou součástí balíčku flash.display, ale budou zděděny z třídy DisplayObject. Všechny třídy, které rozšiřují třídu DisplayObject, dědí její metody a vlastnosti. Více informací naleznete v části „Vlastnosti a metody třídy DisplayObject“ na stránce 273. Můžete konkretizovat objekty následujících tříd zobrazených v balíčku flash.display: • Bitmap - Tato třída slouží k definici bitmapových objektů, buď načtených z externích souborů nebo vykreslených pomocí jazyka ActionScript. Bitmapu můžete načíst z externích souborů pomocí třídy Loader. Načíst můžete soubory ve formátech GIF, JPG nebo PNG. Můžete také vytvořit objekt BitmapData s vlastními daty a poté vytvořit objekt Bitmap, který daná data používá. Můžete použít metody třídy BitmapData pro upravení bitmap, ať jsou načteny nebo vytvořeny v jazyce ActionScript. Více informací naleznete v části „Načtení objektů zobrazení“ na stránce 305 a „Práce s bitmapami“ na stránce 473. • Loader - Třídu Loader používáte pro načtení externích datových zdrojů (buď souborů SWF nebo grafiky). Více informací naleznete v části „Dynamické načtení obsahu zobrazení“ na stránce 305. • Shape - Tato třída slouží k vytvoření vektorových grafik, například obdélníků, čar, kruhů, atd. Více informací naleznete v části „Používání kreslicího rozhraní API“ na stránce 314. • SimpleButton - Objekt SimpleButton je reprezentací jazyka ActionScript symbolu tlačítka vytvořeného ve vývojovém nástroji Flash. Instance SimpleButton má čtyři stavy tlačítka: nahoru, dolů, nad a zahájit test (oblast, která reaguje na události myši a klávesnice). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 270 Programování zobrazení • Sprite - objekt Sprite může obsahovat vlastní grafiku a také podřízené objekty zobrazení. (Třída Sprite rozšiřuje třídu DisplayObjectContainer.) Více informací naleznete v části „Práce s kontejnery objektů zobrazení“ na stránce 273 a „Používání kreslicího rozhraní API“ na stránce 314. • MovieClip - Objekt MovieClip je forma jazyku ActionScript pro symbol filmového klipu vytvořeného ve vývojovém nástroji Flash. V praxi se MovieClip podobá objektu Sprite, s výjimkou toho, že má časovou osu. Více informací naleznete v části „Práce s filmovými klipy“ na stránce 398. Následující třídy, které nejsou v balíčku flash.display, jsou podtřídami třídy DisplayObject: • Třída TextField, která je součástí balíčku flash.text, je objekt zobrazení pro zobrazení textu a vstup. Více informací naleznete v části „Práce s textem“ na stránce 423. • Třída Video, která je součástí balíčku flash.media, je objektem zobrazení používaným pro zobrazování souborů videa. Další informace naleznete v části „Práce s videem“ na stránce 515. Následující třídy v balíčku flash.display rozšiřují třídu DisplayObject, ale nelze vytvořit jejich instance. Místo toho slouží jako nadřazené třídy pro jiné objekty zobrazení a kombinují běžné funkce do jediné třídy. • AVM1Movie - Třída AVM1Movie se používá pro znázornění načtených souborů SWF, které jsou vytvářeny v jazyce ActionScript 1.0 a 2.0. • DisplayObjectContainer - Třídy Loader, Stage, Sprite a MovieClip každá rozšiřují třídu DisplayObjectContainer. Více informací naleznete v části „Práce s kontejnery objektů zobrazení“ na stránce 273. • InteractiveObject - InteractiveObject je základní třída pro všechny objekty používané pro interakci s myší a klávesnicí. Objekty SimpleButton, TextField, Loader, Sprite, Stage, a MovieClip jsou podtřídami třídy InteractiveObject. Více informací ohledně vytváření interakcí myši a klávesnice naleznete v části „Zachycování uživatelských vstupů“ na stránce 585. • MorphShape - Tyto objekty jsou vytvářeny při vytváření doplnění tvaru v nástroji vytváření Flash. Objekty nemůžete konkretizovat pomocí jazyka ActionScript, ale jsou přístupné ze seznamu zobrazení. • Stage - Třída plochy rozšiřuje třídu DisplayObjectContainer. Pro aplikaci existuje jedna instance plochy a je umístěna na prvním místě v hierarchii seznamu zobrazení. Na plochu se dostanete pomocí vlastnosti stage jakékoliv instance DisplayObject. Více informací naleznete v části „Nastavení vlastností plochy“ na stránce 278. Třída StaticText v balíčku flash.text rozšiřuje třídu DisplayObject, ale nelze vytvořit její instanci v kódu. Pole statického textu jsou vytvářena pouze v aplikaci Flash. Výhody přístupu seznamu zobrazení V jazyce ActionScript 3.0 existují samostatné třídy pro různé typy objektů zobrazení. V jazyce ActionScript 1.0 a 2.0 je mnoho stejných typů objektů zahrnuto do jedné třídy: třída MovieClip. Tato individualizace tříd a hierarchická struktura seznamů zobrazení má následující výhody: • Efektivnější vykreslování a menší využití paměti • Vylepšené řešení hloubky • Plné křížení seznamu zobrazení • Objekty zobrazení mimo seznam • Snadnější vytváření podtříd objektů zobrazení PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 271 Programování zobrazení Účinnější vykreslování a menší velikosti souborů V jazyce ActionScript 1.0 a 2.0 můžete kreslit tvary pouze v objektu MovieClip. V jazyce ActionScript 3.0 existují jednodušší třídy objektů zobrazení, ve kterých můžete kreslit tvary. Protože tyto třídy objektů zobrazení jazyka ActionScript 3.0 neobsahují celou sadu metod a vlastností, které objekt MovieClip zahrnuje, využívají méně paměti nebo procesoru. Například každý objekt MovieClip obsahuje vlastnosti pro časovou osu filmového klipu, zatímco objekt Shape nikoliv. Vlastnosti pro řízení časové osy mohou používat mnoho zdrojů paměti a procesoru. V jazyce ActionScript 3.0 vede používání objektů Shape k lepším výsledkům. Objekt Shape má méně doplňků než složitější objekt MovieClip. Aplikace Flash Player a AIR nepotřebuje spravovat nepoužívané vlastnosti MovieClip, které vylepšují rychlost a snižují paměť používanou objekty. Vylepšené řešení hloubky V jazyce ActionScript 1.0 a 2.0 byla hloubka řešena prostřednictvím lineárního schématu řešení hloubky a metod, například getNextHighestDepth(). Jazyk ActionScript 3.0 obsahuje třídu DisplayObjectContainer, která má výhodnější metody a vlastnosti pro řešení hloubky objektů zobrazení. Jestliže v jazyce ActionScript 3.0 přesouváte objekt zobrazení do nového umístění v podřízeném seznamu instance DisplayObjectContainer, změní se automaticky poloha i jiných podřízených prvků v kontejneru objektu zobrazení a jsou jim zde přiřazeny příslušné podřízené indexové pozice. V jazyce ActionScript 3.0 je také vždy možné objevit všechny podřízené objekty jakéhokoliv kontejneru objektů zobrazení. Každá instance DisplayObjectContainer má vlastnost numChildren, která uvádí počet podřízených prvků v kontejneru objektů zobrazení. Vzhledem k tomu, že je podřízený seznam kontejneru objektů zobrazení vždy indexovaným seznamem, můžete zkoumat všechny objekty v seznamu z indexované polohy 0 pomocí poslední indexované polohy (numChildren - 1). Toto nebylo možné s metodami a vlastnostmi objektu MovieClip v jazyce ActionScript 1.0 a 2.0. V jazyce ActionScript 3.0 můžete snadno sekvenčně křížit seznam zobrazení; v podřízeném seznamu kontejneru objektů zobrazení nejsou žádné mezery v číslech indexu. Křížení seznamu zobrazení a ovládání hloubky objektů je snadnější, než v jazycích ActionScript 1.0 a 2.0. V jazycích ActionScript 1.0 a 2.0 mohl filmový klip obsahovat objekty se střídavými mezerami v pořadí hloubky, což mělo za následek složitější křížení seznamu objektů. V jazyce ActionScript 3.0 je každý podřízený seznam kontejnerů objektů zobrazení interně uložen do vyrovnávací paměti jako pole, což umožňuje velice rychlé vyhledávání (dle indexu). Opakování všemi podřízenými prvky kontejneru objektů zobrazení je také velice rychlé. V jazyce ActionScript 3.0 máte také přístup k podřízeným prvkům v kontejneru objektů zobrazení použitím metody getChildByName() třídy DisplayObjectContainer. Plné křížení seznamu zobrazení V jazycích ActionScript 1.0 a 2.0 jste neměli přístup k některým objektům, například k vektorovým tvarům, které byly nakresleny v nástroji Flash. V jazyce ActionScript 3.0 máte přístup ke všem objektům na seznamu zobrazení - k těm vytvořeným pomocí jazyka ActionScript a všem objektům zobrazení vytvořených v nástroji Flash. Podrobnosti naleznete v části „Procházení seznamu zobrazení“ na stránce 277. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 272 Programování zobrazení Objekty zobrazení mimo seznam V jazyce ActionScript 3.0 můžete vytvářet objekty zobrazení, které nejsou na seznamu viditelného zobrazení. Tyto objekty jsou nazývány objekty zobrazení mimo seznam. Objekt zobrazení je přidán k seznamu viditelného zobrazení pouze vyvoláte-li metodu addChild() nebo addChildAt() instance DisplayObjectContainer, která již byla do seznamu zobrazení přidána. Objekty zobrazení mimo seznam můžete používat pro sestavování složitých objektů zobrazení, jako jsou ty, které mají více kontejnerů objektů zobrazení obsahující násobné objekty zobrazení. Uchováváním objektů zobrazení mimo seznam můžete sestavovat komplikované objekty bez použití času zpracování k vykreslování těchto objektů zobrazení. Poté můžete objekt zobrazení mimo seznam kdykoliv přidat do seznamu zobrazení. Můžete také přesunout podřízený prvek kontejneru objektů zobrazení do a mimo seznam a do jakékoliv požadované polohy v seznamu zobrazení. Snadnější vytváření podtříd objektů zobrazení V jazyce ActionScript 1.0 a 2.0 byste často pro vytvoření základních tvarů nebo pro zobrazení bitmap museli přidat nový objekt MovieClip do souboru SWF. V jazyce ActionScript 3.0 zahrnuje třída DisplayObject mnoho zabudovaných podtříd, včetně tvaru a bitmapy. Protože třídy v jazyce ActionScript 3.0 jsou více zaměřeny na specifické typy objektů, je snazší vytvořit základní podtřídy těchto zabudovaných podtříd. Například pro nakreslení kruhu v jazyce ActionScript 2.0 jste mohli vytvořit třídu CustomCircle, která rozšiřuje třídu MovieClip, jestliže je objekt vlastní třídy konkretizován. Nicméně tato třída by také obsahovala několik vlastností a metod z třídy MovieClip (například totalFrames), které se na tuto třídu nevztahují. V jazyce ActionScript 3.0 můžete nicméně vytvořit třídu CustomCircle, která rozšiřuje objekt Shape a nezahrnuje nesouvisející vlastnosti a metody, které jsou obsaženy ve třídě MovieClip. Následující kód ukazuje příklad třídy CustomCircle: import flash.display.*; public class CustomCircle extends Shape { var xPos:Number; var yPos:Number; var radius:Number; var color:uint; public function CustomCircle(xInput:Number, yInput:Number, rInput:Number, colorInput:uint) { xPos = xInput; yPos = yInput; radius = rInput; color = colorInput; this.graphics.beginFill(color); this.graphics.drawCircle(xPos, yPos, radius); } } Práce s objekty zobrazení Nyní, když chápete základní koncepty plochy, kontejnerů objektů zobrazení a seznamu zobrazení, vám tato část nabízí podrobnější informace o práci s objekty zobrazení v jazyce ActionScript 3.0. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 273 Programování zobrazení Vlastnosti a metody třídy DisplayObject Všechny objekty zobrazení jsou podtřídy třídy DisplayObject a jako takové dědí vlastnosti a metody třídy DisplayObject. Zděděné vlastnosti jsou základními vlastnostmi, které se vztahují na všechny objekty zobrazení. Například každý objekt zobrazení má vlastnostxa vlastnost y, která určuje polohu objektu v jeho kontejneru objektů zobrazení. Nemůžete vytvořit instanci DisplayObject pomocí konstruktoru třídy DisplayObject. Musíte vytvořit jiný typ objektu (objekt, který je podtřídou třídy DisplayObject), například Sprite, pro konkretizaci objektu s operátorem new. Také pokud si přejete vytvořit vlastní třídu objektu zobrazení, musíte vytvořit podtřídu jedné z podtříd objektů zobrazení, které mají použitelnou funkci konstruktoru (například třída Shape nebo třída Sprite). Pro více informací viz popis třídy DisplayObject v Referenční příručce jazyka ActionScript 3.0 a jeho komponent. Přidávání objektů zobrazení do seznamu zobrazení Jestliže konkretizujete objekt zobrazení, nezobrazí se na obrazovce (na ploše) dokud instanci objektu zobrazení nepřidáte do kontejneru objektů zobrazení, který je uveden na seznamu zobrazení. Například v následujícím kódu objekt TextField myText by nebyl viditelný, pokud byste vypustili poslední řádek kódu. Na posledním řádku kódu se musí klíčové slovo this vztahovat ke kontejneru objektů zobrazení, který je již přidán do seznamu zobrazení. import flash.display.*; import flash.text.TextField; var myText:TextField = new TextField(); myText.text = "Buenos dias."; this.addChild(myText); Jestliže přidáte jakýkoliv vizuální prvek k ploše, stane se daný prvek podřízeným prvkem objektu Stage. První soubor SWF načtený v aplikaci (například soubor, který vložíte na stránku HTML) je automaticky přidán jako podřízený soubor plochy. Může to být objekt jakéhokoliv typu, který rozšiřuje třídu Sprite. Jakékoliv objekty zobrazení, které vytvořítebez použití jazyka ActionScript—například přidáním tagu MXML do Adobe Flex Builder 3 nebo umístěním položky na plochu v přehrávači Flash jsou přidány do seznamu zobrazení. Ačkoliv tyto objekty zobrazení nepřidáváte prostřednictvím jazyka ActionScript, máte k nim prostřednictvím jazyka ActionScript umožněn přístup. Například následující kód přizpůsobuje šířku objektu pojmenovaného button1, který byl přidán v nástroji pro vytváření (nikoliv prostřednictvím jazyka ActionScript): button1.width = 200; Práce s kontejnery objektů zobrazení Jestliže je objekt DisplayObjectContainer vymazán ze seznamu zobrazení nebo jestliže je přesunut nebo jiným způsobem změněn, každý objekt zobrazený v DisplayObjectContainer je také odstraněn, přesunut nebo změněn. Samotný kontejner objektu zobrazení je typem objektu zobrazení - lze jej přidat k jinému kontejneru objektu zobrazení. Například následující snímek ukazuje kontejner objektu zobrazení pictureScreen, který obsahuje jeden tvar obrysu a čtyři jiné kontejnery objektu zobrazení (typu PictureFrame): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 274 Programování zobrazení A B A. Tvar definující hranici kontejneru zobrazení pictureScreen B. Čtyři kontejnery objektů zobrazení, které jsou podřízené objektu pictureScreen Chcete-li v seznamu zobrazení uvést objekt zobrazení, musíte jej přidat ke kontejneru objektů zobrazení, který je na seznamu zobrazení. Přidání provedete pomocí metody addChild() nebo metodou addChildAt() objektu kontejneru. Například bez závěrečného řádku následujícího kódu by se objekt myTextField nezobrazil: var myTextField:TextField = new TextField(); myTextField.text = "hello"; this.root.addChild(myTextField); V této ukázce kódu ukazuje this.root kontejner objektu zobrazení MovieClip, který daný kód obsahuje. Ve skutečném kódu můžete určit odlišný kontejner. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 275 Programování zobrazení Použijte metodu addChildAt() pro přidání podřízeného prvku k určité pozici v podřízeném seznamu kontejneru objektu zobrazení. Tyto indexové polohy v podřízeném seznamu se základem v nule se vztahují k rozvržení (pořadí odpředu dozadu) objektů zobrazení. Zvažte například následující tři objekty zobrazení. Každý objekt byl vytvořen z vlastní třídy nazvané Ball. Rozvržení těchto objektů zobrazení v jejich kontejnerech lze upravit pomocí metody addChildAt(). Posuďte například následující kód: ball_A = new Ball(0xFFCC00, "a"); ball_A.name = "ball_A"; ball_A.x = 20; ball_A.y = 20; container.addChild(ball_A); ball_B = new Ball(0xFFCC00, "b"); ball_B.name = "ball_B"; ball_B.x = 70; ball_B.y = 20; container.addChild(ball_B); ball_C = new Ball(0xFFCC00, "c"); ball_C.name = "ball_C"; ball_C.x = 40; ball_C.y = 60; container.addChildAt(ball_C, 1); Po provedení tohoto kódu jsou objekty zobrazení umístěny do container objektu DisplayObjectContainer následovně. Všimněte si rozvržení objektů. Pro změnu polohy objektu na první místo seznamu zobrazení jej jednoduše znovu přidejte do seznamu. Například po předcházejícím kódu přesuňte ball_A na první místo skupiny, použijte tento řádek kódu: container.addChild(ball_A); Tento kód účinně odstraní ball_A z jeho umístění v seznamu zobrazení container a znovu jej přidá na první místo v seznamu - konečným výsledkem je jeho přesunutí navrch hromádky. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 276 Programování zobrazení Můžete použít metodu getChildAt() pro ověření pořadí vrstev objektů zobrazení. Metoda getChildAt() vrátí podřízené objekty kontejneru založené na číslu indexu, které jim přiřadíte. Následující kód například odhaluje jména objektů zobrazení na různých pozicích v podřízeném seznamu container objektu DisplayObjectContainer: trace(container.getChildAt(0).name); // ball_A trace(container.getChildAt(1).name); // ball_C trace(container.getChildAt(2).name); // ball_B Jestliže odstraníte objekt zobrazení z podřízeného seznamu nadřazeného kontejneru, vyšší prvky seznamu se posunou o pozici dolů v podřízeném indexu. V návaznosti na předcházející kód například následující kód ukazuje, jak se objekt zobrazení, který byl na pozici 2 v container DisplayObjectContainer přesune do pozice 1, jestliže je objekt zobrazení níže v podřízeném seznamu odstraněn: container.removeChild(ball_C); trace(container.getChildAt(0).name); // ball_A trace(container.getChildAt(1).name); // ball_B Metody removeChild() a removeChildAt() neodstraní úplně instance objektů zobrazení. Tyto metody je jednoduše odstraní z podřízeného seznamu kontejneru. K instanci lze stále odkazovat pomocí jiné proměnné. (Pomocí operátoru delete úplně odstraníte objekt.) Vzhledem k tomu, že objekt zobrazení má pouze jeden nadřazený kontejner, můžete přidat instanci objektu zobrazení pouze do jednoho kontejneru objektu zobrazení. Například následující kód ukazuje, že objekt zobrazení tf1 může existovat pouze v jednom kontejneru (v tomto případě je to Sprite, který rozšiřuje třídu DisplayObjectContainer): tf1:TextField = new TextField(); tf2:TextField = new TextField(); tf1.name = "text 1"; tf2.name = "text 2"; container1:Sprite = new Sprite(); container2:Sprite = new Sprite(); container1.addChild(tf1); container1.addChild(tf2); container2.addChild(tf1); trace(container1.numChildren); // 1 trace(container1.getChildAt(0).name); // text 2 trace(container2.numChildren); // 1 trace(container2.getChildAt(0).name); // text 1 Jestliže přidáte objekt zobrazení, který je obsažen v jednom kontejneru objektů zobrazení do jiného kontejneru objektů zobrazení, je odstraněn z prvního podřízeného seznamu kontejneru objektů zobrazení. Vedle výše popsaných metod třída DisplayObjectContainer definuje několik metod pro práci s podřízenými objekty zobrazení, včetně následujících: • Metoda contains(): Určuje, zda je objekt zobrazení podřízeným objektem DisplayObjectContainer. • Metoda getChildByName(): Dosadí objekt zobrazení podle názvu. • Metoda getChildIndex(): Vrátí indexovou polohu objektu zobrazení. • Metoda setChildIndex(): Změní polohu podřízeného objektu zobrazení. • Metoda swapChildren(): Přepíná pořadí vpředu-vzadu dvou zobrazených objektů. • Metoda swapChildrenAt(): Přepíná pořadí vpředu-vzadu dvou objektů zobrazení, určené jejich indexovými hodnotami. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 277 Programování zobrazení Pro více informací viz relevantní záznamy v Referenční příručce jazyka ActionScript 3.0 a jeho komponent. Vzpomeňte si, že objekt zobrazení, který leží mimo seznam zobrazení - ten, který není obsažen v kontejneru objektů zobrazení, který je podřízeným prvkem plochy - je znám jako objekt zobrazení mimo seznam. Procházení seznamu zobrazení Jak jste si již všimli, seznam zobrazení má stromovou strukturu. Na vrcholu stromu je plocha, která může obsahovat více objektů zobrazení. Tyto objekty zobrazení, které jsou sami kontejnery objektů zobrazení, mohou obsahovat jiné objekty zobrazení nebo kontejnery zobrazení. Vymezená Stageplocha Instance hlavní třídy souboru SWF Objekt zobrazení Kontejner objektu zobrazení Kontejner objektu zobrazení Objekt zobrazení Kontejner objektu zobrazení Objekt zobrazení Kontejner objektu zobrazení Třída DisplayObjectContainer zahrnuje vlastnosti a metody pro křížení seznamu zobrazení, prostřednictvím podřízených seznamů kontejnerů objektu zobrazení. Vezměme například následující kód, který přidá dva objekty zobrazení, title a pict k objektu container (který je Sprite a třída Sprite rozšiřuje třídu DisplayObjectContainer): var container:Sprite = new Sprite(); var title:TextField = new TextField(); title.text = "Hello"; var pict:Loader = new Loader(); var url:URLRequest = new URLRequest("banana.jpg"); pict.load(url); pict.name = "banana loader"; container.addChild(title); container.addChild(pict); Metoda getChildAt() vrátí podřízený prvek seznamu zobrazení v určité poloze indexu: trace(container.getChildAt(0) is TextField); // true PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 278 Programování zobrazení podřízené objekty jsou také přístupné podle jména. Každý objekt zobrazení má vlastnost jména a jestliže ji nepřiřadíte, přiřadí přehrávač Flash Player nebo aplikace AIR výchozí hodnotu, například "instance1". Například následující kód ukazuje, jak použít metodu getChildByName() pro přístup k podřezanému objektu zobrazení s názvem "banana loader": trace(container.getChildByName("banana loader") is Loader); // true Použití metody getChildByName() může mít za následek pomalejší výkon než v případě použití metody getChildAt(). Protože kontejner objektů zobrazení může ve svém seznamu zobrazení obsahovat jiné kontejnery objektu zobrazení jako podřízené objekty, můžete zkřížit plný seznam zobrazení aplikace jako strom. Například ve výpisu kódu uvedeném dříve je po dokončení operace načítání pro objekt pict Loader načten pro objekt pict jeden podřízený objekt zobrazení, což je bitmapa. Pro přístup k tomuto objektu zobrazení bitmapy můžete zadat pict.getChildAt(0). Můžete také zadat container.getChildAt(0).getChildAt(0) (protože container.getChildAt(0) == pict). Následující funkce poskytuje výstup zamýšleného trace() seznamu zobrazení z kontejneru objektů zobrazení: function traceDisplayList(container:DisplayObjectContainer,indentString:String = ""):void { var child:DisplayObject; for (var i:uint=0; i < container.numChildren; i++) { child = container.getChildAt(i); trace(indentString, child, child.name); if (container.getChildAt(i) is DisplayObjectContainer) { traceDisplayList(DisplayObjectContainer(child), indentString + "") } } } Nastavení vlastností plochy Třída Stage potlačí většinu vlastností a metod třídy DisplayObject. Jestliže vyvoláte jednu z těchto potlačených vlastností nebo metod, zobrazí přehrávač Flash Player nebo AIR výjimku. Například objekt Stage nemá vlastnosti x nebo y, protože je jeho pozice fixována jako hlavní kontejner pro aplikaci. Vlastnosti xa y se vztahují k pozici objektu zobrazení relativní k jeho kontejneru, a protože plocha není obsažena v žádném jiném kontejneru objektu zobrazení, tyto vlastnosti se nepoužijí. Poznámka: Některé vlastnosti a metody třídy Stage jsou dostupné pouze pro objekty zobrazení, které jsou ve stejné bezpečnostní schránce jako první načtený soubor SWF. Podrobnosti naleznete v části „Zabezpečení plochy“ na stránce 705 Ovládání rychlosti zpětného přehrávání obrazů Vlastnost framerate třídy Stage se používá pro nastavení kmitočtu obrazů pro všechny soubory SWF načtené do aplikace. Pro více informací viz Referenční příručka jazyka ActionScript 3.0 a jeho komponent. Ovládání měřítka plochy Při změně velikosti části obrazovky představující přehrávač Flash Player nebo AIR, Flash Player nebo AIR automaticky upraví obsah plochy tak, aby odpovídal. Vlastnost třídy plochy scaleMode určuje, jak se obsah plochy upraví. Tuto vlastnost lze nastavit na čtyři různé hodnoty, definované jako obsah ve třídě flash.display.StageScaleMode. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 279 Programování zobrazení Pro tři z hodnot scaleMode (StageScaleMode.EXACT_FIT, StageScaleMode.SHOW_ALL, a StageScaleMode.NO_BORDER), změní přehrávač Flash Player a AIR měřítko obsahu plochy tak, aby byl uvnitř jejích hranic. Tyto tři možnosti se liší v určení, jak je změny stupnice dosaženo: • StageScaleMode.EXACT_FIT určuje poměrnost SWF. • StageScaleMode.SHOW_ALL určuje, zda se zobrazí ohraničení, například černé lišty, které se objeví při zobrazení širokoúhlého filmu na standardní televizi. • StageScaleMode.NO_BORDER určuje, zdamůže být obsah částečně odříznut nebo ne. Jestliže je scaleMode nastaveno na StageScaleMode.NO_SCALE, obsah plochy si při změně velikosti okna přehrávače Flash Player nebo aplikace AIR uchová svou definovanou velikost. Pouze v tomto režimu měřítka lze vlastnosti plochyWidth a Height třídy Stage použít k určení skutečných rozměrů obrazového bodu okna se změněnou velikostí. (V jiných režimech měřítka vlastnosti stageWidth a stageHeight vždy odrážejí původní šířku a výšku SWF.) Jestliže je vlastnost scaleMode nastavena na StageScaleMode.NO_SCALE a u souboru SWF je změněna velikost, událost resize třídy Stage je odeslána a umožní provedení úprav. Je-li následně vlastnost scaleMode nastavena na StageScaleMode.NO_SCALE, umožní vám větší kontrolu nad tím, jak se obsah obrazovky mění se změnou velikosti okna. Například v souboru SWF obsahujícím video a ovládací lištu si můžete přát, aby ovládací lišta měla v případě změny velikosti plochy stejnou velikost a změnit pouze velikost okna videa tak, aby se přizpůsobilo změně velikosti plochy. To je ukázáno na následujícím příkladě: // videoScreen is a display object (e.g. a Video instance) containing a // video; it is positioned at the top-left corner of the Stage, and // it should resize when the SWF resizes. // // // // controlBar is a display object (e.g. a Sprite) containing several buttons; it should stay positioned at the bottom-left corner of the Stage (below videoScreen) and it should not resize when the SWF resizes. import import import import flash.display.Stage; flash.display.StageAlign; flash.display.StageScaleMode; flash.events.Event; var swfStage:Stage = videoScreen.stage; swfStage.scaleMode = StageScaleMode.NO_SCALE; swfStage.align = StageAlign.TOP_LEFT; function resizeDisplay(event:Event):void { var swfWidth:int = swfStage.stageWidth; var swfHeight:int = swfStage.stageHeight; // Resize the video window. var newVideoHeight:Number = swfHeight - controlBar.height; videoScreen.height = newVideoHeight; videoScreen.scaleX = videoScreen.scaleY; // Reposition the control bar. controlBar.y = newVideoHeight; } swfStage.addEventListener(Event.RESIZE, resizeDisplay); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 280 Programování zobrazení Práce v režimu celé obrazovky Režim celé obrazovky vám umožňuje nastavit plochu filmu tak, aby zaplnila celý monitoru bez jakýchkoliv hranic nebo nabídek kontejnerů. Vlastnost třídy Stage displayState se používá k zapínání a vypínání režimu plné obrazovky v souboru SWF. Vlastnost displayState může být nastavena na jednu z hodnot definovanou konstantami ve třídě flash.display.StageDisplayState. Jestliže chcete zapnout režim celé obrazovky, nastavte vlastnost displayState na StageDisplayState.FULL_SCREEN: stage.displayState = StageDisplayState.FULL_SCREEN; V aplikaci Flash Player může být režim celé obrazovky iniciován pouze pomocí jazyka ActionScript v reakci na klepnutí myší (včetně klepnutím pravým tlačítkem) nebo stisknutím klávesy. Obsah aplikace AIR běžící v bezpečnostní schránce aplikace nevyžaduje, aby byl režim celé obrazovky aktivován reakcí na gesto uživatele. Jestliže chcete režim celé obrazovky ukončit, nastavte vlastnost displayState na StageDisplayState.NORMAL. stage.displayState = StageDisplayState.NORMAL; Navíc může uživatel odejít z režimu celé obrazovky přepnutím výběru do jiného okna nebo použitím jedné z několika kombinací kláves: Esc (všechny platformy), Ctrl-W (Windows), Apple-W (Mac) nebo Alt-F4 (Windows). Povolení režimu celé obrazovky v přehrávači Flash Player Chcete-li povolit režim celé obrazovky pro soubor SWF vložený do stránky HTML, musí kód HTML, který bude obsahovat přehrávač Flash Player, zahrnovat tag param, atribut embed s názvem allowFullScreen a hodnotou true, a to následovně: <object> ... <param name="allowFullScreen" value="true" /> <embed ... allowfullscreen="true" /> </object> Vyberte ve vývojovém nástroji Flash položky Soubor -> Nastavení publikování a v dialogovém okně Nastavení publikování na kartě HTML zvolte položku Pouze Flash - Povolit šablonu celé obrazovky. V programu Flex se ujistěte, zda šablona HTML obsahuje tagy <object> a <embed>, které podporují režim celé obrazovky. Jestliže pro generování SWF-vkládajících tagů používáte JavaScript na webové stránce, musíte upravit JavaScript pro přidání tagu allowFullScreen param a atributu. Například jestli vaše stránka HTML používá funkciAC_FL_RunContent() (která je používána HTML stránkami vytvářenými v aplikacích Flex Builder i Flash), měli byste přidat parametr allowFullScreen pro volání dané funkce následovně: AC_FL_RunContent( ... 'allowFullScreen','true', ... ); //end AC code Toto se nevztahuje na soubory SWF spuštěné v samostatném přehrávači Flash Player. Poznámka: Jestliže nastavíte režim okna (wmode v jazyku HTML) na možnost Neprůhledné bez okna (neprůhledné) nebo Průhledné bez okna (průhledné), bude okno celé obrazovky vždy neprůhledné. Používání režimu celé obrazovky s přehrávačem Flash Player v prohlížeči má také omezení související se zabezpečením. Tato omezení jsou popsána v „Zabezpečení přehrávače Flash Player“ na stránce 688. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 281 Programování zobrazení Velikost a změna velikosti vymezené plochy v režimu celé obrazovky Vlastnosti Stage.fullScreenHeight a Stage.fullScreenWidth vrátí výšku a šířku monitoru, který je použit při přechodu na celou obrazovku, jestliže je daný stav ihned aktivován. Tyto hodnoty nemusí být správné, pokud má uživatel po načtení těchto hodnot, ale před přechodem na celou obrazovku, možnost přesunout prohlížeč z jednoho monitoru na druhý. Pokud tyto hodnoty získáte ve stejném manipulačním programu události, ve kterém jste nastavili vlastnost Stage.displayState na hodnotu StageDisplayState.FULL_SCREEN, jsou tyto hodnoty správné. U uživatelů s více monitory se obsah SWF rozšíří tak, aby vyplnil pouze jeden monitor. Aplikace Flash Player i AIR používají metrický systém za účelem určení, který monitor obsahuje největší podíl SWF, a tento monitor použijí pro režim celé obrazovky. Vlastnosti fullScreenHeight a fullScreenWidth odráží pouze velikost monitoru, který slouží pro režim celé obrazovky . Další informace naleznete v částech Stage.fullScreenHeight a Stage.fullScreenWidth dokumentu Referenční příručka jazyka ActionScript 3.0 a jeho komponent. Chování změny měřítka pro režim celé obrazovky je stejné jako za běžnému režimu; změna měřítka je ovládání vlastností třídy Stage scaleMode. Jestliže je vlastnost scaleMode nastavena na StageScaleMode.NO_SCALE, vlastnosti plochy stageWidth a stageHeight se změní tak, aby odrážely velikost prostoru obrazovky, který zabírá soubor SWF (v tomto případě je to celá obrazovka); jestliže je parametr HTML zobrazen v prohlížeči, ovládá nastavení. Událost třídy Stage fullScreen můžete použít tak, aby detekovala a reagovala při zapnutí nebo vypnutí režimu celé obrazovky. Při zapínání nebo vypínání režimu celé obrazovky můžete chtít například změnit polohu, přidat nebo odstranit položky z obrazovky, jako v tomto případě: import flash.events.FullScreenEvent; function fullScreenRedraw(event:FullScreenEvent):void { if (event.fullScreen) { // Remove input text fields. // Add a button that closes full-screen mode. } else { // Re-add input text fields. // Remove the button that closes full-screen mode. } } mySprite.stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullScreenRedraw); Jak ukazuje tento kód, je objekt události pro událost fullScreen instancí třídy flash.events.FullScreenEvent, která zahrnuje vlastnost fullScreen určující, zda je režim celé obrazovky aktivován (true (pravda)) nebo nikoliv (false (nepravda)). Podpora klávesnice v režimu celé obrazovky Je-li přehrávač Flash Player spuštěný v prohlížeči, jsou v režimu celé obrazovky zakázány všechny skripty jazyka ActionScript související s klávesnicí, jako jsou události klávesnice a zadávání textu do instancí TextField. Výjimkami jsou tyto povolené klávesy: • Klávesy nesouvisející s tiskem – konkrétně šipky, mezerník a klávesa Tab. • Klávesové zkratky pro ukončení režimu celé obrazovky: Esc (v systému Windows i počítačích Macintosh), Ctrl-W (Windows), Apple-W (Macintosh) a Alt-F4. Pro obsah SWF, který je spuštěný v samostatné aplikaci Flash Player nebo AIR, tato omezení neexistují. Aplikace AIR podporuje interaktivní režim na celou obrazovku, který umožňuje vstupy klávesnice. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 282 Programování zobrazení Hardwarová změna měřítka v režimu celé obrazovky Můžete použít vlastnost třídy Stage fullScreenSourceRect pro nastavení přehrávače Flash Player nebo aplikace AIR na změnu měřítka určité oblasti plochy na režim celé obrazovky. Je-li tato možnost k dispozici, provádí aplikace Flash Player i AIR změnu měřítka hardwarově; tím se využije grafická a video karta v počítači a obsah se obecně zobrazí rychleji než při programové změně měřítka. Chcete-li využít výhod hardwarové změny velikosti, nastavte celou nebo část vymezené plochy na režim celé obrazovky. Následující kód jazyka ActionScript 3.0 nastaví celou vymezenou plochu na režim celé obrazovky: import flash.geom.*; { stage.fullScreenSourceRect = new Rectangle(0,0,320,240); stage.displayState = StageDisplayState.FULL_SCREEN; } Jestliže je tato vlastnost nastavena pro platný obdélník a vlastnost displayState je nastavena na režim celé obrazovky, přehrávač Flash Player změní velikost určené oblasti. Aktuální velikost vymezené plochy v obr. bodech v rámci jazyka ActionScript se nemění. Přehrávač Flash Player a AIR uplatní minimální omezení velikosti obdélníku, aby se přizpůsobil standardní zprávě „Press Esc to exit full-screen mode“. Tento limit je obvykle okolo 260 na 30 obr. bodů, ale může se lišit v závislosti na platformě a verzi přehrávače Flash Player. Vlastnost fullScreenSourceRect může být nastavena pouze když přehrávač Flash Player nebo AIR není v režimu celé obrazovky. Chcete-li tuto vlastnost použít správně, nejdříve nastavte tuto vlastnost a potom nastavte vlastnost displayState na režim celé obrazovky. Chcete-li povolit změnu měřítka, nastavte vlastnost fullScreenSourceRect na objekt obdélníku. stage.fullScreenSourceRect = new Rectangle(0,0,320,240); Chcete-li zakázat změnu měřítka, nastavte vlastnost fullScreenSourceRect na hodnotu null. stage.fullScreenSourceRect = null; Chcete-li využívat výhod funkcí hardwarové akcelerace u přehrávače Flash Player, zapněte tuto volbu pomocí dialogového okna nastavení přehrávače Flash Player. Chcete-li toto dialogové okno načíst, klepněte ve svém prohlížeči na obsah přehrávače Flash Player pravým tlačítkem (Windows) nebo s klávesou Ctrl (Macintosh). Vyberte kartu Zobrazení, která je kartou první, a zaškrtněte políčko: Povolit hardwarovou akceleraci. Přímé režimy okna a režimy skládání GPU Přehrávač Flash Player 10 uvádí dva režimy okna – přímé okno a okno skládání GPU, které můžete povolit nastavením publikování ve vývojovém nástroji Flash. Tyto režimy nejsou v aplikaci AIR podporovány. Jestliže chcete využít výhod těchto režimů, musíte pro přehrávač Flash Player povolit hardwarovou akceleraci. Přímý režim používá rychlejší, nejpřímější cestu k posunutí grafiky na obrazovku, což je výhodné pro přehrávání videa. Skládání GPU používá k akceleraci skládání jednotku pro zpracování grafiky na video kartě. Skládání videa je proces vrstvení více obrazů k vytvoření jediného obrazu videa. Při akceleraci skládání s GPU může dojít k vylepšení výkonu konverze YUV, opravy barev, rotace, změny měřítka nebo prolnutí. YUV konverze odkazuje na konverzi barev složených analogových signálů použitých pro přenosy na barevný model RGB (červená, zelená, modrá), který používají video kamery a displeje. Používání GPU pro urychlení skládání snižuje požadavky na paměť a skládání, které jsou jinak kladeny na CPU. Výsledkem je také hladší přehrávání pro standardně definované video. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 283 Programování zobrazení Při implementaci těchto režimů oken buďte opatrní. Používání skládání GPU může být náročné pro paměť a zdroje a CPU. Jestliže nelze některé operace (například režimy prolnutí, filtrování, ořezání nebo maskování) provést v GPU, budou provedeny softwarem. Společnost Adobe doporučuje omezit se při používání těchto režimů na jeden soubor SWF na každou stránku HTML. Tyto režimy by neměly být povoleny pro bannery. Zařízení Flash Test Movie nepoužívá hardwarovou akceleraci, ale můžete jí použít pomocí volby Publikovat náhled. Nastavení kmitočtu snímků v souboru SWF na hodnotu vyšší než 60 (maximální kmitočet aktualizace obrazovky) je zbytečné. Nastavení kmitočtu snímků na hodnotu mezi 50 a 55 umožňuje vynechání snímků, ke kterému může občas dojít. V systému Windows vyžaduje používání přímého režimu rozhraní Microsoft DirectX 9 s 128 MB paměti VRAM a u počítačů Apple Macintosh rozhraní OpenGL (v systému Mac OS X verze 10.2 nebo vyšší). Skládání GPU vyžaduje v systému Windows podporu rozhraní Microsoft DirectX 9 a Pixel Shader 2.0 s 128 MB paměti VRAM. V systémech Mac OS X a Linux vyžaduje skládání GPU rozhraní OpenGL 1.5 a několik rozšíření OpenGL (objekt framebuffer, násobnou texturu, objekty clony, jazyk clonění, clonu fragmentu). Režimy akcelerace direct a gpu můžete pro každý soubor SWF aktivovat jednotlivě pomocí dialogového okna Nastavení publikování programu Flash (pomocí nabídky Hardwarová akcelerace na kartě Flash). Jestliže zvolíte možnost Žádná, vrátí se režim okna na default, transparent nebo opaque, dle nastavení Režim okna na kartě HTML. Zpracování událostí pro objekty zobrazení Třída DisplayObject dědí z třídy EventDispatcher. To znamená, že každý objekt zobrazení se může plně účastnit v modelu události (popsáno v části „Zpracování událostí“ na stránce 243). Každý objekt zobrazení může použít svou metodu addEventListener() - získanou z třídy EventDispatcher - pro naslouchání určité události, ale pouze jestliže je naslouchající objekt součástí toku událostí pro danou událost. Když aplikace Flash Player nebo AIR odešle objekt události, daný objekt události dorazí k ploše a objektu zobrazení, kde k události došlo, a zpět. Jestliže uživatel například klepne na objekt zobrazení pojmenovaný child1, přehrávač Flash Player odešle objekt události z plochy hierarchií seznamu zobrazení směrem dolů až k objektu zobrazení child1. Tok událostí je koncepčně rozdělen do tří fází, dle ukázky v tomto diagramu: Vymezená plocha Fáze zachycení Bublinová fáze Nadřazený uzel Podřízený uzel1 Podřízený uzel2 Cílová fáze Další informace viz „Zpracování událostí“ na stránce 243. Jedním důležitým bodem, na který je třeba při práci s událostmi objektů zobrazení pamatovat, je vliv, který přijímače události mohou být na to, zda jsou objekty zobrazení při odstranění ze seznamu zobrazení automaticky odstraněny z paměti (do koše). Jestliže má objekt zobrazení objekty přihlášené ke svým událostem jako přijímače, daný objekt zobrazení nebude odstraněn z paměti, i když je odstraněn se seznamu zobrazení, protože bude mít i nadále odkazy na tyto objekty přijímače. Více informací naleznete v části „Správa posluchačů událostí“ na stránce 257. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 284 Programování zobrazení Výběr podtřídy DisplayObject S nabídkou několika možností, ze kterých si můžete vybrat, je jedním z nejdůležitějších rozhodnutí při práci s objekty zobrazení to, který objekt zobrazení má být za kterým účelem použit. Zde je návod, který vám při rozhodování pomůže. Stejné návrhy platí v případě, jestliže potřebujete instanci třídy, nebo vybíráte základní třídu pro třídu, kterou vytváříte: • Jestliže nepotřebujete objekt, který může být kontejnerem pro jiné objekty zobrazení (tzn. potřebujete pouze jeden, který slouží jako samostatný prvek obrazovky), vyberte jednu z těchto podtříd DisplayObject nebo InteractiveObject, v závislosti pro co bude daný objekt použit: • Bitmapa pro zobrazení obrazu bitmapy. • TextField pro přidání textu. • Video pro zobrazení videa. • Tvar pro plátno pro kreslení obsahu na obrazovce. Zvláště jestliže si přejete vytvořit instanci pro kreslení tvarů na obrazovce a nebude se jednat o kontejner pro jiné objekty zobrazení, získáte použitím Shape místo Sprite nebo MovieClip výrazný výkon. • MorphShape, StaticText nebo SimpleButton pro položky vytvořené vývojovým nástrojem Flash. (Instance těchto tříd nemůžete vytvořit programaticky, ale můžete vytvořit proměnné s těmito typy dat, které se vztahují k položkám vytvořeným pomocí vývojového nástroje Flash.) • Jestliže potřebujete proměnnou, která bude odkazovat na hlavní plochu, použijte třídu Stage a její typ dat. • Jestliže potřebujete kontejner pro načtení externího souboru SWF nebo obrázkového souboru, použijte instanci Loader. Načtený obsah bude přidán k seznamu zobrazení jako podřízený obsah instance Loader. Jeho typ dat bude záviset na povaze načteného obsahu, a to následovně: • Načtený snímek bude instancí bitmapy. • Načtený soubor SWF zapsaný do jazyka ActionScript 3.0 bude instancí Sprite nebo MovieClip (nebo instancí podtřídy těchto tříd, dle určení tvůrcem obsahu). • Načtený soubor SWF zapsaný v jazyce ActionScript 1.0 nebo jazyce ActionScript 2.0 bude instancí AVM1Movie. • Jestliže potřebujete objekt, který bude sloužit jako kontejner pro jiné objekty zobrazení (zda budete také kreslit na objekt zobrazení pomocí jazyka ActionScript či nikoliv), zvolte jednu z podtříd DisplayObjectContainer: • Sprite jestliže objekt bude vytvořen pouze pomocí jazyka ActionScript, nebo jako základní třída pro vlastní objekt zobrazení, který bude vytvořen a spravován pouze v jazyce ActionScript. • MovieClip jestliže vytváříte proměnnou, která odkazuje na filmový klip vytvořený v nástroji pro vytváření Flash. • Jestliže vytváříte třídu, které bude spojena se symbolem filmového klipu v knihovně Flash, zvolte jako základní třídu vaší třídy jednu z těchto podtříd DisplayObjectContainer: • MovieClip jestliže připojený symbol filmového klipu má obsah na více než jednom obrazu • Sprite jestliže má připojený symbol pohyblivého klipu obsah pouze na prvním obrazu PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 285 Programování zobrazení Manipulace s objekty zobrazení Bez ohledu na to, který objekt zobrazení si zvolíte pro použití, existuje několik způsobů manipulace, které všechny objekty zobrazení mají společné jako prvky zobrazené na obrazovce. Například mohou být všechny umístěny na obrazovce, přesunuty dopředu nebo dozadu v pořadí umístění objektů zobrazení, může být změněno měřítko, provedeno otočení, atd. Protože všechny objekty zobrazení dědí tuto funkci ze své společné základní třídy (DisplayObject), tato funkce se chová stejně, ať už manipulujete s instancí TextField, instancí Video a instancí Shape, nebo s jiným objektem zobrazení. Následující část podrobně popisuje některé z běžných manipulací objekty zobrazení. Změna polohy Základní manipulace s jakýmkoliv objektem zobrazení je jeho umístění na obrazovce. Pro nastavení polohy objektů zobrazení změňte vlastnosti objektu x a y. myShape.x = 17; myShape.y = 212; Systém pro polohování objektu zobrazení zachází s plochou jako s kartézským systémem souřadnic (běžný mřížkový systém s horizontální osou x a vertikální osou y). Počátek systému souřadnic (souřadnice 0,0, kde se potkávají osy x a y) je umístěn v horním levém rohu plochy. Z tohoto místa směřují kladné hodnoty x doprava a záporné hodnoty doleva (v porovnání s typickým grafovým systémem), zatímco kladné hodnoty y směřují dolů a záporné nahoru. Například předcházející řádky kódu přesouvají objekt myShape na x-souřadnici 17 (17 obrazových bodů doprava od počátku) a na y-souřadnici 212 (212 obrazových bodů pod počátkem). Dle výchozího nastavení, jestliže je objekt zobrazení vytvořen pomocí jazyka ActionScript, vlastnosti x a y jsou obě nastaveny na hodnotu 0 a umísťují objekt do horního levého rohu svého nadřazeného obsahu. Změna polohy relativní k ploše Je důležité si zapamatovat, že vlastnosti x a y se vždy vztahují k poloze objektu zobrazení relativní k souřadnici 0,0 svého nadřazeného objektu zobrazení. Takže pro instanci Shape (například kruh) obsaženou uvnitř instance Sprite, umístí nastavení vlastností xa y objektů Shape na 0 kruh v horním levém rohu Sprite, což nemusí nezbytně být horní levý roh plochy. Pro umístění objektu relativně k celkovým souřadnicím plochy můžete použít metodu globalToLocal() jakéhokoliv objektu zobrazení a převrátit souřadnice z globálních souřadnic (plocha) na místní souřadnice (kontejnery objektů zobrazení), jako: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 286 Programování zobrazení // Position the shape at the top-left corner of the Stage, // regardless of where its parent is located. // Create a Sprite, positioned at x:200 and y:200. var mySprite:Sprite = new Sprite(); mySprite.x = 200; mySprite.y = 200; this.addChild(mySprite); // Draw a dot at the Sprite's 0,0 coordinate, for reference. mySprite.graphics.lineStyle(1, 0x000000); mySprite.graphics.beginFill(0x000000); mySprite.graphics.moveTo(0, 0); mySprite.graphics.lineTo(1, 0); mySprite.graphics.lineTo(1, 1); mySprite.graphics.lineTo(0, 1); mySprite.graphics.endFill(); // Create the circle Shape instance. var circle:Shape = new Shape(); mySprite.addChild(circle); // Draw a circle with radius 50 and center point at x:50, y:50 in the Shape. circle.graphics.lineStyle(1, 0x000000); circle.graphics.beginFill(0xff0000); circle.graphics.drawCircle(50, 50, 50); circle.graphics.endFill(); // Move the Shape so its top-left corner is at the Stage's 0, 0 coordinate. var stagePoint:Point = new Point(0, 0); var targetPoint:Point = mySprite.globalToLocal(stagePoint); circle.x = targetPoint.x; circle.y = targetPoint.y; Můžete také použít metodu třídy DisplayObject localToGlobal() pro převedení místních souřadnic na souřadnice plochy. Vytváření interakce přetažení Jedním běžným důvodem pro přesunutí objektu zobrazení je vytvoření interakce přetažení. Jestliže uživatel klepne na objekt, objekt se bude přesouvat společně s pohybem myši, dokud neuvolníte tlačítko myši. Interakci přetažení lze vytvořit v jazyce ActionScript dvěma způsoby. V obou případech se používají dvě události myši: při stisknutí tlačítka myši bude objekt sledovat kurzor myši a při uvolnění tlačítka objekt přestane kurzor myši sledovat. První způsob použití metody startDrag() je jednodušší, ale omezenější. Jestliže stisknete tlačítko myši, bude vyvolána metoda startDrag() objektu zobrazení, který má být přetažen. Při uvolnění tlačítka myši je vyvolána metoda stopDrag(). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 287 Programování zobrazení // This code creates a drag-and-drop interaction using the startDrag() // technique. // square is a DisplayObject (e.g. a MovieClip or Sprite instance). import flash.events.MouseEvent; // This function is called when the mouse button is pressed. function startDragging(event:MouseEvent):void { square.startDrag(); } // This function is called when the mouse button is released. function stopDragging(event:MouseEvent):void { square.stopDrag(); } square.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); square.addEventListener(MouseEvent.MOUSE_UP, stopDragging); Tato technika podléhá jednomu významného omezení: pomocí metody startDrag() lze přetáhnout pokaždé pouze jednu položku. Jestliže je jeden objekt zobrazení přetažen a metoda startDrag() je vyvolána na jiném objektu zobrazení, první objekt zobrazení okamžitě přestane sledovat myš. Například jestliže je funkce startDragging() takto změněna, pouze objekt circle bude přetažen, a to i přes volání metody square.startDrag(): function startDragging(event:MouseEvent):void { square.startDrag(); circle.startDrag(); } Následkem toho, že lze pomocí metody startDrag() pokaždé přetáhnout pouze jeden objekt, metoda stopDrag() může být vyvolána na jakémkoliv objektu zobrazení a zastaví jakýkoliv objekt, který je aktuálně tažen. Jestliže potřebujete přetáhnout více než jeden objekt zobrazení nebo zamezit možnosti konfliktů v případě, že jeden nebo více objektů potenciálně používá metodu startDrag(), je nejlepší pro vytvoření efektu přetažení použít techniku sledování myši. V případě této techniky je při stisknutí tlačítka myši události plochy mouseMove připsána funkce jakou poslouchač. Tato funkce, které je poté vyvolána pokaždé s pohybem myši způsobuje, že tažený objekt přeskočí na souřadnice x, y myši. Při uvolnění tlačítka myši je funkce odhlášena jako poslouchač a znamená to, že při pohybu myši již není vyvolána a objekt přestane sledovat kurzor myši. Zde je kód, který demonstruje tuto techniku: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 288 Programování zobrazení // This code creates a drag-and-drop interaction using the mouse-following // technique. // circle is a DisplayObject (e.g. a MovieClip or Sprite instance). import flash.events.MouseEvent; var offsetX:Number; var offsetY:Number; // This function is called when the mouse button is pressed. function startDragging(event:MouseEvent):void { // Record the difference (offset) between where // the cursor was when the mouse button was pressed and the x, y // coordinate of the circle when the mouse button was pressed. offsetX = event.stageX - circle.x; offsetY = event.stageY - circle.y; // tell Flash Player to start listening for the mouseMove event stage.addEventListener(MouseEvent.MOUSE_MOVE, dragCircle); } // This function is called when the mouse button is released. function stopDragging(event:MouseEvent):void { // Tell Flash Player to stop listening for the mouseMove event. stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragCircle); } // This function is called every time the mouse moves, // as long as the mouse button is pressed down. function dragCircle(event:MouseEvent):void { // Move the circle to the location of the cursor, maintaining // the offset between the cursor's location and the // location of the dragged object. circle.x = event.stageX - offsetX; circle.y = event.stageY - offsetY; // Instruct Flash Player to refresh the screen after this event. event.updateAfterEvent(); } circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); circle.addEventListener(MouseEvent.MOUSE_UP, stopDragging); Vedle toho, kdy objekt zobrazení sleduje kurzor myši, zahrnuje běžná část interakce přetažení přesunutí taženého objektu dopředu displeje, takže se bude jevit jako plovoucí nad všemi ostatními objekty. Předpokládejme například, že máte dva objekty, kruh a čtverec, které mají interakci přetažení. Jestliže je kruh na seznamu zobrazení níže než čtverec, na kruh klepnete a táhnete tak, že je kurzor nad čtvercem, bude kruh zdánlivě klouzat za čtvercem a iluze přetažení bude porušena. Můžete také zvolit postup, kdy po klepnutí na kruh dojde k jeho přesunutí na první místo seznamu zobrazení, a proto se vždy zobrazí navrch jakéhokoliv obsahu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 289 Programování zobrazení Následující kód (přejatý z předchozího příkladu) vytvoří interakci přetažení pro dva objekty zobrazení, kruh a čtverec. Kdykoliv stisknete tlačítko myši nad jedním z nich, daná položka je přesunuta na první místo v seznamu zobrazení plochy, takže se přetažená položka vždy objeví nahoře. Kód, který je nový nebo se od předchozího uvedení změní, se zobrazí tučně. // // // // This code creates a drag-and-drop interaction using the mouse-following technique. circle and square are DisplayObjects (e.g. MovieClip or Sprite instances). import flash.display.DisplayObject; import flash.events.MouseEvent; var offsetX:Number; var offsetY:Number; var draggedObject:DisplayObject; // This function is called when the mouse button is pressed. function startDragging(event:MouseEvent):void { // remember which object is being dragged draggedObject = DisplayObject(event.target); // Record the difference (offset) between where the cursor was when // the mouse button was pressed and the x, y coordinate of the // dragged object when the mouse button was pressed. offsetX = event.stageX - draggedObject.x; offsetY = event.stageY - draggedObject.y; // move the selected object to the top of the display list stage.addChild(draggedObject); // Tell Flash Player to start listening for the mouseMove event. stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject); } // This function is called when the mouse button is released. function stopDragging(event:MouseEvent):void { // Tell Flash Player to stop listening for the mouseMove event. stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject); } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 290 Programování zobrazení // This function is called every time the mouse moves, // as long as the mouse button is pressed down. function dragObject(event:MouseEvent):void { // Move the dragged object to the location of the cursor, maintaining // the offset between the cursor's location and the location // of the dragged object. draggedObject.x = event.stageX - offsetX; draggedObject.y = event.stageY - offsetY; // Instruct Flash Player to refresh the screen after this event. event.updateAfterEvent(); } circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); circle.addEventListener(MouseEvent.MOUSE_UP, stopDragging); square.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); square.addEventListener(MouseEvent.MOUSE_UP, stopDragging); Chcete-li dále rozšířit tento efekt, například pro hru, kde jsou tokeny nebo karty přesouvány mezi hromádkami, můžete přetažený objekt do seznamu zobrazení plochy přidat při jeho „vyzvednutí“ a poté jej přidat do jiného seznamu zobrazení - například „hromádka“, kde je objekt umístěn - při uvolnění tlačítka myši. Nakonec pro vylepšení efektu můžete klepnutím na objekt zobrazení použít filtr vrženého stínu (když jej začnete přetahovat) a vržený stín odstranit při uvolnění objektu. Podrobnosti ohledně používání filtrů vrženého stínu a jiných filtrů pro objekty zobrazení v jazyce ActionScript naleznete v části „Filtrování objektů zobrazení“ na stránce 346. Stranový posun a posouvání objekty zobrazení Máte-li objekt zobrazení, který je příliš veliký pro prostor, ve kterém jej chcete zobrazit, můžete použít vlastnost scrollRect pro určení zobrazitelného prostoru objektu zobrazení. Dále změnou vlastnosti scrollRect v reakci na vstup uživatele můžete způsobit vychýlení objektu vlevo a vpravo, nebo procházení nahoru či dolů. Vlastnost scrollRect je instancí třídy Rectangle, která je třídou kombinující hodnoty potřebné k definování obdélníkového prostoru jako jediného objektu. Pro první definování zobrazitelného prostoru objektu zobrazení vytvořte novou instanci obdélníku a přiřaďte ji k vlastnosti objektu zobrazení scrollRect. Později pro procházení nebo posouvání načtete vlastnost scrollRect do samostatné proměnné Rectangle a změníte požadovanou vlastnost (například změníte vlastnost instance x pro posouvání nebo vlastnost y pro procházení). Poté znovu přiřadíte instanci obdélníku vlastnosti scrollRect a uvědomíte tak objekt zobrazení o změněné hodnotě. Následující kód například definuje zobrazitelnou oblast pro objekt TextField pojmenovaný bigText, který je příliš vysoký, aby se vešel do ohraničení souboru SWF. Jestliže klepnete na dvě tlačítka pojmenovaná up a down, vyvolají funkce, které způsobí, že se obsah objektu TextField posune nahoru nebo dolů upravením vlastnosti yinstance scrollRect Rectangle. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 291 Programování zobrazení import flash.events.MouseEvent; import flash.geom.Rectangle; // Define the initial viewable area of the TextField instance: // left: 0, top: 0, width: TextField's width, height: 350 pixels. bigText.scrollRect = new Rectangle(0, 0, bigText.width, 350); // Cache the TextField as a bitmap to improve performance. bigText.cacheAsBitmap = true; // called when the "up" button is clicked function scrollUp(event:MouseEvent):void { // Get access to the current scroll rectangle. var rect:Rectangle = bigText.scrollRect; // Decrease the y value of the rectangle by 20, effectively // shifting the rectangle down by 20 pixels. rect.y -= 20; // Reassign the rectangle to the TextField to "apply" the change. bigText.scrollRect = rect; } // called when the "down" button is clicked function scrollDown(event:MouseEvent):void { // Get access to the current scroll rectangle. var rect:Rectangle = bigText.scrollRect; // Increase the y value of the rectangle by 20, effectively // shifting the rectangle up by 20 pixels. rect.y += 20; // Reassign the rectangle to the TextField to "apply" the change. bigText.scrollRect = rect; } up.addEventListener(MouseEvent.CLICK, scrollUp); down.addEventListener(MouseEvent.CLICK, scrollDown); Jak ukazuje tento příklad, při práci s vlastností objektu zobrazení scrollRect je nejlepší určit, že by aplikace Flash Player nebo AIR měly uložit obsah objektu zobrazení do vyrovnávací paměti jako bitmapu, pomocí vlastnosti cacheAsBitmap. Jestli to určíte, přehrávač Flash Player a AIR nemusí znovu nakreslit celý obsah objektu zobrazení pokaždé při jeho procházení a mohou místo toho pro vykreslování nezbytné části přímo na obrazovku použít do vyrovnávací paměti uloženou bitmapu. Podrobnosti naleznete v části „Ukládání objektů zobrazení do vyrovnávací paměti“ na stránce 294. Manipulace s velikostí a změna měřítka objektů Provádět měření a manipulovat velikostí objektu zobrazení můžete dvěma způsoby, pomocí vlastností rozměrů (width a height) nebo vlastností měřítka scaleX a scaleY). Každý objekt zobrazení má vlastnost width a vlastnost height, které jsou zpočátku nastaveny na velikost objektů v obrazových bodech. Hodnoty těchto vlastností můžete načíst a změřit tak velikost objektu zobrazení. Můžete také určit nové hodnoty a změnit tak velikost objektu, a to následovně: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 292 Programování zobrazení // Resize a display object. square.width = 420; square.height = 420; // Determine the radius of a circle display object. var radius:Number = circle.width / 2; Změna height nebo width objektu zobrazení způsobí změnu měřítka objektu. Jeho obsah se smrští nebo roztáhne tak, aby odpovídal nové oblasti. Jestliže objekt zobrazení obsahuje pouze vektorové tvary, tyto tvary budou překresleny v novém měřítku, bez ztráty kvality. Pro jakékoliv grafické prvky bitmapy v objektu zobrazení bude změněno měřítko, místo toho, aby byly překresleny. Například digitální fotografie, jejíž šířka a výška je zvětšena za aktuální rozměry obrazového bodu v obrazu budou pixelovány a snímek bude vypadat zubatý. Jestliže změníte vlastnosti width nebo height objektu zobrazení, aktualizují aplikace Flash Player a AIR také vlastnostiscaleX a scaleY objektu. Poznámka: Objekty TextField jsou výjimkou tohoto chování změny měřítka. Velikost textových polí je třeba změnit a přizpůsobit tak zabalení textu a velikosti písma, aby po změně velikosti obnovila textové pole své hodnoty scaleX nebo scaleY na 1. Nicméně pokud nastavíte hodnoty scaleX nebo scaleY objektu TextField, hodnoty šířky a výšky se změní tak, aby se přizpůsobily zadaným hodnotám měřítka. Tyto vlastnosti představují relativní velikost objektu zobrazení v porovnání s jeho původní velikostí. Vlastnosti scaleX a scaleY používají zlomky (desetinné hodnoty) pro znázornění procenta. Jestliže byla například vlastnost width objektu zobrazení změněna tak, že je ve vztahu ke své původní velikosti poloviční, velikost objektu scaleX bude mít hodnotu .5, tzn. 50 procent. Jestliže byla výška zdvojnásobena, jeho vlastnost scaleY bude mít hodnotu 2, tzn. 200 procent. // circle is a display object whose width and height are 150 pixels. // At original size, scaleX and scaleY are 1 (100%). trace(circle.scaleX); // output: 1 trace(circle.scaleY); // output: 1 // When you change the width and height properties, // Flash Player changes the scaleX and scaleY properties accordingly. circle.width = 100; circle.height = 75; trace(circle.scaleX); // output: 0.6622516556291391 trace(circle.scaleY); // output: 0.4966887417218543 Změny velikosti nejsou poměrné. Jinými slovy, jestliže změníte vlastnost čtverce height, ale nikoliv width, jeho proporce již nebudou stejné a vnikne z něho obdélník místo čtverce. Jestliže si přejete provádět relativní změny velikosti objektu zobrazení, můžete nastavit hodnoty vlastností scaleX a scaleY a změnit tak velikost objektu, jako alternativu k nastavení vlastností width nebo height. Například tento kód změní vlastnost width objektu zobrazení nazvaného square a poté změní vertikální měřítko scaleY) tak, aby odpovídalo horizontálnímu měřítku, a aby velikost čtverce zůstala proporční. // Change the width directly. square.width = 150; // Change the vertical scale to match the horizontal scale, // to keep the size proportional. square.scaleY = square.scaleX; PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 293 Programování zobrazení Ovládání deformace během změny měřítka Běžně je při změně měřítka objektu zobrazení (například horizontální protažení) následná deformace rovnoměrně rozmístěna přes objekt, takže každá část je protažena o stejné množství. Tento postup je ideální pro grafické a designové prvky. Nicméně někdy je lepší ovládat to, která část objektu zobrazení se protáhne, a která část zůstane nezměněna. Běžným příkladem je tlačítko, které je obdélníkem se zaoblenými rohy. S běžnou změnou měřítka se rohy tlačítka protáhnou a poloměr rohu se při změně velikosti tlačítka také změní. Nicméně v tomto případě by bylo lepší ovládat změnu měřítka - mít možnost určit jisté oblasti, pro které by mělo být změněno měřítko (rovné strany a střed) a oblasti, kde měřítko změněno být nemá (rohy) - takže bude změna měřítka provedena bez viditelné deformace. Můžete použít změnu měřítka s 9 řezy pro vytvoření objektů zobrazení tam, kde ovládáte změnu měřítka objektů. Se změnou měřítka s 9 řezy je objekt zobrazení rozdělen do devíti samostatných obdélníků (do mřížky 3x3). Obdélníky nemají nezbytně stejnou velikost - kterou určujete při umístění linií mřížky. Jakýkoliv obsah, který leží v obdélnících se čtyřmi rohy (např. zaoblené rohy tlačítka) nebude při změně měřítka objektu zobrazení protažen nebo stlačen. Obdélníky horního a dolního středu změní měřítko horizontálně, ale nikoliv vertikálně, zatímco obdélníky v levém a pravém středu změní měřítko vertikálně, ale nikoliv horizontálně. Středový obdélník změní měřítko jak horizontálně, tak vertikálně. Pokud si při vytváření objektu zobrazení přejete, aby určitý objekt nikdy měřítko nezměnil, musíte se ujistit, zda jsou dělicí čáry mřížky měřítka s 9 řezy umístěny tak, že obsah bude nakonec umístěn v jednom z rohových obdélníků. V jazyce ActionScript se nastavení hodnoty pro vlastnost objektu zobrazení scale9Grid zapne pro daný objekt změnu měřítka s 9 řezy a určí velikost obdélníků v mřížce změny měřítka objektu. Instanci třídy Rectangle použijete jako hodnotu pro vlastnost scale9Grid následovně: myButton.scale9Grid = new Rectangle(32, 27, 71, 64); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 294 Programování zobrazení Čtyři parametry konstruktoru obdélníku jsou souřadnice x, y, šířka a výška. V tomto případě je horní levý roh obdélníku na objektu zobrazení pojmenovaném myButton umístěn v bodě x: 32, y: 27. Obdélník je 71 obr. bodů široký a 64 obr. bodů vysoký (takže je jeho pravá hrana na souřadnici x 103 na objektu zobrazení a jeho spodní hrana je na souřadnici y 92 na objektu zobrazení). Vlastní oblast obsažená v oblasti definované instancí Rectangle představuje středový obdélník mřížky. Ostatní obdélníky jsou vypočítány přehrávačem Flash Player a AIR prodloužením velikostí instance Rectangle, jak je uvedeno zde: V tomto případě se při zvětšení nebo zmenšení měřítka zaoblené rohy nenatáhnou nebo nestlačí, ale jiné oblasti budou upraveny tak, aby se přizpůsobily změně měřítka. A B C A. myButton.width = 131;myButton.height = 106; B. myButton.width = 73;myButton.height = 69; C. myButton.width = 54;myButton.height = 141; Ukládání objektů zobrazení do vyrovnávací paměti Když se velikost vašich návrhů v přehrávači Flash zvětšuje, ať už vytváříte aplikaci nebo složitou skriptovanou animaci, musíte zohlednit výkon a optimalizaci. Jestliže máte obsah, který zůstává statický (například instance obdélníkového tvaru), přehrávač Flash Player nebo aplikace AIR neoptimalizuje obsah. Proto při změně polohy obdélníku přehrávač Flash Player nebo aplikace AIR překreslí celou instanci tvaru. Do vyrovnávací paměti můžete uložit určité objekty zobrazení a vylepšit tak výkon vašeho souboru SWF. Objekt zobrazení je povrch, v podstatě verze bitmapy vektorových dat instance, což jsou údaje, které nechcete ve svém souboru SWF významně změnit. Proto instance se zapnutým ukládáním do vyrovnávací paměti nejsou při přehrávání souboru SWF kontinuálně překresleny a umožňují tak rychlé vykreslování souboru SWF. Poznámka: Můžete aktualizovat data vektoru, kdy dojde k opětovnému vytvoření povrchu. Proto vektorová data uložená do vyrovnávací paměti na povrchu nemusí zůstat pro celý soubor SWF beze změn. Nastavení vlastnosti cacheAsBitmap objektu zobrazení na hodnotu true (pravda) vyvolá uložení reprezentace bitmapy objektu zobrazení do vyrovnávací paměti. Aplikace Flash Player nebo aplikace AIR vytvoří pro danou instanci objekt povrchu, kterým je bitmapa uložená do mezipaměti, nikoliv vektorová data. Jestliže změníte ohraničení objektu zobrazení, povrch bude znovu vytvořen a nebude pouze změněna jeho velikost. Povrchy se mohou vnořit do jiných povrchů. podřízený povrch zkopíruje své bitmapy na svůj nadřazený povrch. Více informací naleznete v části „Aktivace ukládání bitmapy do vyrovnávací paměti“ na stránce 296. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 295 Programování zobrazení Vlastnost třídy DisplayObject opaqueBackground a vlastnost scrollRect se vztahují k uložení bitmapy do vyrovnávací paměti pomocí vlastnosti cacheAsBitmap. Ačkoliv jsou tyto tři vlastnosti navzájem nezávislé, vlastnosti opaqueBackground a scrollRect nejlépe fungují, když je objekt uložen do vyrovnávací paměti jako bitmapa výhody ve výkonu pro vlastnosti opaqueBackground a scrollRect uvidíte pouze tehdy, jestliže nastavíte cacheAsBitmap na hodnotu true (pravda). Více informací o procházení obsahu objektu zobrazení naleznete v části „Stranový posun a posouvání objekty zobrazení“ na stránce 290. Více informací o nastavení neprůhledného pozadí naleznete v části „Nastavení neprůhledné barvy pozadí“ na stránce 296. Informace ohledně maskování alfa kanálu, která vyžaduje nastavení vlastnosti cacheAsBitmap na hodnotu true (pravda) naleznete v části „Maskování objektů zobrazení“ na stránce 301. Kdy povolit ukládání do vyrovnávací paměti Zapnutím ukládání do vyrovnávací paměti u objektu zobrazení se vytvoří povrch, který má několik výhod, například pomáhá rychle vykreslovat složité vektorové animace. Existuje několik scénářů, ve kterých je třeba aktivovat ukládání do vyrovnávací paměti. Může se zdát, že si ukládání do vyrovnávací paměti vždy budete přát aktivovat pro zlepšení výkonu svých SWF souborů; nicméně existují situace, kdy aktivace ukládání do vyrovnávací paměti výkon nezlepší, nebo jej dokonce zhorší. Tato část popisuje scénáře, ve který by mělo být ukládání do vyrovnávací paměti použito a ty, kdy je třeba použít běžné objekty zobrazení. Celkový výkon dat uložených do vyrovnávací paměti závisí na tom, jak složitá jsou vektorová data vašich instancí, kolik dat měníte a zda jste nastavili vlastnost opaqueBackground. Pokud měníte malé oblasti, rozdíl mezi použitím povrchu a použitím vektorových dat může být zanedbatelný. Před otevřením aplikace si můžete přát otestovat oba scénáře při práci. Kdy použít ukládání bitmap do vyrovnávací paměti Následující příklady jsou typické scénáře, v nichž můžete vidět významné výhody zapnutí ukládání bitmap do vyrovnávací paměti. • Složitý obraz pozadí: Aplikace, která obsahuje detailní a složitý obraz pozadí s vektorovými daty (například obraz, kde jste použili příkaz sledování bitmapy nebo kresba, kterou jste vytvořili v aplikaci Adobe Illustrator®). Můžete animovat znaky přes pozadí, což animaci zpomalí, protože pozadí potřebuje neustále obnovovat vektorová data. Pro vylepšení výkonu můžete nastavit vlastnost opaqueBackground pozadí objektu zobrazení na true (pravda). Pozadí se rendruje jako bitmapa a je možné je rychle překreslit, takže se vaše animace přehrává rychleji. • Rolovací textové pole: Aplikace, která zobrazuje velké množství textu v rolovacím textovém poli. Textové pole můžete vložit do objektu zobrazení, který pomocí vazeb procházení nastavíte k procházení (vlastnost scrollRect). To umožňuje rychlé procházení obrazovými body určené instance. Když uživatel roluje instanci objektu zobrazení, přehrávač Flash Player nebo aplikace AIR přesune rolované obrazové body nahoru a generují nově odkrytou oblast místo nového generování celého textového pole. • Systém oken: Aplikace se složitým systémem překrývajících se oken. Každé okno může být otevřené nebo zavřené (například okna webového prohlížeče). Pokud označíte každé okno jako povrch (nastavíte vlastnost cacheAsBitmap na hodnotu true (pravda), každé okno je izolované a ukládá se do vyrovnávací paměti. Uživatelé mohou přetahovat okna tak, aby se vzájemně překrývala a každé okno nemusí znovu generovat vektorový obsah. • Maskování alfa kanálu: Při používání maskování alfa kanálu musíte nastavit vlastnost cacheAsBitmap na hodnotu true (pravda). Pro více informací viz „Maskování objektů zobrazení“ na stránce 301. Aktivace ukládání bitmapy do vyrovnávací paměti ve všech těchto scénářích vylepšuje reakce a interakce aplikace optimalizací vektorové grafiky. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 296 Programování zobrazení Dále kdykoliv použijete filtr na objekt zobrazení, cacheAsBitmap je automaticky nastavena na možnost true (pravda), i když ji výslovně nastavíte na false (nepravda). Jestliže z objektu zobrazení vymažete všechny filtry, vlastnost cacheAsBitmap se vrátí na hodnotu, na kterou byla naposledy nastavena. Kdy se vyvarovat ukládání bitmap do vyrovnávací paměti Špatné použití této funkce by mohlo negativně ovlivnit váš soubor SWF. Jestliže používáte ukládání bitmapy do vyrovnávací paměti, zapamatujte si následující návod: • Nepoužívejte povrchy nadměrně (objekty zobrazení se zapnutým ukládáním do vyrovnávací paměti). Každý povrch používá více paměti než běžný objekt zobrazení, což znamená, že povrchy byste měli aktivovat pouze tehdy, když potřebujete vylepšit výkon vykreslování. Bitmapa uložená do vyrovnávací paměti může zabírat podstatně více paměti než normální objekt zobrazení. Například instance Sprite na ploše má velikost 250 obr. bodů x 250 obr. bodů, při ukládání do vyrovnávací paměti může použít 250 KB místo 1 KB v případě běžné instance Sprite (neuloženou do vyrovnávací paměti). • Vyvarujte se zvětšování do povrchů uložených do vyrovnávací paměti. Pokud se nadměrně používá ukládání bitmap do vyrovnávací paměti, zabírá to velké množství paměti (viz předchozí bod), zejména pokud zvětšujete obsah. • Pro instance objektu zobrazení používejte povrchy, které jsou převážně statické (bez animace). Instanci můžete přetahovat nebo přesouvat, ale obsah instance by se neměl příliš animovat nebo měnit. (Animace nebo změna obsahu je pravděpodobnější s instancí MovieClip obsahující animaci nebo instanci Videa.) Pokud například instanci otáčíte nebo transformujete, instance se mění mezi povrchem a vektorovými daty, což se obtížně zpracovává a negativně to ovlivňuje soubor SWF. • Pokud mísíte povrchy s vektorovými daty, zvyšuje se objem zpracování, které Flash Player a AIR (a někdy počítač) musí provádět. Seskupujte povrchy co nejvíce je to možné - například při vytváření aplikací dělení obrazovky. Aktivace ukládání bitmapy do vyrovnávací paměti Pro zapnutí ukládání bitmap do vyrovnávací paměti nastavte její vlastnost cacheAsBitmap na hodnotu true (pravda): mySprite.cacheAsBitmap = true; Po nastavení vlastnosti cacheAsBitmap na hodnotu true (pravda) si můžete všimnout, že se objekt zobrazení automaticky roztáhne přes všechny souřadnice. Při testování souboru SWF byste měli zaznamenat, že se jakákoliv animace na složitém vektorovém obrazu rendruje rychleji. Povrch (bitmapa uložená do vyrovnávací paměti) není vytvořen, i když je cacheAsBitmap nastavena na hodnotu true (pravda), dojde-li k následujícímu: • Bitmapa je větší než 2880 obrazových bodů na výšku nebo na šířku. • Nezdařilo se přiřazení bitových map (vznik chyby „nedostatek paměti“). Nastavení neprůhledné barvy pozadí Pro objekt zobrazení můžete nastavit neprůhledné pozadí. Například jestliže má váš soubor SWF pozadí, které obsahuje složité vektory, můžete nastavit vlastnost opaqueBackground na určitou barvu (obvykle je to stejná barva jako má plocha). Barva je určena jako číslo (běžně šestnáctková hodnota barvy). Pozadí je poté považováno za bitmapu, což pomáhá optimalizovat výkon. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 297 Programování zobrazení Nastavíte-li vlastnost cacheAsBitmap na hodnotu true (pravda), a vlastnost opaqueBackground na určitou barvu, vlastnost opaqueBackground umožní neprůhlednost a rychlejší vykreslování interní bitmapy. Jestliže vlastnost cacheAsBitmap nenastavíte na hodnotu true (pravda), vlastnost opaqueBackground přidá neprůhledný tvar s čtvercovým vektorem k pozadí objektu zobrazení. Bitmapa nebude vytvořena automaticky. Následující příklad ukazuje způsob nastavení pozadí objektu zobrazení na optimální výkon: myShape.cacheAsBitmap = true; myShape.opaqueBackground = 0xFF0000; V tomto případě je barva pozadí tvaru pojmenovaná myShape nastavena na červenou (0xFF0000). Za předpokladu, že instance Shape obsahuje kresbu zeleného trojúhelníku na ploše s bílým pozadím, zobrazí se jako zelený trojúhelník s červenou barvou v prázdném prostoru ohraničujícího pole instance Shape (obdélník, který úplně obklopuje tvar). Tento symbol by samozřejmě dával více smysl, pokud by byl použit na ploše s plným červeným pozadím. Na pozadí s jinou barvou bude místo toho vybrána tato barva. Například v souboru SWF s bílým pozadím by byla vlastnost opaqueBackground nejpravděpodobněji nastavena na 0xFFFFFF, nebo na čistě bílou. Použití režimů prolnutí Režimy prolnutí zahrnují kombinaci barev jednoho obrazu (základního obrazu) s barvami jiného obrazu (obraz prolínání) pro vytvoření třetího obrazu - výsledný obraz je ten, který je skutečně zobrazen na obrazovce. Každá hodnota obr. bodu v obrazu je zpracována s odpovídající hodnotou obr. bodu druhého obrazu pro vytvoření hodnoty obr. bodu pro stejnou pozici ve výsledku. Každý objekt zobrazení má vlastnost blendMode, kterou lze nastavit na jeden z následujících režimů prolnutí. Tyto jsou konstanty určené ve třídě BlendMode. Můžete také použít hodnoty String (v kulatých závorkách), které jsou skutečnými hodnotami těchto konstant. • BlendMode.ADD ("add"): Běžně se používá pro vytvoření efektu prolínání animovaného osvětlení mezi dvěma obrazy. • BlendMode.ALPHA ("alpha"): Běžně se používá pro použití průhlednosti popředí na pozadí. • BlendMode.DARKEN ("darken"): Běžně se používá pro typ překrývání. • BlendMode.DIFFERENCE ("difference"): Běžně se používá pro vytvoření více kmitajících barev. • BlendMode.ERASE ("erase"): Běžně se používá pro vystřižení (vymazání) části pozadí pomocí popředí alfa. • BlendMode.HARDLIGHT ("hardlight"): Běžně se používá pro vytvoření efektu tónování. • BlendMode.INVERT ("invert"): Používá se pro obrácení pozadí. • BlendMode.LAYER ("layer"): Používá se k vytvoření přechodného uložení do vyrovnávací paměti pro předsestavení určitého objektu zobrazení. • BlendMode.LIGHTEN ("lighten"): Používá se pro překrytý typ. • BlendMode.MULTIPLY ("multiply"): Běžně se používá pro vytvoření stínů a efektů hloubky. • BlendMode.NORMAL ("normal"): Používá se pro určení, že hodnoty obr. bodů obrazu prolínání potlačí hodnoty výchozího obrazu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 298 Programování zobrazení • BlendMode.OVERLAY ("overlay"): Běžně se používá pro vytvoření efektu tónování. • BlendMode.SCREEN ("screen"): Běžně se používá pro vytvoření zvýraznění a přesvětlení čoček. • BlendMode.SHADER ("shader"): Používá se pro určení, zda je clona Pixel Bender používána pro vytvoření vlastního efektu prolýnání. Více informací o používání clon naleznete v části „Práce s shadery Pixel Bender“ na stránce 376. • BlendMode.SUBTRACT ("subtract"): Běžně se používá pro vytvoření animovaného efektu ztmavení mezi dvěma obrazy. Úprava barev DisplayObject Pro nastavení barvy nebo zobrazení objektu můžete použít metody třídy ColorTransform (flash.geom.ColorTransform). Každý objekt zobrazení má vlastnost transform, která je instancí třídy Transform a obsahuje informace o různých transformacích, které se aplikují na objekty zobrazení (například otočení, změny měřítka nebo polohy, atd.). Vedle této informace o geometrických transformacích zahrnuje třída transformace také vlastnost colorTransform, která je instancí třídy ColorTransform a poskytuje přístup k provádění úprav barev objektů zobrazení. Pro přístup k informaci o transformaci barvy objektu zobrazení můžete použít kód, například: var colorInfo:ColorTransform = myDisplayObject.transform.colorTransform; Po vytvoření instance ColorTransform můžete načíst hodnoty její vlastnosti a zjistíte tak, které transformace barev byly již použity, nebo můžete tyto hodnoty nastavit tak, aby provedly změny barvy objektu zobrazení. Pro aktualizaci objektu zobrazení po změnách musíte znovu přiřadit instanci ColorTransform zpět k vlastnosti transform.colorTransform. var colorInfo:ColorTransform = my DisplayObject.transform.colorTransform; // Make some color transformations here. // Commit the change. myDisplayObject.transform.colorTransform = colorInfo; Nastavení hodnot barvy pomocí kódu Vlastnost color třídy ColorTransform lze použít pro přiřazení specifické hodnoty červené, zelené, modré (RGB) barvy k objektu zobrazení. Následující příklady používají vlastnosti color pro změnu barvy objektu zobrazení pojmenovaného jako square na modrou, jestliže uživatel klepne na tlačítko s názvem blueBtn: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 299 Programování zobrazení // square is a display object on the Stage. // blueBtn, redBtn, greenBtn, and blackBtn are buttons on the Stage. import flash.events.MouseEvent; import flash.geom.ColorTransform; // Get access to the ColorTransform instance associated with square. var colorInfo:ColorTransform = square.transform.colorTransform; // This function is called when blueBtn is clicked. function makeBlue(event:MouseEvent):void { // Set the color of the ColorTransform object. colorInfo.color = 0x003399; // apply the change to the display object square.transform.colorTransform = colorInfo; } blueBtn.addEventListener(MouseEvent.CLICK, makeBlue); Upozorňujeme, že jestliže změníte barvu objektu zobrazení pomocí vlastnosti color, úplně změní barvu celého objektu, bez ohledu na to, zda měl objekt dříve více barev. Jestliže například existuje objekt zobrazení obsahující zelený kruh s černým textem navrchu, nastavením vlastnosti color k danému objektu asociované instance ColorTransform na odstín červené změníte celý objekt, kruh a text na červenou barvu (takže text již nebude odlišitelný od zbytku objektu). Úprava efektů barvy a jasnosti pomocí kódu Předpokládejme, že máte objekt zobrazení s více barvami (například digitální fotografie) a nechcete úplně změnit barvu objektu; přejete si pouze upravit barvu objektu zobrazení na základě stávajících barev. V tomto scénáři zahrnuje třída ColorTransform sérii násobitele a vlastnosti odsazení, které můžete použít k provedení tohoto typu úpravy. Vlastnosti násobitele pojmenované redMultiplier, greenMultiplier, blueMultipliera alphaMultiplier působí jako barevné fotografické filtry (nebo barevné sluneční brýle), které zvětšují nebo zmenšují určité barvy v objektu zobrazení. Vlastnosti odsazení (redOffset, greenOffset, blueOffset a alphaOffset) lze použít pro přidání dalšího množství určité barvy k objektu nebo pro učení minimální hodnoty, kterou určitá barva může mít. Tyto vlastnosti násobitelů a odsazení jsou totožné s dalšími nastaveními barvy, které jsou k dispozici pro symboly filmového klipu v nástroji vytváření přehrávače Flash, zvolíte-li z vyskakovací nabídky Barva v části Inspektor vlastnosti položku Pokročilé. Následující kód načte snímek ve formátu JPEG a použije na něj transformaci barvy, která přizpůsobí červené a zelené kanály při pohybu ukazovátka myši podél os x a y. Vzhledem k tomu, že v tomto případě nejsou určeny žádné hodnoty odsazení, bude hodnota barvy každého barevného kanálu zobrazeného na obrazovce procentem hodnoty původní barvy v obrazu - znamená to, že většina červené nebo zelené barvy zobrazené v daném obrazovém bodu bude původním množstvím červené nebo zelené barvy v daném obrazovém bodu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 300 Programování zobrazení import import import import import flash.display.Loader; flash.events.MouseEvent; flash.geom.Transform; flash.geom.ColorTransform; flash.net.URLRequest; // Load an image onto the Stage. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); loader.load(url); this.addChild(loader); // This function is called when the mouse moves over the loaded image. function adjustColor(event:MouseEvent):void { // Access the ColorTransform object for the Loader (containing the image) var colorTransformer:ColorTransform = loader.transform.colorTransform; // Set the red and green multipliers according to the mouse position. // The red value ranges from 0% (no red) when the cursor is at the left // to 100% red (normal image appearance) when the cursor is at the right. // The same applies to the green channel, except it's controlled by the // position of the mouse in the y axis. colorTransformer.redMultiplier = (loader.mouseX / loader.width) * 1; colorTransformer.greenMultiplier = (loader.mouseY / loader.height) * 1; // Apply the changes to the display object. loader.transform.colorTransform = colorTransformer; } loader.addEventListener(MouseEvent.MOUSE_MOVE, adjustColor); Otáčení objektů Objekty zobrazení lze otáčet pomocí vlastnosti rotation. Tuto hodnotu můžete načíst a zjistit tak, zda bylo objektem otáčeno nebo pro otočení objektem můžete tuto vlastnost nastavit na číslo (ve stupních) představující otočení, které bude na objekt použito. Například tento řádek kódu otočí objektem pojmenovaným square o 45 stupňů (o jednu osminu celé otáčky): square.rotation = 45; Objektem zobrazení můžete také otáčet pomocí matrice transformace, popsané v části „Práce s geometrií“ na stránce 334. Vyblednutí objektů Průhlednost objektu zobrazení můžete ovládat a změnit ji na částečnou (nebo úplnou průhlednost), nebo změnit průhlednost a objekt se pak bude jevit jako postupně ztmavený nebo zesvětlený. Vlastnost třídy DisplayObject alpha definuje průhlednost (nebo přesněji neprůhlednost) objektu zobrazení. Vlastnost alpha lze nastavit na jakoukoliv hodnotu mezi 0 a 1, kde 0 znamená úplně průhledné a 1 je úplně neprůhledné. Například tyto řádky kódu změní objekt pojmenovaný myBall na částečně (50 procent) průhledný, jestliže na něj klepnete myší: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 301 Programování zobrazení function fadeBall(event:MouseEvent):void { myBall.alpha = .5; } myBall.addEventListener(MouseEvent.CLICK, fadeBall); Průhlednost objektu zobrazení můžete také změnit pomocí úprav barvy dostupných skrze třídu ColorTransform. Více informací naleznete v části „Úprava barev DisplayObject“ na stránce 298. Maskování objektů zobrazení Objekt zobrazení můžete použít jako masku a vytvořit tak otvor, skrze který je viditelný obsah jiného objektu zobrazení. Definování masky Pro označení, že objekt zobrazení bude maskou pro jiný objekt zobrazení, nastavte objekt masky jako vlastnost mask objektu zobrazení, který má být maskován: // Make the object maskSprite be a mask for the object mySprite. mySprite.mask = maskSprite; Maskovaný objekt zobrazení je odhalen pod všemi neprůhlednými prostory objektu zobrazení, který se chová jako maska. Například následující kód vytvoří instanci Shape obsahující červený čtverec o velikosti 100 x 100 obrazových bodů a instanci Sprite obsahující modrý kruh s poloměrem 25 obrazových bodů. Jestliže klepnete na kruh, nastaví se jako maska pro čtverec, takže jediná část čtverce, která je zobrazena, je část pokrytá plnou částí kruhu. Jinak řečeno, viditelný bude pouze červený kruh. // This code assumes it's being run within a display object container // such as a MovieClip or Sprite instance. import flash.display.Shape; // Draw a square and add it to the display list. var square:Shape = new Shape(); square.graphics.lineStyle(1, 0x000000); square.graphics.beginFill(0xff0000); square.graphics.drawRect(0, 0, 100, 100); square.graphics.endFill(); this.addChild(square); // Draw a circle and add it to the display list. var circle:Sprite = new Sprite(); circle.graphics.lineStyle(1, 0x000000); circle.graphics.beginFill(0x0000ff); circle.graphics.drawCircle(25, 25, 25); circle.graphics.endFill(); this.addChild(circle); function maskSquare(event:MouseEvent):void { square.mask = circle; circle.removeEventListener(MouseEvent.CLICK, maskSquare); } circle.addEventListener(MouseEvent.CLICK, maskSquare); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 302 Programování zobrazení Objekt zobrazení, který se chová jako maska, lze přetáhnout, animovat, dynamicky změnit jeho velikost a lze používat samostatné tvary v rámci jediné masky. Maskovací objekt zobrazení není třeba přidat na seznam zobrazení. Nicméně pokud si přejete, aby se měřítko objektu masky změnilo se změnou měřítka plochy, nebo pokud si přejete umožnit interakci uživatele s maskou (například uživatelem ovládané tažení a změna velikosti), musíte objekt masky přidat do seznamu zobrazení. Skutečný z-index (pořadí zepředu dozadu) objektu zobrazení není podstatný, jestliže je objekt zobrazení přidán do seznamu zobrazení. (Objekt masky se na obrazovce nezobrazí, s výjimkou funkce masky.) Jestliže je objekt masky instancí s několika obrazy, přehraje všechny obrazy ve své časové ose, stejně jako kdyby nebyl nastaven jako maska. Masku můžete odstranit nastavením vlastnosti mask na null: // remove the mask from mySprite mySprite.mask = null; Nemůžete použít masku pro maskování jiné masky. Nemůžete nastavit vlastnost alpha maskovacího objektu zobrazení. V objektu zobrazení, který je použit jako maska, jsou použity pouze výplně; tahy jsou ignorovány. O maskování písma zařízení Objekt zobrazení můžete použít pro maskování textu, který je nastaven v písmu zařízení. Jestliže používáte objekt zobrazení pro maskování textu nastaveného v písmu zařízení, obdélníkový ohraničující rámeček masky se použije jako maskovací tvar. To znamená, že pokud vytvoříte pro text s písmem zařízení masku objektu zobrazení jiného než obdélníkového tvaru, pak maska, která se objeví v souboru SWF, převezme tvar obdélníkového ohraničovacího rámečku masky, ne tvar samotné masky. Maskování alfa kanálu Maskování alfa kanálu je podporováno, jestliže maska i maskované objekty zobrazení používají ukládání bitmapy do vyrovnávací paměti, jak je ukázáno níže: // maskShape is a Shape instance which includes a gradient fill. mySprite.cacheAsBitmap = true; maskShape.cacheAsBitmap = true; mySprite.mask = maskShape; Například jednou aplikací maskování alfa kanálu je použít filtr na objekt masky nezávisle na filtru, který je použit na maskovaný objekt zobrazení. V následujícím příkladu je externí soubor obrazu načten do plochy. Daný obraz (nebo přesněji, instance Loader, do které je načten) bude objektem zobrazení, který je maskován. Elipsa přechodu (plný černý střed měnící se na okrajích v průhledný) je nakreslena přes snímek; toto bude maska alfa. Oba objekty zobrazení mají zapnuté ukládání bitmapy do vyrovnávací paměti. Elipsa je nastavena jako maska pro snímek a poté ji lze přetáhnout. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 303 Programování zobrazení // This code assumes it's being run within a display object container // such as a MovieClip or Sprite instance. import import import import import flash.display.GradientType; flash.display.Loader; flash.display.Sprite; flash.geom.Matrix; flash.net.URLRequest; // Load an image and add it to the display list. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); loader.load(url); this.addChild(loader); // Create a Sprite. var oval:Sprite = new Sprite(); // Draw a gradient oval. var colors:Array = [0x000000, 0x000000]; var alphas:Array = [1, 0]; var ratios:Array = [0, 255]; var matrix:Matrix = new Matrix(); matrix.createGradientBox(200, 100, 0, -100, -50); oval.graphics.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, matrix); oval.graphics.drawEllipse(-100, -50, 200, 100); oval.graphics.endFill(); // add the Sprite to the display list this.addChild(oval); // Set cacheAsBitmap = true for both display objects. loader.cacheAsBitmap = true; oval.cacheAsBitmap = true; // Set the oval as the mask for the loader (and its child, the loaded image) loader.mask = oval; // Make the oval draggable. oval.startDrag(true); Animace objektů Animace je proces hýbaní nebo také vyvolávání změny. Skriptovaná animace je základní částí videoher a je často používána pro přidání lesku a užitečných bodů interakce jiným aplikacím. Základní myšlenkou skriptované animace je nutnost změny a to, že změna musí být rozdělena do postupných přírůstků. V jazyce ActionScript snadno nastavíte opakování, a to prostřednictvím běžného příkazu smyčky. Nicméně opakování proběhne všemi svými interakcemi před tím, než dojde k aktualizaci zobrazení. Pro vytvoření skriptované animace potřebujete napsat ActionScript, který provede určitou akci opakovaně a také aktualizuje obrazovku při každém jejím spuštění. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 304 Programování zobrazení Představte si například, že si přejete vytvořit jednoduchou animaci, například cestu míče přes obrazovku. Jazyk ActionScript zahrnuje jednoduchý mechanismus, který vám umožňuje vysledovat tok času a příslušně aktualizovat obrazovku - to znamená, že můžete zadat kód, který pohybuje míčem pokaždé o malý kus, dokud nedosáhne cílového místa. Po každém pohybu se aktualizuje obrazovka a pohyb přes plochu bude viditelný. Z praktického hlediska je rozumné synchronizovat skriptovanou animaci s kmitočtem obrazů souboru SWF (jinými slovy – nastavit změnu animace tak, aby proběhla pokaždé při zobrazení nového obrazu), protože definuje, jak často aplikace Flash Player nebo AIR aktualizují obrazovku. Každý objekt zobrazení má událost enterFrame, která je odeslána v souladu s kmitočtem obrazů souboru SWF - jedna událost na snímek. Většina vývojářů, kteří vytvářejí skriptovanou animaci používají událost enterFrame jako způsob vytvoření akcí, které se opakují. Můžete napsat kód, který naslouchá události enterFrame, pohybuje animovaným míčem o určitý kus s každým obrazem a při aktualizaci obrazovky (každého obrazu) je míč znovu nakreslen v nové pozici a vytváří tak pohyb. Poznámka: Dalším způsobem provedení opakované akce je použití třídy Timer. Instance Timer spustí oznámení o události pokaždé, když uplyne určitá doba. Můžete napsat kód, který provede animaci manipulací s časovou událostí třídy Timer a nastavením krátkého časového intervalu (zlomek vteřiny). Více informací o používání třídy Timer naleznete v části „Kontrola časových intervalů“ na stránce 132. V následujícím případě je na ploše vytvořena instance Sprite, pojmenovaná circle. Při klepnutí na kruh je zahájena sekvence skriptované animace a circle vybledne (jeho vlastnost alpha se zmenší), dokud není zcela průhledný: import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; // draw a circle and add it to the display list var circle:Sprite = new Sprite(); circle.graphics.beginFill(0x990000); circle.graphics.drawCircle(50, 50, 50); circle.graphics.endFill(); addChild(circle); // When this animation starts, this function is called every frame. // The change made by this function (updated to the screen every // frame) is what causes the animation to occur. function fadeCircle(event:Event):void { circle.alpha -= .05; if (circle.alpha <= 0) { circle.removeEventListener(Event.ENTER_FRAME, fadeCircle); } } function startAnimation(event:MouseEvent):void { circle.addEventListener(Event.ENTER_FRAME, fadeCircle); } circle.addEventListener(MouseEvent.CLICK, startAnimation); Klepne-li uživatel na kruh, funkce fadeCircle() je připsána jako poslouchač události enterFrame, což znamená, že bude vyvolána jednou na snímek. Tato funkce zesvětlí circle změnou jeho vlastnosti alpha, takže jednou za snímek se hodnota kruhu alpha sníží o 0,05 (5 procent) a obrazovka se aktualizuje. Jestliže je hodnota alpha 0 (circle je zcela průhledný), funkce fadeCircle() je odstraněna jako poslouchač události a ukončí tak animaci. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 305 Programování zobrazení Stejný kód lze například použít pro vytvoření animovaného pohybu místo vyblednutí. Nahrazením jiné vlastnosti za vlastnost alpha ve funkci, která je poslouchačem události enterFrame dojde k animaci dané vlastnosti. Například změna tohoto řádku circle.alpha -= .05; na tento kód circle.x += 5; provede animaci vlastnosti xa kruh se tím přesune napravo od plochy. Podmínka, která ukončí animaci může být změněna pro ukončení animace (tj. odepsání poslouchače enterFrame) v případě, že bylo dosaženo požadované souřadnice x. Dynamické načtení obsahu zobrazení Jakýkoliv z následujících externích datových zdrojů zobrazení můžete načíst do jazyka ActionScript 3.0: • Soubor SWF vytvořený v jazyce ActionScript 3.0 - Tento soubor může být třídou Sprite, MovieClip nebo jakoukoliv třídou, která rozšiřuje třídu Sprite. • Soubor s obrazem - zahrnuje soubory JPG, PNG a GIF. • Soubor AVM1 SWF - jedná se o soubor SWF zapsaný v jazyce ActionScript 1.0 nebo 2.0. Tyto datové zdroje můžete načíst pomocí třídy Loader. Načtení objektů zobrazení Objekty Loader jsou používány pro načtení souborů SWF a souborů grafiky do aplikace. Třída Loader je podtřídou třídy DisplayObjectContainer. Objekt Loader může ve svém seznamu zobrazení obsahovat pouze jeden podřízený objekt - objekt zobrazení reprezentující SWF nebo grafický soubor, který načítá. Přidáte-li objekt Loader k seznamu zobrazení, jako v následujícím kódu, přidáváte také načtený podřízený objekt zobrazení k seznamu zobrazení, jakmile se nahraje: var pictLdr:Loader = new Loader(); var pictURL:String = "banana.jpg" var pictURLReq:URLRequest = new URLRequest(pictURL); pictLdr.load(pictURLReq); this.addChild(pictLdr); Jakmile je soubor SWF nebo snímek načten, můžete přesunout načtený objekt do jiné schránky objektu zobrazení, jako je container objektu DisplayObjectContainer v tomto příkladě: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 306 Programování zobrazení import flash.display.*; import flash.net.URLRequest; import flash.events.Event; var container:Sprite = new Sprite(); addChild(container); var pictLdr:Loader = new Loader(); var pictURL:String = "banana.jpg" var pictURLReq:URLRequest = new URLRequest(pictURL); pictLdr.load(pictURLReq); pictLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoaded); function imgLoaded(event:Event):void { container.addChild(pictLdr.content); } Monitorování průběhu načítání Jakmile začne nahrávání souboru, vytvoří se objekt LoaderInfo. Objekt LoaderInfo poskytuje informace jako postup načítání, adresu URL načítajícího objektu a načítaného obsahu, celkový počet bytů média a jmenovitou výšku a šířku média. Objekt LoaderInfo také odesílá události pro monitorování průběhu načítání. Následující diagram ukazuje rozdílné použití objektu LoaderInfo - pro instanci hlavní třídy souboru SWF, pro objekt Loader a pro objekt načtený objektem Loader: Vymezená plocha Objekt LoaderInfo Vlastnost loaderInfo Instance hlavní třídy souboru SWF Objekt LoaderInfo Vlastnost contentLoaderInfo Objekt LoaderInfo obsah Vlastnost loaderInfo Objekt LoaderInfo je dostupný jako vlastnost objektu Loader i vlastnost načteného objektu zobrazení. Jakmile začne načítání, je objekt LoaderInfo dostupný prostřednictvím vlastnosti contentLoaderInfo objektu Loader. Jakmile objekt zobrazení dokončil načítání, objekt LoaderInfo je dostupný jako vlastnost načteného objektu zobrazení prostřednictvím vlastnosti objektu zobrazení loaderInfo. Vlastnost loaderInfo načteného objektu zobrazení se vztahuje ke stejnému objektu LoaderInfo jako vlastnost contentLoaderInfo objektu Loader. Jinými slovy objekt LoaderInfo je sdílen mezi souborem načteného objektu a objektem Loader, který jej načetl. Pro přístup k vlastnostem načteného obsahu přidejte poslouchač události do objektu LoaderInfo, jako v následujícím kódu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 307 Programování zobrazení import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; var ldr:Loader = new Loader(); var urlReq:URLRequest = new URLRequest("Circle.swf"); ldr.load(urlReq); ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded); addChild(ldr); function loaded(event:Event):void { var content:Sprite = event.target.content; content.scaleX = 2; } Další informace viz „Zpracování událostí“ na stránce 243. Určení kontextu načítání Při načítání externího souboru do přehrávače Flash Player nebo aplikace AIR pomocí metody load() nebo loadBytes() třídy Loader, můžete také určit parametr context. Tento parametr je objektem LoaderContext. Třída LoaderContext zahrnuje tři vlastnosti, které vám umožňují definovat kontext způsobu použití načteného obsahu. • checkPolicyFile: Tuto vlastnost použijte pouze při načítání souboru obrazu (nikoliv souboru SWF). Jestliže tuto vlastnost nastavíte na true, Loader vyhledá v původním serveru soubor zásad (viz „Ovládací prvky webového místa (soubory zásad)“ na stránce 694). Toto je nezbytné pouze pro obsah pocházející z domén jiných než domén souboru SWF, který obsahuje objekt Loader. Jestliže server udělí doméně Loader povolení, má jazyk ActionScript ze souborů SWF v doméně Loader přístup k údajům v načteném obrazu; jinými slovy pro přístup k údajům v načteném obrazu můžete použít příkaz BitmapData.draw(). Upozorňujeme, že soubor SWF z jiných domén, než z domén objektu Loader, může vyvolat Security.allowDomain() pro povolení určité domény. • securityDomain: Tuto vlastnost používejte pouze při načítání souboru SWF (nikoliv obrazu). Určete ji pro soubor SWF z domény jiné než domény souboru obsahujícího objekt Loader. Jestliže určíte tuto volbu, zkontroluje přehrávač Flash Player existenci souboru postupů a jestliže existuje, soubory SWF z domén povolených v souboru křížových postupů mohou skriptovat načtený obsah SWF. Jako tento parametr můžete určit flash.system.SecurityDomain.currentDomain. • applicationDomain: Tuto vlastnost používejte pouze v případě, že načítáte soubor SWF napsaný v jazyku 3.0 (nikoliv obraz nebo soubor SWF napsaný v jazyce ActionScript 1.0 nebo ActionScript 2.0). Při načítání souboru můžete stanovit, aby byl daný soubor zahrnut do stejné domény aplikace, jako je doména objektu Loader, a to nastavením parametru applicationDomain na flash.system.ApplicationDomain.currentDomain. Umístění načteného souboru SWF do stejné aplikační domény zajistí přímý přístup k jeho třídám. To může být užitečné v případě, že načítáte soubor SWF, který obsahuje vložená média, ke kterým máte přístup pomocí názvů jejich přidružených tříd. Více informací naleznete v části „Použití třídy ApplicationDomain“ na stránce 641. Zde je příklad vyhledání souboru zásad při načítání bitmapy z jiné domény: var context:LoaderContext = new LoaderContext(); context.checkPolicyFile = true; var urlReq:URLRequest = new URLRequest("http://www.[your_domain_here].com/photo11.jpg"); var ldr:Loader = new Loader(); ldr.load(urlReq, context); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 308 Programování zobrazení Zde je příklad vyhledání souboru zásad při načítání souboru SWF z jiné domény, pro umístění souboru do stejné bezpečnostní schránky jako v případě objektu Loader. Kód dále přidá třídy v načteném souboru SWF do stejné domény aplikace, jako v případě objektu Loader: var context:LoaderContext = new LoaderContext(); context.securityDomain = SecurityDomain.currentDomain; context.applicationDomain = ApplicationDomain.currentDomain; var urlReq:URLRequest = new URLRequest("http://www.[your_domain_here].com/library.swf"); var ldr:Loader = new Loader(); ldr.load(urlReq, context); Pro více informací viz popis třídy LoaderContext v Referenční příručce jazyka ActionScript 3.0 a jeho komponent. Příklad: SpriteArranger Vzorová aplikace SpriteArranger je založena na vzorové aplikaci geometrických tvarů, která je popsána zvlášť (viz „Příklad: GeometricShapes“ na stránce 121). Vzorová aplikace SpriteArranger uvádí několik konceptů pro práci s objekty zobrazení: • Rozšíření tříd objektů zobrazení • Přidávání objektů zobrazení k seznamu zobrazení • Vrstvení objektů zobrazení a práce s kontejnery objektů zobrazení • Odezvy na události objektů zobrazení • Používání vlastností a metod objektů zobrazení Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace SpriteArranger naleznete ve složce Examples/SpriteArranger. Aplikace sestává z následujících souborů: Soubor Popis SpriteArranger.mxml Hlavní soubor aplikace v programu Flash (FLA) nebo Flex (MXML). nebo SpriteArranger.fla com/example/programmingas3/SpriteArranger/CircleSprite.as Třída definující typ objektu Sprite, který rendruje kruh na obrazovce. com/example/programmingas3/SpriteArranger/DrawingCanvas.as Třída definující plátna, což je kontejner objektu zobrazení, který obsahuje objekty GeometricSprite. com/example/programmingas3/SpriteArranger/SquareSprite.as Třída definující typ objektu Sprite, který rendruje čtverec na obrazovce. com/example/programmingas3/SpriteArranger/TriangleSprite.as Třída definující typ objektu Sprite, který rendruje trojúhelník na obrazovce. com/example/programmingas3/SpriteArranger/GeometricSprite.as Třída, která rozšiřuje objekt Sprite, používaná pro určení tvaru na obrazovce. CircleSprite, SquareSprite a TriangleSprite rozšiřují tuto třídu. com/example/programmingas3/geometricshapes/IGeometricShape.as Metody definující základní rozhraní, které budou použity všemi třídami geometrických tvarů. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 309 Programování zobrazení Soubor Popis com/example/programmingas3/geometricshapes/IPolygon.as Metody definující základní rozhraní, které budou použity třídami geometrických tvarů, které mají více stran. com/example/programmingas3/geometricshapes/RegularPolygon.as Typ geometrického tvaru, který má stejně dlouhé strany, umístěné symetricky okolo středu tvaru. com/example/programmingas3/geometricshapes/Circle.as Typ geometrického tvaru, který definuje kruh. com/example/programmingas3/geometricshapes/EquilateralTriangle.as Podtřída RegularPolygon, která definuje trojúhelník, jehož strany mají stejné délky. com/example/programmingas3/geometricshapes/Square.as Podtřída RegularPolygon definující obdélník, jehož všechny strany jsou stejně dlouhé. com/example/programmingas3/geometricshapes/GeometricShapeFactory.as Třída obsahující „metodu závodu“ pro vytvoření tvarů se stanoveným typem a velikostí. Definice tříd SpriteArranger Aplikace SpriteArranger umožňuje uživateli přidávat různé objekty zobrazení k „plátnům“ na obrazovce. Třída DrawingCanvas definuje prostor pro kreslení, typ kontejneru objektů zobrazení, do kterého může uživatel přidávat tvary na obrazovce. Tyto tvary na obrazovce jsou instancemi jedné z podtříd třídy GeometricSprite. Třída DrawingCanvas Třída DrawingCanvas rozšiřuje třídu Sprite a tato dědičnost je definována v popisu třídy DrawingCanvas následovně: public class DrawingCanvas extends Sprite Třída Sprite je podtřídou tříd DisplayObjectContainer a DisplayObject a třída DrawingCanvas používá metody a vlastnosti těchto tříd. Metoda konstruktoru DrawingCanvas() nastaví obdélníkový objekt bounds, což je vlastnost, která se později používá v kreslení obrysu plátna. Poté vyvolá metodu initCanvas() následovně: this.bounds = new Rectangle(0, 0, w, h); initCanvas(fillColor, lineColor); Jak ukazuje následující příklad, metoda initCanvas() definuje různé vlastnosti objektu DrawingCanvas, které byly přidány jako argumenty k funkci konstruktoru: this.lineColor = lineColor; this.fillColor = fillColor; this.width = 500; this.height = 200; Metoda initCanvas() poté vyvolá metodu drawBounds(), které nakreslí plátna pomocí vlastnosti graphics třídy DrawingCanvas. Vlastnost graphics je zděděna ze třídy Shape. this.graphics.clear(); this.graphics.lineStyle(1.0, this.lineColor, 1.0); this.graphics.beginFill(this.fillColor, 1.0); this.graphics.drawRect(bounds.left - 1, bounds.top - 1, bounds.width + 2, bounds.height + 2); this.graphics.endFill(); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 310 Programování zobrazení Následující dodatečné metody třídy DrawingCanvas jsou vyvolány na základě interakcí uživatele a aplikace: • Metody addShape() a describeChildren(), které jsou popsány v části „Přidávání objektů zobrazení k plátnům“ na stránce 310 • Metody moveToBack(), moveDown(), moveToFront() a moveUp(), které jsou popsány v části „Nové uspořádání rozmístění objektů zobrazení“ na stránce 313 • Metoda onMouseUp(), která je popsána v části „Klepnutí na objekty zobrazení a jejich tažení“ na stránce 312 Třída GeometricSprite a její podtřídy Každý objekt zobrazení, který uživatel může přidat do plátna, je instancí následujících podtříd třídy GeometricSprite: • CircleSprite • SquareSprite • TriangleSprite Třída GeometricSprite rozšiřuje třídu flash.display.Sprite: public class GeometricSprite extends Sprite Třída GeometricSprite zahrnuje několik vlastností, které jsou společné pro všechny objekty GeometricSprite. Tyto vlastnosti jsou nastaveny ve funkci konstruktoru, na základě parametrů přiřazených dané funkci. Například: this.size = size; this.lineColor = lColor; this.fillColor = fColor; Vlastnost geometricShape třídy GeometricSprite definuje rozhraní IGeometricShape, které definuje matematické vlastnosti, ale nikoliv vizuální vlastnosti tvaru. Třídy, které implementují rozhraní IGeometricShape jsou definovány ve vzorové aplikaci GeometricShapes (viz. „Příklad: GeometricShapes“ na stránce 121). Třída GeometricSprite definuje metodu drawShape(), která je dále znovu definována v potlačených definicích v každé podtřídě GeometricSprite. Více informací naleznete v následující části „Přidávání objektů zobrazení k plátnům“. Třída GeometricSprite také nabízí následující metody: • Metody onMouseDown() a onMouseUp(), které jsou popsány v části „Klepnutí na objekty zobrazení a jejich tažení“ na stránce 312 • Metody showSelected() a hideSelected(), které jsou popsány v části „Klepnutí na objekty zobrazení a jejich tažení“ na stránce 312 Přidávání objektů zobrazení k plátnům Jestliže uživatel klepne na tlačítko Přidat tvar, aplikace vyvolá metodu addShape() třídy DrawingCanvas. Tato metoda zkonkretizuje novou třídu GeometricSprite vyvoláním příslušné funkce konstruktoru z jedné z podtříd GeometricSprite, dle následujícího příkladu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 311 Programování zobrazení public function addShape(shapeName:String, len:Number):void { var newShape:GeometricSprite; switch (shapeName) { case "Triangle": newShape = new TriangleSprite(len); break; case "Square": newShape = new SquareSprite(len); break; case "Circle": newShape = new CircleSprite(len); break; } newShape.alpha = 0.8; this.addChild(newShape); } Každá metoda konstruktoru vyvolá metodu drawShape(), která používá vlastnost graphics dané třídy (zděděnou ze třídy Sprite) pro nakreslení příslušné vektorové grafiky. Například metoda drawShape() třídy CircleSprite obsahuje následující kód: this.graphics.clear(); this.graphics.lineStyle(1.0, this.lineColor, 1.0); this.graphics.beginFill(this.fillColor, 1.0); var radius:Number = this.size / 2; this.graphics.drawCircle(radius, radius, radius); Druhý až poslední řádek funkce addShape() nastaví hodnotu vlastnosti alpha objektu zobrazení (zděděnou z třídy DisplayObject), takže každý objekt zobrazení přidaný do plátna je lehce průhledný a uživatel tak může vidět objekty za ním. Poslední řádek metody addChild() přidá nový objekt zobrazení na podřízený seznam instance třídy DrawingCanvas, která je již na seznamu zobrazení. Tím se nový objekt zobrazení objeví na ploše. Rozhraní pro aplikaci zahrnuje dvě textová pole, selectedSpriteTxt a outputTxt. Vlastnosti textu těchto dvou textových polích jsou aktualizovány informací o objektech GeometricSprite, které byly přidány na plátno nebo zvoleny uživatelem. Třída GeometricSprite zachází s touto úlohou hlášení informací potlačením metody toString(), a to následovně: public override function toString():String { return this.shapeType + " of size " + this.size + " at " + this.x + ", " + this.y; } Vlastnost shapeType je nastavena na příslušnou hodnotu v metodě konstruktoru každé podtřídy GeometricSprite. Například metoda toString() může vrátit následující hodnotu pro instanci CircleSprite nedávno přidanou k instanci DrawingCanvas: Circle of size 50 at 0, 0 Metoda describeChildren() třídy DrawingCanvas se opakuje v podřízeném seznamu plátna a pomocí vlastnosti numChildren (zděděné z třídy DisplayObjectContainer) nastaví limit opakování for cyklu. Vytvoří řetězec uvádějící každý podřízený prvek, a to následovně: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 312 Programování zobrazení var desc:String = ""; var child:DisplayObject; for (var i:int=0; i < this.numChildren; i++) { child = this.getChildAt(i); desc += i + ": " + child + '\n'; } Výsledný řetězec se používá k nastavení vlastnosti text textového pole outputTxt. Klepnutí na objekty zobrazení a jejich tažení Když uživatel klepne na instanci GeometricSprite, aplikace vyvolá obsluhu události onMouseDown(). Jak je uvedeno níže, tato obsluha události je nastavena na poslouchání událostí „myš dolů“ ve funkci konstruktoru třídy GeometricSprite: this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); Metoda onMouseDown() poté vyvolá metodu showSelected() objektu GeometricSprite. Jestliže byla v tomto případě tato metoda pro objekt vyvolána poprvé, metoda vytvoří nový objekt Shape s názvem selectionIndicator a použije jej jako vlastnost graphic objektu Shape pro nakreslení červeně zvýrazněného obdélníku, a to následovně: this.selectionIndicator = new Shape(); this.selectionIndicator.graphics.lineStyle(1.0, 0xFF0000, 1.0); this.selectionIndicator.graphics.drawRect(-1, -1, this.size + 1, this.size + 1); this.addChild(this.selectionIndicator); Jestliže se nejedná o první vyvolání metody onMouseDown(), metoda jednoduše nastaví vlastnost visibletvaru selectionIndicator (zděděnou z třídy DisplayObject) následovně: this.selectionIndicator.visible = true; Metoda hideSelected() skryje tvar selectionIndicator předešle zvoleného objektu nastavením jeho vlastnosti visible na hodnotu false (nepravda). Metoda obsluhy události onMouseDown() také vyvolá metodu startDrag() (zděděnou ze třídy Sprite), která obsahuje následující kód: var boundsRect:Rectangle = this.parent.getRect(this.parent); boundsRect.width -= this.size; boundsRect.height -= this.size; this.startDrag(false, boundsRect); To umožní uživateli přetáhnout vybraný objekt kolem plátna, uvnitř hranic stanovených obdélníkem boundsRect. Když uživatel uvolní tlačítko myši, událost mouseUp bude odeslána. Metoda konstruktoru DrawingCanvas nastaví následující poslouchač události: this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); Tento poslouchač události je nastaven pro objekt DrawingCanvas, spíše než pro jednotlivé objekty GeometricSprite. Důvodem je to, že při tažení objektu GeometricSprite může být objekt při uvolnění myši umístěn za jiný objekt zobrazení (jiný objekt GeometricSprite). Objekt zobrazení v popředí obdrží událost uvolnění myši, ale objekt zobrazení tažený uživatelem nikoliv. Přidání poslouchače k objektu DrawingCanvas zajistí, že událost bude vždy zpracována. Metoda onMouseUp() vyvolá metodu onMouseUp() objektu GeometricSprite, která zase vyvolá metodu stopDrag() objektu GeometricSprite. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 313 Programování zobrazení Nové uspořádání rozmístění objektů zobrazení Uživatelské rozhraní aplikace obsahuje tlačítka označená Pohyb zpět, Pohyb dolů, Pohyb nahoru a Pohyb vpřed. Jestliže uživatel klepne na jedno z těchto tlačítek, aplikace vyvolá odpovídající metodu třídy DrawingCanvas: moveToBack(), moveDown(), moveUp() nebo moveToFront(). Například metoda moveToBack() obsahuje následující kód: public function moveToBack(shape:GeometricSprite):void { var index:int = this.getChildIndex(shape); if (index > 0) { this.setChildIndex(shape, 0); } } Metoda používá metodu setChildIndex() (zděděnou ze třídy DisplayObjectContainer) pro umístění objektu zobrazení na indexovou polohu 0 v podřízeném souboru instance DrawingCanvas (this). Metoda moveDown() funguje podobně, s výjimkou, že snižuje indexovou pozici objektu zobrazení v podřízeném seznamu instance DrawingCanvas o 1: public function moveDown(shape:GeometricSprite):void { var index:int = this.getChildIndex(shape); if (index > 0) { this.setChildIndex(shape, index - 1); } } Metody moveUp() a moveToFront() pracují podobně jako metody moveToBack() a moveDown(). 314 Kapitola 14: Používání kreslicího rozhraní API I když jsou importované obrazy a kresby důležité, funkce známé jako kreslicí rozhraní API, které umožňuje kreslit čáry a tvary v jazyku ActionScript, poskytuje svobodu v možnosti zahájit aplikaci v počítačovém ekvivalentu čistého plátna, na kterém můžete vytvořit jakýkoliv obraz. Schopnost vytvářet vlastní grafiku otevírá pro vaši aplikaci široké možnosti. S technikami probranými v této kapitole můžete vytvořit kreslicí program, vytvářet animovanou, interaktivní grafiku nebo programově vytvářet své vlastní elementy uživatelského rozhraní a jiné. Základy použití kreslicího rozhraní API Úvod k používání kreslicího rozhraní API Kreslicí rozhraní API je název pro funkci zabudovanou do jazyka ActionScript, která vám umožňuje vyvářet vektorovou grafiku—rovné čáry, křivky, tvary, výplň a přechody—a zobrazí je na obrazovce pomocí jazyka ActionScript. Třída flash.display.Graphics tuto funkci poskytuje. S jazykem ActionScript můžete vykreslit jakoukoliv instanci Shape, Sprite nebo MovieClip pomocí vlastnosti graphics definované v každé z těchto tříd. (Každá z vlastností těchto tříd graphics je vlastně instancí třídy Graphics.) Jestliže s kreslením svého kódu teprve začínáte, zahrnuje třída Graphics několik metod usnadňujících kreslení běžných tvarů, např. kruhů, elips, obdélníků a obdélníků se zaoblenými rohy. Tyto tvary můžete kreslit jako prázdné čáry nebo plné tvary. Jestliže potřebujete více pokročilé funkce, třída Graphics také zahrnuje metody pro kreslení čar a kvadratických Bézierových křivek, které lze použít ve spojení s trigonometrickými funkcemi ve třídě Math pro vytvoření jakýchkoliv tvarů. Přehrávač Flash Player 10 a aplikace Adobe AIR 1.5 přidávají dodatečná rozhraní API pro kreslení, která vám umožňují programaticky kreslit celé tvary pomocí jediného příkazu. Jakmile se seznámíte s třídou Graphics a úlohami uvedenými v tématu „Základy používání kreslicích rozhraní API“, pokračujte s částí „Pokročilé použití kreslicího rozhraní API“ na stránce 326 pro více informací o funkcích těchto kreslicích rozhraní API. Běžné úlohy kreslicího rozhraní API Následující úlohy budete pravděpodobně chtít provést pomocí kreslicích rozhraní API v jazyce ActionScript, která jsou popsána v této kapitole: • Definování stylů čar a výplní pro kreslení tvarů • Kreslení rovných čar a křivek • Používání metod pro kreslení tvarů, například kruhů, elips a obdélníků • Kreslení čar s přechodem a výplní • Definice matrice pro vytvoření přechodu • Používání trigonometrie s kreslicími rozhraními API • Začlenění kreslicího rozhraní API do animace PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 315 Používání kreslicího rozhraní API Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Kotevní bod: jeden ze dvou koncových bodů kvadratické Bézierovy křivky. • Řídicí bod: bod definující směr a množství křivky kvadratické Bézierovy křivky. Zakřivená čára nikdy nedosáhne řídicího bodu; čára se nicméně zakřiví, jako by byla tažena směrem k řídicímu bodu. • Souřadnicový prostor: graf se souřadnicemi obsažený v objektu zobrazení, na který jsou umísťovány podřízené elementy. • Výplň: plná vnitřní část tvaru, která má čáru vyplněnou barvou nebo celý tvar bez obrysu. • Přechod: barva složená z postupného přechodu z jedné barvy na jinou nebo více barev (oproti plné barvě). • Bod: jednotlivé umístění v souřadnicovém prostoru. V soustavě souřadnic 2-d používané v jazyku ActionScript, je bod definován svým umístěním podél osy x a osy y (souřadnicemi bodu). • Kvadratická Bézierova křivka: typ křivky definované určitým matematickým vzorcem. U tohoto typu křivky je tvar křivky vypočten na pozicích kotevních bodů (koncový bod dané křivky) a řídicího bodu, který definuje množství a směr dané křivky. • Měřítko: velikost určitého objektu vzhledem k jeho původní velikosti. Nastavení měřítka, resp. velikosti určitého objektu znamená změnu jeho velikosti zvětšením, resp. zmenšením daného objektu. • Tah: část obrysu tvaru, který má čáru vyplněnou barvou nebo čáry nevyplněného tvaru. • Posunutí: změna souřadnic určitého bodu z jednoho souřadnicového prostoru na jiný. • Osa x: vodorovná osa ve dvojrozměrné soustavě souřadnic používané v jazyku ActionScript. • Osa y: svislá osa ve dvojrozměrné soustavě souřadnic používané v jazyku ActionScript. Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. Protože se tato kapitola věnuje kreslení vizuálního obsahu, testování kódu zahrnuje spuštění kódu a zobrazení výsledků v souboru SWF, který je vytvořen. Postup testování uvedených příkladů kódu: 1 Vytvořte prázdný dokument Flash. 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Spusťte program pomocí příkazu Ovládání > Testovat film. Výsledky kódu budou zobrazeny v souboru SWF, který je vytvořen. Vysvětlení třídy Graphics Každý objekt Shape, Sprite a MovieClip má vlastnost graphics, která je instancí třídy Graphics. Třída Graphics zahrnuje vlastnosti a metody pro kreslení čar, výplní a tvarů. Chcete-li využívat objekt zobrazení pouze jako plátno pro obsah kreslení, můžete použít instanci Shape. Instance Shape bude pro kreslení fungovat lépe než jiné objekty zobrazení, protože nemá nadbytečné funkce ve třídách Sprite a MovieClip. Chcete-li objekt zobrazení, na který můžete kreslit grafický obsah a současně chcete, aby tento objekt obsahoval jiné objekty zobrazení, můžete použít instanci Sprite. Další informace k rozhodnutí, jaký objekt zobrazení použít pro různé úlohy, viz „Výběr podtřídy DisplayObject“ na stránce 284. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 316 Používání kreslicího rozhraní API Kreslení čar a křivek Všechny kresby prováděné s instancí Graphics jsou založeny na základním kreslení čar a křivek. V důsledku toho musí být všechny kresby v jazyku ActionScript prováděny podle stejného postupu: • Definování stylů čáry a výplně • Nastavení počáteční polohy kresby • Kreslení čar, křivek a tvarů (volitelně přesouvání kreslicího bodu) • Zakončení vytvořením výplně v případě potřeby Definování stylů čáry a výplně Chcete-li kreslit pomocí vlastnosti graphics, instance Shape, Sprite nebo MovieClip, musíte nejprve definovat styl (velikost a barvu čáry, barvu výplně), který se při kreslení použije. Stejně jako při použití kreslicích nástrojů v aplikaci Adobe® Flash® CS4 Professional nebo jiné kreslicí aplikaci můžete při použití jazyka ActionScript kreslit s tahem nebo bez a s barvou výplně nebo bez. Vzhled tahu určíte pomocí metody lineStyle() nebo lineGradientStyle(). Chcete-li vytvořit plnou čáru, použijte metodu lineStyle(). Při volání této metody budete nejčastěji zadávat první tři parametry: tloušťku čáry, barvu a hodnotu alfa. Například tento řádek kódu sdělí instanci Shape s názvem myShape, aby kreslila čáry 2 obr. body tlusté, červené (0x990000) a ze 75 % průhledné: myShape.graphics.lineStyle(2, 0x990000, .75); Výchozí hodnota parametru alfa je 1,0 (100 %), takže chcete-li, aby byla čára zcela neprůhledná, můžete tento parametr nechat vypnutý. Metoda lineStyle() přijímá také dva další parametry pro hintování obr. bodů a režim měřítka. Další informace o používání těchto parametrů najdete v popisu metody Graphics.lineStyle() v Referenční příručce jazyka ActionScript 3.0 a jeho součástí. Chcete-li vytvořit čáru přechodu, použijte metodu lineGradientStyle(). Tato metoda je popsána v části „Vytváření čar a výplní přechodu“ na stránce 319. Chcete-li vytvořit vyplněný tvar, vyvolejte před započetím kreslení metodu beginFill(), beginGradientFill(), beginBitmapFill() nebo beginShaderFill(). Nejzákladnější metoda z nich, beginFill(), přijímá dva parametry: barvu výplně a (volitelně) hodnotu alfa pro barvu výplně. Chcete-li například nakreslit tvar s plnou zelenou výplní, měli byste použít následující kód (za předpokladu, že kreslíte na objekt s názvem myShape): myShape.graphics.beginFill(0x00FF00); Vyvolání jakékoli metody výplně implicitně ukončí případnou předchozí výplň, než se začne vytvářet nová. Volání libovolné metody, která určuje styl tahu, nahradí předchozí tah, ale nezmění dříve určenou výplň a naopak. Jakmile jste určili styl čáry a vlastnosti výplně, další krok je určit počáteční bod kresby. Instance Graphics má kreslicí bod, jako hrot pera na kousku papíru. Příští akce kreslení začne právě v místě umístění kreslicího bodu. Na začátku začne objekt Graphics s kreslicím bodem v bodě 0, 0 v souřadnicovém prostoru objektu, na který kreslíte. Chcete-li začít kreslit v jiném bodě, můžete před vyvoláním některé z kreslicích metod vyvolat nejprve metodu moveTo(). To je stejné jako zvednutí hrotu pera z papíru a přesunutí na novou pozici. S kreslicím bodem na místě kreslíte pomocí série volání kreslicích metod lineTo() (pro kreslení rovných čar) a curveTo() (pro kreslení zakřivených čar). Během kreslení můžete kdykoli vyvolat metodu moveTo() pro přesunutí kreslicího bodu na novou pozici bez kreslení. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 317 Používání kreslicího rozhraní API Jestliže jste určili barvu výplně, můžete během kreslení sdělit aplikaci Flash Player nebo Adobe® AIR™, aby vyvoláním metody endfill() ukončila výplň. Jestliže jste nenakreslili uzavřený tvar (jinými slovy, jestliže v době, kdy voláte metodu endFill(), není kreslicí bod v počátečním bodu tvaru), když voláte metodu endFill(), aplikace Flash Player nebo AIR automaticky uzavře tvar nakreslením rovné čáry od aktuálního kreslicího bodu k místu určenému při posledním volání metody moveTo(). Jestliže jste zahájili výplň a nevyvolali jste metodu endFill(), uzavře volání metody beginFill() (nebo některé z ostatních metod výplně) aktuální výplň a zahájí novou. Kreslení rovných čar Když vyvoláte metodu lineTo(), objekt Graphics nakreslí rovnou čáru od aktuálního kreslicího bodu po souřadnice, které určíte jako dva parametry při volání metody, přičemž použije styl čáry, který jste určili. Například následující řádek kódu nastaví kreslicí bod do bodu 100, 100 a poté nakreslí čáru do bodu 200, 200: myShape.graphics.moveTo(100, 100); myShape.graphics.lineTo(200, 200); V následujícím příkladu se nakreslí červené a zelené trojúhelníky o výšce 100 obr. bodů: var triangleHeight:uint = 100; var triangle:Shape = new Shape(); // red triangle, starting at point 0, 0 triangle.graphics.beginFill(0xFF0000); triangle.graphics.moveTo(triangleHeight / 2, 0); triangle.graphics.lineTo(triangleHeight, triangleHeight); triangle.graphics.lineTo(0, triangleHeight); triangle.graphics.lineTo(triangleHeight / 2, 0); // green triangle, starting at point 200, 0 triangle.graphics.beginFill(0x00FF00); triangle.graphics.moveTo(200 + triangleHeight / 2, 0); triangle.graphics.lineTo(200 + triangleHeight, triangleHeight); triangle.graphics.lineTo(200, triangleHeight); triangle.graphics.lineTo(200 + triangleHeight / 2, 0); this.addChild(triangle); Kreslení křivek Metoda curveTo() nakreslí kvadratickou Beziérovu křivku. Tento kód nakreslí oblouk, který spojuje dva body (nazývané kotvící body), přičemž se bude ohýbat směrem ke třetímu bodu (nazývanému ovládací bod). Objekt Graphics použije jako první kotvící bod aktuální kreslicí pozici. Při volání metody curveTo() předáváte čtyři parametry: souřadnice x a y ovládacího bodu, následované souřadnicemi x a y druhého kotvícího bodu. Například následující kód nakreslí křivku začínající v bodě 100, 100 a končící v bodě 200, 200. Protože ovládací bod je v bodě 175, 125, vytvoří se křivka, která je nakloněná doprava a potom směrem dolů: myShape.graphics.moveTo(100, 100); myShape.graphics.curveTo(175, 125, 200, 200); V následujícím příkladu se nakreslí červené a zelené kružnice o šířce a výšce 100 obr. bodů. Všimněte si, že kvůli povaze kvadratické Bézierovy rovnice to nejsou dokonalé kružnice: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 318 Používání kreslicího rozhraní API var size:uint = 100; var roundObject:Shape = new Shape(); // red circular shape roundObject.graphics.beginFill(0xFF0000); roundObject.graphics.moveTo(size / 2, 0); roundObject.graphics.curveTo(size, 0, size, size / 2); roundObject.graphics.curveTo(size, size, size / 2, size); roundObject.graphics.curveTo(0, size, 0, size / 2); roundObject.graphics.curveTo(0, 0, size / 2, 0); // green circular shape roundObject.graphics.beginFill(0x00FF00); roundObject.graphics.moveTo(200 + size / 2, 0); roundObject.graphics.curveTo(200 + size, 0, 200 + size, size / 2); roundObject.graphics.curveTo(200 + size, size, 200 + size / 2, size); roundObject.graphics.curveTo(200, size, 200, size / 2); roundObject.graphics.curveTo(200, 0, 200 + size / 2, 0); this.addChild(roundObject); Kreslení tvarů pomocí vestavěných metod Pro pohodlné kreslení obecných tvarů, jako kruhů, elips, obdélníků a obdélníků se zaoblenými rohy jsou v jazyku ActionScript 3.0 metody, které tyto běžné tvary nakreslí za vás. Jsou to metody drawCircle(), drawEllipse(), drawRect(), drawRoundRect() a drawRoundRectComplex() z třídy Graphics. Tyto metody můžete použít místo metod lineTo() a curveTo(). Všimněte si však, že i přesto musíte před voláním těchto metod určit styl čáry a výplně. V následujícím příkladu jsou znovu vytvořeny červené, zelené a modré čtverce o šířce a výšce 100 obr. bodů. Tento kód použije metodu drawRect() a navíc určí, že barva výplně bude mít hodnotu alfa 50 % (0,5): var squareSize:uint = 100; var square:Shape = new Shape(); square.graphics.beginFill(0xFF0000, 0.5); square.graphics.drawRect(0, 0, squareSize, squareSize); square.graphics.beginFill(0x00FF00, 0.5); square.graphics.drawRect(200, 0, squareSize, squareSize); square.graphics.beginFill(0x0000FF, 0.5); square.graphics.drawRect(400, 0, squareSize, squareSize); square.graphics.endFill(); this.addChild(square); V objektu Sprite nebo MovieClip se obsah kreslení vytvořený pomocí vlastnosti graphics vždy objeví za všemi podřízenými objekty zobrazení, které daný objekt obsahuje. Obsah vlastnosti graphics také není nezávislý objekt zobrazení, takže se neobjevuje v seznamu potomků objektu Sprite nebo MovieClip. Například následující objekt Sprite má kruh nakreslený pomocí své vlastnosti graphics a ve svém seznamu podřízených objektů zobrazení má objekt TextField: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 319 Používání kreslicího rozhraní API var mySprite:Sprite = new Sprite(); mySprite.graphics.beginFill(0xFFCC00); mySprite.graphics.drawCircle(30, 30, 30); var label:TextField = new TextField(); label.width = 200; label.text = "They call me mellow yellow..."; label.x = 20; label.y = 20; mySprite.addChild(label); this.addChild(mySprite); Všimněte si, že objekt TextField se objeví nad kruhem nakresleným pomocí objektu grafiky. Vytváření čar a výplní přechodu Grafický objekt může kreslit také tahy a výplně s přechody místo plných barev. Tah přechodu vytvoříte pomocí metody lineGradientStyle() a výplň přechodu pomocí metody beginGradientFill(). Obě metody přijímají stejné parametry. První čtyři parametry jsou vyžadované: typ, barvy, hodnoty alfa a poměry. Zbývající čtyři jsou volitelné, ale užitečné pro pokročilé přizpůsobení. • První parametr určuje typ přechodu, který chcete vytvořit. Přijatelné hodnoty jsou GradientFill.LINEAR nebo GradientFill.RADIAL. • Druhý parametr určuje pole hodnot barev, které budou použity. U lineárního přechodu budou barvy uspořádány zleva doprava. U radiálního přechodu budou uspořádány zevnitř ven. Pořadí barev pole představuje pořadí, ve kterém budou barvy v přechodu malovány. • Třetí parametr určuje hodnoty průhlednosti alfa odpovídajících barev v předchozím parametru. • Čtvrtý parametr určuje poměry neboli zvýraznění jednotlivých barev v rámci přechodu. Přípustné hodnoty jsou v rozsahu od 0 do 255. Tyto hodnoty nepředstavují šířku ani výšku, ale polohu v rámci přechodu: 0 představuje počátek přechodu, 255 představuje konec přechodu. Pole poměrů musí narůstat spojitě a musí mít stejný počet zadání jako pole barev i hodnot alfa určená ve druhém a třetím parametru. I když pátý parametr, matice transformace, je volitelný, je často používaný, protože poskytuje snadný a účinný způsob ovládání vzhledu přechodu. Tento parametr přijímá instanci Matrix. Nejjednodušší způsob vytvoření objektu Matrix pro přechod je použít metodu createGradientBox() třídy Matrix. Definování objektu Matrix pro použití s přechodem Metody beginGradientFill() a lineGradientStyle() z třídy flash.display.Graphics slouží k definování přechodů pro použití u tvarů. Když definujete přechod, dodáte matici jako jeden z parametrů těchto metod. Nejjednodušší způsob definování matice je pomocí metody createGradientBox() třídy Matrix, která vytvoří matici používanou k definování přechodu. Pomocí parametrů předaných metodě createGradientBox() definujete měřítko, natočení a polohu přechodu. Metoda createGradientBox() přijímá následující parametry: • Šířka pole přechodu: šířka (v obr. bodech), přes kterou bude přechod roztažen • Výška pole přechodu: výška (v obr. bodech), přes kterou bude přechod roztažen • Natočení pole přechodu: natočení (v radiánech), které bude aplikováno na přechod • Vodorovný posun: jak rychle (v obr. bodech) bude přechod vodorovně posouván • Svislý posun: jak rychle (v obr. bodech) bude přechod svisle posouván PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 320 Používání kreslicího rozhraní API Například uvažujte přechod s následujícími charakteristickými rysy: • GradientType.LINEAR • Dvě barvy, zelená a modrá s polem ratios nastaveným na [0, • SpreadMethod.PAD • InterpolationMethod.LINEAR_RGB 255] Následující příklady ukazují přechody, u kterých se parametr rotation metody createGradientBox() liší, jak je naznačeno, ale všechna ostatní nastavení zůstávají stejná: width = 100; height = 100; rotation = 0; tx = 0; ty = 0; width = 100; height = 100; rotation = Math.PI/4; // 45° tx = 0; ty = 0; width = 100; height = 100; rotation = Math.PI/2; // 90° tx = 0; ty = 0; Příklady: zobrazit efekt lineárního přechodu ze zelené na modrou, kde se rotation, tx a ty parametry z metody createGradientBox() liší jak je uvedeno, ale všechna ostatní nastavení zůstávají stejná: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 321 Používání kreslicího rozhraní API width = 50; height = 100; rotation = 0; tx = 0; ty = 0; width = 50; height = 100; rotation = 0 tx = 50; ty = 0; width = 100; height = 50; rotation = Math.PI/2; // 90° tx = 0; ty = 0; width = 100; height = 50; rotation = Math.PI/2; // 90° tx = 0; ty = 50; Parametry width, height, tx a ty metody createGradientBox() ovlivňují také velikost a polohu radiální výplně přechodu, jak ukazuje následující příklad: width = 50; height = 100; rotation = 0; tx = 25; ty = 0; Následující kód vytvoří poslední znázorněný radiální přechod: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 322 Používání kreslicího rozhraní API import flash.display.Shape; import flash.display.GradientType; import flash.geom.Matrix; var var var var var var var type:String = GradientType.RADIAL; colors:Array = [0x00FF00, 0x000088]; alphas:Array = [1, 1]; ratios:Array = [0, 255]; spreadMethod:String = SpreadMethod.PAD; interp:String = InterpolationMethod.LINEAR_RGB; focalPtRatio:Number = 0; var matrix:Matrix = new Matrix(); var boxWidth:Number = 50; var boxHeight:Number = 100; var boxRotation:Number = Math.PI/2; // 90° var tx:Number = 25; var ty:Number = 0; matrix.createGradientBox(boxWidth, boxHeight, boxRotation, tx, ty); var square:Shape = new Shape; square.graphics.beginGradientFill(type, colors, alphas, ratios, matrix, spreadMethod, interp, focalPtRatio); square.graphics.drawRect(0, 0, 100, 100); addChild(square); Všimněte si, že šířka a výška výplně přechodu je určena šířkou a výškou matice přechodu a ne šířkou a výškou, která je nakreslena pomocí objektu Graphics. Při kreslení pomocí objektu Graphics nakreslíte to, co existuje na daných souřadnicích v matici přechodu. I když použijete jednu z metod tvaru objektu Graphics, např. drawRect(), přechod se neroztáhne na velikost nakresleného tvaru–velikost přechodu musí být určena v samotné matici přechodu. Následuje znázornění vizuálního rozdílu mezi rozměry matice přechodu a rozměry samotné kresby: var myShape:Shape = new Shape(); var gradientBoxMatrix:Matrix = new Matrix(); gradientBoxMatrix.createGradientBox(100, 40, 0, 0, 0); myShape.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x00FF00, 0x0000FF], [1, 1, 1], [0, 128, 255], gradientBoxMatrix); myShape.graphics.drawRect(0, 0, 50, 40); myShape.graphics.drawRect(0, 50, 100, 40); myShape.graphics.drawRect(0, 100, 150, 40); myShape.graphics.endFill(); this.addChild(myShape); Tento kód nakreslí přechody se stejným stylem výplně, určené stejným rozložením červené, zelené a modré. Přechody se nakreslí pomocí metody drawRect() s šířkami 50, 100, resp. 150 obr. bodů. Matice přechodu, která je určena v metodě beginGradientFill(), je vytvořena s šířkou 100 obr. bodů. To znamená, že první přechod obsáhne pouze polovinu spektra přechodu, druhý obsáhne celé a třetí obsáhne celé spektrum a dalších 50 obr. bodů modré s přesahem doprava. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 323 Používání kreslicího rozhraní API Metoda lineGradientStyle() funguje podobně jako metoda beginGradientFill() s tím rozdílem, že kromě definování přechodu musíte před kreslením určit i tloušťku tahu pomocí metody lineStyle(). Následující kód nakreslí čtverec s červeným, zeleným a modrým tahem přechodu: var myShape:Shape = new Shape(); var gradientBoxMatrix:Matrix = new Matrix(); gradientBoxMatrix.createGradientBox(200, 40, 0, 0, 0); myShape.graphics.lineStyle(5, 0); myShape.graphics.lineGradientStyle(GradientType.LINEAR, [0xFF0000, 0x00FF00, 0x0000FF], [1, 1, 1], [0, 128, 255], gradientBoxMatrix); myShape.graphics.drawRect(0, 0, 200, 40); this.addChild(myShape); Další informace o třídě Matrix najdete v části „Používání objektů Matrix“ na stránce 340. Použití třídy Math s kreslicími metodami Objekt Graphics kreslí kružnice a čtverce, ale může kreslit i složitější tvary, zvláště při použití kreslicích metod v kombinaci s vlastnostmi a metodami třídy Math. Třída Math obsahuje běžné matematické konstanty, např. Math.PI (cca 3,14159265...), konstantu pro poměr obvodu kruhu k jeho průměru. Obsahuje takém metody pro trigonometrické funkce, včetně Math.sin(), Math.cos() a Math.tan() aj. Kreslení tvarů pomocí těchto metod a konstant vytváří dynamičtější vizuální efekty, zvláště při použití s opakováním nebo rekurzí. Mnohé metody třídy Math očekávají kruhové míry v radiánech a ne ve stupních. Převody mezi těmito dvěma typy jednotek patří k běžným využitím třídy Math: var degrees = 121; var radians = degrees * Math.PI / 180; trace(radians) // 2.111848394913139 V následujícím příkladu je vytvořena sinusová vlna a kosinusová vlna pro zvýraznění rozdílu mezi metodami Math.sin() a Math.cos() při dané hodnotě. var var var var var var sinWavePosition = 100; cosWavePosition = 200; sinWaveColor:uint = 0xFF0000; cosWaveColor:uint = 0x00FF00; waveMultiplier:Number = 10; waveStretcher:Number = 5; var i:uint; for(i = 1; i < stage.stageWidth; i++) { var sinPosY:Number = Math.sin(i / waveStretcher) * waveMultiplier; var cosPosY:Number = Math.cos(i / waveStretcher) * waveMultiplier; graphics.beginFill(sinWaveColor); graphics.drawRect(i, sinWavePosition + sinPosY, 2, 2); graphics.beginFill(cosWaveColor); graphics.drawRect(i, cosWavePosition + cosPosY, 2, 2); } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 324 Používání kreslicího rozhraní API Animování s kreslicím rozhraním API Jednou z výhod vytváření obsahu pomocí kreslicího rozhraní API je, že nejste omezeni jedním nastavením pozice obsahu. To, co nakreslíte, můžete změnit údržbou a úpravou proměnných, které používáte při kreslení. Animaci můžete vést změnou proměnných a překreslením, buď v určitém intervalu snímků nebo pomocí časovače. Například následující kód změní zobrazení s každým snímkem (posloucháním události Event.ENTER_FRAME), přičemž zvýší aktuální počet stupňů a předá grafickému objektu instrukci, aby se vymazal a překreslil s aktualizovanou polohou. stage.frameRate = 31; var currentDegrees:Number = 0; var radius:Number = 40; var satelliteRadius:Number = 6; var container:Sprite = new Sprite(); container.x = stage.stageWidth / 2; container.y = stage.stageHeight / 2; addChild(container); var satellite:Shape = new Shape(); container.addChild(satellite); addEventListener(Event.ENTER_FRAME, doEveryFrame); function doEveryFrame(event:Event):void { currentDegrees += 4; var radians:Number = getRadians(currentDegrees); var posX:Number = Math.sin(radians) * radius; var posY:Number = Math.cos(radians) * radius; satellite.graphics.clear(); satellite.graphics.beginFill(0); satellite.graphics.drawCircle(posX, posY, satelliteRadius); } function getRadians(degrees:Number):Number { return degrees * Math.PI / 180; } Chcete-li dostat značně odlišný výsledek, můžete experimentovat se změnou počátečních proměnných na začátku kódu, currentDegrees, radius a satelliteRadius. Zkuste například zmenšit proměnnou radius, popř. zvýšit proměnnou totalSatellites. Toto je pouze jeden příklad toho, jak může kreslicí rozhraní API vytvářet vizuální zobrazení, jehož složitost zakrývá jednoduchost jeho tvorby. Příklad: Algoritmický vizuální generátor Příklad algoritmického vizuálního generátoru dynamicky nakreslí do vymezené plochy několik „satelitů“, neboli kružnic pohybujících se po kruhové oběžné dráze. Mezi zkoumané vlastnosti patří: • Použití kreslicího rozhraní API ke kreslení základních tvarů s dynamickým vzhledem • Spojení interakce s uživatelem s vlastnostmi používanými při kreslení PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 325 Používání kreslicího rozhraní API • Vedení animace vymazáním a překreslením vymezené plochy při každém snímku V příkladu v předchozí podsekci byl animován jediný „satelit“ pomocí události Event.ENTER_FRAME. Tento příklad je toho rozšířením, kdy je vytvořen ovládací panel s řadou posuvníků, které okamžitě aktualizují vizuální zobrazení několika satelitů. V tomto příkladu se kód formalizuje do externích tříd a kód pro vytvoření satelitu se zalomí do smyčky, přičemž se odkazy na jednotlivé satelity uloží do pole satellites. Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Aplikační soubory najdete ve složce Samples/AlgorithmicVisualGenerator. Tato složka obsahuje následující soubory: Soubor Popis AlgorithmicVisualGenerator.fla Hlavní aplikační soubor v programu Flash (FLA). com/example/programmingas3/algorithmic/AlgorithmicVisualGenerator.as Třída, která poskytuje hlavní funkce aplikace, včetně kreslení satelitů do vymezené plochy a reagování na události z ovládacího panelu za účelem aktualizace proměnných, které ovlivňují kreslení satelitů. com/example/programmingas3/algorithmic/ControlPanel.as Třída, která spravuje interakci s uživatelem, s několika posuvníky a odesíláním událostí při jejich výskytu. com/example/programmingas3/algorithmic/Satellite.as Třída, která představuje objekt zobrazení, který se otáčí po oběžné dráze kolem středu a obsahuje vlastnosti týkající se jeho aktuálního stavu kreslení. Nastavení posluchačů Aplikace vytvoří nejprve tři posluchače. První poslouchá událost odeslanou z ovládacího panelu oznamující nutnost nového vytvoření satelitů. Druhý poslouchá změny velikosti vymezené plochy souboru SWF. Třetí poslouchá přecházení jednotlivých snímků v souboru SWF za účelem překreslení pomocí funkce doEveryFrame(). Vytvoření satelitů Jakmile jsou zmíněné posluchače nastaveny, bude vyvolána funkce build(). Tato funkce nejprve vyvolá funkci clear(), která vyprázdní pole satellites a vymaže všechny dosavadní kresby ve vymezené ploše. To je nutné, protože funkce build() by mohla být znovu vyvolána vždy, když ovládací panel pošle nějakou událost, např. když dojde ke změně nastavení barev. V takovém případě je třeba satelity odstranit a vytvořit znovu. Daná funkce pak vytvoří satelity, přičemž nastaví počáteční vlastnosti potřebné pro vytvoření, např. proměnnou position, která začíná na náhodné pozici na oběžné dráze, a proměnnou color, která se v tomto příkladu po vytvoření satelitu nemění. Jakmile je každý satelit vytvořen, do pole satellites je na něj přidán odkaz. Jakmile bude vyvolána funkce doEveryFrame(), aktualizuje se na všechny satelity v tomto poli. Aktualizace polohy satelitu Funkce doEveryFrame() je jádrem animačního procesu aplikace. Je vyvolávána pro každý snímek, rychlostí rovnající se rychlosti snímků souboru SWF. Protože proměnné kreslení se mírně liší, určuje to vzhled animace. Uvedená funkce nejprve vymaže všechny dosavadní kresby a znovu nakreslí pozadí. Dále bude cyklicky procházet kontejner každého satelitu a zvyšovat jeho vlastnost position a aktualizuje vlastnosti radius a orbitRadius, které se mohly díky interakci uživatele s ovládacím panelem změnit. Nakonec satelit aktualizuje vyvoláním metody draw() třídy Satellite na svou novou polohu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 326 Používání kreslicího rozhraní API Všimněte si, že počitadlo i se zvyšuje pouze do hodnoty proměnné visibleSatellites. To je z toho důvodu, že kdyby uživatel prostřednictvím ovládacího panelu omezil množství zobrazených satelitů, zbývající satelity ve smyčce by se neměly překreslovat, ale měly by být skryté. To se vyskytuje ve smyčce, která následuje ihned po smyčce odpovědné za kreslení. Jakmile je funkce doEveryFrame() dokončena, počet viditelných satelitů, visibleSatellites, na obrazovce se aktualizuje. Reagování na interakci s uživatelem Interakce s uživatelem je realizována prostřednictvím ovládacího panelu, který je spravován třídou ControlPanel. Tato třída nastaví posluchač spolu s individuálním minimem, maximem a výchozími hodnotami jednotlivých posuvníků. Když uživatel těmito posuvníky pohne, vyvolá se funkce changeSetting(). Tato funkce aktualizuje vlastnosti ovládacího panelu. Jestliže změna vyžaduje nové vytvoření zobrazení, je odeslána událost, která je následně zpracována v hlavním aplikačním souboru. Po změně nastavení ovládacího panelu nakreslí funkce doEveryFrame() jednotlivé satelity s aktualizovanými proměnnými. Další přizpůsobení Tento příklad je pouze základním schématem způsobu generování vizuálních objektů pomocí kreslicího rozhraní API. Pomocí relativně pár řádků kódu je v něm vytvořen interaktivní zážitek, který vypadá poměrně složitě. Přesto by tento kód mohl být s menšími změnami rozšířen. Pár nápadů: • Funkce doEveryFrame() by mohla zvyšovat hodnotu barvy satelitu. • Funkce doEveryFrame() by mohla zmenšovat nebo zvětšovat poloměr satelitu v závislosti na času. • Poloměr satelitu nemusí být kruhový. Mohl by se měnit pomocí třídy Math např. na sinusovou vlnu. • Satelity by mohly reagovat na dotyk s jinými satelity. Kreslicí rozhraní API je možno použít jako alternativu pro vytváření vizuálních efektů ve vývojovém prostředí Flash ke kreslení základních tvarů při běhu. Může však také sloužit k vytváření vizuálních efektů takové rozmanitosti a rozsahu, jakých při ručním kreslení nelze dosáhnout. Pomocí kreslicího rozhraní API a trochy matematiky může autor kódu ActionScript zplodit mnoho neočekávaných výtvorů. Pokročilé použití kreslicího rozhraní API Úvod k používání pokročilého kreslicího rozhraní API Verze Flash Player 10 a Adobe AIR 1.5 zavádí podporu pokročilé sady kreslících funkcí. Vylepšení kreslícího rozhraní API rozšiřují kreslicí metody z předchozích verzí, takže můžete zavést množiny dat pro vygenerování tvarů, měnit tvary za běhu i vytvářet trojrozměrné efekty. Vylepšení kreslícího rozhraní API slučují stávající metody do alternativních příkazů. Tyto příkazy využívají vektorová pole a třídy výčtu k poskytování množin dat pro metody kreslení. Používání vektorových polí vám umožňuje rychlejší vykreslování složitějších tvarů a vývojáři tak mohou programaticky změnit hodnoty pole pro vykreslování dynamického tvaru v době běhu. Funkce kreslení zavedené v přehrávači Flash Player 10 jsou popsány v následujících tématech: „Cesty kreslení“ na stránce 327, „Definování pravidel vinutí“ na stránce 329, „Používání tříd grafických dat“ na stránce 330, a „O použití metody drawTriangles()“ na stránce 333. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 327 Používání kreslicího rozhraní API Běžné úlohy pokročilého kreslicího rozhraní API Následující úlohy jsou věci, které budete pravděpodobně chtít pomocí pokročilých kreslicích rozhraní API v jazyce ActionScript zrealizovat: • Použití vektorových objektů k ukládání dat pro metody kreslení • Definování cest pro programatické kreslení tvarů • Pravidla vinutí pro určení výplně překrývajících se tvarů • Používání tříd grafických dat • Použití trojúhelníků a metod kreslení pro 3D efekty Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této části: • Vektor: pole hodnot se stejným datovým typem. Objekt Vector může uchovávat pole hodnot, které metody kreslení používají ke konstrukci čar a tvarů pomocí jediného příkazu. Více informací o objektech Vector naleznete v tématu „Indexovaná pole“ na stránce 154. • Cesta: cesta je tvořena jedním nebo více přímými nebo zakřivenými segmenty. Začátek a konec každého segmentu jsou označeny souřadnicemi, které fungují jako špendlíky, držící na místě drát. Cesta může být buď uzavřená (například kružnice), nebo otevřená, to znamená se zřetelnými koncovými body (například vlnovka). • Vinutí: směr cesty dle interpretace autora, buď kladný (po směru hodinových ručiček) nebo záporný (proti směru hodinových ručiček). • GraphicsStroke: třída pro nastavení stylu čáry. I když termín „tah“ (anglicky „stroke“) není součástí vylepšení kreslícího rozhraní API, použití třídy určené k navržení stylu čáru s vlastní vlastností výplně je součástí tohoto vylepšení. Styl čáry můžete dynamicky upravit pomocí třídy GraphicsStroke. • Objekt výplně: objekty vytvořené pomocí tříd zobrazení, např. flash.display.GraphicsBitmapFill a flash.display.GraphicsGradientFill, které jsou předány kreslicímu příkazu Graphics.drawGraphicsData(). Objekty výplně a vylepšené příkazy kreslení zavádějí programovací přístup více orientovaný na objekt pro replikaci Graphics.beginBitmapFill() a Graphics.beginGradientFill(). Cesty kreslení Část o kreslení čar a křivek (viz „Kreslení čar a křivek“ na stránce 316) uvedla příkazy k vytvoření tvaru kreslením jediné čáry (Graphics.lineTo()) nebo křivky (Graphics.curveTo()) a následným přesunutím čáry do jiného bodu (Graphics.moveTo()). Přehrávač Flash Player 10 a aplikace Adobe AIR 1.5 zavádí podporu pro vylepšení kreslicího rozhraní API jazyka ActionScript, např. Graphics.drawPath()a Graphics.drawTriangles(), která využívají stávající kreslicí příkazy a parametry. Série příkazů Graphics.lineTo(), Graphics.curveTo() nebo Graphics.moveTo() jsou tak spuštěny v jediném příkazu. Dvě z těchto vylepšení kreslicího rozhraní API umožňují slučovat stávající příkazy pomocí metod Graphics.drawPath() a Graphics.drawTriangles(): • Třída výčtu GraphicsPathCommand: třída GraphicsPathCommand spojí několik kreslicích příkazů s konstantními hodnotami. Série těchto hodnot můžete použít jako parametry pro metodu Graphics.drawPath(). Poté můžete pomocí jediného příkazu vykreslit celý tvar nebo několik tvarů. Můžete také dynamicky změnit hodnoty předané k těmto metodám a změnit tak již existující tvar. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 328 Používání kreslicího rozhraní API • Vektorová pole: vektorová pole obsahují hodnoty specifického datového typu. Proto ukládáte sérii konstant GraphicsPathCommand do objektu Vector a sérii souřadnic do jiného objektu Vector. Graphics.drawPath() nebo Graphics.drawTriangles() přiřadí tyto hodnoty společně a vytvoří cestu kreslení nebo tvar. Již nepotřebujete oddělené příkazy pro každý segment tvaru. Například metoda Graphics.drawPath() sloučí Graphics.moveTo(), Graphics.lineTo() a Graphics.curveTo() do jediné metody. Namísto toho, aby byly metody volány samostatně, jsou abstraktně vytvořeny do numerických identifikátorů, dle definice ve třídě GraphicsPathCommand. Operace moveTo() je označena 1, zatímco operace lineTo() je označena 2. Pole těchto hodnot uložte do objektu Vector.<int> a použijte jej v parametru commands. Poté vytvořte další pole obsahující souřadnice v objektu Vector.<Number> pro parametr data. Každá hodnota GraphicsPathCommand odpovídá hodnotám souřadnic uložených v datovém parametru, kde dvě po sobě jdoucí čísla definují umístění v cílovém prostoru souřadnic. Poznámka: Hodnoty ve vektoru nejsou objekty Point; vektor je řada čísel, kde každá skupina dvou čísel představuje dvojici souřadnic x/y. Metoda Graphics.drawPath() přiřadí ke každému příkazu jeho příslušné hodnoty bodů (soubor dvou nebo čtyř čísel) pro vytvoření cesty v objektu Graphics: package{ import flash.display.*; public class DrawPathExample extends Sprite { public function DrawPathExample(){ var square_commands:Vector.<int> = new Vector.<int>(5,true); square_commands[0] = 1;//moveTo square_commands[1] = 2;//lineTo square_commands[2] = 2; square_commands[3] = 2; square_commands[4] = 2; var square_coord:Vector.<Number> = new Vector.<Number>(10,true); square_coord[0] = 20; //x square_coord[1] = 10; //y square_coord[2] = 50; square_coord[3] = 10; square_coord[4] = 50; square_coord[5] = 40; square_coord[6] = 20; square_coord[7] = 40; square_coord[8] = 20; square_coord[9] = 10; graphics.beginFill(0x442266);//set the color graphics.drawPath(square_commands, square_coord); } } } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 329 Používání kreslicího rozhraní API Definování pravidel vinutí Verze Flash Player 10 a Adobe AIR 1.5 zavádí také koncept „vinutí“ (směru) cesty. Vinutí cesty je buď kladné (po směru hodinových ručiček) nebo záporné (proti směru hodinových ručiček). Pořadí, ve kterém vykreslování udává souřadnice poskytnuté vektorem pro daný datový parametr, určuje vinutí. A 0 1 0 3 3 2 1 2 B C Kladné a záporné vinutí A. Šipky udávají směr kreslení B. Kladné vinutí (po směru hodinových ručiček) C. Záporné vinutí (proti směru hodinových ručiček) Dále si všimněte, že metoda Graphics.drawPath() má volitelný třetí parametr nazvaný „vinutí“: drawPath(commands:Vector.<int>, data:Vector.<Number>, winding:String = "evenOdd"):void V tomto kontextu je třetí parametr řetězec nebo konstanta, která určuje vinutí nebo pravidlo výplně pro protínající se cesty. (Hodnoty konstanty jsou definovány ve třídě GraphicsPathWinding jako GraphicsPathWinding.EVEN_ODD nebo GraphicsPathWinding.NON_ZERO.) Pravidlo vinutí je důležité při protnutí cest. Pravidlo lichý-sudý je standardním pravidlem vinutí a je používáno všemi staršími kreslicími rozhraními API. Pravidlo lichý-sudý je také výchozím pravidlem pro metodu Graphics.drawPath(). V případě pravidla lichý-sudý jsou jakékoliv protnuté cesty střídavě otevřené a vyplněné. Pokud se protnou dva čtverce se stejnou výplní, oblast průniku se vyplní. Obecně nejsou obě oblasti ani vyplněny ani nevyplněny. Na druhou stranu nenulové pravidlo závisí na vinutí (směru kreslení) pro určení, zda budou oblasti definované protínajícími se cestami vyplněny. Pokud se protnou cesty s opačným vinutím, budou definovány jako nevyplněné, stejně jako v případě pravidla lichý-sudý. U cest se stejným vinutím bude vyplněna oblast, která by jinak zůstala bez výplně: A B Pravidla vinutí pro protínající se oblasti A. Pravidlo vinutí lichý-sudý B. Nenulové pravidlo vinutí PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 330 Používání kreslicího rozhraní API Názvy pravidel vinutí Názvy se vztahují ke specifičtějšímu pravidlu, které definuje zpracování těchto výplní. Kladně vinutým cestám je přiřazena hodnota +1; záporně vinutým cestám je přiřazena hodnota -1. Z bodu v uzavřené oblasti tvaru nakreslete nekonečnou čáru. Počet průsečíků čáry s cestou a kombinované hodnoty těchto cest jsou použity k určení výplně. Pro vinutí lichý-sudý se použije počet míst, kde čára přetíná cestu. Je-li tento počet lichý, oblast se vyplní. V případě sudého počtu zůstane oblast nevyplněna. U nenulového vinutí jsou použity hodnoty přiřazené k cestám. Jestliže kombinované hodnoty cesty nejsou 0, oblast se vyplní. Jestliže je kombinovaná hodnota 0, oblast zůstane nevyplněna. A B Počty a výplně pravidla vinutí A. Pravidlo vinutí lichý-sudý B. Nenulové pravidlo vinutí Použití pravidel vinutí Tato pravidla vinutí jsou složitá, ale v určitých situacích jsou nezbytná. Zvažte například nakreslení tvaru hvězdy. U standardního pravidla lichý-sudý by daný tvar vyžadoval deset různých čar. U nenulového pravidla vinutí je počet čar snížen na pět. Zde je jazyk ActionScript pro hvězdu s pěti čarami a nenulovým pravidlem vynutí: fill.graphics.beginFill(0x60A0FF);graphics.drawPath( Vector.<int>([1,2,2,2,2]), Vector.<Number>([66,10, 23,127, 122,50, 10,49, 109,127]), GraphicsPathWinding.NON_ZERO); A zde je tvar hvězdy: A B C Tvar hvězdy pomocí různých pravidel vinutí A. Lichý-sudý 10 čar B. Lichý-sudý 5 čar C. Nenulový 5 čar Když jsou obrazy animovány nebo používány na 3D objektech a překrývají se, pravidla vynutí se jsou důležitější. Používání tříd grafických dat Verze Flash Player 10 a Adobe AIR 1.5 zavádí v balíčku flash.display nový soubor tříd, které mají typ IGraphicsData (rozhraní, které každá třída implementuje). Třídy, které implementují rozhraní IGraphicsData, slouží jako datové kontejnery pro metody kreslicích rozhraní API. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 331 Používání kreslicího rozhraní API Následující třídy implementují rozhraní IGraphicsData: • GraphicsBitmapFill • GraphicsEndFill • GraphicsGradientFill • GraphicsPath • GraphicsShaderFill • GraphicsSolidFill • GraphicsStroke • GraphicsTrianglePath Pomocí těchto tříd můžete ukládat kompletní výkresy do pole vektorového objektu typu IGraphicsData. (Vector.<IGraphicsData>), který lze znovu použít jako zdroj dat pro instance jiných tvarů nebo k ukládání informací kreslení pro pozdější použití. Všimněte si, že pro každý styl výplně existuje více tříd výplně, ale pouze jedna třída tahu. Jazyk ActionScript má pouze jednu třídu tahu IGraphicsData, protože daná třída tahu používá třídy výplně k definici svého stylu. Proto je každý tah vlastně třídou tahu a třídou výplně. V opačném případě odrážejí kreslicí rozhraní API pro tyto třídy grafických dat metody, které představují ve třídě flash.display.Graphics: Grafické metody Třída Data beginBitmapFill() GraphicsBitmapFill beginFill() GraphicsSolidFill beginGradientFill() GraphicsGradientFill beginShaderFill() GraphicsShaderFill lineBitmapStyle() GraphicsStroke + GraphicsBitmapFill lineGradientStyle() GraphicsStroke + GraphicsGradientFill lineShaderStyle() GraphicsStroke + GraphicsShaderFill lineStyle() GraphicsStroke + GraphicsSolidFill moveTo() GraphicsPath lineTo() curveTo() drawPath() drawTriangles() GraphicsTrianglePath Dále má třída GraphicsPath svou vlastní metodu utility GraphicsPath.moveTo(), GraphicsPath.lineTo(), GraphicsPath.curveTo(), GraphicsPath.wideLineTo() a GraphicsPath.wideMoveTo() pro snadné definování příkazů pro instanci GraphicsPath. Tyto metody utility také přímo definují nebo aktualizují příkazy a hodnoty dat. Máte-li soubor instancí IGraphicsData, použijte metodu Graphics.drawGraphicsData() k vykreslení grafiky. Metoda Graphics.drawGraphicsData() spustí vektor instancí IGraphicsData pomocí kreslicích rozhraní API v sekvenčním pořadí: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 332 Používání kreslicího rozhraní API // stroke object var stroke:GraphicsStroke = new GraphicsStroke(3); stroke.joints = JointStyle.MITER; stroke.fill = new GraphicsSolidFill(0x102020);// solid stroke // fill object var fill:GraphicsGradientFill = new GraphicsGradientFill(); fill.colors = [0x0000FF, 0xEEFFEE]; fill.matrix = new Matrix(); fill.matrix.createGradientBox(70,70, Math.PI/2); // path object var path:GraphicsPath = new GraphicsPath(new Vector.<int>(), new Vector.<Number>()); path.commands.push(1,2,2); path.data.push(125,0, 50,100, 175,0); // combine objects for complete drawing var drawing:Vector.<IGraphicsData> = new Vector.<IGraphicsData>(); drawing.push(stroke, fill, path); // draw the drawing graphics.drawGraphicsData(drawing); Úpravou jedné hodnoty v cestě použité kreslením v tomto příkladě lze tvar několikrát překreslit a získat tak složitější obraz: // draw the drawing multiple times // change one value to modify each variation graphics.drawGraphicsData(drawing); path.data[2] += 200; graphics.drawGraphicsData(drawing); path.data[2] -= 150; graphics.drawGraphicsData(drawing); path.data[2] += 100; graphics.drawGraphicsData(drawing); path.data[2] -= 50;graphicsS.drawGraphicsData(drawing); Ačkoliv mohou objekty IGraphicsData definovat styly výplně a tahů, nejsou tyto styly vyžadovány. Jinak řečeno, metody třídy Graphics lze použít k nastavení stylů, zatímco objekty IGraphicsData lze použít k nakreslení uloženého souboru cest, či naopak. Poznámka: Pokud nepokračujete v původním výkresu (viz výše uvedený příklad), vyčistěte před zahájením nového výkresu předchozí výkres pomocí metody Graphics.clear(). Při změně jedné části cesty nebo souboru objektů IGraphicsData překreslete celý výkres, aby se zobrazily změny. Při používání tříd grafických dat je výplň vykreslena kdykoliv při nakreslení tří nebo více bodů, protože daný tvar je dědičně v daném bodě uzavřen. Výplň se uzavře, ale tah nikoliv. Toto chování se liší v případě použití více příkazů Graphics.lineTo() nebo Graphics.moveTo(). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 333 Používání kreslicího rozhraní API O použití metody drawTriangles() Další pokročilá metoda zavedená ve verzích Flash Player 10 a Adobe AIR 1.5, Graphics.drawTriangles(), je podobná metodě Graphics.drawPath(). Metoda Graphics.drawTriangles() také používá objekt Vector.<Number> k určení polohy bodů pro nakreslení cesty. Opravdovým účelem metody Graphics.drawTriangles() je nicméně umožnit 3D efekty pomocí jazyka ActionScript. Informace o používání metody Graphics.drawTriangles() k vytvoření 3D efektů naleznete v tématu „Používání trojúhelníků pro 3D efekty“ na stránce 507. 334 Kapitola 15: Práce s geometrií Balíček flash.geom obsahuje třídy, které definují geometrické objekty jako body, obdélníky a matice transformace. Tyto třídy slouží k definování vlastností objektů, které se používají v jiných třídách. Základy geometrie Úvod k práci s geometrií Geometrie je možná předmět, který se mnoho lidí snaží ve škole nějak překlepat a přitom si zapamatovat co nejméně, ale trocha znalostí z geometrie může být v jazyku ActionScript mocným nástrojem. Balíček flash.geom obsahuje třídy, které definují geometrické objekty jako body, obdélníky a matice transformace. Tyto třídy neposkytují nutně funkce samy o sobě. Avšak používají se k definování vlastností objektů, které se používají v jiných třídách. Všechny geometrické třídy jsou založeny na skutečnosti, že každé umístění na obrazovce je reprezentováno jako dvojrozměrná rovina. Obrazovka je nahlížena jako plochý graf s vodorovnou osou (x) a svislou osou (y). Jakékoli umístění (neboli bod) na obrazovce může být představen jako pár hodnot x a y – souřadnice tohoto umístění. Každý objekt zobrazení, včetně vymezené plochy, má vlastní souřadnicový prostor – v podstatě svůj vlastní graf pro vynášení umístění podřízených objektů zobrazení, kreseb atd. Počátek (místo se souřadnicemi 0, 0, kde je průsečík osy x a osy y) je většinou umístěn v levém horním rohu objektu zobrazení. Ačkoli toto vždy platí pro vymezenou plochu, nemusí to nutně platit pro jiný objekt zobrazení. Jako ve standardním dvojrozměrném souřadnicovém prostoru, hodnoty na ose x narůstají směrem doprava a klesají směrem doleva – u umístění vlevo od počátku jsou hodnoty osy x záporné. Avšak narozdíl od tradičních souřadnicových soustav, v jazyku ActionScript hodnoty na ose y na obrazovce narůstají směrem dolů a klesají směrem nahoru (přičemž hodnoty nad počátkem jsou záporné). Protože levý horní roh vymezené plochy je počátek jeho souřadnicového prostoru, každý objekt ve vymezené ploše bude mít souřadnici x větší než 0 a menší než šířka vymezené plochy a souřadnici y větší než 0 a menší než výška vymezené plochy. Instance třídy Point můžete použít k reprezentaci jednotlivých bodů v souřadnicovém prostoru. Můžete vytvořit instanci Rectangle k reprezentaci obdélníkové plochy v souřadnicovém prostoru. Pokročilí uživatelé mohou použít instanci třídy Matrix k aplikaci několika transformací nebo nějaké složité transformace na objekt zobrazení. Pomocí vlastností určitého objektu zobrazení můžete přímo na tento objekt aplikovat mnoho jednoduchých transformací, např. změna natočení, polohy a velikosti. Další informace o aplikování transformací pomocí vlastností objektu zobrazení viz „Manipulace s objekty zobrazení“ na stránce 285. Běžné geometrické úlohy Následující úlohy jsou věci, které budete pravděpodobně chtít pomocí tříd geometrie v jazyku ActionScript zrealizovat: • Výpočet vzdálenosti mezi dvěma body • Určování souřadnic bodu v různých souřadnicových prostorech • Posouvání objektu zobrazení pomocí úhlu a vzdálenosti • Práce s instancemi Rectangle: • Přemístění instance Rectangle PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 335 Práce s geometrií • Změna velikosti instance Rectangle • Určování kombinované velikosti nebo překrývajících se oblastí instancí Rectangle • Vytváření objektů Matrix • Používání objektů Matrix k aplikaci transformací na objekt zobrazení Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Pravoúhlé souřadnice: souřadnice jsou obvykle zapisovány jako pár čísel (např. 5, 12 nebo 17, -23). Tato dvě čísla vyjadřují hodnotu na ose x, resp. y. • Souřadnicový prostor: graf se souřadnicemi obsažený v objektu zobrazení, na který jsou umísťovány podřízené elementy. • Počátek: bod v souřadnicovém prostoru, kde je průsečík osy x a osy y. Tento bod má souřadnice 0, 0. • Bod: jednotlivé umístění v souřadnicovém prostoru. V soustavě souřadnic 3D používané v jazyku ActionScript, je bod definován svým umístěním podél osy x a osy y (souřadnicemi bodu). • Vztažný bod: v objektu zobrazení počátek (souřadnice 0, 0) jeho souřadnicového prostoru. • Měřítko: velikost určitého objektu vzhledem k jeho původní velikosti. Nastavení měřítka, resp. velikosti určitého objektu znamená změnu jeho velikosti zvětšením, resp. zmenšením daného objektu. • Posunutí: změna souřadnic určitého bodu z jednoho souřadnicového prostoru na jiný. • Transformace: Úprava vizuálních vlastností grafiky, jako je otočení objektu, změna velikosti, zkosení nebo deformace tvaru či změna barvy. • Osa x: vodorovná osa ve dvojrozměrné soustavě souřadnic používané v jazyku ActionScript. • Osa y: svislá osa ve dvojrozměrné soustavě souřadnic používané v jazyku ActionScript. Procházení příkladů v kapitole Mnoho z příkladů v této kapitole představuje výpočty nebo změny hodnot. Většina z těchto příkladů zahrnuje volání odpovídající funkce trace() za účelem demonstrace výsledků kódu. Zde je postup pro vyzkoušení těchto příkladů: 1 Pomocí vývojového nástroje Flash vytvořte prázdný dokument. 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Spusťte program pomocí příkazu Ovládání > Testovat film. Výsledky funkcí trace() uvedených kódů uvidíte v panelu Výstup. Některé z příkladů v této kapitole ukazují aplikování transformací na objekty zobrazení. U těchto příkladů budou výsledky příkladu spíše vizuální než textové. Zde je postup pro vyzkoušení příkladů transformace: 1 Pomocí vývojového nástroje Flash vytvořte prázdný dokument. 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Vytvořte ve vymezené ploše instanci symbolu filmového klipu. Například nakreslete tvar, vyberte jej, zvolte příkaz Změnit > Převést na symbol... a pojmenujte symbol. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 336 Práce s geometrií 5 V Inspektoru vlastností vyberte filmový klip Stage a udělte mu název instance. Tento název by se měl shodovat s názvem použitým pro objekt zobrazení v uvedeném příkladu kódu – např. jestliže uvedený kód aplikuje transformaci na objekt s názvem myDisplayObject, měli byste instanci filmového klipu pojmenovat také myDisplayObject. 6 Spusťte program pomocí příkazu Ovládání > Testovat film. Na obrazovce uvidíte výsledky transformací aplikovaných na daný objekt, jak jsou určeny v příkladu kódu. Techniky pro zkoušení uvedených příkladů kódů jsou podrobněji vysvětleny v části „Testování příkladů kódu v této kapitole“ na stránce 34. Používání objektů Point Objekt Point definuje pár pravoúhlých souřadnic. Představuje umístění v dvourozměrném souřadnicovém systému, kde x představuje vodorovnou osu y představuje svislou osu. Chcete-li definovat objekt Point, nastavte jeho vlastnosti x a y, viz níže: import flash.geom.*; var pt1:Point = new Point(10, 20); // x == 10; y == 20 var pt2:Point = new Point(); pt2.x = 10; pt2.y = 20; Nalezení vzdálenosti mezi dvěma body Pomocí metody distance() třídy Point můžete zjistit rozdíl mezi dvěma body v souřadnicovém prostoru. Například následující kód najde rozdíl mezi vztažnými body dvou objektů zobrazení, circle1 a circle2 ve stejném kontejneru objektu zobrazení: import flash.geom.*; var pt1:Point = new Point(circle1.x, circle1.y); var pt2:Point = new Point(circle2.x, circle2.y); var distance:Number = Point.distance(pt1, pt2); Posouvání souřadnicových prostorů Jsou-li dva objekty zobrazení v různých kontejnerech objektu zobrazení, mohou se nacházet v různých souřadnicových prostorech. Pomocí metody localToGlobal() třídy DisplayObject můžete posunout souřadnice do stejného (globálního) souřadnicového prostoru náležejícího k vymezené ploše. Například následující kód najde rozdíl mezi vztažnými body dvou objektů zobrazení, circle1 a circle2 v různých kontejnerech objektu zobrazení: import flash.geom.*; var pt1:Point = new Point(circle1.x, circle1.y); pt1 = circle1.localToGlobal(pt1); var pt2:Point = new Point(circle2.x, circle2.y); pt2 = circle2.localToGlobal(pt2); var distance:Number = Point.distance(pt1, pt2); Podobně chcete-li zjistit vzdálenost vztažného bodu objektu zobrazení s názvem target od určitého bodu ve vymezené ploše, můžete použít metodu localToGlobal() třídy DisplayObject: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 337 Práce s geometrií import flash.geom.*; var stageCenter:Point = new Point(); stageCenter.x = this.stage.stageWidth / 2; stageCenter.y = this.stage.stageHeight / 2; var targetCenter:Point = new Point(target.x, target.y); targetCenter = target.localToGlobal(targetCenter); var distance:Number = Point.distance(stageCenter, targetCenter); Posouvání objektu zobrazení pomocí zadaného úhlu a vzdálenosti Pomocí metody polar() třídy Point můžete posunout objekt zobrazení o určitou vzdálenost a pod určitým úhlem. Například následující kód posune objekt myDisplayObject o 100 obr. bodů pod úhlem 60 stupňů: import flash.geom.*; var distance:Number = 100; var angle:Number = 2 * Math.PI * (90 / 360); var translatePoint:Point = Point.polar(distance, angle); myDisplayObject.x += translatePoint.x; myDisplayObject.y += translatePoint.y; Další použití třídy Point Objekty Point můžete použít s následujícími metodami a vlastnostmi: Třída Metody nebo vlastnosti Popis DisplayObjectContainer areInaccessibleObjectsUnderPoint()getObject sUnderPoint() Používá se k vrácení seznamu objektů pod bodem v kontejneru objektu zobrazení. BitmapData hitTest() Používá se k definování obrazového bodu v objektu BitmapData a také bodu, který označujete pro klepnutí. BitmapData applyFilter() Používá se k definování pozic obdélníků, které definují operace. copyChannel() merge() paletteMap() pixelDissolve() threshold() Matice deltaTransformPoint() transformPoint() Obdélník bottomRight Používá se k definování bodů, u kterých chcete aplikovat transformaci. Používá se k definování těchto vlastností. size topLeft Používání objektů Rectangle Objekt Rectangle definuje obdélníkovou plochu. Objekt Rectangle má polohu definovanou souřadnicemi x a y svého levého horního rohu, vlastnost width a vlastnost height. U nového objektu Rectangle můžete tyto vlastnosti definovat pomocí metody Rectangle(), viz níže: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 338 Práce s geometrií import flash.geom.Rectangle; var rx:Number = 0; var ry:Number = 0; var rwidth:Number = 100; var rheight:Number = 50; var rect1:Rectangle = new Rectangle(rx, ry, rwidth, rheight); Změna velikosti a přemístění objektů Rectangle Existuje několik způsobů změny velikosti a přemístění objektů Rectangle. Objekt Rectangle můžete přemístit přímo změnou jeho vlastností x a y. To nemá vliv na šířku ani na výšku objektu Rectangle. import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.x = 20; rect1.y = 30; trace(rect1); // (x=20, y=30, w=100, h=50) Jak ukazuje následující kód, změníte-li vlastnost left nebo top objektu Rectangle, objekt se také přemístí, přičemž jeho souřadnice x a y budou odpovídat vlastnostem left a top. Poloha levého dolního rohu objektu Rectangle se však při změně velikosti nezmění. import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.left = 20; rect1.top = 30; trace(rect1); // (x=20, y=30, w=80, h=20) Podobně, jak ukazuje následující příklad, změníte-li vlastnost bottom nebo right objektu Rectangle, poloha jeho levého horního rohu se nezmění, takže se odpovídajícím způsobem změní jeho velikost. import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.right = 60; trect1.bottom = 20; trace(rect1); // (x=0, y=0, w=60, h=20) Objekt Rectangle můžete také přemístit pomocí metody offset() viz níže: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 339 Práce s geometrií import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.offset(20, 30); trace(rect1); // (x=20, y=30, w=100, h=50) Metoda offsetPt() funguje podobně, s tou výjimkou, že bere jako svůj parametr objekt Point a ne hodnoty posunu x a y. Velikost objektu Rectangle můžete změnit také pomocí metody inflate(), která zahrnuje dva parametry, dx a dy. Parametr dx představuje počet obrazových bodů, o který se posune levá a pravá strana obdélníku od středu, a parametr dy představuje počet obrazových bodů, o které se posune horní a dolní strana obdélníku od středu: import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.inflate(6,4); trace(rect1); // (x=-6, y=-4, w=112, h=58) Metoda inflatePt() funguje podobně, s tou výjimkou, že bere jako svůj parametr objekt Point a ne hodnoty dx a dy. Nalezení sjednocení a průsečíků objektů Rectangle Metoda union() slouží k nalezení obdélníkové plochy tvořené hranicemi dvou obdélníků: import flash.display.*; import flash.geom.Rectangle; var rect1:Rectangle = new Rectangle(0, 0, 100, 100); trace(rect1); // (x=0, y=0, w=100, h=100) var rect2:Rectangle = new Rectangle(120, 60, 100, 100); trace(rect2); // (x=120, y=60, w=100, h=100) trace(rect1.union(rect2)); // (x=0, y=0, w=220, h=160) Metoda intersection() slouží k nalezení obdélníkové plochy tvořené překrývající se plochou dvou obdélníků: import flash.display.*; import flash.geom.Rectangle; var rect1:Rectangle = new Rectangle(0, 0, 100, 100); trace(rect1); // (x=0, y=0, w=100, h=100) var rect2:Rectangle = new Rectangle(80, 60, 100, 100); trace(rect2); // (x=120, y=60, w=100, h=100) trace(rect1.intersection(rect2)); // (x=80, y=60, w=20, h=40) Pomocí metody intersects() můžete zjistit, zda se dva obdélníky protínají. Metodu intersects() můžete také použít k zjištění, zda se objekt zobrazení nachází v určité oblasti vymezené plochy. Například v následujícím kódu se předpokládá, že souřadnicový prostor kontejneru objektu zobrazení, který obsahuje objekt circle, je stejný jako souřadnicový prostor vymezené plochy. Tento příklad ukazuje použití metody intersects() k určení, jestli objekt circle protíná určené oblasti vymezené plochy, definované pomocí objektů Rectangle target1 a target2: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 340 Práce s geometrií import flash.display.*; import flash.geom.Rectangle; var circle:Shape = new Shape(); circle.graphics.lineStyle(2, 0xFF0000); circle.graphics.drawCircle(250, 250, 100); addChild(circle); var circleBounds:Rectangle = circle.getBounds(stage); var target1:Rectangle = new Rectangle(0, 0, 100, 100); trace(circleBounds.intersects(target1)); // false var target2:Rectangle = new Rectangle(0, 0, 300, 300); trace(circleBounds.intersects(target2)); // true Podobně můžete pomocí metody intersects() zjistit, zda se ohraničující obdélníky dvou objektů zobrazení překrývají. Metoda getRect() třídy DisplayObject slouží k zahrnutí určitého dodatečného prostoru, jenž mohou tahy objektu zobrazení přidat, k ohraničující oblasti. Další použití objektů Rectangle Objekty Rectangle se používají v následujících metodách a vlastnostech: Třída Metody nebo vlastnosti Popis BitmapData applyFilter(), colorTransform(), copyChannel(), copyPixels(), draw(), fillRect(), generateFilterRect(), getColorBoundsRect(), getPixels(), merge(), paletteMap(), pixelDissolve(), setPixels() a threshold() Používá se jako typ pro některé parametry k definování oblasti objektu BitmapData. DisplayObject getBounds(), getRect(), scrollRect, scale9Grid Používá se jako typ dat pro vlastnost nebo vrácený typ dat. PrintJob addPage() Používá se k definování parametru printArea. Sprite startDrag() Používá se k definování parametru bounds. TextField getCharBoundaries() Používá se jako vrácený typ hodnoty. Transformace pixelBounds Používá se jako typ dat. Používání objektů Matrix Třída Matrix představuje matici transformace, která určuje, jak se mají mapovat body od jednoho souřadnicového prostoru k druhému. Na objektu zobrazení můžete vykonávat různé grafické transformace nastavením vlastností objektu Matrix, aplikováním objektu Matrix na vlastnost matrix objektu Transform a pak aplikováním objektu Transform jako vlastnosti transform objektu zobrazení. Tyto transformační funkce zahrnují posun (přemístění x a y), natočení, změnu velikosti a zkosení. Definování objektů Matrix I když byste matici mohli definovat přímo úpravou vlastností (a, b, c, d, tx, ty) objektu Matrix, je jednodušší použít metodu createBox(). Tato metoda zahrnuje parametry, které umožňují přímo definovat efekty změny velikosti, natočení a posunutí výsledné matice. Například následující kód vytvoří objekt Matrix, který má efekt vodorovné změny velikosti objektu o 2,0, svislé změny velikosti o 3,0, natočení o 45 stupňů, posun (posunutí) o 10 obr. bodů doprava a posunutí o 20 obr. bodů dolů: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 341 Práce s geometrií var matrix:Matrix = new Matrix(); var scaleX:Number = 2.0; var scaleY:Number = 3.0; var rotation:Number = 2 * Math.PI * (45 / 360); var tx:Number = 10; var ty:Number = 20; matrix.createBox(scaleX, scaleY, rotation, tx, ty); Můžete upravit také efekty změny velikosti, natočení a posunutí objektu Matrix pomocí metod scale(), rotate() a translate(). Všimněte si, že tyto metody se kombinují s hodnotami stávajícího objektu Matrix. Například následující kód nastaví objekt Matrix, který změní velikost objektu čtyřnásobně a otočí jej o 60 stupňů, protože metody scale() a rotate() jsou vyvolány dvakrát: var matrix:Matrix = new Matrix(); var rotation:Number = 2 * Math.PI * (30 / 360); // 30° var scaleFactor:Number = 2; matrix.scale(scaleFactor, scaleFactor); matrix.rotate(rotation); matrix.scale(scaleX, scaleY); matrix.rotate(rotation); myDisplayObject.transform.matrix = matrix; Chcete-li na objekt Matrix aplikovat transformaci zkosení, upravte jeho vlastnost b nebo c. Úprava vlastnosti b způsobí svislé zkosení matice a úprava vlastnosti c vodorovné zkosení matice. Následující kód zkosí objekt Matrix myMatrix svisle dvojnásobně: var skewMatrix:Matrix = new Matrix(); skewMatrix.b = Math.tan(2); myMatrix.concat(skewMatrix); Transformaci Matrix můžete aplikovat na vlastnost transform objektu zobrazení. Například následující kód aplikuje transformaci matice na objekt zobrazení s názvem myDisplayObject: var matrix:Matrix = myDisplayObject.transform.matrix; var scaleFactor:Number = 2; var rotation:Number = 2 * Math.PI * (60 / 360); // 60° matrix.scale(scaleFactor, scaleFactor); matrix.rotate(rotation); myDisplayObject.transform.matrix = matrix; První řádek nastaví objekt Matrix na stávající matici transformace používanou objektem zobrazení myDisplayObject (vlastnost matrix vlastnosti transformation objektu zobrazení myDisplayObject). Takto budou mít metody třídy Matrix, které vyvoláte, kumulativní účinek na stávající polohu, měřítko a natočení daného objektu zobrazení. Poznámka: Třída ColorTransform je také součástí balíčku flash.geometry. Tato třída se používá k nastavení vlastnosti colorTransform objektu Transform. Protože neaplikuje žádné geometrické transformace, není v této kapitole probírána. Další informace viz třídu ColorTransform Referenční příručce jazyka ActionScript 3.0 a jeho součástí. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 342 Práce s geometrií Příklad: Použití transformace matice na objekt zobrazení Aplikace ukázky DisplayObjectTransformer ukazuje několik funkcí použití třídy Matrix k transformaci objektu zobrazení, včetně následujících: • Natočení objektu zobrazení • Změna velikosti objektu zobrazení • Posunutí (přemístění) objektu zobrazení • Zkosení objektu zobrazení Tato aplikace poskytuje rozhraní pro úpravu parametrů transformace matice, viz níže: Jakmile uživatel klepne na tlačítko Transformace, aplikace použije příslušnou transformaci. Původní objekt zobrazení a objekt zobrazení otočený o -45° a se změnou velikosti o 50 % Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace DisplayObjectTransformer najdete ve složce Samples/DisplayObjectTransformer. Aplikace sestává z následujících souborů: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 343 Práce s geometrií Soubor Popis DisplayObjectTransformer.mxml Hlavní aplikační soubor v aplikaci Flash (FLA) nebo Flex (MXML) nebo DisplayObjectTransformer.fla com/example/programmingas3/geometry/MatrixTransformer.as Třída, která obsahuje metody pro použití transformací matice. img/ Adresář obsahující ukázkové obrazové soubory používané touto aplikací. Definování třídy MatrixTransformer Třída MatrixTransformer obsahuje statické metody, které aplikují geometrické transformace objektů Matrix. Metoda transform() Metoda transform() zahrnuje parametry pro následující: • sourceMatrix – vstupní matice, kterou metoda transformuje • xScale a yScale – měřítko x a y • dx a dy – velikost posunutí x a y v obrazových bodech • rotation – velikost natočení ve stupních • skew – míra zkosení v procentech • skewType – směr zkosení, buď "right" nebo "left" Vrácená hodnota je výsledná matice. Metoda transform() vyvolá následující statické metody dané třídy: • skew() • scale() • translate() • rotate() Každá z těchto metod vrátí zdrojovou matici s použitou transformací. Metoda skew() Metoda skew() zkosí matici úpravou vlastností b a c dané matice. Volitelný parametr, unit, určuje jednotky používané k definování úhlu zkosení a v případě potřeby tato metoda převede hodnotu angle na radiány: if (unit == { angle = } if (unit == { angle = } "degrees") Math.PI * 2 * angle / 360; "gradients") Math.PI * 2 * angle / 100; Vytvoří se objekt Matrix skewMatrix a upraví se pro použití transformace zkosení. Na počátku je to jednotková matice, viz níže: var skewMatrix:Matrix = new Matrix(); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 344 Práce s geometrií Parametr skewSide určuje stranu, na kterou se zkosení aplikuje. Je-li nastaven na "right", nastaví následující kód vlastnost b dané matice: skewMatrix.b = Math.tan(angle); Jinak bude zkosena spodní strana úpravou vlastnosti c matice, viz níže: skewMatrix.c = Math.tan(angle); Výsledné zkosení bude poté aplikováno na stávající matici sloučením dvou matic, jak ukazuje následující příklad: sourceMatrix.concat(skewMatrix); return sourceMatrix; Metoda scale() Jak ukazuje následující příklad, metoda scale() nejprve upraví měřítko, je-li dodáno v procentuální hodnotě, a dále použije metodu scale() objektu matice: if (percent) { xScale = xScale / 100; yScale = yScale / 100; } sourceMatrix.scale(xScale, yScale); return sourceMatrix; Metoda translate() Metoda translate() jen aplikuje činitele posunutí dx a dy vyvoláním metody translate() objektu matice, viz níže: sourceMatrix.translate(dx, dy); return sourceMatrix; Metoda rotate() Metoda rotate() převede vstupní činitel natočení na radiány (je-li dodán ve stupních nebo gradientech) a poté vyvolá metodu rotate() objektu matice: if (unit == "degrees") { angle = Math.PI * 2 * angle / 360; } if (unit == "gradients") { angle = Math.PI * 2 * angle / 100; } sourceMatrix.rotate(angle); return sourceMatrix; Volání metody MatrixTransformer.transform() z aplikace Tato aplikace obsahuje uživatelské rozhraní pro získání parametrů transformace od uživatele. Ty potom předá, spolu s vlastností matrix vlastnosti transform objektu zobrazení, metodě Matrix.transform(), viz níže: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 345 Práce s geometrií tempMatrix = MatrixTransformer.transform(tempMatrix, xScaleSlider.value, yScaleSlider.value, dxSlider.value, dySlider.value, rotationSlider.value, skewSlider.value, skewSide ); Aplikace poté použije vrácenou hodnotu na vlastnost matrix vlastnosti transform objektu zobrazení a tím spustí transformaci: img.content.transform.matrix = tempMatrix; 346 Kapitola 16: Filtrování objektů zobrazení Použití efektů filtrů na snímky bitmapy je doménou specializovaného software pro úpravu snímků, například programů Adobe Photoshop® a Adobe Fireworks®. Jazyk ActionScript 3.0 zahrnuje balík flash.filters, který obsahuje třídy filtrů efektů bitmap a umožňuje tak vývojářům programaticky použít filtry na bitmapy a objekty zobrazení a dosáhnout mnoha stejných efektů, které jsou dostupné v aplikacích pro manipulaci s grafikou. Základní informace o filtrování objektů zobrazení Úvod k filtrování objektů zobrazení Jedním způsobem vylepšení aplikace je přidání jednoduchých grafických efektů, například vrženého stínu za fotografii pro vytvoření iluze třetího rozměru nebo záře okolo tlačítka, která ukazuje, že tlačítko je aktivní. Jazyk ActionScript 3.0 obsahuje devět filtrů, které můžete použít na jakýkoliv objekt zobrazení nebo na instanci BitmapData. Tyto filtry se pohybují od základních filtrů, například vrženého stínu a filtru záře, po složité filtry k vytváření různých efektů, například filtry mapy přestavění a filtr konvoluce. Běžné úlohy filtrování Následující úlohy představují výsledky, kterých budete pravděpodobně chtít použitím filtrů v jazyce ActionScript dosáhnout: • Vytváření filtru • Použití filtru na objekt zobrazení • Odstranění filtru z objektu zobrazení • Použití filtru na data obrazu v instanci BitmapData • Odstranění filtrů z objektu • Vytváření různých efektů filtru, například záře, rozostření, vrženého stínu, zostření, přestavění, detekce okrajů, reliéf a jiných. Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Úkos: Okraj vytvořený osvětlením obrazových bodů na dvou stranách a ztmavením obrazových bodů na opačných dvou stranách. Vytvoří se tak efekt trojrozměrné hranice, který se běžně používá pro vyvýšená nebo odsazená tlačítka a podobnou grafiku. • Konvoluce: Zkreslení obrazových bodů v obrazu kombinováním hodnoty každého obrazového bodu s hodnotami některých nebo všech jeho sousedících obrazových bodů, a to pomocí různých poměrů. • Přestavění: Posouvání nebo pohybování obrazovými body na obrazu do nových poloh. • Matice: Mřížka čísel používaná pro provedení určitých matematických výpočtů aplikací čísel ve mřížce na různé hodnoty a následným zkombinováním výsledků. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 347 Filtrování objektů zobrazení Procházení příkladů v kapitole Při práci s kapitolou si můžete přát otestovat ukázky kódů, které jsou k dispozici. Protože se tato kapitola věnuje vytváření a zpracovávání vizuálního obsahu, testování kódu zahrnuje spuštění kódu a zobrazení výsledků v souboru SWF, který je vytvořen. Skoro všechny příklady buď vytvoří obsah pomocí výkresových API nebo nahrají obrazy, na které se filtry použijí. Chcete-li testovat kód v této kapitole: 1 Pomocí vývojového nástroje Flash vytvořte prázdný dokument. 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte kód do panelu Skript. 4 Spusťte program pomocí příkazu Ovládání > Testovat film. Výsledky kódu budou zobrazeny v souboru SWF, který je vytvořen. Skoro všechny příklady kódu zahrnují kód, který vytváří obraz bitmapy, takže kód můžete testovat přímo bez potřeby poskytnout obsah bitmapy. Alternativně můžete změnit ukázku kódu, nahrát tak své vlastní obrazy a použít je namísto obrazů v příkladu. Vytváření a používání filtrů Filtry vám umožňují použít různé efekty na bitmapy a objekty zobrazení, od vržených stínů až po úkosy a rozostření. Každý filtr je definován jako třída, takže použití filtrů zahrnuje vytvoření instancí objektů filtrů, což se neliší od konstruování jakéhokoliv jiného objektu. Jakmile jste vytvořili instanci objektu filtru, můžete ji snadno použít na objekty zobrazení pomocí vlastnosti objektu filters, nebo v případě objektu BitmapData použitím metody applyFilter(). Vytváření nového filtru Pro vytvoření nového objektu filtru jednoduše volejte metodu konstruktoru své vybrané třídy filtru. Například pro vytvoření nového objektu DropShadowFilter použijte následující kód: import flash.filters.DropShadowFilter; var myFilter:DropShadowFilter = new DropShadowFilter(); Ačkoliv to zde není ukázáno, konstruktor DropShadowFilter() (jako všechny konstruktory tříd filtru) přijímá několik volitelných parametrů, které lze použít pro vlastní nastavení vzhledu efektu filtru. Použití filtru Jakmile jste vytvořili objekt filtru, můžete jej použít na objekt zobrazení nebo objekt BitmapData; způsob použití filtru závisí na objektu, na který jej používáte. Použití filtru na objekt zobrazení Když použijete efekty filtru na objekt zobrazení, použijete je pomocí vlastnosti filters . Vlastnost filters objektu zobrazení je instance Array, jejíž elementy jsou objekty zobrazení použité na objekt zobrazení. Pro použití jediného filtru na objekt zobrazení vytvořte instanci filtru, přidejte ji k instanci Array a přiřaďte daný objekt Array k vlastnosti objektu zobrazení filters: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 348 Filtrování objektů zobrazení import flash.display.Bitmap; import flash.display.BitmapData; import flash.filters.DropShadowFilter; // Create a bitmapData object and render it to screen var myBitmapData:BitmapData = new BitmapData(100,100,false,0xFFFF3300); var myDisplayObject:Bitmap = new Bitmap(myBitmapData); addChild(myDisplayObject); // Create a DropShadowFilter instance. var dropShadow:DropShadowFilter = new DropShadowFilter(); // Create the filters array, adding the filter to the array by passing it as // a parameter to the Array() constructor. var filtersArray:Array = new Array(dropShadow); // Assign the filters array to the display object to apply the filter. myDisplayObject.filters = filtersArray; Jestliže si k objektu přejete přiřadit více filtrů, jednoduše přidejte všechny filtry k instanci Array před tím, než ji přiřadíte k vlastnosti filters. Více objektů k instanci Array lze přidat tak, že je předáte jako parametry k jejich konstruktoru. Tento kód například použije filtr úkosu a vrženého stínu na předchozí vytvořený objekt zobrazení: import flash.filters.BevelFilter; import flash.filters.GlowFilter; // Create the filters and add them to an array. var bevel:BevelFilter = new BevelFilter(); var glow:GlowFilter = new GlowFilter(); var filtersArray:Array = new Array(bevel, glow); // Assign the filters array to the display object to apply the filter. myDisplayObject.filters = filtersArray; Při vytváření pole obsahujícího filtry jej můžete vytvořit pomocí konstruktoru new Array() (jak je uvedeno v předchozím příkladě) nebo můžete použít syntaxi literálu a vložit filtry do hranatých závorek ([]). Například tento řádek kódu: var filters:Array = new Array(dropShadow, blur); má stejnou funkci jako tento řádek kódu: var filters:Array = [dropShadow, blur]; Jestliže na objekty zobrazení použijete více filtrů, použijí se kumulativním, sekvenčním způsobem. Jestliže má například pole filtrů dva elementy, filtr úkosu přidal první a filtr vrženého stínu přidal druhý element. Filtr vrženého stínu je použit na filtr úkosu i na objekt zobrazení. Důvodem je to, že filtr vrženého stínu je v poli filtru na druhé pozici. Jestliže si přejete použít filtry nikoliv kumulativním způsobem, musíte každý filtr použít na novou kopii objektu zobrazení. Jestliže objektu zobrazení přiřazujete pouze jeden nebo několik málo filtrů, můžete vytvořit instanci filtru a přiřadit ji danému objektu v jediném příkazu. Například následující řádek kódu použije efekt rozostření na objekt zobrazení nazvaný myDisplayObject: myDisplayObject.filters = [new BlurFilter()]; Předcházející kód vytvoří instanci Array pomocí syntaxe literálu Array (čtvercové závorky), vytvoří novou instanci BlurFilter jako element ve třídě Array a přiřadí dané pole vlastnosti filters objektu zobrazení pojmenovanému myDisplayObject. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 349 Filtrování objektů zobrazení Odstranění filtrů z objektu zobrazení Odstraňování všech filtrů z objektu zobrazení je stejně jednoduché jako přiřazení nulové hodnoty k vlastnosti filters: myDisplayObject.filters = null; Jestliže jste na objekt použili více filtrů a přejete si odstranit pouze jeden z těchto filtrů, musíte pro změnu pole vlastnosti filters provést několik kroků. Pro více informací viz „Možné problémy při práci s filtry“ na stránce 349. Použití filtru na objekt BitmapData Použití filtru na objekt BitmapData vyžaduje použití metody BitmapData applyFilter(): var rect:Rectangle = new Rectangle(); var origin:Point = new Point(); myBitmapData.applyFilter(sourceBitmapData, rect, origin, new BlurFilter()); Metoda applyFilter() použije filtr na zdrojový objekt BitmapData a vytvoří nový filtrovaný obraz. Tato metoda neupravuje původní zdrojový obraz; namísto toho je výsledek filtru použitého na zdrojový obraz uložen v instanci BitmapData, na které je volána metoda applyFilter(). Jak filtr funguje Filtrování objektu zobrazení pracuje pomocí uložení kopie původního objektu zobrazení do vyrovnávací paměti jako průhledné bitmapy. Jakmile byl filtr použit na objekt zobrazení, program Adobe Flash Player nebo Adobe® AIR™ uloží daný objekt do vyrovnávací paměti jako bitmapu, po tak dlouho dobu, po jakou má daný objekt platný seznam filtrů. Tato zdrojová bitmapa je poté použita jako původní obraz pro všechny následně použité efekty filtrů. Každý objekt zobrazení obvykle obsahuje dvě bitmapy: jednu s původním nefiltrovaným objektem zobrazení a další pro konečný obraz po filtrování. Konečný obraz se použije při vykreslení. Dokud se objekt zobrazení nezmění, konečný obraz není třeba aktualizovat. Možné problémy při práci s filtry Existuje několik možných zdrojů nejasností nebo potíží, které je třeba mít při používání filtrů na paměti. Tyto zdroje jsou popsány v následujících částech. Filtry a ukládání bitmap do vyrovnávací paměti Pro použití filtru na objekt zobrazení musí být pro daný objekt aktivováno stahování bitmap do vyrovnávací paměti. Jestliže použijete filtr na objekt zobrazení, jehož vlastnost cacheAsBitmap je nastavena na false, přehrávač Flash Player nebo program AIR automaticky nastaví hodnotu vlastnosti objektu cacheAsBitmap na true. Jestliže později odstraníte všechny filtry z objektu zobrazení, přehrávač Flash Player nebo program AIR znovu nastaví vlastnost cacheAsBitmap na poslední hodnotu, na kterou byla nastavena. Změna filtrů v době běhu Jestliže je na objekt zobrazení již použit jeden nebo více filtrů, nemůžete nastavení filtrů změnit přidáním dodatečných filtrů nebo odstraněním filtrů z pole vlastnosti filters. Namísto toho musíte pro přidání nebo změnu sady použitých filtrů provést změny v samostatném poli a poté dané pole přiřadit vlastnostem filtrů objektu zobrazení, aby byly filtry na objekt použity. Nejjednodušším způsobem provedení změn je načíst pole vlastnosti filters do proměnné Array a provést své úpravy do tohoto přechodného pole. Poté můžete toto pole přiřadit zpět vlastnosti filters objektu zobrazení. Ve složitějších případech můžete potřebovat zachovat samostatné hlavní pole filtrů. V daném hlavním poli filtru provedete libovolné změny a po každé změně jej znovu přiřadíte vlastnosti objektu zobrazení filters. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 350 Filtrování objektů zobrazení Přidání dodatečného filtru Následující kód uvádí proces přidání dodatečných filtru k objektu zobrazení, na který je již použit jeden nebo více filtrů. Původně je filtr záře použit na objekt zobrazení pojmenovaný myDisplayObject; později je po klepnutí na objekt zobrazení volána metoda addFilters(). V této funkci jsou na myDisplayObjectpoužity dva dodatečné filtry: import flash.events.MouseEvent; import flash.filters.*; myDisplayObject.filters = [new GlowFilter()]; function addFilters(event:MouseEvent):void { // Make a copy of the filters array. var filtersCopy:Array = myDisplayObject.filters; // Make desired changes to the filters (in this case, adding filters). filtersCopy.push(new BlurFilter()); filtersCopy.push(new DropShadowFilter()); // Apply the changes by reassigning the array to the filters property. myDisplayObject.filters = filtersCopy; } myDisplayObject.addEventListener(MouseEvent.CLICK, addFilters); Odstranění jednoho filtru ze sady filtrů Jestliže je na objekt zobrazení použito více filtrů a přejete-li si jeden z těchto filtrů odstranit, zatímco ostatní filtry budou i nadále na daný objekt použity, odstraňte nechtěný filtr z daného pole a přechodné pole znovu přiřaďte vlastnosti objektu zobrazení filters. Několik způsobů pro odstranění jednoho nebo více elementů z jakéhokoliv pole je popsáno v části „Načítání hodnot a odstraňování elementů pole“ na stránce 158. Nejjednodušší situace je odstranění filtru na nejvyšší úrovni objektu (poslední filtr použitý na daný objekt). Pro odstranění filtru z pole můžete použít metodu třídy Array pop(): // Example of removing the top-most filter from a display object // named "filteredObject". var tempFilters:Array = filteredObject.filters; // Remove the last element from the Array (the top-most filter). tempFilters.pop(); // Apply the new set of filters to the display object. filteredObject.filters = tempFilters; Podobně pro odstranění filtru na nejnižší úrovni (první použitý na objekt) můžete použít stejný kód a nahradit tak metodou třídy Array shift() metodu pop(). Pro odstranění filtru ze středu pole filtrů (za předpokladu, že má dané pole více než dva filtry) můžete použít metodu splice(). Musíte znát index (polohu v poli) filtru, který si přejete odstranit. Například následující kód odstraní z objektu zobrazení druhý filtr (filtr v indexu 1): PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 351 Filtrování objektů zobrazení // Example of removing a filter from the middle of a stack of filters // applied to a display object named "filteredObject". var tempFilters:Array = filteredObject.filters; // Remove the second filter from the array. It's the item at index 1 // because Array indexes start from 0. // The first "1" indicates the index of the filter to remove; the // second "1" indicates how many elements to remove. tempFilters.splice(1, 1); // Apply the new set of filters to the display object. filteredObject.filters = tempFilters; Určení indexu filtru Musíte vědět, který filtr má být z pole odstraněn. To znamená, že musíte znát index daného filtru. Musíte buď znát (díky způsobu, jakým je aplikace navržena) nebo vypočítat index filtru, který si přejete odstranit. Nejlepším přístupem je navrhnout vaší aplikaci tak, aby byl filtr, který si přejete odstranit, v sadě filtrů vždy ve stejné pozici. Jestliže máte například jediný objekt zobrazení s filtrem konvoluce, na který je použit filtr vrženého stínu (v tomto pořadí) a přejete si filtr vrženého stínu odstranit, ale filtr konvoluce zachovat, filtr je ve známé pozici (filtr na nejvyšší úrovni), takže dopředu víte, kterou metodu Array použít (v tomto příkladě metodu Array.pop() pro odstranění filtru vrženého stínu). Jestliže má filtr, který si přejete odstranit, určitý typ, ale není vždy v sadě filtrů na stejné pozici, můžete zkontrolovat datový typ každého filtru v daném poli a určit tak, který filtr má být odstraněn. Například následující kód ukazuje, který ze sady filtrů je filtr záře a tento filtr odstraní ze seznamu. // Example of removing a glow filter from a set of filters, where the //filter you want to remove is the only GlowFilter instance applied // to the filtered object. var tempFilters:Array = filteredObject.filters; // Loop through the filters to find the index of the GlowFilter instance. var glowIndex:int; var numFilters:int = tempFilters.length; for (var i:int = 0; i < numFilters; i++) { if (tempFilters[i] is GlowFilter) { glowIndex = i; break; } } // Remove the glow filter from the array. tempFilters.splice(glowIndex, 1); // Apply the new set of filters to the display object. filteredObject.filters = tempFilters; Ve složitějších případech, například pokud je filtr k odstranění vybrán v době běhu, je nejlepším přístupem zachovat samostatnou trvalou kopii pole filtru, která slouží jako hlavní seznam filtrů. Kdykoliv provedete změnu nastavení filtrů (přidáváte filtr nebo odstraňujete filtr), změňte hlavní seznam a poté dané pole filtru použijte jako vlastnost filters objektu zobrazení. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 352 Filtrování objektů zobrazení Například v následující ukázce kódu jsou na objekt zobrazení pro vytvoření vizuálních efektů použity násobné filtry konvoluce a později je v aplikaci jeden z těchto filtrů odstraněn, zatímco jiné jsou zachovány. V tomto případě kód uchová hlavní kopii pole filtrů, i referenci na filtr, který má být odstraněn. Vyhledávání a odstraňování filtru je podobné předcházejícímu přístupu s výjimkou, že namísto vytvoření přechodné kopie pole filtrů je zpracována hlavní kopie a je poté použita na objekt zobrazení. // // // // Example of removing a filter from a set of filters, where there may be more than one of that type of filter applied to the filtered object, and you only want to remove one. // A master list of filters is stored in a separate, // persistent Array variable. var masterFilterList:Array; // At some point, you store a reference to the filter you // want to remove. var filterToRemove:ConvolutionFilter; // ... assume the filters have been added to masterFilterList, // which is then assigned as the filteredObject.filters: filteredObject.filters = masterFilterList; // ... later, when it's time to remove the filter, this code gets called: // Loop through the filters to find the index of masterFilterList. var removeIndex:int = -1; var numFilters:int = masterFilterList.length; for (var i:int = 0; i < numFilters; i++) { if (masterFilterList[i] == filterToRemove) { removeIndex = i; break; } } if (removeIndex >= 0) { // Remove the filter from the array. masterFilterList.splice(removeIndex, 1); // Apply the new set of filters to the display object. filteredObject.filters = masterFilterList; } V tomto přístupu (jestliže porovnáváte uloženou referenci filtru s položkami v poli filtrů a přejete si určit, který filtr má být odstraněn), musíte zachovat samostatnou kopii pole filtrů - kód nefunguje, jestliže porovnáváte uloženou referenci filtru s elementy v přechodném poli zkopírovaném z vlastnosti objektu zobrazení filters. Důvod je interní - pokud přiřazujete pole k vlastnosti filtrů filters, přehrávač Flash Player nebo program AIR vytvoří kopii každého objektu filtru v daném poli. Tyto kopie (spíše než původní objekty) se použijí na objekt zobrazení a když načtete vlastnost filters do přechodného pole, obsahuje přechodné pole reference na kopírované objekty filtru, spíše než reference na původní objekty filtru. Jestliže se v předcházejícím příkladě pokusíte určit index filterToRemove jeho porovnáním s filtry v přechodném poli filtrů, nebude nalezena žádná shoda. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 353 Filtrování objektů zobrazení Transformace filtrů a objektů Žádná filtrovaná oblast - například vržený stín - mimo ohraničující rámeček objektu zobrazení není za účelem detekce shody považována za část povrchu (určení, jestli instance přesahuje nebo protíná jinou instanci). Protože jsou metody pro detekci shody třídy DisplayObject založeny na vektorech, nemůžete detekci shody provést na výsledku bitmapy. Jestliže například použijete filtr úkosu na instanci tlačítka, detekce shody není na zkosené části instance dostupná. Změna měřítka, otočení a zkosení nejsou filtry podporovány; jestliže je u samotného objektu zobrazení změněno měřítko, (jestliže scaleX a scaleY nejsou 100%), účinek filtru nezmění měřítko společně s instancí. To znamená, že původní tvar instance rotuje, mění měřítko nebo je zkosený; nicméně filtr nerotuje, nemění měřítko a není zkosený společně s instancí. Pomocí filtru můžete animovat instanci a vytvořit tak realistické efekty, nebo můžete instance vnořit, použít třídu BitmapData pro animaci filtrů a dosáhnout tak požadovaného efektu. Filtry a objekty Bitmap Jestliže na objekt BitmapData použijete libovolný filtr, vlastnost cacheAsBitmap je automaticky nastavena na true. Tímto způsobem je filtr vlastně použit na kopii objektu, nikoliv na jeho originál. Tato kopie je poté umístěna do hlavního zobrazení (překryje původní objekt) co nejblíže nejbližšímu obrazovému bodu. Jestliže se hranice původní bitmapy změní, bitmapa filtrované kopie je znovu vytvořena z originálu a není natažena nebo zdeformována. Jestliže vymažete všechny filtry pro objekt zobrazení, vlastnost cacheAsBitmap je resetována na původní hodnotu před použitím filtru. Dostupné filtry zobrazení Jazyk ActionScript 3.0 zahrnuje deset tříd filtrů, které lze použít na objekty zobrazení a objekty BitmapData: • Filtr úkosu (třída BevelFilter) • Filtr rozostření (třída BlurFilter) • Filtr vrženého stínu (třída DropShadowFilter) • Filtr záře (třída GlowFilter) • Filtr úkosu s přechodem (třída GradientBevelFilter) • Filtr záře s přechodem (třída GradientGlowFilter) • Filtr matice barev (třída ColorMatrixFilter) • Filtr konvoluce (Třída ConvolutionFilter) • Filtr mapy přestavění (třída DisplacementMapFilter) • Třída clony (třída ShaderFilter) Prvních šest filtrů jsou jednoduché filtry, které lze použít pro vytvoření jednoho specifického efektu, s určitým uživatelským nastavením dostupného efektu. Těchto šest filtrů lze použít pomocí jazyka ActionScript a lze je také použít na objekty v programu Adobe Flash CS4 Professional pomocí panelu Filtry. I když tedy používáte filtry pomocí jazyka ActionScript, jestliže máte vývojový nástroj Flash, můžete použít vizuální rozhraní pro rychlé vyzkoušení různých filtrů a nastavení a zjistit, jak vytvořit požadovaný efekt. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 354 Filtrování objektů zobrazení Závěrečné čtyři filtry jsou dostupné pouze v jazyce ActionScript. Tyto filtry, filtr matice barev, filtr konvoluce, filtr mapy přestavění a filtr clony, jsou o mnoho flexibilnější co do typů efektů, které mohou vytvořit. Spíše než optimalizaci pro jediný efekt poskytují výkon a flexibilitu. Například výběrem různých hodnot pro svou matici lze filtr konvoluce použít pro vytvoření efektů, například rozostření, reliéf, zostření, nalezení okrajů barev, transformace a další. Každý z těchto filtrů, ať už jednoduchý nebo složitý, lze pomocí jeho vlastností upravit na míru. Obecně máte při nastavování vlastností filtrů dvě volby. Všechny filtry vám umožňují nastavit vlastnosti předáním hodnot jejich parametru do konstruktoru objektu filtru. Ať už vlastnosti filtru nastavíte nebo nenastavíte předáním parametrů, můžete filtry upravit později nastavením hodnot na vlastnosti daného objektu filtru. Aby byly příklady snazší, většina uvedených příkladů kódu nastaví vlastnosti přímo. Nicméně stejného výsledku můžete obvykle dosáhnout v méně řádcích kódu, a to předáním hodnot jako parametrů do konstruktoru objektu filtru. Více informací o specifikacích každého filtru, jeho vlastnostech a parametrech jeho konstruktoru naleznete v ukázkách pro balík flash.filters v Referenční příručce jazyka ActionScript 3.0 a jeho komponent. Filtr úkosu Třída BevelFilter vám umožňuje přidat k filtrovanému objektu 3D zkosený okraj. Tento filtr vytváří pevné okraje nebo hrany vašeho objektu, které vypadají, jako by byly opracovány nebo zkoseny směrem pryč. Vlastnosti třídy BevelFilter vám umožňují upravit vzhled úkosu. Můžete nastavit barvy zvýraznění a stínu, rozostření úhlu úkosu, úhly úkosu a umístění hrany úkosu; můžete také vytvořit efekt vyseknutí. Následující příklad načte externí obraz a použije na něj filtr úkosu. import import import import import flash.display.*; flash.filters.BevelFilter; flash.filters.BitmapFilterQuality; flash.filters.BitmapFilterType; flash.net.URLRequest; // Load an image onto the Stage. var imageLoader:Loader = new Loader(); var url:String = "http://www.helpexamples.com/flash/images/image3.jpg"; var urlReq:URLRequest = new URLRequest(url); imageLoader.load(urlReq); addChild(imageLoader); // Create the bevel filter and set filter properties. var bevel:BevelFilter = new BevelFilter(); bevel.distance = 5; bevel.angle = 45; bevel.highlightColor = 0xFFFF00; bevel.highlightAlpha = 0.8; bevel.shadowColor = 0x666666; bevel.shadowAlpha = 0.8; bevel.blurX = 5; bevel.blurY = 5; bevel.strength = 5; bevel.quality = BitmapFilterQuality.HIGH; bevel.type = BitmapFilterType.INNER; bevel.knockout = false; // Apply filter to the image. imageLoader.filters = [bevel]; PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 355 Filtrování objektů zobrazení Filtr rozostření Třída BlurFilter rozmaže nebo rozostří objekt zobrazení a jeho obsah. Efekty rozostření jsou užitečné pro vyvolání dojmu, že je objekt nezaostřen nebo pro simulaci rychlého pohybu, například při rozostření pohybu. Nastavením vlastnosti quality filtru rozostření na nízkou hodnotu můžete simulovat jemný efekt nezaostřené čočky. Nastavením vlastnosti quality na vysoké hodnoty vytvoříte hladký efekt rozostření, podobný gausově rozostření. Následující příklad vytvoří použitím metody drawCircle() třídy Graphics kruhový objekt a použije na něj filtr rozostření: import flash.display.Sprite; import flash.filters.BitmapFilterQuality; import flash.filters.BlurFilter; // Draw a circle. var redDotCutout:Sprite = new Sprite(); redDotCutout.graphics.lineStyle(); redDotCutout.graphics.beginFill(0xFF0000); redDotCutout.graphics.drawCircle(145, 90, 25); redDotCutout.graphics.endFill(); // Add the circle to the display list. addChild(redDotCutout); // Apply the blur filter to the rectangle. var blur:BlurFilter = new BlurFilter(); blur.blurX = 10; blur.blurY = 10; blur.quality = BitmapFilterQuality.MEDIUM; redDotCutout.filters = [blur]; Filtr vrženého stínu Vržené stíny vyvolají dojem, že je nad cílovým objektem umístěn samostatný zdroj světla. Polohu a intenzitu tohoto zdroje světla lze upravit tak, aby vznikly různé efekty vrženého stínu. Třída DropShadowFilter používá algoritmus, který se podobá algoritmu filtru rozostření. Hlavním rozdílem je to, že filtr vrženého stínu má o více vlastností, které lze upravit a simulovat tak různé atributu zdroje světla (například alfa, barva, odsazení a jas). Filtr vrženého stínu vám také umožňuje použít vlastní volby transformace na styl vrženého stínu, včetně vnitřního a vnějšího stínu a režimu vyseknutí (známého také jako režim vystřižení). Následující kód vytvoří pohyblivý symbol čtvercového rámečku a použije na něj filtr vrženého stínu: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 356 Filtrování objektů zobrazení import flash.display.Sprite; import flash.filters.DropShadowFilter; // Draw a box. var boxShadow:Sprite = new Sprite(); boxShadow.graphics.lineStyle(1); boxShadow.graphics.beginFill(0xFF3300); boxShadow.graphics.drawRect(0, 0, 100, 100); boxShadow.graphics.endFill(); addChild(boxShadow); // Apply the drop shadow filter to the box. var shadow:DropShadowFilter = new DropShadowFilter(); shadow.distance = 10; shadow.angle = 25; // You can also set other properties, such as the shadow color, // alpha, amount of blur, strength, quality, and options for // inner shadows and knockout effects. boxShadow.filters = [shadow]; Filtr záře Třída GlowFilter použije na objekty zobrazení efekt osvětlení a vyvolá dojem, že světlo vychází zpod objektu a vytváří tak jemnou záři. Podobně jako u filtru vrženého stínu, zahrnuje filtr záře vlastnosti pro úpravu vzdálenosti, úhlu a barvy zdroje světla, které vytvoří vlastní efekty. Filtr GlowFilter má také několik možností úprav stylu záře, včetně vnitřní a vnější záře a režimu vyseknutí. Následující kód vytvoří řez pomocí třídy Sprite a použije na něj filtr záře: import flash.display.Sprite; import flash.filters.BitmapFilterQuality; import flash.filters.GlowFilter; // Create a cross graphic. var crossGraphic:Sprite = new Sprite(); crossGraphic.graphics.lineStyle(); crossGraphic.graphics.beginFill(0xCCCC00); crossGraphic.graphics.drawRect(60, 90, 100, 20); crossGraphic.graphics.drawRect(100, 50, 20, 100); crossGraphic.graphics.endFill(); addChild(crossGraphic); // Apply the glow filter to the cross shape. var glow:GlowFilter = new GlowFilter(); glow.color = 0x009922; glow.alpha = 1; glow.blurX = 25; glow.blurY = 25; glow.quality = BitmapFilterQuality.MEDIUM; crossGraphic.filters = [glow]; PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 357 Filtrování objektů zobrazení Filtr úkosu s přechodem Třída GradientBevelFilter vám umožňuje použít pokročilý efekt zkosení na objekty zobrazení nebo na objekty BitmapData. Použitím barvy přechodu na úkos výrazně vylepšíte prostorovou hloubku úkosu a hrany budou mít tak realističtější 3D vzhled. Následující kód vytvoří pomocí metody drawRect() třídy Shape obdélníkový objekt a použije na něj filtr úkosu s přechodem. import flash.display.Shape; import flash.filters.BitmapFilterQuality; import flash.filters.GradientBevelFilter; // Draw a rectangle. var box:Shape = new Shape(); box.graphics.lineStyle(); box.graphics.beginFill(0xFEFE78); box.graphics.drawRect(100, 50, 90, 200); box.graphics.endFill(); // Apply a gradient bevel to the rectangle. var gradientBevel:GradientBevelFilter = new GradientBevelFilter(); gradientBevel.distance = 8; gradientBevel.angle = 225; // opposite of 45 degrees gradientBevel.colors = [0xFFFFCC, 0xFEFE78, 0x8F8E01]; gradientBevel.alphas = [1, 0, 1]; gradientBevel.ratios = [0, 128, 255]; gradientBevel.blurX = 8; gradientBevel.blurY = 8; gradientBevel.quality = BitmapFilterQuality.HIGH; // Other properties let you set the filter strength and set options // for inner bevel and knockout effects. box.filters = [gradientBevel]; // Add the graphic to the display list. addChild(box); Filtr záře s přechodem Třída GradientGlowFilter vám umožňuje použít pokročilý efekt záře na objekty zobrazení nebo na objekty BitmapData. Tento efekt vám umožňuje lépe ovládat záři a vytváří tak realističtější efekt záře. Dále vám filtr záře s přechodem umožňuje použít záři s přechodem na vnitřní, vnější nebo horní hrany objektu. Následující příklad nakreslí na ploše čtverec a použije na něj filtr záře. Při posouvání myši dále doprava a dolů vzroste množství rozostření v horizontálním, respektive vertikálním směru. Kdykoliv klepnete na plochu, intenzita rozostření se zvýší. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 358 Filtrování objektů zobrazení import import import import flash.events.MouseEvent; flash.filters.BitmapFilterQuality; flash.filters.BitmapFilterType; flash.filters.GradientGlowFilter; // Create a new Shape instance. var shape:Shape = new Shape(); // Draw the shape. shape.graphics.beginFill(0xFF0000, 100); shape.graphics.moveTo(0, 0); shape.graphics.lineTo(100, 0); shape.graphics.lineTo(100, 100); shape.graphics.lineTo(0, 100); shape.graphics.lineTo(0, 0); shape.graphics.endFill(); // Position the shape on the Stage. addChild(shape); shape.x = 100; shape.y = 100; // Define a gradient glow. var gradientGlow:GradientGlowFilter = new GradientGlowFilter(); gradientGlow.distance = 0; gradientGlow.angle = 45; gradientGlow.colors = [0x000000, 0xFF0000]; gradientGlow.alphas = [0, 1]; gradientGlow.ratios = [0, 255]; gradientGlow.blurX = 10; gradientGlow.blurY = 10; gradientGlow.strength = 2; gradientGlow.quality = BitmapFilterQuality.HIGH; gradientGlow.type = BitmapFilterType.OUTER; // Define functions to listen for two events. function onClick(event:MouseEvent):void { gradientGlow.strength++; shape.filters = [gradientGlow]; } function onMouseMove(event:MouseEvent):void { gradientGlow.blurX = (stage.mouseX / stage.stageWidth) * 255; gradientGlow.blurY = (stage.mouseY / stage.stageHeight) * 255; shape.filters = [gradientGlow]; } stage.addEventListener(MouseEvent.CLICK, onClick); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); Příklad: Kombinování základních filtrů Následující příklad kódu používá několik základních filtrů kombinovaných s časovačem pro vytvoření opakujících se akcí, za účelem vytvoření animované simulace dopravních světel. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 359 Filtrování objektů zobrazení import import import import import import import import var var var var var var var var var var var var flash.display.Shape; flash.events.TimerEvent; flash.filters.BitmapFilterQuality; flash.filters.BitmapFilterType; flash.filters.DropShadowFilter; flash.filters.GlowFilter; flash.filters.GradientBevelFilter; flash.utils.Timer; count:Number = 1; distance:Number = 8; angleInDegrees:Number = 225; // opposite of 45 degrees colors:Array = [0xFFFFCC, 0xFEFE78, 0x8F8E01]; alphas:Array = [1, 0, 1]; ratios:Array = [0, 128, 255]; blurX:Number = 8; blurY:Number = 8; strength:Number = 1; quality:Number = BitmapFilterQuality.HIGH; type:String = BitmapFilterType.INNER; knockout:Boolean = false; // Draw the rectangle background for the traffic light. var box:Shape = new Shape(); box.graphics.lineStyle(); box.graphics.beginFill(0xFEFE78); box.graphics.drawRect(100, 50, 90, 200); box.graphics.endFill(); // Draw the 3 circles for the three lights. var stopLight:Shape = new Shape(); stopLight.graphics.lineStyle(); stopLight.graphics.beginFill(0xFF0000); stopLight.graphics.drawCircle(145,90,25); stopLight.graphics.endFill(); var cautionLight:Shape = new Shape(); cautionLight.graphics.lineStyle(); cautionLight.graphics.beginFill(0xFF9900); cautionLight.graphics.drawCircle(145,150,25); cautionLight.graphics.endFill(); var goLight:Shape = new Shape(); goLight.graphics.lineStyle(); goLight.graphics.beginFill(0x00CC00); goLight.graphics.drawCircle(145,210,25); goLight.graphics.endFill(); // Add the graphics to the display list. addChild(box); addChild(stopLight); addChild(cautionLight); addChild(goLight); // Apply a gradient bevel to the traffic light rectangle. var gradientBevel:GradientBevelFilter = new GradientBevelFilter(distance, angleInDegrees, colors, alphas, ratios, blurX, blurY, strength, quality, type, knockout); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 360 Filtrování objektů zobrazení box.filters = [gradientBevel]; // Create the inner shadow (for lights when off) and glow // (for lights when on). var innerShadow:DropShadowFilter = new DropShadowFilter(5, 45, 0, 0.5, 3, 3, 1, 1, true, false); var redGlow:GlowFilter = new GlowFilter(0xFF0000, 1, 30, 30, 1, 1, false, false); var yellowGlow:GlowFilter = new GlowFilter(0xFF9900, 1, 30, 30, 1, 1, false, false); var greenGlow:GlowFilter = new GlowFilter(0x00CC00, 1, 30, 30, 1, 1, false, false); // Set the starting state of the lights (green on, red/yellow off). stopLight.filters = [innerShadow]; cautionLight.filters = [innerShadow]; goLight.filters = [greenGlow]; // Swap the filters based on the count value. function trafficControl(event:TimerEvent):void { if (count == 4) { count = 1; } switch (count) { case 1: stopLight.filters = [innerShadow]; cautionLight.filters = [yellowGlow]; goLight.filters = [innerShadow]; break; case 2: stopLight.filters = [redGlow]; cautionLight.filters = [innerShadow]; goLight.filters = [innerShadow]; break; case 3: stopLight.filters = [innerShadow]; cautionLight.filters = [innerShadow]; goLight.filters = [greenGlow]; break; } count++; } // Create a timer to swap the filters at a 3 second interval. var timer:Timer = new Timer(3000, 9); timer.addEventListener(TimerEvent.TIMER, trafficControl); timer.start(); Filtr matice barev Třída ColorMatrixFilter se používá k manipulaci barvy a alfa hodnot filtrovaného objektu. To vám umožňuje měnit sytost, natočení odstínu (posunutí palety z jednoho rozpětí barvy do jiného), změny osvětlení na alfa a další práci s barevnými efekty pomocí hodnot z jednoho barevného kanálu a potenciálně je použít na jiné kanály. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 361 Filtrování objektů zobrazení Koncepčně filtr postupně prochází obrazovými body ve zdrojovém obrazu a rozděluje každý obrazový bod na jeho komponenty červené, zelené, modré a alfa. Poté pracuje s hodnotami poskytnutými v matrici barev každou z těchto hodnot, výsledky sečte a určí tak výslednou hodnotu barvy, která bude pro daný obrazový bod na obrazovce zobrazena. Vlastnost matrix filtru je pole obsahující 20 čísel, která jsou použita při výpočtu výsledné barvy. Podrobnosti o určitém algoritmu použitém k výpočtu hodnot barev naleznete v zápisu popisujícím vlastnost matrice třídy ColorMatrixFilter v Referenční příručce jazyka ActionScript 3.0 a jeho komponent. Další informace a příklady filtru matice barev naleznete v článku „ Používání matric pro transformace, úpravy barev a efekty konvoluce v programu Flash“ na internetové stránce Adobe Developer Center. Filtr konvoluce Třídu ConvolutionFilter lze použít k aplikování širokého rozpětí transformací obrazů na objekty BitmapData nebo na objekty zobrazení, například rozostření, detekce okraje, zostření, reliéf a úkos. Filtr konvoluce koncepčně prochází postupně každým obrazovým bodem ve zdrojovém obraze a určí konečnou barvu daného obrazového bodu pomocí hodnoty obrazového bodu a s ním sousedících bodů. Matice, specifikovaná jako pole s numerickými hodnotami, určuje, do jaké míry hodnota každého určitého sousedícího obrazového bodu ovlivňuje konečnou hodnotu. Vezměte v úvahu nejběžněji používaný typ matice, kterou je matice tři x tři. Matice obsahuje devět hodnot: N N N N P N N N N Jestliže přehrávač Flash Player nebo program AIR použije filtr konvoluce na určitý obrazový bod, zaměří se na hodnotu barvy samotného obrazového bodu (v příkladu označeno jako „P“), i na hodnoty okolních obrazových bodů (v příkladu označeno jako „N“). Nicméně nastavením hodnot v matrici můžete určit, jakou prioritu mají určité obrazové body v ovlivňování výsledného obrazu. Například následující matice použitá pomocí filtru konvoluce zachová obraz ve stejné podobně, jakou měl dříve: 0 0 0 0 1 0 0 0 0 Důvod, proč je obraz nezměněn, je, že původní hodnota obrazového bodu má v určení konečné barvy obrazového bodu relativní sílu 1, zatímco hodnoty okolních obrazových bodů mají relativní sílu 0 - což znamená, že jejich barvy neovlivňují výsledný obraz. Podobně tato matice způsobí posun obrazových bodů obrazu o jeden obrazový bod doleva: 0 0 0 0 0 0 0 1 0 Všimněte si, že v tomto případě nemá samotný obrazový bod žádný vliv na výslednou hodnotu obrazového bodu zobrazeného v daném umístění na výsledném obrazu - hodnota obrazového bodu napravo je pouze použita pro určení výsledné hodnoty obrazového bodu. V jazyku ActionScript vytvoříte matici jako kombinaci instance Array obsahující hodnoty a dvou vlastností obsahujících počet řádků a sloupců v matici. Následující příklad načte obraz a po dokončení načítání obrazu použije na obraz filtr konvoluce pomocí matice v předchozí ukázce: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 362 Filtrování objektů zobrazení // Load an image onto the Stage. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); loader.load(url); this.addChild(loader); function applyFilter(event:MouseEvent):void { // Create the convolution matrix. var matrix:Array = [0, 0, 0, 0, 0, 1, 0, 0, 0]; var convolution:ConvolutionFilter = new ConvolutionFilter(); convolution.matrixX = 3; convolution.matrixY = 3; convolution.matrix = matrix; convolution.divisor = 1; loader.filters = [convolution]; } loader.addEventListener(MouseEvent.CLICK, applyFilter); V tomto kódu není efekt použití hodnot v matici jiných než 1 nebo 0 zřejmý. Například stejná matice s číslem 8 namísto čísla 1 v pozici napravo provede stejnou akci (posunutí obrazových bodů doleva). Dále ovlivní barvy obrazu, které budou osmkrát jasnější. Důvodem je vypočtení výsledných hodnot barvy obrazových bodů vynásobením hodnot matice barvami původního obrazového bodu, sečtením hodnot a dělením hodnotou vlastnosti filtru divisor. Všimněte si, že v daném příklad kódu je vlastnost divisor nastavena na 1. Obecné pravidlo zní, že pokud si přejete, aby jas barev zůstal stejný jako v původním obraze, měl by se dělitel rovnat součtu hodnot matice. Takže v případě matice, kde součet hodnot představuje 8 a dělitel má hodnotu 1, bude výsledný obraz přibližně 8krát jasnější než původní obraz. Ačkoliv není efekt této matice dobře viditelný, jiné hodnoty matice lze použít pro vytvoření různých efektů. Zde je několik standardních sad hodnot matric pro odlišné efekty použitím matice tři krát tři: • Základní rozostření (dělitel 5): 0 1 0 1 1 1 0 1 0 • Zaostření (dělitel 1): 0, -1, 0 -1, 5, -1 0, -1, 0 • Detekce okrajů (dělitel 1): 0, -1, 0 -1, 4, -1 0, -1, 0 • Efekt reliéfu (dělitel 1): -2, -1, 0 -1, 1, 1 0, 1, 2 PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 363 Filtrování objektů zobrazení Všimněte si, že u většiny z těchto efektů je dělitel 1. Důvodem je to, že záporné hodnoty matice jsou přidány ke kladným hodnotám matice a výsledek bude 1 (nebo 0 v případě detekce okrajů, ale hodnota vlastnosti divisor nemůže být 0). Filtr mapy přestavění Třída DisplacementMapFilter používá hodnoty obrazových bodů z objektu BitmapData (známého jako obrazová mapa přemístění) k provedení efektu přemístění na novém objektu. Obraz mapy přestavění je obvykle odlišný od skutečného objektu zobrazení nebo instance BitmapData, na kterou se filtr použije. Efekt přestavění obsahuje vychýlení obrazových bodů v daném filtrovaném obrazu - jinými slovy, do určité míry přesun obrazových hodnot mimo jejich původní umístění. Tento filtr lze použít pro vytvoření posunutého a pokřiveného efektu, či efektu skvrn. Umístění a množství přestavění použitého na daný obrazový bod je určeno hodnotou barvy obrazu mapy přestavění. Při práci s filtrem určujete pro ovládání způsobu výpočtu přestavění z obrazu mapy vedle určení obrazu mapy následující hodnoty: • Bod mapy: Umístění na filtrovaném obrazu, kde se použije filtr přestavění horního levého rohu. Toho můžete využít, pouze pokud si přejete filtr použít na část obrazu. • Komponenta X: Jaký barevný kanál snímku mapy ovlivňuje polohu x obrazových bodů. • Komponenta Y: Jaký barevný kanál snímku mapy ovlivňuje polohu y obrazových bodů. • Měřítko X: Hodnota násobitele, která určuje, jak silné je přestavění osy x. • Měřítko Y: Hodnota násobitele, která určuje, jak silné je přestavění osy y. • Režim filtru: Určuje, co by měl přehrávač Flash Player nebo program AIR udělat v jakýchkoliv prázdných prostorech vytvořených posunem obrazových bodů mimo. Tyto možnosti, definované jako konstanty ve třídě DisplacementMapFilterMode, jsou určeny k zobrazení původních obrazových bodů (režim filtru IGNORE), pro zabalení obrazových bodů ze druhé strany obrazu (režim filtru WRAP, který je implicitní), pro použití nejbližšího posunutého obrazového bodu (režim filtru CLAMP), nebo pro vyplnění míst barvou (režim filtru COLOR). K pochopení, jak filtr mapy přemístění pracuje, si všimněte následujícího příkladu. V následujícím kódu je načten obraz a jakmile se stahování dokončí, je obraz vycentrován na ploše a je na něj použita mapa přestavěná, která způsobí celkový horizontální posun celého obrazu doleva. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 364 Filtrování objektů zobrazení import import import import import import flash.display.BitmapData; flash.display.Loader; flash.events.MouseEvent; flash.filters.DisplacementMapFilter; flash.geom.Point; flash.net.URLRequest; // Load an image onto the Stage. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image3.jpg"); loader.load(url); this.addChild(loader); var mapImage:BitmapData; var displacementMap:DisplacementMapFilter; // This function is called when the image finishes loading. function setupStage(event:Event):void { // Center the loaded image on the Stage. loader.x = (stage.stageWidth - loader.width) / 2; loader.y = (stage.stageHeight - loader.height) / 2; // Create the displacement map image. mapImage = new BitmapData(loader.width, loader.height, false, 0xFF0000); // Create the displacement filter. displacementMap = new DisplacementMapFilter(); displacementMap.mapBitmap = mapImage; displacementMap.mapPoint = new Point(0, 0); displacementMap.componentX = BitmapDataChannel.RED; displacementMap.scaleX = 250; loader.filters = [displacementMap]; } loader.contentLoaderInfo.addEventListener(Event.COMPLETE, setupStage); Vlastnosti použité k definování přestavění jsou následující: • Bitmapa mapy: Bitmapa přestavění je nová instance BitmapData vytvořená kódem. Její rozměry odpovídají rozměrům načteného obrazu (přestavění je tedy použito na celý obraz). Obraz je vyplněn plnými červenými obrazovými body. • Bod mapy: Tato hodnota je nastavena na bod 0, 0 - a opět způsobí, že přestavění je použito na celý snímek. • Komponenta X: Tato hodnota je nastavena na konstantu BitmapDataChannel.RED, což znamená, že červená hodnota bitmapy mapy určí, kolik obrazových bodů bude vychýleno (jak moc se pohybují) podél osy x. • Měřítko x: Tato hodnota je nastavena na 250. Úplné množství přestavění (z obrazu mapy, který je úplně červený) vychýlí snímek pouze o malé množství (přibližně o polovinu obrazového bodu), takže pokud je tato hodnota nastavena na 1, obraz se posune pouze o 0,5 obrazových bodů horizontálně. Nastavením této hodnoty na 250 se obraz posune přibližně o 125 obrazových bodů. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 365 Filtrování objektů zobrazení Toto nastavení způsobí posun obrazových bodů filtrovaného obrazu o 250 obrazových bodů doleva. Směr (vlevo nebo vpravo) a míra posunutí je určen hodnotou barvy obrazových bodů v obrazu mapy. Přehrávač Flash Player nebo program AIR koncepčně postupně projde obrazové body filtrovaného snímku (minimálně obrazové body v oblasti, kde je filtr použit, což v tomto případě znamená všechny obrazové body) a s každým obrazovým bodem provede následující: 1 Nalezne odpovídající obrazový bod v obrazu mapy. Například jestliže přehrávač Flash Player nebo program AIR vypočítává míru přestavění pro obrazové body v horním levém rohu filtrovaného snímku, zaměří se na obrazové body v levém horním rohu obrazu mapy. 2 Určuje hodnotu specifikovaného barevného kanálu v obrazovém bodu mapy. V tomto případě je barevný kanál komponenty x červeným kanálem, takže přehrávač Flash Player a program AIR zjistí, která hodnota červeného kanálu obrazu mapy je daný obrazový bod. Protože je obraz mapy plný červený, červený kanál obrazového bodu je 0xFF nebo 255. To je použito jako hodnota přestavění. 3 Porovná hodnotu přestavění se „středovou“ hodnotou (127, která je vždy v půlce mezi 0 a 255). Jestliže je hodnota přestavění nižší než středová hodnota, obrazový bod se posune kladným směrem (napravo pro přestavění x; dolů pro přestavění y). Je-li na druhou stranu hodnota přestavění vyšší než střední hodnota (jako v tomto příkladě), posune se obrazový bod záporným směrem (doleva pro přestavění x; nahoru pro přestavění y). Přesněji, přehrávač Flash Player a program AIR odečtou hodnotu přestavění od 127 a výsledkem (kladným nebo záporným) je poměrná hodnota přestavění, která je použita. 4 Nakonec určí skutečnou hodnotu posunu určením toho, jaké procento plného posunu představuje relativní hodnota posunu. V tomto případě znamená plná červená 100% posun. Toto procento je poté vynásobeno hodnotou stupnice x nebo y pro určení počtu obrazových bodů posunu, který bude použit. V tomto příkladě, 100% krát dělitel 250 určuje množství posunu - přibližně 125 obrazových bodů vlevo. Protože pro komponentu y a stupnici y nejsou určeny žádné hodnoty, použijí se hodnoty výchozí (které nevyvolají žádný posun)—to je důvod, proč se obraz ve vertikálním směru vůbec neposune. V příkladě je použito výchozí nastavení režimu filtru, WRAP, takže jakmile se obrazové body posunou doleva, prázdné místo napravo se vyplní obrazovými body, které posunuly pravý okraj obrazu. S touto hodnotou můžete experimentovat a zobrazit tak různé efekty. Pokud například přidáte následující řádek k části kódu, kde jsou nastavovány vlastnosti posunu (před řádek loader.filters = [displacementMap]), bude obraz vypadat, jako by byl rozmazán přes plochu: displacementMap.mode = DisplacementMapFilterMode.CLAMP; U složitějšího případu ukazuje následující ukázka filtr mapy posunu pro vytvoření efektu skla na obraze: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 366 Filtrování objektů zobrazení import import import import import import import import import import import import flash.display.Bitmap; flash.display.BitmapData; flash.display.BitmapDataChannel; flash.display.GradientType; flash.display.Loader; flash.display.Shape; flash.events.MouseEvent; flash.filters.DisplacementMapFilter; flash.filters.DisplacementMapFilterMode; flash.geom.Matrix; flash.geom.Point; flash.net.URLRequest; // Create the gradient circles that will together form the // displacement map image var radius:uint = 50; var type:String = GradientType.LINEAR; var redColors:Array = [0xFF0000, 0x000000]; var blueColors:Array = [0x0000FF, 0x000000]; var alphas:Array = [1, 1]; var ratios:Array = [0, 255]; var xMatrix:Matrix = new Matrix(); xMatrix.createGradientBox(radius * 2, radius * 2); var yMatrix:Matrix = new Matrix(); yMatrix.createGradientBox(radius * 2, radius * 2, Math.PI / 2); var xCircle:Shape = new Shape(); xCircle.graphics.lineStyle(0, 0, 0); xCircle.graphics.beginGradientFill(type, redColors, alphas, ratios, xMatrix); xCircle.graphics.drawCircle(radius, radius, radius); var yCircle:Shape = new Shape(); yCircle.graphics.lineStyle(0, 0, 0); yCircle.graphics.beginGradientFill(type, blueColors, alphas, ratios, yMatrix); yCircle.graphics.drawCircle(radius, radius, radius); // Position the circles at the bottom of the screen, for reference. this.addChild(xCircle); xCircle.y = stage.stageHeight - xCircle.height; this.addChild(yCircle); yCircle.y = stage.stageHeight - yCircle.height; yCircle.x = 200; // Load an image onto the Stage. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); loader.load(url); this.addChild(loader); // Create the map image by combining the two gradient circles. var map:BitmapData = new BitmapData(xCircle.width, xCircle.height, false, 0x7F7F7F); map.draw(xCircle); var yMap:BitmapData = new BitmapData(yCircle.width, yCircle.height, false, 0x7F7F7F); yMap.draw(yCircle); map.copyChannel(yMap, yMap.rect, new Point(0, 0), BitmapDataChannel.BLUE, BitmapDataChannel.BLUE); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 367 Filtrování objektů zobrazení yMap.dispose(); // Display the map image on the Stage, for reference. var mapBitmap:Bitmap = new Bitmap(map); this.addChild(mapBitmap); mapBitmap.x = 400; mapBitmap.y = stage.stageHeight - mapBitmap.height; // This function creates the displacement map filter at the mouse location. function magnify():void { // Position the filter. var filterX:Number = (loader.mouseX) - (map.width / 2); var filterY:Number = (loader.mouseY) - (map.height / 2); var pt:Point = new Point(filterX, filterY); var xyFilter:DisplacementMapFilter = new DisplacementMapFilter(); xyFilter.mapBitmap = map; xyFilter.mapPoint = pt; // The red in the map image will control x displacement. xyFilter.componentX = BitmapDataChannel.RED; // The blue in the map image will control y displacement. xyFilter.componentY = BitmapDataChannel.BLUE; xyFilter.scaleX = 35; xyFilter.scaleY = 35; xyFilter.mode = DisplacementMapFilterMode.IGNORE; loader.filters = [xyFilter]; } // This function is called when the mouse moves. If the mouse is // over the loaded image, it applies the filter. function moveMagnifier(event:MouseEvent):void { if (loader.hitTestPoint(loader.mouseX, loader.mouseY)) { magnify(); } } loader.addEventListener(MouseEvent.MOUSE_MOVE, moveMagnifier); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 368 Filtrování objektů zobrazení Kód nejprve vygeneruje dva přechodové kruhy, které jsou zkombinovány a vytvářejí obraz mapy přestavění. Červený kruh vytvoří přestavění osy x xyFilter.componentX = BitmapDataChannel.RED) a modrý kruh vytvoří přestavění osy y(xyFilter.componentY = BitmapDataChannel.BLUE). Abyste pochopili, jak obraz mapy přestavění vypadá, přidá kód původní kruhy i kombinovaný kruh, který slouží jako obraz mapy na spodní část obrazovky. Kód poté načte obraz a při pohybu myší použije filtr přestavění na část obrazu, která leží pod myší. Přechodové kruhy použité jako obraz mapy přestavění způsobí, že se oblast přestavění rozšíří směrem od kurzoru myši. Všimněte si, že šedé oblasti obrazu mapy přestavění žádné přestavění nezpůsobí. Šedá barva je 0x7F7F7F. Modré a červené kanály daného odstínu šedé přesně odpovídají střednímu odstínu těchto barevných kanálů, takže v šedé oblasti obrazu mapy nedojde k žádnému přestavění. Podobně také ve středu kruhu nedojde k žádnému přestavění. Ačkoliv barva není šedá, modrý a červený kanál dané barvy jsou identické s modrým a červeným kanálem středně šedé, a protože jsou modrá a červená barvy, které způsobují přestavění, nedojde zde k žádnému přestavění. Filtr clony Třída ShaderFilter vám umožňuje použít vlastní efekt filtru definovaný jako shader Pixel Bender. Protože je daný filtr zapsán jako clona Pixel Bender, daný efekt lze kompletně upravit dle potřeby. Filtrovaný obsah je předán do clony jako vstup obrazu a výsledek operace clony se stane výsledkem filtru. Poznámka: Filtr clony je dostupný od verzí Flash Player 10 a Adobe AIR 1.5. Pro použití filtru clony na objekt nejprve vytvořte instanci Shader reprezentující clonu Pixel Bender, kterou používáte. Více podrobností o postupu vytvoření instance Shader a o způsobu určení vstupního obrazu a hodnot parametru naleznete v části „Práce s shadery Pixel Bender“ na stránce 376. Při používání clony jako filtru si je třeba zapamatovat tři důležité věci: • Clona musí být definována tak, aby přijala minimálně jeden vstupní obraz. • Filtrovaný objekt (objekt zobrazení nebo objekt BitmapData, na který je daný filtr použit) je předán ke cloně jako první hodnota vstupního obrazu. Z tohoto důvodu byste neměli ručně určit hodnotu pro první vstup obrazu. • Jestliže clona definuje více než jeden vstupní obraz, dodatečné vstupy musí být specifikovány ručně (tj. nastavením vlastnosti input libovolné instance ShaderInput, která patří k instanci Shader). PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 369 Filtrování objektů zobrazení Jakmile máte objekt Shader pro vaši clonu, vytvoříte instanci ShaderFilter. Jedná se o skutečný objekt filtru, který používáte jako všechny ostatní filtry. Pro vytvoření ShaderFilter, který používá objekt Shader, volejte konstruktor ShaderFilter() a předejte objekt Shader jako argument, viz. následující ukázka: var myFilter:ShaderFilter = new ShaderFilter(myShader); Kompletní příklad používání filtru shaderu naleznete v tématu „Použití shaderu jako filtru“ na stránce 393. Příklad: Filter Workbench Aplikace Filter Workbench poskytuje uživatelské rozhraní pro použití různých filtrů na obrazy a jiný vizuální obsah a zobrazení výsledného kódu, který lze použít pro vytvoření stejného efektu v jazyce ActionScript. Vedle poskytování nástroje pro pokusy s filtry, tato aplikace ukazuje následující techniky: • Vytváření instancí různých filtrů • Používání více filtrů na objekt zobrazení Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace Filter Workbench lze nalézt ve složce Samples/FilterWorkbench. Aplikace sestává z následujících souborů: Soubor Popis com/example/programmingas3/filterWorkbench/FilterWorkbenchController.as Třída, která poskytuje hlavní funkce aplikace, včetně přepínání obsahu, na který jsou soubory použity a používání filtrů na obsah. com/example/programmingas3/filterWorkbench/IFilterFactory.as Rozhraní definující společné metody, které jsou implementovány každou ze tříd rodiny filtru. Toto rozhranní definuje společné funkce, které třída FilterWorkbenchController používá pro interakci s jednotlivými třídami rodiny filtrů. ve složce com/example/programmingas3/filterWorkbench/: Sada tříd, kde každá z nich implementuje rozhraní IFilterFactory. Každá z těchto tříd poskytuje funkce vytváření a nastavování hodnot pro jediný typ filtru. Panely vlastnosti filtru v aplikaci používají tyto třídy rodiny pro vytváření instancí svých určitých filtrů, které třída FilterWorkbenchController dosazuje a používá na obsah obrazu. BevelFactory.as BlurFactory.as ColorMatrixFactory.as ConvolutionFactory.as DropShadowFactory.as GlowFactory.as GradientBevelFactory.as GradientGlowFactory.as com/example/programmingas3/filterWorkbench/IFilterPanel.as Rozhranní definující společné metody implementované třídami definující panely rozhraní uživatele, které jsou použity pro manipulaci hodnotami filtrů v dané aplikaci. com/example/programmingas3/filterWorkbench/ColorStringFormatter.as Třída utility, která zahrnuje metodu pro převedení numerické hodnoty barvy na hexadecimální formát řetězce. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 370 Filtrování objektů zobrazení Soubor Popis com/example/programmingas3/filterWorkbench/GradientColor.as Třída, která slouží jako objekt hodnoty, kombinuje do jediného objektu tři hodnoty (barva, alfa a poměr), které jsou spojeny s každou barvou v GradientBevelFilter a GradientGlowFilter Uživatelské rozhraní (Flash) FilterWorkbench.fla Hlavní soubor definující uživatelské rozhraní aplikace. flashapp/FilterWorkbench.as Třída, která poskytuje funkce pro hlavní uživatelské rozhraní aplikace; tato třída je používána jako třída dokumentu pro soubor FLA aplikace. Ve složce flashapp/filterPanels: Sada tříd, která poskytuje funkci pro každý panel použitý při nastavení voleb pro jediný filtr. BevelPanel.as BlurPanel.as ColorMatrixPanel.as ConvolutionPanel.as DropShadowPanel.as Pro každou třídu také existuje přidružený symbol MovieClip v knihovně hlavního souboru aplikace FLA, jehož název odpovídá názvu dané třídy (například symbol „BlurPanel“ je propojen s třídou definovanou v BlurPanel.as). Komponenty vytvářející uživatelské rozhraní jsou umístěny a pojmenovány v rámci těchto symbolů. GlowPanel.as GradientBevelPanel.as GradientGlowPanel.as flashapp/ImageContainer.as Objekt zobrazení, který slouží jako kontejner pro načtený snímek na obrazovce. flashapp/BGColorCellRenderer.as Vlastní objekt pro vykreslení buňky použitý pro změnu barvy pozadí buňky v komponentě DataGrid flashapp/ButtonCellRenderer.as Vlastní objekt pro vykreslení buňky použitý pro zahrnutí komponenty tlačítka do buňky v komponentě DataGrid Obsah filtrovaného snímku com/example/programmingas3/filterWorkbench/ImageType.as Tato třída slouží jako objekt hodnoty obsahující typ a URL jediného souboru obrazu, který může aplikace načíst a na který může použít filtry. Třída také obsahuje sadu konstant reprezentujících skutečné dostupné soubory obrazu. images/sampleAnimation.swf, Obrazy a jiný vizuální obsah, na který jsou filtry v aplikaci použity. images/sampleImage1.jpg, images/sampleImage2.jpg Experimentování s filtry jazyka ActionScript Aplikace Filter Workbench je navržena tak, aby vám pomohla při pokusech s různými efekty filtrů a vytváření relevantního kódu jazyka ActionScript pro daný efekt. Aplikace vám umožňuje výběr ze tří odlišných souborů zahrnujících vizuální obsah, včetně obrazů bitmap a animace vytvořené nástrojem Flash, a použití osmi odlišných filtrů jazyka ActionScript na zvolený obraz, a to buď jednotlivě nebo v kombinaci s jinými filtry. Aplikace zahrnuje následující filtry: • Úkos (flash.filters.BevelFilter) PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 371 Filtrování objektů zobrazení • Rozostření (flash.filters.BlurFilter) • Matice barvy (flash.filters.ColorMatrixFilter) • Konvoluce (flash.filters.ConvolutionFilter) • Vržený stín (flash.filters.DropShadowFilter) • Záře (flash.filters.GlowFilter) • Úkos s přechodem (flash.filters.GradientBevelFilter) • Záře s přechodem (flash.filters.GradientGlowFilter) Jakmile uživatel vybere obraz a filtr, který bude na daný obraz použit, aplikace zobrazí panel s ovládáním pro nastavení specifických vlastností zvoleného filtru. Například následující obraz zobrazí aplikaci s vybraným filtrem úkosu: Jakmile uživatel nastaví vlastnosti filtru, náhled se aktualizuje v reálném čase. Uživatel může také použít více filtrů, a to vlastním nastavením jednoho filtru, klepnutím na tlačítko Použít, vlastním nastavením jiného filtru, klepnutím na tlačítko Použít, atd. Na panelech filtrů aplikace existuje několik funkcí a omezení: • Filtr matice barev zahrnuje sadu ovládání pro přímé zpracovávání společných vlastností obrazu včetně jasu, kontrastu, sytosti a odstínu. Dále lze určit vlastní hodnoty matice barev. • Filtr konvoluce, který je dostupný pouze pomocí jazyka ActionScript, zahrnuje sadu běžně používaných hodnot matice konvoluce, nebo můžete určit vlastní hodnoty. Nicméně zatímco třída ConvolutionFilter přijímá matici libovolné velikosti, aplikace Filter Workbench používá fixní matici 3 x 3, nejběžněji používanou velikost filtru. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 372 Filtrování objektů zobrazení • Filtr mapy přestavění a filtr clony, které jsou dostupné pouze v jazyku ActionScript, nejsou dostupné v aplikaci Filter Workbench. Filtr mapy přestavění vyžaduje vedle obsahu filtrovaného obrazu mapu obrazu. Obraz mapy filtru mapy přestavění je primární výstup, který určuje výsledek filtru, takže bez schopnosti načíst nebo vytvořit obraz mapy by byla schopnost experimentovat s filtrem mapy přestavění velice omezená. Podobně filtr clony vyžaduje vedle obsahu filtrovaného obsahu bytový kód Pixel Bender. Bez schopnosti načíst bytový kód clony je nemožné filtr clony použít. Vytváření instancí filtrů Aplikace Filter Workbench obsahuje sadu tříd, jednu pro každý z dostupných filtrů, které jsou použity jednotlivými panely pro vytvoření filtrů. Když uživatel vybere filtr, kód jazyka ActionScript připojený k panelu filtru vytvoří instanci příslušné třídy rodiny filtru. (Tyto třídy jsou známé jako factory classes, protože jejich účelem je vytvoření instancí jiných objektů, stejně jako továrny v reálném světě vytvářejí jednotlivé produkty.) Kdykoliv uživatel změní hodnotu vlastnosti na panelu, kód panelu volá příslušnou metodu ve třídě rodiny. Každá třída rodiny zahrnuje specifické metody, které panel používá pro vytvoření instance příslušného filtru. Jestliže uživatel například vybere filtr rozostření, aplikace vytvoří instanci BlurFactory. Třída BlurFactory zahrnuje metodu modifyFilter(), která přijímá tři parametry: blurX, blurYa quality, které jsou dohromady použity pro vytvoření požadované instance BlurFilter: private var _filter:BlurFilter; public function modifyFilter(blurX:Number = 4, blurY:Number = 4, quality:int = 1):void { _filter = new BlurFilter(blurX, blurY, quality); dispatchEvent(new Event(Event.CHANGE)); } Jestliže uživatel naopak vybere filtr konvoluce, daný filtr umožní o mnoho větší flexibilitu a následně nabízí větší sadu vlastností k ovládání. Když uživatel vybere na panelu filtru odlišnou hodnotu, je ve třídě ConvolutionFactory volán následující kód: private var _filter:ConvolutionFilter; public function modifyFilter(matrixX:Number = 0, matrixY:Number = 0, matrix:Array = null, divisor:Number = 1.0, bias:Number = 0.0, preserveAlpha:Boolean = true, clamp:Boolean = true, color:uint = 0, alpha:Number = 0.0):void { _filter = new ConvolutionFilter(matrixX, matrixY, matrix, divisor, bias, preserveAlpha, clamp, color, alpha); dispatchEvent(new Event(Event.CHANGE)); } Všimněte si, že v každém případě změny hodnot filtru, odešle objekt rodiny událost Event.CHANGE a upozorní tak posluchače, že hodnoty filtru byly změněny. Třída FilterWorkbenchController, která vlastně používá filtry na filtrovaný obsah, poslouchá danou událost pro zjištění, kdy musí získat novou kopii filtru a znovu jí použít na filtrovaný obsah. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 373 Filtrování objektů zobrazení Třída FilterWorkbenchController nepotřebuje znát specifické detaily každé třídy rodiny filtru - potřebuje pouze vědět, že se filtr změnil a musí být schopna získat přístup ke kopii filtru. Proto aplikace obsahuje rozhraní IFilterFactory definující chování, které třída rodiny filtru musí poskytnout, aby mohla instance aplikace FilterWorkbenchController provést svoji funkci. IFilterFactory definuje metodu getFilter(), která je použita ve třídě FilterWorkbenchController: function getFilter():BitmapFilter; Všimněte si, že definice metody rozhraní getFilter() určuje, že metoda vrátí instanci BitmapFilter, spíše než specifický typ filtru. Třída BitmapFilter nedefinuje specifický typ filtru. BitmapFilter je spíše základní třídou, na které jsou všechny filtry vystavěny. Každá třída rodiny filtru definuje specifickou implementaci metody getFilter(), ve které metoda vrátí referenci na daný objekt filtru, který vytvořila. Zde je například zkrácená verze zdrojového kódu třídy ConvolutionFactory: public class ConvolutionFactory extends EventDispatcher implements IFilterFactory { // ------- Private vars ------private var _filter:ConvolutionFilter; ... // ------- IFilterFactory implementation ------public function getFilter():BitmapFilter { return _filter; } ... } V implementaci třídy ConvolutionFactory metody getFilter() vrátí instanci ConvolutionFilter, ačkoliv libovolný objekt volající metodu getFilter() nemusí nutně vědět, že - podle definice metody getFilter(), která následuje ConvolutionFactory, musí vrátit libovolnou instanci BitmapFilter, což by mohla být instance libovolné třídy jazyka ActionScript. Používání filtrů na objekty zobrazení Jak bylo vysvětleno v předchozí části, aplikace Workbench používá instanci třídy FilterWorkbenchController (dále uváděnou jako „instance ovladače“), která provádí skutečnou úlohu použití filtrů na vybraný vizuální objekt. Před tím, než může instance kontroleru použít filtr, potřebuje nejprve znát, na který obraz nebo vizuální obsah by měl být filtr použit. Když uživatel vybere obraz, aplikace volá metodu setFilterTarget() ve třídě FilterWorkbenchController a předá jednu z konstant definovanou ve třídě ImageType: public function setFilterTarget(targetType:ImageType):void { ... _loader = new Loader(); ... _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, targetLoadComplete); ... } Pomocí dané informace načte instance ovladače určený soubor a jakmile se načte, uchová jej v proměnné instance pojmenované _currentTarget: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 374 Filtrování objektů zobrazení private var _currentTarget:DisplayObject; private function targetLoadComplete(event:Event):void { ... _currentTarget = _loader.content; ... } Když uživatel vybere filtr, aplikace volá metodu ovladače instance setFilter() a předá ovladači referenci na příslušný objekt rodiny filtru, kterou uchovává v proměnné instance pojmenované _filterFactory. private var _filterFactory:IFilterFactory; public function setFilter(factory:IFilterFactory):void { ... _filterFactory = factory; _filterFactory.addEventListener(Event.CHANGE, filterChange); } Všimněte si, že jak již bylo popsáno výše, instance ovladače nezná určitý datový typ instance rodiny filtru, který je zadán; instance ovladače pouze ví, že daný objekt implementuje instanci IFilterFactory, což znamená, že má metodu getFilter() a při změně filtru odesílá událost change (Event.CHANGE). Když uživatel změní vlastnosti filtru na panelu filtrů, instance ovladače zjistí, že se filtr změnil pomocí události rodiny filtru change, která volá metodu instance ovladače filterChange(). Daná metoda naopak volá metodu applyTemporaryFilter(): private function filterChange(event:Event):void { applyTemporaryFilter(); } private function applyTemporaryFilter():void { var currentFilter:BitmapFilter = _filterFactory.getFilter(); // Add the current filter to the set temporarily _currentFilters.push(currentFilter); // Refresh the filter set of the filter target _currentTarget.filters = _currentFilters; // Remove the current filter from the set // (This doesn't remove it from the filter target, since // the target uses a copy of the filters array internally.) _currentFilters.pop(); } K použití filtru na objekt zobrazení dochází v rámci metody applyTemporaryFilter(). Ovladač nejprve získá referenci na objekt filtru vyvoláním metody rodiny filtru getFilter(). var currentFilter:BitmapFilter = _filterFactory.getFilter(); Instance ovladače má proměnnou instance Array pojmenovanou _currentFilters, ve které uchovává všechny filtry, které byly na objekt zobrazení použity. Dalším krokem je přidání nově aktualizovaného filtru do daného pole: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 375 Filtrování objektů zobrazení _currentFilters.push(currentFilter); Dále kód přiřadí pole filtrů vlastnosti objektu zobrazení filters, která vlastně dané filtry použije na obraz: _currentTarget.filters = _currentFilters; Nakonec, protože je tento nejnověji přidaný filtr stále aktivním filtrem, neměl by být permanentně použit na objekt zobrazení a je tedy odstraněn z pole _currentFilters: _currentFilters.pop(); Odstranění tohoto filtru z pole neovlivní filtrovaný objekt zobrazení, protože objekt zobrazení vytvoří při přiřazení k vlastnosti filters kopii pole filtrů a použije dané interní pole spíše než pole původní. Z tohoto důvodu neovlivní žádné změny provedené v poli filtrů objekt zobrazení, pokud dané pole není opět přiřazeno vlastnosti objektu zobrazení filters. 376 Kapitola 17: Práce s shadery Pixel Bender Sada nástrojů Adobe Pixel Bender umožňuje vývojovým pracovníkům psát shadery, které vytvářejí grafické efekty a provádějí jiná zpracování obrazů a dat. Bytový kód sady Pixel Bender lze provést v jazyku ActionScript k použití efektu na obrazová data nebo vizuální obsah. Použití shaderů Pixel Bender v jazyku ActionScript vám poskytne kapacitu pro vytváření vlastních vizuálních efektů a provádění zpracování dat přesahující vestavěné schopnosti jazyka ActionScript. Poznámka: Podpora sady nástrojů Pixel Bender je dostupná od verzí Flash Player 10 a Adobe AIR 1.5. Základy shaderů Pixel Bender Úvod k práci se shadery Pixel Bender Adobe Pixel Bender je programovací jazyk, který se používá k vytvoření nebo manipulaci obsahem obrazu. Pomocí jazyka Pixel Bender vytvoříte jádro, kterému se v tomto dokumentu také říká shader. Shader definuje jedinou funkci, která je provedena na každém obrazovém bodu obrazu individuálně. Výsledek každého volání funkce je výstupní barva na zadaných souřadnicích obrazového bodu v obraze. Vstupní hodnoty obrazů a parametrů lze určit k vlastní úpravě operace. V jediném provedení shaderu jsou vstupní hodnoty a hodnoty parametru konstantní. Jediná věc, která se mění, je souřadnice obrazového bodu, jehož barva je výsledkem volání funkce. Pokud je to možné, funkce shaderu je volána pro více výstupních souřadnic obrazového pole paralelně. Tím dojde k vylepšení výkonu shaderu a můžete využít zpracovávání s vysokým výkonem. V programech Flash Player a Adobe AIR lze pomocí shaderu snadno vytvořit tři typy efektů. • Výplň kresby • režim prolnutí • filtr Shader lze také provést v nezávislém režimu. Pomocí nezávislého režimu můžete k výsledku shaderu získat přístup přímo, místo toho, abyste předem určili jeho zamýšlené použití. K výsledku můžete získat přístup jako k obrazovým datům nebo jako k binárním či numerickým datům. Daná data nemusí být vůbec data obrazu. Takto můžete udělit shaderu množinu dat jako vstup. Shader zpracovává data a k výsledným datům vráceným daným shaderem můžete získat přístup. Poznámka: Podpora sady nástrojů Pixel Bender je dostupná od verzí Flash Player 10 a Adobe AIR 1.5. Běžné úlohy shaderů Pixel Bender Následující úlohy představují výsledky, kterých budete pravděpodobně chtít použitím filtrů v jazyce ActionScript dosáhnout: • Načtení shaderu do běžící SWF aplikace nebo vložení shaderu v době kompilace a přístup v době běhu. • Přístup k metadatům shaderu • Identifikace a určení hodnoty pro vstupy shaderu (obvykle obrazy) • Identifikace a určování hodnot pro parametry shaderu PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 377 Práce s shadery Pixel Bender • Shader můžete použít následujícími způsoby: • Jako výplň kresby • Jako režim prolnutí • Jako filtr • V nezávislém režimu Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny, na které narazíte v této kapitole: • Jádro: v Pixel Bender je jádro shodné se shaderem. Pomocí Pixel Bender definuje váš kód jádro, které definuje jedinou funkci provádějící na každém obrazovém bodu obraz individuálně. • Bajtový kód Pixel Bender: při kompilaci jádra Pixel Bender je jádro transformováno do bajtového kódu Pixel Bender. K bajtovému kódu můžete získat přístup a provést jej programem Flash Player nebo Adobe AIR v době běhu. • Jazyk Pixel Bender: programovací jazyk použitý k vytvoření jádra Pixel Bender. • Sada nástrojů Pixel Bender: aplikace použitá k vytvoření souboru bajtového kódu Pixel Bender ze zdrojového kódu Pixel Bender. Sada nástrojů vám vždy umožňuje zapsat, testovat a kompilovat zdrojový kód Pixel Bender. • Shader: pro účely tohoto dokumentu je shader sada funkcí zapsaných v jazyce Pixel Bender. Kód shaderu vytvoří vizuální efekt nebo provede výpočet. V obou případech vrátí shader sadu dat (obvykle obrazové body snímku). Shader provede stejnou operaci na každém datovém bodu, kdy jediným rozdílem jsou souřadnice výstupního obrazového bodu. Shader není zapsán v jazyce ActionScript. Je zapsán v jazyce Pixel Bender a kompilován do bajtového kódu Pixel Bender. Shader lze vložit do souboru SWF v době kompilace nebo jej lze načíst jako externí soubor v době běhu. V obou případech je k shaderu získáván přístup v jazyce ActionScript vytvořením objektu Shader a propojením daného objektu s bajtovým kódem shaderu. • Vstup shaderu: komplexní vstup, obvykle data obrazu bitmapy, který je poskytnut shaderu k použití ve výpočtech shaderu. Pro každou proměnnou vstupu definovanou v shaderu je jediná hodnota (tj. jediný obraz nebo binární data) použita pro celé provedení shaderu. • Parametr shaderu: jediná hodnota (nebo limitovaná množina hodnot), která je poskytnuta shaderu k použití ve výpočtech. Každá hodnota parametru je definována pro jediné provedení shaderu a stejná hodnota je použita během celého provádění shaderu. Procházení příkladů v kapitole Při práci s kapitolou si můžete přát otestovat ukázky kódů, které jsou k dispozici. Protože se tato kapitola věnuje vytváření a zpracovávání vizuálního obsahu, testování kódu zahrnuje spuštění kódu a zobrazení výsledků v souboru SWF, který je vytvořen. Všechny příklady vytváří pomocí kreslicích rozhraní API obsah, který používá efekt shaderu nebo je pomocí tohoto efektu upraven. Většina z příkladů kódu zahrnuje dvě části. Jedná část je zdrojový kód Pixel Bender pro shader použitý v daném příkladu. Nejprve musíte použít sadu nástrojů Pixel Bender ke kompilaci zdrojového kódu na soubor bajtového kódu Pixel Bender. Podle těchto kroků vytvoříte soubor bajtového kódu Pixel Bender: 1 Otevřete sadu nástrojů Adobe Pixel Bender. V případě potřeby vyberte z nabídky Build možnost „Zapnout varování a chyby Flash Player“. 2 Zkopírujte výpis kódu Pixel Bender a vložte jej do panelu editoru kódu sady nástrojů Pixel Bender. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 378 Práce s shadery Pixel Bender 3 Z nabídky Soubor vyberte možnost „Exportovat filtr jádra pro Flash Player“. 4 Uložte soubor bajtového kódu Pixel Bender do stejného adresáře jako dokument Flash. Název souboru by měl odpovídat názvu zadanému v popisu příkladu. Část jazyka ActionScript každého příkladu je zapsána jako soubor třídy. Testování příkladu: 1 Vytvořte prázdný dokument Flash a uložte ho ve svém počítači. 2 Vytvořte nový soubor ActionScript a uložte ho do stejného adresáře jako dokument Flash. Název souboru by měl být stejný jako název třídy ve výpisu kódu. Jestliže například výpis kódu definuje třídu s názvem MyApplication, použijte k uložení souboru ActionScript název MyApplication.as. 3 Zkopírujte výpis kódu do souboru ActionScript a soubor uložte. 4 V dokumentu Flash klepněte na prázdnou část Plochy nebo pracovní oblasti a aktivujte Inspektor vlastností dokumentu. 5 V Inspektoru vlastností zadejte do pole Třída dokumentu název třídy ActionScript vykopírovaný z textu. 6 Spusťte program pomocí volby Ovládání > Testovat film Výsledky příkladu se zobrazí v okně náhledu. Tyto techniky testování příkladu kódu jsou vysvětleny podrobněji v kapitole „Testování příkladů kódu v této kapitole“ na stránce 34. Načtení nebo vložení shaderu Prvním krokem je použití shaderu Pixel Bender v jazyku ActionScript k získání přístupu k shaderu ve vašem kódu ActionScript. Protože shader je vytvořen pomocí sady nástrojů Adobe Pixel Bender a napsán v jazyku Pixel Bender, nemůže být v jazyku ActionScript použit přímo. Musíte nejprve vytvořit instanci třídy Shader, která bude zastupovat shader Pixel Bender v jazyku ActionScript. Objekt Shader umožňuje zjistit informace o shaderu, např. jestli očekává parametry nebo vstupní obrazové hodnoty. Chcete-li shader skutečně použít, předáte objekt Shader jiným objektům. Například, chcete-li použít shader jako filtr, přiřadíte objekt Shader vlastnosti shader objektu ShaderFilter. Nebo chcete-li použít shader jako výplň kresby, předáte objekt Shader jako argument metodě Graphics.beginShaderFill(). Váš kód ActionScript se k shaderu vytvořenému pomocí sady nástrojů Adobe Pixel Bender (soubor .pbj) může dostat dvěma způsoby: • Načtený při běhu: soubor shaderu je možno načíst jako externí datový zdroj pomocí objektu URLLoader. Tato technika je jako načítání externího datového zdroje, např. textového souboru. Následující příklad demonstruje načtení souboru bytového kódu shaderu za běhu a jeho propojení s instancí Shader: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 379 Práce s shadery Pixel Bender var loader:URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("myShader.pbj")); var shader:Shader; function onLoadComplete(event:Event):void { // Create a new shader and set the loaded data as its bytecode shader = new Shader(); shader.byteCode = loader.data; // You can also pass the bytecode to the Shader() constructor like this: // shader = new Shader(loader.data); // do something with the shader } • Vložený v souboru SWF: soubor shaderu může být vložený v souboru SWF při kompilaci pomocí tagu metadat [Embed]. Tag metadat [Embed] je dostupný, pouze použijete-li ke kompilaci SWF souboru aplikaci Flex SDK. Parametr source tagu [Embed] ukazuje na soubor shaderu a jeho parametr mimeType je "application/octetstream", jako v následujícím příkladu: [Embed(source="myShader.pbj", mimeType="application/octet-stream")] var MyShaderClass:Class; // ... // create a shader and set the embedded shader as its bytecode var shaderShader = new Shader(); shader.byteCode = new MyShaderClass(); // You can also pass the bytecode to the Shader() constructor like this: // var shader:Shader = new Shader(new MyShaderClass()); // do something with the shader V obou případech spojujete nezpracovaný bytový kód shaderu (vlastnost URLLoader.data nebo instanci datové třídy [Embed]) s instancí Shader. Jak je vidět na předcházejících příkladech, bytový kód shaderu můžete přiřadit k instanci Shader dvěma způsoby. Můžete zadat bytový kód shaderu jako argument konstruktoru Shader(). Případně můžete nastavit vlastnost byteCode instance Shader. Jakmile byl vytvořen objekt Shader a navázán na objekt Shader, můžete použít shader k vytváření efektů několika způsoby. Můžete jej použít jako filtr, režim prolnutí, bitmapovou výplň nebo pro nezávislé zpracování bitmapy nebo jiných dat. Pomocí vlastnosti data objektu Shader se také můžete dostat k metadatům shaderu, určit vstupní obrazy a nastavit hodnoty parametrů. Přístup k metadatům shaderu Při vytváření jádra shaderu Pixel Bender může autor určit metadata o shaderu ve zdrojovém kódu Pixel Bender. Při vytváření shaderu v kódu ActionScript můžete shader prověřit a vyjmout jeho metadata. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 380 Práce s shadery Pixel Bender Když vytváříte instanci Shader a navazujete ji na shader Pixel Bender, bude vytvořen objekt ShaderData obsahující data o shaderu a uložen do vlastnosti data objektu Shader. Třída ShaderData nedefinuje žádné svoje vlastní vlastnosti. Při běhu je však vlastnost dynamicky přidána k objektu ShaderData pro každou hodnotu metadat definovanou ve zdrojovém kódu shaderu. Název udělený každé vlastnosti je stejný jako název určený v metadatech. Například dejme tomu, že zdrojový kód shaderu Pixel Bender obsahuje následující definici metadat: namespace : "Adobe::Example"; vendor : "Bob Jones"; version : 1; description : "Creates a version of the specified image with the specified brightness."; Objekt ShaderData vytvořený pro daný shader je vytvořen s následujícími vlastnostmi a hodnotami: • namespace (String): "Adobe::Example" • vendor (String): "Bob Jones" • version (String): "1" • description (String): "Creates a version of the specified image with the specified brightness" Protože vlastnosti metadat jsou dynamicky přidávány k objektu ShaderData, můžete pomocí smyčky for..in prověřit objekt ShaderData. Pomocí této techniky můžete zjistit, jestli má shader nějaká metadata a jaké jsou jejich hodnoty. Kromě vlastností metadata může mít objekt ShaderData vlastnosti představující vstupy a parametry, které jsou definované v shaderu. Při použití smyčky for..in k prověření objektu ShaderData zkontrolujte typ dat jednotlivých vlastností, abyste určili, jestli je vlastnost vstup (instance ShaderInput), parametr (instance ShaderParameter) nebo hodnotou metadat (instance String). Následující příklad ukazuje použití smyčky for..in k prověření dynamických vlastností vlastnosti data shaderu. Každá hodnota metadat bude přidána do instance Vector s názvem metadata. Všimněte si, že v tomto příkladu se předpokládá, že instance Shader s názvem myShader je již vytvořená: var shaderData:ShaderData = myShader.data; var metadata:Vector.<String> = new Vector.<String>(); for (var prop:String in shaderData) { if (!(shaderData[prop] is ShaderInput) && !(shaderData[prop] is ShaderParameter)) { metadata[metadata.length] = shaderData[prop]; } } // do something with the metadata Verze tohoto příkladu, kde jsou také vyjmuty vstupy a parametry shaderu je uvedena v části „Určení vstupů a parametrů shaderu“ na stránce 381. Další informace o vlastnostech vstupu a parametrů najdete v části „Určení hodnot vstupu a parametrů shaderu“ na stránce 380. Určení hodnot vstupu a parametrů shaderu Mnohé shadery Pixel Bender jsou definovány pro použití jednoho nebo více vstupních obrazů, které jsou použity ve zpracování shaderu. Pro shader je například běžné, že přijme zdrojový obraz a odevzdá tento obraz s použitým příslušným efektem. Podle toho, jak je shader použit, může být vstupní hodnota určena automaticky nebo může vyžadovat explicitní poskytnutí hodnoty. Podobně mnohé shadery určují parametry, které se používají k přizpůsobení výstupu shaderu. Před použitím shaderu musíte explicitně nastavit i hodnotu jednotlivých parametrů. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 381 Práce s shadery Pixel Bender Vlastnost data objektu Shader slouží k nastavení vstupů a parametrů shaderu a k určení, jestli příslušný shader očekává vstupy nebo parametry. Vlastnost data je instance ShaderData. Určení vstupů a parametrů shaderu Prvním krokem určení hodnot vstupu a parametrů shaderu je zjistit, zda daný shader, který používáte, očekává nějaké vstupní obrazy nebo parametry. Každá instance Shader má vlastnost data obsahující objekt ShaderData. Definuje-li shader nějaké vstupy nebo parametry, jsou přístupné jako vlastnosti toho objektu ShaderData. Názvy vlastností se shodují s názvy určenými pro vstupy a parametry ve zdrojovém kódu shaderu. Například, definuje-li shader vstup s názvem src, bude mít objekt ShaderData vlastnost s názvem src představující daný vstup. Každá vlastnost, která představuje nějaký vstup, je instancí ShaderInput a každá vlastnost, která představuje nějaký parametr, je instancí ShaderParameter. V ideálním případě poskytne autor shaderu dokumentaci k shaderu, kde je uvedeno, jaké hodnoty a parametry vstupního obrazu shader očekává, co představují, jejich vhodné hodnoty atd. Není-li však k shaderu přiložená dokumentace (a nemáte jeho zdrojový kód), můžete určit vstupy a parametry prozkoumáním dat shaderu. Vlastnosti představující vstupy a parametry jsou dynamicky přidány k objektu ShaderData. Můžete tedy pomocí smyčky for..in prozkoumat objekt ShaderData, abyste zjistili, zda jeho přidružený shader definuje nějaké vstupy nebo parametry. Jak je popsáno v části „Přístup k metadatům shaderu“ na stránce 379, k hodnotě metadat definované pro daný shader je přístup také jako k dynamické vlastnosti přidané k vlastnosti Shader.data. Při použití této techniky k určení vstupů a parametrů shaderu zkontrolujte typ dat dynamických vlastností. Je-li vlastnost instancí ShaderInput, představuje vstup. Je-li vlastnost instancí ShaderParameter, představuje parametr. Jinak je to hodnota metadat. Následující příklad ukazuje použití smyčky for..in k prověření dynamických vlastností vlastnosti data shaderu. Každý vstup (objekt ShaderInput) bude přidán k instanci Vector s názvem inputs. Každý parametr (objekt ShaderParameter) bude přidán k instanci Vector s názvem parameters. A konečně veškeré vlastnosti metadat budou přidány k instanci Vector s názvem metadata. Všimněte si, že v tomto příkladu se předpokládá, že instance Shader s názvem myShader je již vytvořená: var var var var shaderData:ShaderData = myShader.data; inputs:Vector.<ShaderInput> = new Vector.<ShaderInput>(); parameters:Vector.<ShaderParameter> = new Vector.<ShaderParameter>(); metadata:Vector.<String> = new Vector.<String>(); for (var prop:String in shaderData) { if (shaderData[prop] is ShaderInput) { inputs[inputs.length] = shaderData[prop]; } else if (shaderData[prop] is ShaderParameter) { parameters[parameters.length] = shaderData[prop]; } else { metadata[metadata.length] = shaderData[prop]; } } // do something with the inputs or properties PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 382 Práce s shadery Pixel Bender Určení vstupních hodnot shaderu Mnohé shadery očekávají jeden nebo více vstupních obrazů, které se použijí při zpracování shaderu. V mnoha případech je však vstup určen automaticky při použití objektu Shader. Například dejme tomu, že shader vyžaduje jeden vstup a že se tento shader používá jako filtr. Při aplikaci tohoto filtru na objekt zobrazení nebo objekt BitmapData bude daný objekt automaticky nastaven jako vstup. V takovém případě nenastavujete explicitně vstupní hodnotu. Avšak v některých případech, zejména pokud shader definuje více vstupů, musíte explicitně nastavit hodnotu pro vstup. Každý vstup, který je definován v shaderu, je v kódu ActionScript zastoupen objektem ShaderInput. Objekt ShaderInput je vlastnost instance ShaderData ve vlastnosti data objektu Shader, jak je popsáno v části „Určení vstupů a parametrů shaderu“ na stránce 381. Například dejme tomu, že shader definuje vstup s názvem src a že je tento shader napojen na objekt Shader s názvem myShader. V takovém případě se dostanete k objektu ShaderInput odpovídajícímu vstupu src pomocí následujícího identifikátoru: myShader.data.src Každý objekt ShaderInput má vlastnost input, která se používá k nastavení hodnoty pro vstup. Chcete-li určit obrazová data, nastavte vlastnost input na instanci BitmapData. Vlastnost input můžete také nastavit na instanci BitmapData nebo Vector.<Number> k určení binárních nebo číselných dat. Podrobnosti a omezení ohledně používání instance BitmapData nebo Vektor.<Number> jako vstup najdete v přehledu ShaderInput.input v referenční příručce jazyka. Kromě vlastnosti input má objekt ShaderInput také vlastnosti, které můžete použít k určení, jaký typ obrazu je na vstupu očekáván. Sem patří vlastnosti width, height a channels. Každý objekt ShaderInput má také vlastnost index, která je užitečná pro určení, zda je pro vstup třeba poskytnout explicitní hodnotu. Jestliže shader očekává více vstupů, než je automaticky nastavený počet, pak musíte hodnoty pro tyto vstupy nastavit sami. Podrobnosti k různým způsobům použití shaderu a určení, zda se vstupní hodnoty nastavují automaticky, jsou uvedeny v části „Používání shaderu“ na stránce 386. Určení hodnot parametrů shaderu Některé shadery definují hodnoty parametrů, které shader používá při vytváření svého výsledku. Například, shader, který mění jas obrazu, může určovat parametr jas, který určuje, jaký vliv bude mít operace na jas. Jeden parametr definovaný v shaderu může očekávat jednu hodnotu nebo více hodnot, podle definice parametru v shaderu. Každý parametr, který je definován v shaderu, je v kódu ActionScript zastoupen objektem ShaderParameter. Objekt ShaderParameter je vlastnost instance ShaderData ve vlastnosti data objektu Shader, jak je popsáno v části „Určení vstupů a parametrů shaderu“ na stránce 381. Například dejme tomu, že shader definuje parametr s názvem brightness a že je tento shader zastoupen objektem Shader s názvem myShader. V takovém případě se dostanete k objektu ShaderParameter odpovídajícímu parametru brightness pomocí následujícího identifikátoru: myShader.data.brightness Chcete-li zadat hodnotu (nebo hodnoty) pro parametr, vytvořte pole ActionScript obsahující hodnotu nebo hodnoty a přiřaďte jej k vlastnosti value objektu ShaderParameter. Vlastnost value je definována jako instance Array, protože je možné, že jeden parametr shaderu vyžaduje více hodnot. I kdyby parametr shaderu očekával jen jednu hodnotu, musíte tuto hodnotu zabalit do objektu Array, abyste ji mohli přiřadit k vlastnosti ShaderParameter.value. Následující přehled předvádí nastavení jedné hodnoty jako vlastnosti value: myShader.data.brightness.value = [75]; PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 383 Práce s shadery Pixel Bender Jestliže zdrojový kód Pixel Bender pro shader definuje výchozí hodnotu pro parametr, bude při vytváření objektu Shader vytvořeno pole obsahující výchozí hodnotu nebo hodnoty a přiřazeno k vlastnosti value objektu ShaderParameter. Jakmile bylo pole přiřazeno k vlastnosti value (i v případě, že se jedná o výchozí hodnotu), můžete změnou hodnoty elementu pole změnit hodnotu parametru. Nemusíte vytvářet nové pole a přiřazovat je vlastnosti value. Následující příklad ukazuje nastavení hodnoty parametru shaderu v jazyce ActionScript. V tomto příkladu shader definuje parametr s názvem color. Parametr color je deklarován jako proměnnáfloat4 ve zdrojovém kódu Pixel Bender, což znamená, že to je pole se čtyřmi čísly s pohyblivou desetinnou čárkou. V tomto příkladu se hodnota parametru color nepřetržitě mění a při každé změně se pomocí shaderu nakreslí na obrazovce barevný obdélník. Výsledkem je animovaná změna barvy. Poznámka: Kód pro tento příklad napsal Ryan Taylor. Děkujeme Ryanovi za tento příklad. Ryanovo portfolio a jeho zápis si můžete prohlédnout na webové adrese www.boostworthy.com. Kód ActionScript se soustředí kolem tří metod: • init(): v metodě init() načte kód soubor bajtového kódu Pixel Bender obsahující shader. Při načtení souboru je volána metoda onLoadComplete(). • onLoadComplete(): v metodě onLoadComplete() vytvoří kód objekt Shader pojmenovaný shader. Vytvoří také instanci Sprite pojmenovanou texture. V metodě renderShader() nakreslí kód výsledek shaderu dotexture jednou za snímek. • onEnterFrame(): Metoda onEnterFrame() je vyvolána jedenkrát za snímek, což vytvoří efekt animace. V této metodě kód nastaví hodnotu parametru shaderu na novou barvu, dále vyvolá metodu renderShader() k nakreslení výsledku shaderu v podobě obdélníku. • renderShader(): v metodě renderShader()kód vyvolá metodu Graphics.beginShaderFill() k určení výplně shaderu. Poté nakreslí obdélník, jehož výplň je definována výstupem shaderu (generovaná barva). Další informace o používání shaderu za tímto účelem naleznete v části „Použití shaderu jako výplně kresby“ na stránce 386. Následuje kód ActionScript pro tento příklad. Tuto třídu použijte jako hlavní třídu aplikace pro projekt pouze s jazykem ActionScript v programu Flex, nebo jako třídu dokumentu pro soubor FLA ve vývojovém nástroji Flash: package { import import import import import import flash.display.Shader; flash.display.Sprite; flash.events.Event; flash.net.URLLoader; flash.net.URLLoaderDataFormat; flash.net.URLRequest; public class ColorFilterExample extends Sprite { private const DELTA_OFFSET:Number = Math.PI * 0.5; private var loader:URLLoader; private var shader:Shader; private var texture:Sprite; private var delta:Number = 0; public function ColorFilterExample() { init(); } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 384 Práce s shadery Pixel Bender private function init():void { loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("ColorFilter.pbj")); } private function onLoadComplete(event:Event):void { shader = new Shader(loader.data); shader.data.point1.value = [topMiddle.x, topMiddle,y]; shader.data.point2.value = [bottomLeft.x, bottomLeft.y]; shader.data.point3.value = [bottomRight.x, bottomRight.y]; texture = new Sprite(); addChild(texture); addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(event:Event):void { shader.data.color.value[0] = 0.5 + Math.cos(delta - DELTA_OFFSET) * 0.5; shader.data.color.value[1] = 0.5 + Math.cos(delta) * 0.5; shader.data.color.value[2] = 0.5 + Math.cos(delta + DELTA_OFFSET) * 0.5; // The alpha channel value (index 3) is set to 1 by the kernel's default // value. This value doesn't need to change. delta += 0.1; renderShader(); } private function renderShader():void { texture:graphics.clear(); texture.graphics.beginShaderFill(shader); texture.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight); texture.graphics.endFill(); } } } Následuje zdrojový kód pro jádro shaderu ColorFilter, použitý k vytvoření souboru bytového kódu Pixel Bender „ColorFilter.pbj“: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 385 Práce s shadery Pixel Bender <languageVersion : 1.0;> kernel ColorFilter < namespace : "boostworthy::Example"; vendor : "Ryan Taylor"; version : 1; description : "Creates an image where every pixel has the specified color value."; > { output pixel4 result; parameter float4 color < minValue:float4(0, 0, 0, 0); maxValue:float4(1, 1, 1, 1); defaultValue:float4(0, 0, 0, 1); >; void evaluatePixel() { result = color; } } Používáte-li shader, jehož parametry nejsou zdokumentovány, můžete zjistit, kolik elementů a jakého typu musí být obsaženo v poli tak, že zkontrolujete vlastnost type objektu ShaderParameter. Vlastnost type udává typ dat parametru, jak je definován v samotném shaderu. Seznam počtu a typů elementů očekávaných jednotlivými typy parametrů je uveden v přehledu vlastnosti ShaderParameter.value v referenční příručce jazyka. Každý objekt ShaderParameter má také vlastnost index, která udává, kam daný parametr patří v pořadí parametrů shaderu. Kromě těchto vlastností může mít objekt ShaderParameter ještě další vlastnosti obsahující hodnoty metadat poskytnuté autorem shaderu. Autor může určit například hodnoty metadat jako minimální, maximální a výchozí hodnoty pro parametr. Všechny hodnoty metadat, které autor určil, jsou přidány do objektu ShaderParameter jako dynamické vlastnosti. Chcete-li tyto vlastnosti prověřit, použijte smyčku for..in k cyklickému procházení dynamických vlastností objektu ShaderParameter pro určení jeho metadat. Následující příklad ukazuje použití smyčky for..in k určení metadat objektu ShaderParameter. Každá hodnota metadat bude přidána do instance Vector s názvem metadata. Všimněte si, že v tomto příkladu se předpokládá, že instance Shader s názvem myShader je již vytvořená a že je známo, že má parametr s názvem brightness: var brightness:ShaderParameter = myShader.data.brightness; var metadata:Vector.<String> = new Vector.<String>(); for (var prop:String in brightness) { if (brightness[prop] is String) { metadata[metadata.length] = brightness[prop]; } } // do something with the metadata PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 386 Práce s shadery Pixel Bender Používání shaderu Jakmile je shader dostupný v kódu ActionScript jako objekt Shader, můžete jej použít několika způsoby: • Výplň kresby shaderu: shader definuje část výplně ve tvaru nakresleném pomocí kreslicího rozhraní api • Režim prolnutí: shader definuje prolnutí mezi dvěma překrývajícími se objekty zobrazení • Filtr: shader definuje filtr, který upraví vzhled vizuálního obsahu • Nezávislé zpracování shaderu: zpracování shaderu běží bez určení zamýšleného použití jeho výstupu. Shader může volitelně běžet na pozadí, přičemž výsledek bude k dispozici při dokončení zpracování. Tuto techniku můžete použít ke generování bitmapových dat a také ke zpracování nevizuálních dat. Použití shaderu jako výplně kresby Používáte-li shader k vytvoření výplně kresby, používáte k vytvoření tvaru vektoru metody kreslicího rozhraní api. Výstup shaderu je použit k vyplnění tvaru stejným způsobem, kterým lze použít jakýkoliv obraz bitmapy použitý jako výplň bitmapy pomocí kreslicího rozhraní api. K vytvoření výplně shaderu v bodě svého kódu, ve kterém si přejete zahájit kreslení tvaru, volejte metodu objektu Graphics beginShaderFill(). Předejte objekt Shader jako první argument k metodě beginShaderFill(), viz následující výpis: var canvas:Sprite = new Sprite(); canvas.graphics.beginShaderFill(myShader); canvas.graphics.drawRect(10, 10, 150, 150); canvas.graphics.endFill(); // add canvas to the display list to see the result Používáte-li shader jako výplně kresby, nastavte jakékoliv vstupní hodnoty obrazu a hodnoty parametru, které shader vyžaduje. Následující příklad ukazuje použití shaderu jako výplně kresby. V tomto příkladě vytvoří shader tříbodový přechod. Tento přechod má tři barvy, každá v bodě trojúhelníku, s prolínáním přechodu mezi těmito body. Mimo to tyto obsahy rotují k vytvoření animovaného efektu otáčející se barvy. Poznámka: Kód pro tento příklad napsal Petri Leskinen. Děkujeme Petrimu za tento příklad. Více jeho příkladů a výukových programů naleznete na webové adrese http://pixelero.wordpress.com. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 387 Práce s shadery Pixel Bender Kód jazyka ActionScript je ve třech metodách: • init(): Metoda init() je volána při načtení aplikace. V této metodě kód nastaví počáteční hodnoty objektů Point představující body trojúhelníku. Kód také vytvoří instanci Sprite pojmenovanou canvas. Později v metodě updateShaderFill() nakreslí kód výsledek shaderu docanvas jednou za snímek. Nakonec soubor načte soubor bajtového kódu shaderu. • onLoadComplete(): v metodě onLoadComplete() vytvoří kód objekt Shader pojmenovaný shader. Nastaví také počáteční hodnoty parametru. Nakonec kód přidá metodu updateShaderFill() jako posluchač události enterFrame, což znamená, že je volána jednou za snímek k vytvoření efektu animace. • updateShaderFill(): metoda updateShaderFill() je vyvolána jedenkrát za snímek, což vytvoří efekt animace. V této metodě kód vypočte a nastaví hodnoty parametru shaderu. Kód poté volá metodu beginShaderFill() k vytvoření výplně shaderu a volá jiné metody kreslicích rozhraní api k nakreslení výsledku shaderu v trojúhelníku. Následuje kód ActionScript pro tento příklad. Tuto třídu použijte jako hlavní třídu aplikace pro projekt pouze s jazykem ActionScript v programu Flex, nebo jako třídu dokumentu pro soubor FLA ve vývojovém nástroji Flash: package { import import import import import import import flash.display.Shader; flash.display.Sprite; flash.events.Event; flash.geom.Point; flash.net.URLLoader; flash.net.URLLoaderDataFormat; flash.net.URLRequest; public class ThreePointGradient extends Sprite { private var canvas:Sprite; private var shader:Shader; private var loader:URLLoader; private var topMiddle:Point; private var bottomLeft:Point; private var bottomRight:Point; private var colorAngle:Number = 0.0; private const d120:Number = 120 / 180 * Math.PI; // 120 degrees in radians public function ThreePointGradient() { init(); } private function init():void { canvas = new Sprite(); addChild(canvas); var size:int = 400; topMiddle = new Point(size / 2, 10); bottomLeft = new Point(0, size - 10); bottomRight = new Point(size, size - 10); PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 388 Práce s shadery Pixel Bender loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("ThreePointGradient.pbj")); } private function onLoadComplete(event:Event):void { shader = new Shader(loader.data); shader.data.point1.value = [topMiddle.x, topMiddle,y]; shader.data.point2.value = [bottomLeft.x, bottomLeft.y]; shader.data.point3.value = [bottomRight.x, bottomRight.y]; addEventListener.Event.ENTER_FRAME, updateShaderFill); } private function updateShaderFill(event:Event):void { colorAngle += .06; var c1:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle); var c2:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle + d120); var c3:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle - d120; shader.data.color1.value = [c1, c2, c3, 1.0]; shader.data.color2.value = [c3, c1, c2, 1.0]; shader.data.color3.value = [c2, c3, c1, 1.0]; canvas.graphics.clear(); canvas.graphics.beginShaderFill(shader); canvas.graphics.moveTo(topMiddle.x, topMiddle.y); canvas.graphics.lineTo(bottomLeft.x, bottomLeft.y); canvas.graphics.lineTo(bottomRight.x, bottomLeft.y); canvas.graphics.endFill(); } } } Následuje zdrojový kód pro jádro shaderu ThreePointGradient, použitý k vytvoření souboru bytového kódu Pixel Bender „ThreePointGradient.pbj“: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 389 Práce s shadery Pixel Bender <languageVersion : 1.0;> kernel ThreePointGradient < namespace : "Petri Leskinen::Example"; vendor : "Petri Leskinen"; version : 1; description : "Creates a gradient fill using three specified points and colors."; > { parameter float2 point1 // coordinates of the first point < minValue:float2(0, 0); maxValue:float2(4000, 4000); defaultValue:float2(0, 0); >; parameter float4 color1 // color at the first point, opaque red by default < defaultValue:float4(1.0, 0.0, 0.0, 1.0); >; parameter float2 point2 // coordinates of the second point < minValue:float2(0, 0); maxValue:float2(4000, 4000); defaultValue:float2(0, 500); >; parameter float4 color2 // color at the second point, opaque green by default < defaultValue:float4(0.0, 1.0, 0.0, 1.0); >; parameter float2 point3 // coordinates of the third point < minValue:float2(0, 0); maxValue:float2(4000, 4000); defaultValue:float2(0, 500); >; parameter float4 color3 // color at the third point, opaque blue by default < defaultValue:float4(0.0, 0.0, 1.0, 1.0); >; PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 390 Práce s shadery Pixel Bender output pixel4 dst; void evaluatePixel() { float2 d2 = point2 - point1; float2 d3 = point3 - point1; // transformation to a new coordinate system // transforms point 1 to origin, point2 to (1, 0), and point3 to (0, 1) float2x2 mtrx = float2x2(d3.y, -d2.y, -d3.x, d2.x) / (d2.x * d3.y - d3.x * d2.y); float2 pNew = mtrx * (outCoord() - point1); // repeat the edge colors on the outside pNew.xy = clamp(pNew.xy, 0.0, 1.0); // set the range to 0.0 ... 1.0 // interpolating the output color or alpha value dst = mix(mix(color1, color2, pNew.x), color3, pNew.y); } } Pro více informací o kreslení tvarů pomocí kreslicího rozhraní api viz „Používání kreslicího rozhraní API“ na stránce 314. Použití shaderu jako režimu prolnutí Používání shaderu jako režimu prolnutí je podobné používání jiných režimů prolnutí. Shader definuje vzhled, který je výsledkem vizuálního prolnutí dvou objektů zobrazení. K použití shaderu jako režimu prolnutí přiřaďte objekt Shader k vlastnosti blendShader objektu zobrazení v popředí. Přiřazení hodnoty jiné nežnull k vlastnosti blendShader automaticky nastaví vlastnost objektu zobrazení blendMode na BlendMode.SHADER. Následující výpis ukazuje použití shaderu jako režimu prolnutí. Tento příklad předpokládá, že existuje objekt zobrazení pojmenovaný foreground obsažený ve stejném nadřazeném objektu na seznamu zobrazení jako další obsah zobrazení, kde foreground překrývá další obsah: foreground.blendShader = myShader; Jestliže používáte shader jako režim prolnutí, musí být shader definován minimálně pomocí dvou vstupů. Jak ukazuje příklad, nemusíte ve svém kódu nastavit vstupní hodnoty. Namísto toho se dané dva prolnuté obrazy automaticky použijí jako vstupy shaderu. Obraz v popředí je nastaven jako druhý obraz. (Toto je objekt zobrazení, na který je režim prolnutí použit.) Obraz pozadí je vytvořen přetažením složení všech obrazových bodů za ohraničovací rámeček obrazu popředí. Tento obraz pozadí je nastaven jako první vstupní obraz. Jestliže používáte shader, který očekává více než pouze dva vstupy, zadejte hodnotu pro jakýkoliv vstup mimo první dva vstupy. Následující výpis ukazuje použití shaderu jako režimu prolnutí. Tento příklad používá režim zesvětleného prolnutí na základě světlosti. Výsledek prolnutí je, že se hodnota nejsvětlejšího obrazového bodu z některého z prolnutých objektů stane obrazovým bodem, který je zobrazen. Poznámka: Kód pro tento příklad napsal Mario Klingemann. Děkujeme Mariovi za tento příklad. Více práce Maria a jeho zápisy naleznete na webové adrese www.quasimondo.com. Důležitý kód jazyka ActionScript je v následujících dvou metodách: • init(): metoda init() je volána při načtení aplikace. V této metodě načte kód soubor bajtového kódu shaderu. • onLoadComplete(): v metodě onLoadComplete() vytvoří kód objekt Shader pojmenovaný shader. Poté nakreslí tři objekty. První, backdrop, je tmavě šedé pozadí za prolnutými objekty. Druhý, backgroundShape, je zelená přechodová elipsa. Třetí objekt, foregroundShape, je oranžová přechodová elipsa. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 391 Práce s shadery Pixel Bender Elipsa foregroundShape je objekt popředí prolnutí. Obraz pozadí prolnutí je tvořen částí backdrop a části backgroundShape, které jsou překryty ohraničujícím rámečkem objektu foregroundShape. Objekt foregroundShape je objekt nejvíce v popředí seznamu zobrazení. Tento objekt částečně překrývá backgroundShape a zcela překrývábackdrop. Z důvodu tohoto překrytí bez použití režimu prolnutí je oranžová elipsa foregroundShape) zobrazena kompletně a zakrývá část zelené elipsy (backgroundShape). Nicméně použijete-li režim prolnutí, jasnější část zelené elipsy bude prosvítat, protože je jasnější než část foregroundShape, kterou překrývá. Následuje kód ActionScript pro tento příklad. Tuto třídu použijte jako hlavní třídu aplikace pro projekt pouze s jazykem ActionScript v programu Flex, nebo jako třídu dokumentu pro soubor FLA ve vývojovém nástroji Flash: package { import import import import import import import import import import import flash.display.BlendMode; flash.display.GradientType; flash.display.Graphics; flash.display.Shader; flash.display.Shape; flash.display.Sprite; flash.events.Event; flash.geom.Matrix; flash.net.URLLoader; flash.net.URLLoaderDataFormat; flash.net.URLRequest; public class LumaLighten extends Sprite { private var shader:Shader; private var loader:URLLoader; public function LumaLighten() { init(); } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 392 Práce s shadery Pixel Bender private function init():void { loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("LumaLighten.pbj")); } private function onLoadComplete(event:Event):void { shader = new Shader(loader.data); var backdrop:Shape = new Shape(); var g0:Graphics = backdrop.graphics; g0.beginFill(0x303030); g0.drawRect(0, 0, 400, 200); g0.endFill(); addChild(backdrop); var backgroundShape:Shape = new Shape(); var g1:Graphics = backgroundShape.graphics; var c1:Array = [0x336600, 0x80ff00]; var a1:Array = [255, 255]; var r1:Array = [100, 255]; var m1:Matrix = new Matrix(); m1.createGradientBox(300, 200); g1.beginGradientFill(GradientType.LINEAR, c1, a1, r1, m1); g1.drawEllipse(0, 0, 300, 200); g1.endFill(); addChild(backgroundShape); var foregroundShape:Shape = new Shape(); var g2:Graphics = foregroundShape.graphics; var c2:Array = [0xff8000, 0x663300]; var a2:Array = [255, 255]; var r2:Array = [100, 255]; var m2:Matrix = new Matrix(); m2.createGradientBox(300, 200); g2.beginGradientFill(GradientType.LINEAR, c2, a2, r2, m2); g2.drawEllipse(100, 0, 300, 200); g2.endFill(); addChild(foregroundShape); foregroundShape.blendShader = shader; foregroundShape.blendMode = BlendMode.SHADER; } } } Následuje zdrojový kód pro jádro shaderu LumaLighten, použitý k vytvoření souboru bytového kódu Pixel Bender „LumaLighten.pbj“: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 393 Práce s shadery Pixel Bender <languageVersion : 1.0;> kernel LumaLighten < namespace : "com.quasimondo.blendModes"; vendor : "Quasimondo.com"; version : 1; description : "Luminance based lighten blend mode"; > { input image4 background; input image4 foreground; output pixel4 dst; const float3 LUMA = float3(0.212671, 0.715160, 0.072169); void evaluatePixel() { float4 a = sampleNearest(foreground, outCoord()); float4 b = sampleNearest(background, outCoord()); float luma_a = a.r * LUMA.r + a.g * LUMA.g + a.b * LUMA.b; float luma_b = b.r * LUMA.r + b.g * LUMA.g + b.b * LUMA.b; dst = luma_a > luma_b ? a : b; } } Pro více informací o používání režimů prolnutí viz „Použití režimů prolnutí“ na stránce 297. Použití shaderu jako filtru Použití shaderu jako filtru se podobá použití jakéhokoliv jiného filtru jazyka ActionScript. Když používáte shader jako filtr, je filtrovaný obraz (objekt zobrazení nebo objekt BitmapData) předán k shaderu. Shader používá vstupní obraz k vytvoření vstupu filtru, který je obvykle upravenou verzí původního obrazu. Jestliže je filtrovaný objekt objektem zobrazení, je výstup shaderu zobrazen na obrazovce namísto filtrovaného objektu zobrazení. Jestliže je filtrovaný objekt objekt BitmapData, stane se výstup shaderu obsahem objektu BitmapData, jehož metoda applyFilter() je volána. K použití shaderu jako filtru použijte objekt Shader dle popisu v „Načtení nebo vložení shaderu“ na stránce 378. Poté vytvořte objekt ShaderFilter propojený s objektem Shader. Objekt ShaderFilter je filtr, který lze použít na daný filtrovaný objekt. Filtr použijete na objekt stejným způsobem jako jakýkoliv jiný filtr. Filtr předáte vlastnosti filters objektu zobrazení nebo voláte metodu applyFilter() na objektu BitmapData. Například následující kód vytvoří objekt ShaderFilter a použije daný filtr na objekt zobrazení pojmenovaný homeButton. var myFilter:ShaderFilter = new ShaderFilter(myShader); homeButton.filters = [myFilter]; Jestliže používáte shader jako filtr, musí být shader definován minimálně pomocí jednoho vstupu. Jak ukazuje příklad, nemusíte ve svém kódu nastavit vstupní hodnotu. Namísto toho je filtrovaný objekt zobrazení nebo objekt BitmapData nastaven jako vstupní obraz. Jestliže používáte shader, který očekává více než pouze jen vstup, zadejte hodnotu pro jakýkoliv vstup mimo první vstup. V některých případech změní filtr rozměry původního obrazu. Například typický efekt vrženého stínu přidá navíc obrazové body obsahující stín, který je přidán k obrazu. Jestliže používáte shader, který změní rozměry obrazu, nastavte vlastnosti leftExtension, rightExtension, topExtension a bottomExtension k určení rozsahu změny velikosti obrazu. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 394 Práce s shadery Pixel Bender Následující výpis ukazuje použití shaderu jako filtru. Filtr v tomto příkladě obrátí hodnoty červeného, zeleného a modrého kanálu obrazu. Výsledkem je „záporná“ verze obrazu. Poznámka: Shader použitý v tomto příkladu je jádro invertRGB.pbk Pixel Bender, které je součástí sady nástrojů Pixel Bender. Zdrojový kód pro jádro můžete načíst z instalačního adresáře sady nástrojů Pixel Bender. Kompilujte zdrojový kód a uložte soubor bajtového kódu ve stejném adresáři jako zdrojový kód. Důležitý kód jazyka ActionScript je v následujících dvou metodách: • init(): metoda init() je volána při načtení aplikace. V této metodě načte kód soubor bajtového kódu shaderu. • onLoadComplete(): v metodě onLoadComplete() vytvoří kód objekt Shader pojmenovaný shader. Poté vytvoří a nakreslí obsah objektu pojmenovaného target. Objekt target je obdélník vyplněný barvou lineárního přechodu, který je červený nalevo, žlutozelený ve středu a světle modrý napravo. Nefiltrovaný objekt vypadá následovně: Pomocí použitého filtru jsou barvy obráceny a obdélník bude vypadat následovně: Shader použitý v tomto příkladu je ukázkové jádro „invertRGB.pbk“ Pixel Bender, které je součástí sady nástrojů Pixel Bender. Zdrojový kód je k dispozici v souboru „invertRGB.pbk“ v instalačním adresáři sady nástrojů Pixel Bender. Kompilujte zdrojový kód a poté uložte soubor bajtového kódu pojmenovaný „invertRGB.pbj“ do stejného adresáře jako zdrojový kód jazyka ActionScript. Následuje kód ActionScript pro tento příklad. Tuto třídu použijte jako hlavní třídu aplikace pro projekt pouze s jazykem ActionScript v programu Flex, nebo jako třídu dokumentu pro soubor FLA ve vývojovém nástroji Flash: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 395 Práce s shadery Pixel Bender package { import import import import import import import import import import import flash.display.GradientType; flash.display.Graphics; flash.display.Shader; flash.display.Shape; flash.display.Sprite; flash.filters.ShaderFilter; flash.events.Event; flash.geom.Matrix; flash.net.URLLoader; flash.net.URLLoaderDataFormat; flash.net.URLRequest; public class InvertRGB extends Sprite { private var shader:Shader; private var loader:URLLoader; public function InvertRGB() { init(); } private function init():void { loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("invertRGB.pbj")); } private function onLoadComplete(event:Event):void { PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 396 Práce s shadery Pixel Bender shader = new Shader(loader.data); var target:Shape = new Shape(); addChild(target); var g:Graphics = target.graphics; var c:Array = [0x990000, 0x445500, 0x007799]; var a:Array = [255, 255, 255]; var r:Array = [0, 127, 255]; var m:Matrix = new Matrix(); m.createGradientBox(w, h); g.beginGradientFill(GradientType.LINEAR, c, a, r, m); g.drawRect(10, 10, w, h); g.endFill(); var invertFilter:ShaderFilter = new ShaderFilter(shader); target.filters = [invertFilter]; } } } Pro více informací o používání filtrů viz „Vytváření a používání filtrů“ na stránce 347. Použití shaderu v nezávislém režimu Jestliže používáte shader v nezávislém režimu, zpracování shaderu běží nezávisle na zamýšleném způsobu použití výstupu. Určete shader, který má být proveden, nastavte vstupní hodnoty a hodnoty parametru a určete objekt, do kterého budou výsledná data umístěna. Shader můžete v nezávislém režimu použít za dvěma účely: • Zpracování neobrazových dat: v nezávislém režimu můžete předat libovolná binární nebo numerická data k shaderu namísto obrazových dat bitmapy. Vedle obrazových dat bitmapy můžete nastavit, aby byl výsledek shaderu vrácen jako binární data nebo numerická data. • Zpracovávání na pozadí: spustíte-li shader v nezávislém režimu, provedení bude implicitně asynchronní. To znamená, že daný shader běží na pozadí, zatímco vaše aplikace pokračuje a váš kód je uvědomen o ukončení zpracovávání shaderu. Můžete použít shader, jehož spuštění trvá dlouho a během běhu nedojde k zamrznutí uživatelského rozhraní aplikace nebo jiného zpracovávání. Objekt ShaderJob můžete použít k provedení shaderu v nezávislém režimu. Nejprve vytvořte objekt ShaderJob a poté jej propojte s objektem Shader představujícím shader, který má být proveden: var job:ShaderJob = new ShaderJob(myShader); Dále nastavte libovolné hodnoty výstupu nebo parametru, které shader očekává. Jestliže shader provádíte na pozadí, zaregistrujte také posluchač události objektu ShaderJob complete. Váš posluchač je volán, když shader dokončí svou práci: function completeHandler(event:ShaderEvent):void { // do something with the shader result } job.addEventListener(ShaderEvent.COMPLETE, completeHandler); Dále vytvořte objekt, do kterého bude po ukončení operace shaderu zapsán její výsledek. Daný objekt přiřadíte k vlastnosti objektu ShaderJob target: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 397 Práce s shadery Pixel Bender var jobResult:BitmapData = new BitmapData(100, 75); job.target = jobResult; Jestliže používáte ShaderJob ke zpracovávání obrazů, přiřaďte instanci BitmapData vlastnosti target. Jestliže zpracováváte binární nebo numerická data, přiřaďte objekt ByteArray nebo instanci Vector.<Number> instance k vlastnosti target. V daném případě musíte nastavit vlastnosti objektu ShaderJob width a height k určení množství dat pro výstup do objektu target. Poznámka: Vlastnosti objektu ShaderJob shader, target,width a height můžete nastavit v jediném kroku, a to předáním argumentů ke konstruktoru ShaderJob(), např.:var job:ShaderJob = new ShaderJob(myShader, myTarget, myWidth, myHeight); Jste-li připraveni shader provést, volejte metodu objektu ShaderJob start(): job.start(); Volání start() implicitně vyvolá asynchronní provedení ShaderJob. V daném případě provádění programu pokračuje ihned s dalším řádkem a nečeká na dokončení shaderu. Po dokončení operace shaderu objekt ShaderJob volá posluchače své vlastnosti complete a uvědomí je o dokončení. V daném okamžiku (tj. v těle posluchače událosticomplete) objekt target obsahuje výsledek operace shaderu. Poznámka: Namísto použití objektu vlastnosti target můžete načíst výsledek shaderu přímo z objektu události, který je předán metodě vašeho posluchače. Objekt události je instance ShaderEvent. Objekt ShaderEvent má tři vlastnosti, které lze použít k získání přístupu k výsledku, v závislosti na datovém typu objektu, který nastavíte jako vlastnost target: ShaderEvent.bitmapData, ShaderEvent.byteArray a ShaderEvent.vector. Můžete také předat argument true metodě start(). V daném případě je operace shaderu provedena synchronně. Při provádění shaderu je celý kód zastaven (včetně interakce s uživatelským rozhraním a jiných událostí). Po dokončení shaderu objekt target obsahuje výsledek shaderu a program pokračuje s dalším řádkem kódu. job.start(true); 398 Kapitola 18: Práce s filmovými klipy Třída MovieClip je základní třídou pro symboly animací a filmových klipů vytvořené v aplikaci Adobe® Flash® CS4 Professional. Tato třída má chování a funkce objektů zobrazení, ale s dodatečnými vlastnostmi a metodami pro ovládání časové osy filmových klipů. V této kapitole se dozvíte jak pomocí jazyka ActionScript ovládat přehrávání filmových klipů a dynamicky vytvářet filmové klipy. Základy filmových klipů Úvod k práci s filmovými klipy Filmové klipy jsou klíčovým prvkem pro lidi tvořící animovaný obsah pomocí vývojového nástroje Flash a chtějí ovládat tento obsah pomocí jazyka ActionScript. Vždy, když vytvoříte filmový klip v programu Flash, přidá se symbol do knihovny dokumentu Flash. Při výchozím nastavení se tento symbol stane instancí třída MovieClip, a jako taková má vlastnosti a metody třídy MovieClip. Jakmile umístíte instanci filmového klipu do vymezené plochy, filmový klip se začne automaticky odvíjet po své časové ose (pokud má více než jeden snímek), dokud nebude přehrávání zrušeno kódem ActionScript. Právě tato časová osa rozlišuje třídu MovieClip a umožňuje tak vytvořit animaci prostřednictvím doplnění pohybu nebo tvaru ve vývojovém nástroji Flash. Naproti tomu u objektu zobrazení, který je instancí třídy Sprite, vytvoříte animaci pouze naprogramováním změny hodnot daného objektu. V předchozích verzích jazyka ActionScript byla třída MovieClip základní třídou všech instancí ve vymezené ploše. V jazyku ActionScript 3.0 je filmový klip pouze jedním z mnoha objektů zobrazení, které se mohou objevit na obrazovce. Není-li časová osa pro funkci objektu zobrazení nutná, může použití třídy Shape nebo třídy Sprite místo třídy MovieClip zlepšit výkon vykreslování. Další informace o výběru vhodného objektu zobrazení viz „Výběr podtřídy DisplayObject“ na stránce 284. Běžné úlohy filmového klipu V této kapitole jsou popsány následující běžné úlohy filmového klipu: • Spouštění a zastavování filmových klipů • Přehrávání filmových klipů pozpátku • Přesun přehrávací hlavy na určité místo na časové ose filmového klipu • Práce s popisy snímků v jazyku ActionScript • Přístup k informacím o scéně v jazyku ActionScript • Vytváření instancí symbolů filmových klipů z knihovny pomocí jazyka ActionScript • Načítání a ovládání externích souborů SWF, včetně souborů vytvořených pro předchozí verze programu Flash Player • Vytvoření systému ActionScript pro tvorbu grafických datových zdrojů pro načtení a používání při běhu PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 399 Práce s filmovými klipy Důležité pojmy a termíny Následující referenční seznam obsahuje důležité termíny používané v této kapitole: • AVM1 SWF: soubor SWF vytvořený pomocí kódu ActionScript 1.0 nebo ActionScript 2.0, obvykle se zaměřením na verzi Flash Player 8 nebo dřívější. • AVM2 SWF: Soubor SWF vytvořený pomocí kódu ActionScript 3.0 pro verzi Flash Player 9 nebo pozdější či aplikaci Adobe AIR. • Externí SWF: soubor SWF, který je vytvořený zvlášť ze souboru SWF projektu a určený k načtení do souboru SWF projektu a přehrávaný v tomto souboru SWF. • Snímek: nejmenší dílek času na časové ose. Podobně jako u filmového pásu filmu má každý snímek podobu fotografického snímku animace v čase a když jsou snímky přehrávány rychle za sebou, vzniká efekt animace. • Časová osa: metaforické vyjádření série snímků, které tvoří animační sekvenci filmového klipu. časová osa objektu MovieClip je obdobou časové osy ve vývojovém nástroji Flash. • Přehrávací hlava: ukazatel udávající umístění (snímek) na časové ose, který je v daném okamžiku zobrazen. Procházení příkladů v kapitole Jak budete procházet tuto kapitolu, možná si budete chtít sami vyzkoušet některé z uvedených příkladů kódů. Protože tato kapitola pojednává o práci s filmovými klipy v jazyku ActionScript, tak v podstatě všechny kódy uvedené v této kapitole jsou napsány za účelem manipulace se symbolem filmového klipu, který byl vytvořen a umístěn do vymezené plochy. Při zkoušení ukázky budete potřebovat zobrazit výsledek v přehrávači Flash Player nebo AIR, abyste viděli účinky kódu na symbol. Návod na vyzkoušení kódů uvedených v této kapitole: 1 Vytvořte prázdný dokument Flash. 2 Vyberte klíčový snímek na časové ose. 3 Otevřete panel Akce a zkopírujte uvedený kód do dílčího panelu Script. 4 Vytvořte ve vymezené ploše instanci symbolu filmového klipu. Například nakreslete tvar, vyberte jej, zvolte příkaz Změnit > Převést na symbol... a pojmenujte symbol. 5 V Inspektoru vlastností vyberte filmový klip a dejte mu název instance. Název by se měl shodovat s názvem používaným pro daný filmový klip v kódu z příkladu – např. jestliže kód manipuluje s filmovým klipem s názvem myMovieClip, měli byste instanci svého filmového klipu pojmenovat také myMovieClip. 6 Spusťte program pomocí příkazu Ovládání > Testovat film. Na obrazovce uvidíte výsledky kódu manipulujícího s filmovým klipem, jak je uveden v příkladu v kapitole. Další techniky vyzkoušení ukázek kódů jsou podrobněji vysvětleny v části „Testování příkladů kódu v této kapitole“ na stránce 34. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 400 Práce s filmovými klipy Práce s objekty MovieClip Při publikování souboru SWF program Flash převede všechny instance symbolů filmových klipů ve vymezené ploše na objekty MovieClip. Symbol filmového klipu můžete zpřístupnit pro jazyk ActionScript tak, že mu dáte název instance v poli Název instance v Inspektoru vlastností. Jakmile je vytvořen soubor SWF, program Flash vygeneruje kód, který vytvoří instanci MovieClip ve vymezené ploše a deklaruje proměnnou pomocí uvedeného názvu instance. Máte-li pojmenované filmové klipy vnořené v jiných pojmenovaných filmových klipech, bude s těmito podřízenými filmovými klipy zacházeno jako s vlastnostmi nadřízeného filmového klipu – k podřízenému filmovému klipu se můžete dostat pomocí tečkové syntaxe. Například, je-li filmový klip s názvem instance childClip vnořen do jiného klipu s názvem instance parentClip, můžete přehrávání animace časové osy podřízeného klipu spustit vyvoláním následujícího kódu: parentClip.childClip.play(); Poznámka: : K podřízeným instancím umístěným na vymezenou plochu ve zdrojovém nástroji Flash nemůže být přistupováno z kódu zevnitř konstruktoru nadřazené instance, protože nebyly v tomto bodu vytvořeny vykonáním kódu. Před přístupem k potomkovi musí rodič buď kódem vytvořit dceřinou instanci nebo pozdržet přístup do funkce callback, která čeká než potomek vyšle událost Event.ADDED_TO_STAGE. Zatímco některé starší metody a vlastnosti třídy MovieClip jazyka ActionScript 2.0 zůstávají stejné, jiné se změnily. Všechny vlastnosti s předponou v podobě podtržítka byly přejmenovány. Například k vlastnostem _width a _height se nyní dostanete přes názvy width a height, zatímco vlastnosti _xscale a _yscale mají nyní názvy scaleX a scaleY. Kompletní seznam vlastností a metod třídy MovieClip najdete v Referenční příručce jazyka ActionScript 3.0 a jeho součástí. Ovládání přehrávání filmových klipů Program Flash používá metaforu časové osy k zajištění animace nebo změny stavu. Každý vizuální objekt, který používá časovou osu, musí být buď objekt MovieClip nebo rozšíření třídy MovieClip. Zatímco jazyk ActionScript může filmový klip zastavit, přehrát nebo přejít na jiné místo na časové ose, nelze ho použít k dynamickému vytvoření časové osy nebo přidání obsahu na určité snímky. Toto je možné pouze pomocí vývojového nástroje Flash. Když se objekt MovieClip přehrává, postupuje podél své časové osy rychlostí předepsanou rychlostí snímků souboru SWF. Toto nastavení můžete potlačit nastavením vlastnosti Stage.frameRate v jazyku ActionScript. Spouštění a zastavování přehrávání filmových klipů Metody play() a stop() umožňují základní ovládání filmového klipu napříč jeho časovou osou. Například předpokládejme, že máte ve vymezené ploše symbol filmového klipu, který obsahuje animaci bicyklu pohybujícího se po obrazovce, s názvem instance nastaveným na bicycle. Přidáte-li k některému klíčovému snímku na hlavní časové ose následující kód, bicycle.stop(); bicykl se nebude pohybovat (jeho animace se nebude přehrávat). Pohyb bicyklu by mohl začít na základě nějaké jiné interakce s uživatelem. Kdybyste například měli tlačítko s názvem startButton, následující kód na klíčovém snímku na hlavní časové ose by to obstaral tak, že po klepnutí na toto tlačítko by se animace začala přehrávat: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 401 Práce s filmovými klipy // This function will be called when the button is clicked. It causes the // bicycle animation to play. function playAnimation(event:MouseEvent):void { bicycle.play(); } // Register the function as a listener with the button. startButton.addEventListener(MouseEvent.CLICK, playAnimation); Rychlý posun dopředu a přetáčení Metody play() a stop() nepředstavují jediný způsob ovládání přehrávání ve filmovém klipu. Přehrávací hlavu můžete posouvat po časové ose dopředu nebo přetáčet také ručně, pomocí metod nextFrame() a prevFrame(). Vyvoláním jedné z těchto metod zastavíte přehrávání a posunete přehrávací hlavu o jeden snímek dopředu, resp. zpět. Použití metody play() je odpovídá vyvolání metody nextFrame() při každém spuštění události enterFrame objektu filmového klipu. Na základě toho byste mohli zajistit zpětné přehrávání filmového klipu bicycle tak, že byste vytvořili posluchač události pro událost enterFrame a sdělili klipu bicycle, aby se vrátil k předcházejícímu snímku ve funkci posluchače následujícím způsobem: // This function is called when the enterFrame event is triggered, meaning // it's called once per frame. function everyFrame(event:Event):void { if (bicycle.currentFrame == 1) { bicycle.gotoAndStop(bicycle.totalFrames); } else { bicycle.prevFrame(); } } bicycle.addEventListener(Event.ENTER_FRAME, everyFrame); Jestliže v běžném přehrávání filmový klip obsahuje více než jeden snímek, vytvoří při přehrávání nekonečnou smyčku. To znamená, že jakmile přejde přes poslední snímek, vrátí se zpět ke Snímku 1. Při použití metod prevFrame() nebo nextFrame() k tomuto nedojde automaticky (vyvolání metody prevFrame(), když je přehrávací hlava na Snímku 1 neposune přehrávací hlavu na poslední snímek). Podmínka if ve výše uvedeném příkladu kontroluje, zda se již přehrávací hlava dostala zpět k prvnímu snímku, a nastaví ji dopředu na poslední snímek, čímž efektivně vytvoří nekonečnou smyčku filmového klipu přehrávaného pozpátku. Skok na jiný snímek a používání popisů snímků Poslání filmového klipu na nový snímek je jednoduchá záležitost. Vyvolání metody gotoAndPlay() nebo gotoAndStop() způsobí skok filmového snímku na číslo snímku uvedené v parametru. Můžete také předat řetězec, který se shoduje s názvem popisu snímku. Popis můžete přiřadit libovolnému snímku na časové ose. Provedete to tak, že vyberete určitý snímek na časové ose a v Inspektoru vlastností zadáte do pole Popis snímku jeho název. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 402 Práce s filmovými klipy Výhody používání popisů snímků místo čísel jsou zřejmé zejména při vytváření složitých filmových klipů. Když máte v animaci příliš velký počet snímků, hodně vrstev a doplnění, zvažte popsání důležitých snímků vysvětlujícími popisy, které budou představovat posuny v chování filmového klipu (např. „vypnuto“, „chůze“ nebo „běh“). Tím se zlepší srozumitelnost kódu a také se tím zajistí pružnost, protože volání kódu ActionScript pro přechod na pojmenovaný snímek jsou spíše ukazatelem na jediný odkaz – popis – než na konkrétní číslo snímku. Když se potom později rozhodnete přesunout určitý segment animace na jiný snímek, nebudete muset měnit kód ActionScript, pokud zachováte stejný popis pro snímky i na novém místě. Jazyk ActionScript 3.0 obsahuje třídu FrameLabel, která umožňuje zastoupení popisů snímků v kódu. Každá instance této třídy představuje jeden popis snímku a má vlastnost name představující název popisu snímku, jak je uveden v Inspektoru vlastností, a vlastnost frame představující číslo snímku, na kterém je popis umístěn na časové ose. Třída MovieClip obsahuje dvě vlastnosti, které vrací přímo objekty FrameLabel, aby byl umožněn přístup k instancím FrameLabel souvisejícím s instancí filmového klipu. Vlastnost currentLabels vrací pole tvořené všemi objekty FrameLabel na celé časové ose filmového klipu. Vlastnost currentLabel vrací řetězec obsahující název popisu snímku, na který přehrávač na časové ose naposled narazil. Dejme tomu, že jste vytvořili filmový klip s názvem robot a popsali jste různé stavy jeho animace. Mohli byste nastavit podmínku, která by kontrolovala vlastnost currentLabel za účelem přístupu k aktuálnímu stavu klipu robot, jako v následujícím kódu: if (robot.currentLabel == "walking") { // do something } Práce se scénami Ve vývojovém prostředí Flash můžete používat scény k vymezení série časových os, jimiž bude soubor SWF procházet. Pomocí parametru metod gotoAndPlay() nebo gotoAndStop() můžete určit scénu, na kterou se má poslat přehrávací hlava. Všechny soubory FLA začínají pouze počáteční scénou, můžete však vytvořit nové scény. Používání scén není vždy nejlepším přístupem, protože scény mají několik nevýhod. Dokument Flash, který obsahuje více scén, může být obtížné spravovat, zvláště v prostředích s více autory. Více scén může být také neefektivních v šířce pásma, protože během publikování se všechny scény sloučí do jedné časové osy. To způsobí postupné stahování všech scén, i kdyby nebyly vůbec přehrávány. Z těchto důvodů se od používání scén často odrazuje, kromě případů uspořádání více delších animací na bázi časové osy. Vlastnost scenes třídy MovieClip vrací pole objektů Scene představujících všechny scény v souboru SWF. Vlastnost currentScene vrací objekt Scene, který představuje aktuálně přehrávanou scénu. Třída Scene má několik vlastností poskytujících informace o dané scéně. Vlastnost labels vrací pole objektů FrameLabel představujících popisy snímků v dané scéně. Vlastnost name vrací název dané scény v podobě řetězce. Vlastnost numFrames vrací číslo typu int představující celkový počet snímků ve scéně. Vytváření objektů MovieClip pomocí kódu ActionScript Jedním způsobem, jak v programu Flash přidat obsah na obrazovku, je přetažením datových zdrojů z knihovny do vymezené plochy, není to však jediný pracovní postup. U komplexních projektů dávají zkušení vývojoví pracovníci většinou přednost vytváření filmových klipů programováním. Tento přístup přináší několik výhod: snadnější opakované používání kódu, kratší dobu kompilace a propracovanější úpravy, které jsou dostupné pouze v jazyku ActionScript. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 403 Práce s filmovými klipy API se seznamem zobrazení jazyka ActionScript 3.0 redukuje proces dynamického vytváření objektů MovieClip. Schopnost přímé konkretizace instance MovieClip, odděleně od procesu jejího přidání do seznamu zobrazení, zajišťuje pružnost a jednoduchost bez nutnosti vzdát se kontroly. Když v jazyku ActionScript 3.0 programově vytváříte instanci filmového klipu (nebo jakéhokoli jiného objektu zobrazení), nebude na obrazovce viditelná, dokud ji nepřidáte do seznamu zobrazení vyvoláním metody addChild() nebo addChildAt() na kontejneru objektu zobrazení. To umožňuje vytvořit filmový klip, nastavit jeho vlastnosti, dokonce i vyvolat metody ještě před vykreslením na obrazovku. Další informace o práci se seznamem zobrazení viz „Práce s kontejnery objektů zobrazení“ na stránce 273. Exportování symbolů knihovny pro kód ActionScript Při výchozím nastavení nelze instance symbolů filmových klipů v knihovně dokumentu Flash vytvářet dynamicky (tj. vytvářet pouze pomocí kódu ActionScript). Důvodem je, že každý symbol, který je exportován pro použití v jazyku ActionScript, zvětší velikost souboru SWF a připouštíme, že některé symboly nemusí být určeny pro použití ve vymezené ploše. Z toho důvodu je třeba určit, že by měl být symbol exportován pro jazyk ActionScript, aby byl v jazyku ActionScript dostupný. Postup exportování symbolu pro jazyk ActionScript: 1 Vyberte symbol na panelu Knihovna a otevřete jeho dialogové okno Vlastnosti symbolu. 2 V případě potřeby aktivujte nastavení Pokročilé. 3 V části Navázání aktivujte zaškrtávací pole Exportovat pro ActionScript. Tím se aktivují pole Třída a Základní třída. Při výchozím nastavení je pole Třída zaplněno názvy symbolů s odstraněnými přebytečnými mezerami (např. symbol s názvem „Tree House“ bude mít podobu „TreeHouse“). Chcete-li určit, že by měl symbol pro své chování používat vlastní třídu, zadejte do pole celý název této třídy, včetně jejího balíčku. Chcete-li mít možnost vytvářet instance symbolu v jazyku ActionScript, ale nepotřebujete přidávat žádné dodatečné chování, můžete tento název třídy ponechat tak, jak je. Pole Základní třída bude nastaveno na výchozí hodnotu flash.display.MovieClip. Chcete-li, aby váš symbol rozšiřoval funkce jiné vlastní třídy, můžete zde určit název dané třídy, pokud tato třída rozšiřuje třídu Sprite (nebo MovieClip). 4 Chcete-li uložit změny, stiskněte tlačítko OK. Jestliže v této chvíli nemůže program Flash najít externí soubor ActionScript s definicí pro určenou třídu (např. pokud jste nepotřebovali přidávat dodatečné chování pro symbol), zobrazí se upozornění: V cestě tříd (classpath) nelze nalézt definici pro tuto třídu, proto se bude při exportu automaticky generovat v souboru SWF. Pokud váš symbol knihovny nevyžaduje jedinečné funkce přesahující funkce třídy MovieClip, můžete toto upozornění ignorovat. Jestliže neposkytnete pro svůj symbol třídu, vytvoří program Flash pro váš symbol třídu ekvivalentní k následující třídě: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 404 Práce s filmovými klipy package { import flash.display.MovieClip; public class ExampleMovieClip extends MovieClip { public function ExampleMovieClip() { } } } Jestliže chcete k vašemu symbolu přidat další funkce jazyka ActionScript, přidejte příslušné vlastnosti a metody ke kódu s následující strukturou. Předpokládejme například, že máte symbol filmového klipu obsahující kruh o šířce 50 obr. bodů a výšce 50 obr. bodů a tento symbol je určen pro export pro jazyk ActionScript s třídou s názvem Circle. Vložíte-li následující kód do souboru Circle.as, rozšíří třídu MovieClip a poskytne symbol s dodatečnými metodami getArea() a getCircumference(): package { import flash.display.MovieClip; public class Circle extends MovieClip { public function Circle() { } public function getArea():Number { // The formula is Pi times the radius squared. return Math.PI * Math.pow((width / 2), 2); } public function getCircumference():Number { // The formula is Pi times the diameter. return Math.PI * width; } } } Následující kód, umístěný na klíčový snímek na Snímku 1 dokumentu Flash, vytvoří instanci symbolu a zobrazí ji na obrazovce: var c:Circle = new Circle(); addChild(c); trace(c.width); trace(c.height); trace(c.getArea()); trace(c.getCircumference()); Tento kód ukazuje konkretizaci na bázi kódu ActionScript jako alternativu k přetahování jednotlivých datových zdrojů do vymezené plochy. Vytvoří kruh se všemi vlastnostmi filmového klipu i s metodami definovanými v třídě Circle. Toto je velmi základní příklad – váš symbol knihovny může ve své třídě určovat libovolný počet vlastností a metod. PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 405 Práce s filmovými klipy Konkretizace na bázi kódu ActionScript je výkonná, protože umožňuje dynamicky vytvářet velká množství instancí, které by byly příliš obtížné uspořádat ručně. Je také flexibilní, protože si můžete přizpůsobit jednotlivé vlastnosti instance během jejího vytváření. Obě tyto výhody můžete pochopit při použití smyčky k dynamickému vytvoření několika instancí třídy Circle. Na základě předchozího popisu symbolu a třídy Circle ve vaší knihovně dokumentu Flash umístěte na klíčový snímek na Snímku 1 následující kód: import flash.geom.ColorTransform; var totalCircles:uint = 10; var i:uint; for (i = 0; i < totalCircles; i++) { // Create a new Circle instance. var c:Circle = new Circle(); // Place the new Circle at an x coordinate that will space the circles // evenly across the Stage. c.x = (stage.stageWidth / totalCircles) * i; // Place the Circle instance at the vertical center of the Stage. c.y = stage.stageHeight / 2; // Change the Circle instance to a random color c.transform.colorTransform = getRandomColor(); // Add the Circle instance to the current timeline. addChild(c); } function getRandomColor():ColorTransform { // Generate random values for the red, green, and blue color channels. var red:Number = (Math.random() * 512) - 255; var green:Number = (Math.random() * 512) - 255; var blue:Number = (Math.random() * 512) - 255; // Create and return a ColorTransform object with the random colors. return new ColorTransform(1, 1, 1, 1, red, green, blue, 0); } Tento příklad ukazuje, jak můžete pomocí kódu rychle vytvořit a přizpůsobit si více instancí symbolu. Každá instance je umístěna na základě aktuálního počtu v rámci smyčky a každé instanci je přidělena náhodná barva nastavením vlastnosti transform (kterou třída Circle zdědí rozšířením třídy MovieClip). Načítání externích souborů SWF V jazyku ActionScript 3.0 jsou soubory SWF načítány pomocí třídy Loader. Chcete-li načíst externí soubor SWF, musí váš kód ActionScript provést čtyři věci: 1 Vytvořte nový objekt URLRequest s URL souboru. 2 Vytvořte nový objekt Loader. 3 Vyvolejte metodu load() objektu Loader tak, že předáte instanci URLRequest jako parametr. 4 Vyvolejte metodu addChild() na kontejneru objektu zobrazení (např. hlavní časová osa dokumentu Flash) a instance Loader bude přidána do seznamu zobrazení. Nakonec bude kód vypadat takto: PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 406 Práce s filmovými klipy var request:URLRequest = new URLRequest("http://www.[yourdomain].com/externalSwf.swf"); var loader:Loader = new Loader() loader.load(request); addChild(loader); Tento stejný kód lze použít k načtení externího souboru obrazu, např. ve formátu JPEG, GIF nebo PNG, určením URL souboru obrazu namísto určení URL souboru SWF. Soubor SWF může narozdíl od souboru obrazu obsahovat kód ActionScript. I když tedy proces načítání souboru SWF může být totožný s načítáním obrázku, tak při načítání externího souboru SWF musí být soubor SWF, který načítání provádí, i načítaný soubor SWF umístěny ve stejné karanténě zabezpečení, jestliže přehrávač Flash Player nebo AIR provádí přehrávání SWF a vy plánujete k jakékoli komunikaci s externím souborem SWF použít kód ActionScript. Navíc, obsahuje-li externí soubor SWF třídy, které sdílejí stejný jmenný prostor jako třídy v načítajícím souboru SWF, budete možná muset vytvořit pro načtený soubor SWF novou aplikační doménu, abyste se vyhnuli konfliktům jmenného prostoru. Další informace o posouzení zabezpečení a aplikační domény viz „Použití třídy ApplicationDomain“ na stránce 641 a „Načítání souborů SWF a obrazů“ na stránce 702. Jakmile je externí soubor SWF úspěšně načten, můžete se k němu dostat prostřednictvím vlastnosti Loader.content. Je-li externí soubor SWF publikován pro jazyk ActionScript 3.0, bude to buď filmový klip nebo pohyblivý symbol, podle toho, kterou třídu rozšiřuje. Posouzení načtení staršího souboru SWF Jestliže byl soubor SWF publikován pomocí starší verze jazyka ActionScript, je třeba vzít v úvahu důležitá omezení. Narozdíl od souboru SWF ActionScript 3.0, který běží v AVM2 (ActionScript Virtual Machine 2), soubor SWF publikovaný pro ActionScript 1.0 nebo 2.0 běží v AVM1 (ActionScript Virtual Machine 1). Jakmile je soubor SWF AVM1 úspěšně načten, načtený objekt (vlastnost Loader.content) bude objekt AVM1Movie. Instance třídy AVM1Movie není stejná jako instance třídy MovieClip. Je to objekt zobrazení, ale narozdíl od filmového klipu nezahrnuje metody ani vlastnosti na bázi časové osy. Nadřízený soubor SWF AVM2 nebude mít přístup k vlastnostem, metodám ani objektům načteného objektu AVM1Movie. Existují další omezení k otevření souboru SWF AVM1 načteného souborem SWF AVM2. Podrobnosti viz přehled třídy AVM1Movie v Referenční příručce jazyka ActionScript 3.0 a jeho součástí. Příklad: RuntimeAssetsExplorer Export pro ActionScript může být výhodný zejména pro knihovny, které mohou být užitečné pro více projektů současně. Jestliže přehrávač Flash Player nebo AIR provede soubor SWF, symboly, které byly exportovány do jazyka ActionScript, budou dostupné pro libovolný soubor SWF ve stejné karanténě zabezpečení jako soubor SWF, který jej načítá. Tímto způsobem může jeden dokument Flash vygenerovat soubor SWF, který má jediný účel – uchovávat grafické datové zdroje. Tato technika je zvláště užitečná pro větší projekty, kde návrháři pracující na vizuálních datových zdrojích mohou pracovat souběžně s vývojovými pracovníky, kteří vytvářejí „zabalovací“ soubor SWF, který pak načte soubor SWF grafických datových zdrojů při běhu. Tuto metodu můžete používat ke správě série souborů pro konkrétní verzi, kde grafické datové zdroje nejsou závislé na průběhu vývoje programování. Aplikace RuntimeAssetsExplorer načte každý soubor SWF, který je podtřídou třídy RuntimeAsset a umožní procházet dostupné datové zdroje tohoto souboru SWF. Příklad ukazuje následující: • Načítání externích souborů SWF pomocí metody Loader.load() • Dynamické vytvoření symbolu knihovny exportovaného pro ActionScript • Ovládání přehrávání objektů MovieClip pomocí kódu ActionScript PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 407 Práce s filmovými klipy Než začnete, zajistěte, aby každý soubor SWF, který chcete spustit v přehrávači Flash Player, byl umístěn ve stejné karanténě zabezpečení. Další informace viz „Karantény zabezpečení“ na stránce 690 Aplikační soubory pro tuto ukázku najdete na adrese www.adobe.com/go/learn_programmingAS3samples_flash_cz. Soubory aplikace RuntimeAssetsExplorer jsou umístěny ve složce Samples/RuntimeAssetsExplorer. Aplikace sestává z následujících souborů: Soubor Popis RuntimeAssetsExample.mxml Uživatelské rozhraní pro aplikaci pro Flex (MXML) nebo Flash (FLA). nebo RuntimeAssetsExample.fla RuntimeAssetsExample.as Třída dokumentu pro aplikaci Flash (FLA). GeometricAssets.as Ukázková třída, která implementuje rozhraní RuntimeAsset. GeometricAssets.fla Soubor FLA připojený k třídě GeometricAssets (třída dokumentu souboru FLA) obsahující symboly, které jsou exportovány pro ActionScript. com/example/programmingas3/runtimeassetexplorer/RuntimeLibrary.as Rozhraní, které definuje vyžadované metody očekávané od všech souborů SWF s datovými zdroji za běhu, které budou načteny do kontejneru průzkumníku. com/example/programmingas3/runtimeassetexplorer/AnimatingBox.as Třída symbolu knihovny ve tvaru rotujícího čtverečku. com/example/programmingas3/runtimeassetexplorer/AnimatingStar.as Třída symbolu knihovny ve tvaru rotující hvězdy. Zavedení rozhraní knihovny za běhu Struktura knihoven datových zdrojů za běhu musí být formalizována, aby byla interakce průzkumníku s knihovnou SWF správná. Toho dosáhnete vytvořením rozhraní, které je podobné třídě v tom, že je to plán metod, které vymezují očekávanou strukturu, ale narozdíl od třídy nezahrnuje hlavní části metod. Toto rozhraní poskytuje způsob vzájemné komunikace mezi knihovnou za běhu a průzkumníkem. Každý soubor SWF datových zdrojů za běhu, který je načtený do prohlížeče, bude implementovat toto rozhraní. Další informace o rozhraních a způsobu jejich využití viz „Rozhraní“ na stránce 104. Rozhraní RuntimeLibrary bude velmi jednoduché – vyžaduje pouze funkci, která může dodat průzkumníku pole cest pro třídy pro symboly, které budou exportovány a dostupné v knihovně za běhu. Pro tento účel má rozhraní jen jednu metodu: getAssets(). package com.example.programmingas3.runtimeassetexplorer { public interface RuntimeLibrary { function getAssets():Array; } } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 408 Práce s filmovými klipy Vytváření souborů SWF knihovny datových zdrojů Když definujete rozhraní RuntimeLibrary, můžete vytvářet více souborů SWF knihovny datových zdrojů, které je možné načíst do jiného souboru SWF. Vytvoření individuální knihovny SWF datových zdrojů obnáší čtyři úlohy: • Vytvoření třídy pro soubor SWF knihovny datových zdrojů • Vytváření tříd pro jednotlivé datové zdroje obsažené v knihovně • Vytváření aktuálních grafických datových zdrojů • Přiřazování grafických elementů k třídám a publikování souborů SWF knihovny Vytvoření třídy pro implementaci rozhraní RuntimeLibrary Dále vytvoříme třídu GeometricAssets, která implementuje rozhraní runtimeLibrary. To bude třída dokumentu souboru FLA. Kód pro tuto třídu je velmi podobný rozhraní RuntimeLibrary – rozdíl mezi nimi je v tom, že v definici třídy má metoda getAssets() hlavní část metody. package { import flash.display.Sprite; import com.example.programmingas3.runtimeassetexplorer.RuntimeLibrary; public class GeometricAssets extends Sprite implements RuntimeLibrary { public function GeometricAssets() { } public function getAssets():Array { return [ "com.example.programmingas3.runtimeassetexplorer.AnimatingBox", "com.example.programmingas3.runtimeassetexplorer.AnimatingStar" ]; } } } Kdybychom měli vytvořit druhou knihovnu za běhu, mohli bychom vytvořit jiný soubor FLA na bázi jiné třídy (např. AnimationAssets), která poskytuje svou vlastní implementaci metody getAssests(). Vytváření tříd pro jednotlivé datové zdroje MovieClip Pro tento příklad pouze rozšíříme třídu MovieClip, aniž bychom k vlastním datovým zdrojům přidávali nějaké funkce. Následující kód pro třídu AnimatingStar je obdobný jako pro třídu AnimatingBox: package com.example.programmingas3.runtimeassetexplorer { import flash.display.MovieClip; public class AnimatingStar extends MovieClip { public function AnimatingStar() { } } } PROGRAMOVÁNÍ V JAZYCE ACTIONSCRIPT 3.0 PRO APLIKACI FLASH 409 Práce s filmovými klipy Publikování knihovny Nyní připojíme datové zdroje na bázi třídy MovieClip k nové třídě tak, že vytvoříme nový soubor FLA a do pole Třída dokumentu v Inspektoru vlastností zadáme GeometricAssets. Pro účely tohoto příkladu vytvoříme dva velmi základní tvary, které pomocí doplnění časové osy provedou jedno natočení po směru hodinových ručiček v délce 360 snímků. Symboly animatingBox i animatingStar jsou nastaveny na Export pro ActionScript a mají pole Třída nastavené na příslušné cesty pro třídy určené v implementaci metody getAssets(). Výchozí základní třída balíčku flash.display.MovieClip zůstává, neboť chceme vytvořit podtřídu se standardními metodami třídy MovieClip. Po nastavení exportních voleb symbolu publikujte soubor FLA. Právě jste vytvořil svou první knihovnu za běhu. Tento soubor SWF by mohl být načten do jiného souboru SWF AVM2 a pro tento nový soubor SWF by byly dostupné symboly AnimatingBox a AnimatingStar. Načtení knihovny do jiného souboru SWF Nakonec se ještě musíme vypořádat s uživatelským rozhraním pro průzkumník datových zdrojů. V tomto příkladu je cesta ke knihovně za chodu napevno zakódována jako proměnná s názvem ASSETS_PATH. Také byste mohli použít např. třídu FileReference – k vytvoření rozhraní pro procházení konkrétního souboru SWF na vašem pevném disku. Jakmile je knihovna za chodu úspěšně načtena, přehrávač Flash Player vyvolá metodu runtimeAssetsLoadComplete(): private function runtimeAssetsLoadComplete(event:Event):void { var rl:* = event.target.content; var assetList:Array = rl.getAssets(); populateDropdown(assetList); stage.frameRate = 60; } Proměnná rl v této metodě představuje načtený soubor SWF. Kód vyvolá metodu getAssets() načteného souboru SWF, obsahující seznam dostupných datových zdrojů, a jimi zaplní komponentu ComboBox vyvoláním metody populateDropDown(). Tato metoda dále uloží celou cestu pro třídy každého datového zdroje. Klepnutí na tlačítko Přidat na uživatelském rozhraní spustí metodu addAsset(): private { var var var ... } function addAsset():void className:String = assetNameCbo.selectedItem.data; AssetClass:Class = getDefinitionByName(className) as Class; mc:MovieClip = new AssetClass(); která získá cestu pro třídy každého právě vybraného datového zdroje v komponentě ComboBox (assetNameCbo.selectedItem.data) a pomocí funkce getDefinitionByName() (z balíčku flash.utils.package) získá aktuální odkaz na třídu datového zdroje za účelem vytvoření nové instance daného zdroje. 410 Kapitola 19: Práce s doplněními pohyby „Animace objektů“ na stránce 303 popisuje způsob implementace skriptované animace v jazyce ActionScrip
Podobné dokumenty
(zveřejněna 8. 9. 2011) PDF
složka s technickými metadaty – obsahuje pro každou naskenovanou stránku čísla časopisu 1 METS
soubor (AMD_METS.xml). Záměrně nejsou tato metadata v hlavním METS záznamu (hlavni_METS.xml),
protože ...
Diplomový projekt
běžet jak v prostředí Microsoft Windows, Mac OS X, GNU/Linux, SGI IRIX nebo na jiných
platformách UNIXu. Potřebuje pouze překladač C++ jazyka a knihovnu OpenGl (nebo
jinou knihovnu, která implement...
Ročníkový projekt
Microsoft Windows, Mac OS X, GNU/Linux, SGI IRIX nebo na jiných platformách UNIXu.
Potřebuje pouze překladač C++ jazyka a knihovnu OpenGl (nebo jinou knihovnu, která
implementuje OpenGl API, jako j...
ActionScript
Používání předdefinovaných objektů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Použití speciálních objektů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ....
Zobrazit nápovědu v souboru
Některá zlepšení výkonu neznamenají znatelné zlepšení pro uživatele. Je důležité zaměřit optimalizaci výkonu do
oblastí, které jsou problematické z pohledu vaší specifické aplikace. Některé způsoby...
Zobrazit nápovědu v souboru
Právní upozornění viz http://help.adobe.com/cs_CZ/legalnotices/index.html.
Zobrazit celý článek - JTIE - Journal of Technology and Information
1/2013, Volume5, Issue 1
ISSN 1803-537X
Základy Adobe FLASH CS4 []
jak vypadá tlačítko normálně,
jak vypadá při najeti myší,
při stisku tlačítka na myši,
oblast reakce myši.