Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Статьи (http://www.flasher.ru/forum/forumdisplay.php?f=101)
-   -   ActionScript 3 Tips and Tricks (http://www.flasher.ru/forum/showthread.php?t=85645)

MerlinTwi 02.11.2006 20:31

13. Событие MOUSE_LEAVE или как узнать что мышка за пределами SWF
 
В ActionScript 3 можно определить что мышка ушла за пределы флеш-ролика, используя событие mouseLeave для stage. Это событие происходит каждый раз, когда мышка покидает пределы ролика. Нет события mouseEnter, но можно использовать mouseMove для определения того, что мышка вернулась к нам.
Простой пример использования нарисованного квадрата в качестве своего курсора.
Код:

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.ui.Mouse;
   
    public class Test extends Sprite {
       
        private var cursor:Sprite = new Sprite();
       
        public function Test() {
            cursor.graphics.beginFill(0xFF);
            cursor.graphics.drawRect(0, 0, 25, 25);
            addChild(cursor);
           
            stage.addEventListener(Event.MOUSE_LEAVE, cursorHide);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, cursorFollow);
            Mouse.hide();
        }
       
        public function cursorHide(evt:Event):void {
            cursor.visible = false;
        }
       
        public function cursorFollow(evt:MouseEvent):void {
            if (!cursor.visible) cursor.visible = true;
            cursor.x = stage.mouseX;
            cursor.y = stage.mouseY;
            evt.updateAfterEvent();
        }
    }
}

Когда мышка уходит за пределы флеш-ролика, наш курсор прячется. Когда мышка возвращается по событию mouseMove курсор снова отображается. Сделать такое в предыдущих версиях AS было нельзя.

MerlinTwi 02.11.2006 20:37

15. Немного о синтаксисе в Array
 
При определении массива в ActionScript 3 с использованием квадратных скобок, теперь можно оставить запятую после последнего элемента и это не вызовет ошибки. Например:
Код:

var myList:Array = [
    "The",
    "quick",
    "brown",
    "fox",
];

Наличие запятой после "fox" в ActionScript 1 и 2 вызвало бы ошибку.
Это не работает с Array() или new Array(), только с [].
Это конечно мелочь, но при отладке может сэкономить время, если вам, к примеру, нужно временно убрать последний элемент массива, просто закомментировать его. Раньше еще приходилось и убирать запятую перед ним, теперь все проще.

MerlinTwi 02.11.2006 20:48

16. Пакеты в AS3
 
Пакеты в ActionScript 3 немного отличаются от пакетов в ActionScript 2. Теперь пакет это не часть имени класса, а блок определяемый ключевым словом package, который содержит в себе определение класса. Структура такова:
Код:

package my.package.path {
    class MyClass {
    }
}

В AS2 подобная запись выглядела бы так:
Код:

// ActionScript 2:
class my.package.path.MyClass {
}

Фактически в AS3 все классы должны быть внутри пакета, если не нужно давать имя пакету, то следует записать так:
Код:

package {
    class NotInAPackageClass {
    }
}

Каждый пакет с определением класса или функции необходимо сохранить в файле имя которого совпадает с именем класса или функции, а расширение ".as". К примеру:
Код:

package com.kirupa.utils {
    function StripString(str:String):void {
        // ...
    }
}

Нужно сохранить в файле: StripString.as в папке com/kirupa/utils

MerlinTwi 02.11.2006 20:51

19. Абстрактные классы
 
К сожалению, ActionScript 3 НЕ поддерживает абстрактные классы (экземпляры которых нельзя создать, а можно только унаследовать). Т.е. вы не можете создавать ваши собственные абстрактные классы. Однако, обратите внимание, что некоторые из внутренних классов ActionScript сами по себе являются абстрактными. Эти классы включают:
  • DisplayObject
  • InteractiveObject
  • DisplayObjectContainer
  • Graphics
Как и с абстрактными классами вы не можете создавать их экземпляры с помощью ключевого слова new.
Код:

var myObj:InteractiveObject = new InteractiveObject(); // ERROR
Однако, в дополнение к этому, в ActionScript вы также не можете непосредственно расширять эти классы и создавать экземпляры таких подклассов
Код:

package {
    import flash.display.DisplayObject;
    public class MyDisplay extends DisplayObject{
        public function MyDisplay (){
            // ERROR
        }
    }
}

Если вы попытаетесь унаследовать один из них и создать экземпляр своего наследника, вы получите тот же Argument Error, что и при попытке создать экземпляр одного из этих классов непосредственно.

Вместо этого вам необходимо расширять те внутренние классы, которые уже являются наследниками этих классов. К примеру, если вы хотите расширить DisplayObject, вы можете вместо этого расширить Shape, легкий встроенный класс, унаследованный от DisplayObject.

MerlinTwi 02.11.2006 20:54

20. Ключевое слово override
 
Перекрытием (overriding) называется переопределение метода в классе, который в противном случае был бы унаследован. Новый метод будет использоваться вместо унаследованного (хотя унаследованный метод остается доступен с использованием super).

В ActionScript 3, когда вы перекрываете метод или свойство родительского класса, вы должны использовать аттрибут override. Он указывает на то, что создаваемый вами член класса будет перекрывать тот, который иначе был бы унаследован. Если вы не укажете override для метода, который уже существует в родительском классе, возникнет ошибка компиляции.

Пример:
Код:

package {
    import flash.display.*;
    class MySprite extends Sprite {

        private var children:Array = new Array();

        public function MySprite() {
        }

        public override function addChild(child:DisplayObject):DisplayObject {
            children.push(child);
            super.addChild(child);
            return child;
        }
    }
}

Т.к. addChild уже существует в родительском классе Sprite, необходимо использовать override для успешного определения нового метода addChild, который добавляет кроме прочего переданный child в массив children.

Обратите внимание, что описание метода должно соответствовать перекрываемому

Перекрытие работает как с обычными методами класса, так и с getter/setter методами (свойствами), однако оно не будет работать ни с чем из нижеперечисленного:
  • Переменные
  • Константы
  • Статические методы
  • Методы, которые не унаследованы
  • Методы, реализующие интерфейс
  • Унаследованные методы, отмеченные как финальные (final) в родительском классе

Обратите также внимание, что перекрытие не требуется для методов, которые наследуются непосредственно от класса Object. Это:
  • hasOwnProperty
  • isPrototypeOf
  • propertyIsEnumerable
  • setPropertyIsEnumerable
  • toString
  • valueOf
Эти методы добавляются динамически и не являются частью действительного определения класса. Ключевое слово override используется только для методов, которые присутствуют в исходном описании класса.

Однако, если расширяется класс, в котором приведенные выше методы являются частью его описания, ключевое слово override необходимо. Например, если вы расширяете класс Object, вам не нужно использовать override для метода toString. Но если вы расширяете класс Sprite, вам потребуется перекрывать toString, т.к. класс Sprite имеет в своем описании собственный toString.

MerlinTwi 02.11.2006 21:05

90. Операторы (.) и (..) для XML
 
Для доступа к вложенным объектам (детям) в XML вы можете использовать оператор точка (.) (XML dot operator). Пример:
Код:

var myXML:XML =
    <foo>
        <bar />
        <bar />
        <bar />
    </foo>;
   
trace(myXML.bar.toXMLString());

Результат:
Код:

<bar/>
<bar/>
<bar/>

Это аналогично использованию метода elements (XML.elements()).
Код:

trace(myXML.elements("bar").toXMLString());
Однако, есть еще похожий оператор две точки (..) (descendant accessor operator). Который работает аналогично, но возвращает и объекты более глубокого уровня вложенности. Пример:
Код:

var myXML:XML =
    <note>
        <replying-to>
            <note>
                <author>Julie</author>
                <title>Reminder</title>
                <body>Take out the trash</body>
            </note>
        </replying-to>
        <author>Kevin</author>
        <title>Re: Reminder</title>
        <body>I will.</body>
    </note>;
   
trace("Children:");
trace(myXML.author.toXMLString());
trace("Decendants:");
trace(myXML..author.toXMLString());

Результат:
Код:

Children:
<author>Kevin</author>
Decendants:
<author>Julie</author>
<author>Kevin</author>

Есть и специальный метод, который выполняет ту же задачу decendants (XML.descendants()).
Код:

trace(myXML.descendants("author").toXMLString());

MerlinTwi 02.11.2006 21:09

91. Array.indexOf и Array.lastIndexOf
 
В классе Array (Top level Array) добавлены новые методы indexOf и lastIndexOf.
Код:

AS3 function indexOf(searchElement:*, fromIndex:int = 0):int
AS3 function lastIndexOf(searchElement:*, fromIndex:int = 0x7fffffff):int

По сути они работают аналогично String.indexOf и String.lastIndexOf, возвращают позицию искомого элемента в массиве. Если объект не найден возвращается -1
Код:

var sprite:Sprite = new Sprite();
var object:Object = new Object();
var boolean:Boolean = true;
var number:Number = 10;

var array:Array = new Array(sprite, object, number);
trace(array.indexOf(sprite)); // 0
trace(array.indexOf(number)); // 2
trace(array.indexOf(boolean)); // -1


MerlinTwi 02.11.2006 21:17

92. "asfunction:" теперь "event:"
 
Для создания ссылок в текстовом поле, клик по которым можно программно отловить, теперь нужно использовать слово event (flash.text.TextField.event:link), а не asfunction как это было в ActionScript 1 и 2. Кроме того, event теперь не вызывает указанную функцию а создает событие TextEvent (flash.events.TextEvent) с типом TextEvent.LINK, а в свойство text записывается текст указанный в ссылке после слова event.
Пример:
Код:

var linkText:TextField = new TextField();
linkText.htmlText = 'Link: <a href="event:Link Clicked">Click</a>';
addChild(linkText);

linkText.addEventListener(TextEvent.LINK, linkEvent);

function linkEvent(event:TextEvent):void {
    trace(event.text); // Link Clicked
}


MerlinTwi 08.11.2006 16:32

93. Proxy: методы перечисления (nextName(), nextValue(), nextNameIndex())
 
Помимо создания динамических свойств и методов в Proxy (flash.utils.Proxy) есть возможность управлять порядком перечисления свойств в циклах for..in и for each..in. Для этого используются методы класса:
  • nextName(index:int):String
  • nextValue(index:int):*
  • nextNameIndex(index:int):int
Метод nextName возвращает название свойства по порядковому номеру для цикла for..in (аналогично nextValue для цикла for each..in). nextNameIndex вызывается перед началом каждой итерации в цикле и отвечает за две вещи:
1) предоставляет порядковый номер для nextName и nextValue (если возвращаемое значение >0), или
2) прерывает цикл (если возвращаемое значение равно нулю).
При начале цикла nextNameIndex получает порядковый номер равный нулю. Каждое последующее значение возвращаемое nextNameIndex отлично от нуля и передается методам nextName и nextValue. Если nextNameIndex возвращает ноль, то цикл заканчивается.
К примеру, proxy имеет 3 свойства (x,y,visible), попробуем их перечислить в цикле for..in
Код:

for (var prop:String in proxy) {
    trace(prop);
}

Здесь будут вызываться методы nextNameIndex и nextName:
Код:

for (var prop:String in proxy) {
        [ proxy.nextNameIndex(0) -> return 1 ]
        [ proxy.nextName(1) -> return "x" ]
        [ prop = "x" ]
        trace(prop); // x
        (end for block, repeat)
        [ proxy.nextNameIndex(1) -> return 2 ]
        [ proxy.nextName(2) -> return "y" ]
        [ prop = "y" ]
        trace(prop); // y
        (end for block, repeat)
        [ proxy.nextNameIndex(2) -> return 3 ]
        [ proxy.nextName(3) -> return "visible" ]
        [ prop = "visible" ]
        trace(prop); // visible
        [ proxy.nextNameIndex(3) -> return 0 ]
        (0 index, break from for block)
}

Если использовать цикл for each..in, то nextValue будет вызываться вместо nextName.
Поскольку в циклах используется порядковый номер, то удобно хранить динамические свойства в массиве и в методах nextName или nextValue просто вернуть элемент массива index-1 (поскольку nextName и nextValue никогда не получают порядкового номера 0).
Создадим прокси-класс, который реализует пример выше. Помните, что методы proxy определены в пространстве имен flash_proxy.
Код:

package {
   
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;
   
    public class ProxyEnum extends Proxy {
       
        private var props:Array = ["x", "y", "visible"]; // массив свойств
       
        // nextNameIndex вызывается при начале итерации в цикле
        override flash_proxy function nextNameIndex (index:int):int {
            if (index < props.length) {
                // первый вызов 0, возвращаем 1 + index
                // т.е. порядковый номер будет 1, затем 2, 3
                return index + 1;
            } else {
                // все свойства перечислены для прерывания цикла
                // возвращаем 0
                return 0;
            }
        }
       
        // nextName вызывается после nextNameIndex и порядковый номер начинается с 1
        override flash_proxy function nextName(index:int):String {
            // возвращаем элемент массива index – 1
            return props[index - 1];
        }
    }
}

Пример использования:
Код:

var proxy:ProxyEnum = new ProxyEnum();
for (var prop in proxy) {
    trace(prop);
}
/* output:
x
y
visible
*/

Для полной картины необходимо еще переопределить методы nextValue и getProperty. Но для них нужны возвращаемые значения, пусть класс принимает в конструкторе ссылку на какой-то отображаемый объект, его свойства и будем возвращать.
Код:

package {
   
    import flash.display.DisplayObject;
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;
   
    public class ProxyEnum extends Proxy {
       
        private var props:Array = ["x", "y", "visible"]; // массив свойств
        private var _target:DisplayObject;
       
        function ProxyEnum(target:DisplayObject) {
            _target = target;
        }
       
        // nextNameIndex вызывается при начале итерации в цикле
        override flash_proxy function nextNameIndex (index:int):int {
            if (index < props.length) {
                // первый вызов 0, возвращаем 1 + index
                // т.е. порядковый номер будет 1, затем 2, 3
                return index + 1;
            } else {
                // все свойства перечислены для прерывания цикла
                // возвращаем 0
                return 0;
            }
        }
       
        // nextName вызывается после nextNameIndex и порядковый номер начинается с 1
        override flash_proxy function nextName(index:int):String {
            // возвращаем элемент массива index – 1
            return props[index - 1];
        }
       
        // nextValue вызывается после nextNameIndex в циклах for each..in
        override flash_proxy function nextValue(index:int):* {
            // получаем название свойства из массива
            var prop:String = props[index - 1];
            // и возвращаем его значение
            return _target[prop];
        }
       
        // возвращает значение свойства по его имени
        override flash_proxy function getProperty(name:*):* {
            return _target[name];
        }
    }
}

Пример использования:
Код:

var proxy:ProxyEnum = new ProxyEnum(my_mc);

for (var prop:String in proxy) { // nextName/nextNameIndex
    trace(prop);
    trace(proxy[prop]); // getProperty
}
/* output:
x
34
y
76
visible
true
*/

for each(var value:* in proxy) { // nextValue/nextNameIndex
    trace(value);
}
/* output:
34
76
true
*/


MerlinTwi 09.11.2006 12:36

94. Перехват событий мышки и mouseEnabled
 
MerlinTwi: Поскольку этот совет (Event Capturing and mouseEnabled) в оригинале практически дублирует (72. mouseEnabled и блокирование событий), видимо senocular где-то ошибся, то я сам расскажу еще про mouseEnabled.
К примеру, создаем класс текстовой кнопки, есть фоновый мувиклип, который растягивается под ширину текста и сверху на него накладывается текст (TextField). Если обработчики событий от мышки (MOUSE_OVER, MOUSE_OUT, CLICK) добавить к фоновому мувиклипу, то события будут срабатывать только на краях кнопки, где нет текста. Это происходит потому, что все интерактивные отображаемые объекты создаются по умолчанию с mouseEnabled=true, т.е. реагируют на события от мышки, а как было показано в предыдущих советах событие от мышки получает только самый верхний объект на сцене. Поэтому в таких случаях нужно не забывать запрещать текстовому полю перехватывать события от мышки:
Код:

mouseEnabled=false;
А вообще, при создании кнопки лучше сделать:
Код:

buttonMode=true;


Часовой пояс GMT +4, время: 23:55.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.