Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0 > Статьи

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 24.10.2006, 13:15
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 61  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 67. Метод callProperty класса Proxy

Если в классе наследнике от Proxy попытаться вызвать несуществующий метод, то будет вызван метод callProperty, которому передается название метода с массивом аргументов. Это можно использовать для создания динамических методов.

Как и все методы класса Proxy, callProperty объявлен в пространстве имен «flash_proxy» (flash.utils.flash_proxy), чтобы не возникало конфликтов с публичными методами. Для переопределения метода в своем классе обязательно нужно указывать пространство имен flash_proxy.

Пример: класс CustomObject наследуется от Proxy и переопределяет метод callProperty для управления динамическими методами.
Код:
package {
    
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;
    
    dynamic public class CustomObject extends Proxy {
        
        private var variables:Object = new Object(); // хранилище переменных
        
        public function CustomObject() {
        }
        
        // Вызывает при обращении к динамическому методу
        override flash_proxy function callProperty(name:*, ... args):* {
            
            // Преобразуем name в строку
            name = String(name);
            
            var callType:String = name.slice(0,3); // get или set
            var callVariable:String = name.slice(3); // название переменной
            
            switch(callType) {
                
                case 'get':
                    // Если «get», то возвращает значение переменной, если она существует
                    if (callVariable in variables) {
                        return variables[callVariable];
                    }
                    return null;
                    
                case 'set':
                    // Если «set» запомним новую переменную
                    variables[callVariable] = args[0];
            }
        }
    }
}
В этом примере, с использованием callProperty, реализованы динамические методы для чтения и записи «переменных».
Код:
// пример использования
var myObj:CustomObject = new CustomObject();
trace(myObj.getMyVar()); // null
myObj.setMyVar("foo");
trace(myObj.getMyVar()); // foo
myObj.setMyVar("bar");
trace(myObj.getMyVar()); // bar
trace(myObj.MyVar); // не существует (get property error)
В начале getMyVar возвращает null, поскольку переменная «MyVar», еще не определена. После записи при помощи setMyVar, getMyVar возвращает записанное значение.
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 24.10.2006, 13:42
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 62  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 68. Копирование динамической графики с помощью класса Proxy

В ActionScript 3 нет возможности непосредственно скопировать графику созданную в Graphics. Но можно использовать класс Proxy для записи всех вызванных методов, чтобы потом их воспроизвести при копировании. Например, такой вариант:
Код:
package com.senocular.display {
    
    import flash.display.Graphics;
    import flash.utils.flash_proxy;
    import flash.utils.Proxy;
    
    /**
     * Класс для расширения graphics с возможностью создания копии рисунка
     */
    public class GraphicsCopy extends Proxy {
        
        private var _graphics:Graphics;
        private var history:Array = new Array();
        
        /**
         * Ссылка на graphics
         */
        public function get graphics():Graphics {
            return _graphics;
        }
        public function set graphics(g:Graphics):void {
            _graphics = g;
            
            // Создаем копию рисунка на новом Graphics
            copy(this);
        }
        
        /**
         * Конструктор
         * @param graphics Ссылка на Graphics рисование по которому  запоминаем
         */
        public function GraphicsCopy(graphics:Graphics = null) {
            _graphics = graphics;
        }
        
        /**
         * Копирует сюда рисунок из другого класса GraphicsCopy
         */
        public function copy(graphicsCopy:GraphicsCopy):void {
            var hist:Array = graphicsCopy.history;
            history = hist.slice();
            if (_graphics) {
                var i:int;
                var n:int = hist.length;
                _graphics.clear();
                for (i=0; i<n; i += 2) {
                    _graphics[hist[i]].apply(_graphics, hist[i + 1]);
                }
            }
        }
        
        // Перехват вызова несуществующего метода, с помощью этого
        // метода PROXY и реализована запись процесса рисования.
        override flash_proxy function callProperty(methodName:*, ... args):* {
            methodName = String(methodName);
            switch(methodName) {
                case "clear":
                    history.length = 0;
                    break;
                default:
                    history.push(methodName, args);
            }
            if (_graphics && methodName in _graphics) {
                return _graphics[methodName].apply(_graphics, args);
            }
        }
    }
}
Теперь достаточно при рисовании вместо свойства graphics использовать экземпляр класса GraphicsCopy, который запоминает историю вызванных при рисовании методов и может ее воспроизвести, при создании копии.
Пример:
Код:
// MyClass.as Класс наследник от Shape с использованием GraphicsCopy
package {
    
    import flash.display.Shape;
    import com.senocular.display.GraphicsCopy;
    
    class MyShape extends Shape {
        
        // свойство graphicsCopy
        private var _graphicsCopy:GraphicsCopy;
        public function get graphicsCopy():GraphicsCopy {
            return _graphicsCopy;
        }
        
        // Конструктор
        function MyShape(){
            _graphicsCopy = new GraphicsCopy(graphics);
        }
    }
}
Код:
// Пример использования 
// Что-то рисуем на shape 1
var shape1:MyShape = new MyShape();
shape1.graphicsCopy.beginFill(0xFF80);
shape1.graphicsCopy.lineStyle(2, 0);
shape1.graphicsCopy.drawRect(0, 0, 50, 50);

// Делаем копию рисунка на  shape2
var shape2:MyShape = new MyShape();
shape2.graphicsCopy.copy(shape1.graphicsCopy);

// Добавляем на экран
addChild(shape1);
addChild(shape2);
shape2.x += 100;
В результате вы увидите два зеленых квадрата, первый нарисован нами (метод drawRect), а вторая копия воспроизведена автоматически.
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 24.10.2006, 13:46
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 63  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 69. TextField.appendText()

В класс TextField (flash.text.TextField) добавлен новый метод appendText (flash.text.TextField.appendText()), который добавляет новый текст в конец существующего в текстовом поле (обычный текст, не html). Этот метод аналог TextField.text += newText, но работает гораздо быстрее.
Код:
var my_tf = new TextField();
my_tf.text = "Hello";
my_tf.appendText(" world!");  // my_tf.text == "Hello world!"
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 25.10.2006, 11:46
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 64  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 70. Директива include

В ActionScript 3 оставлена директива include для вставки кода из другого файла, только изменился синтаксис, теперь не нужно писать символ #
Код:
include "scripts/myscript.as"
Храните подключаемые внешние файлы вне папки class path чтобы они не интерпретировались как классы.
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 25.10.2006, 12:00
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 65  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 71. Двойное объявление переменной

В ActionScript 1 и 2 можно было объявить одну переменную дважды в одной области видимости и это не вызывало ошибки. Например:
Код:
// ActionScript 1 и 2  
var i:Number = 1;
var i:String = 2;
В ActionScript 3 так нельзя. Вы можете только один раз объявить переменную в одной области видимости. Так же нельзя изменить тип переменной.
Код:
// ActionScript 3  
var i:Number = 1;
var i:String = 2; // ERROR: duplicate definition or undefined property
В ситуации, где переменная используется в разных блоках for или if, вы должны объявить ее до блока:
Код:
// Это НЕВЕРНО для ActionScript 3 
// (но работает в AS1 и AS2)
if (my_btn.enabled == true) {
    var returnValue:Number = 1;
}else{
    var returnValue:Number = 0;
}
if (provideAsString == true) {
    var returnValue:String = "1";
}else{
    var returnValue:String = "0";
}
Правильно для AS3 в данной ситуации будет так:
Код:
// ПРАВИЛЬНО для ActionScript 3 
var returnValueNum:Number;
var returnValueStr:String;
if (my_btn.enabled == true) {
    returnValueNum = 1;
}else{
    returnValueNum = 0;
}
if (provideAsString == true) {
    returnValueStr = "1";
}else{
    returnValueStr = "0";
}
Если же неприемлемо использование двух переменных и обязательно должна быть одна, которая должна принимать как числовое значение так и строку, нужно использовать универсальный тип переменных *
Код:
// Также ПРАВИЛЬНО для ActionScript 3 
var returnValue:*;
if (my_btn.enabled == true) {
    returnValue = 1;
}else{
    returnValue = 0;
}
if (provideAsString == true) {
    returnValue = "1";
}else{
    returnValue = "0";
}
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 25.10.2006, 12:39
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 66  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 72. mouseEnabled и блокирование событий

В ActionScript 1 и 2, в случае если несколько мувиклипов, обрабатывающих события от мышки, частично или полностью перекрываются, то события от мышки (onPress, onRollOver …) получал только верхний мувиклип. Для того чтобы событие от мышки мог получить нижестоящий мувиклип, нужно или удалить верхний или удалить у него все обработчики событий мышки, тогда мувиклип станет «прозрачен» для событий от мышки.
В ActionScript 3 ситуация примерно аналогичная, но проверка на то, прозрачен мувиклип для событий от мышки или нет, лежит не на наличие обработчиков этих событий, а на свойстве mouseEnabled (flash.display.InteractiveObject.mouseEnabled).
Если mouseEnabled=true (так по умолчанию), то мувиклип перехватывает и обрабатывает события от мышки. Если же mouseEnabled=false, то он становится прозрачен для мышки и события смогут получать и мувиклипы лежащие под ним.

В примере ниже, рисуются два частично перекрывающихся круга. Внизу "circle 1" и над ним "circle 2". При клике мышкой по любому кругу вызывается обработчик события "click", который показывает по какому кругу кликнули и переключается свойство mouseEnabled для верхнего "circle 2". Таким образом, если кликать мышкой в область, где круги пересекаются, то сначала событие перехватывает верхний "circle 2", а на второй клик реагирует уже нижний "circle 1", т.к. у вернего круга mouseEnabled=false;
Код:
function createCircle(name:String = ""):Sprite {
    var circle:Sprite = new Sprite();
    circle.name = name;
    circle.graphics.lineStyle(0);
    circle.graphics.beginFill(0xFF8080);
    circle.graphics.drawCircle(50, 50, 50);
    return circle;
}

var circle1:Sprite = createCircle("circle 1");
var circle2:Sprite = createCircle("circle 2");
circle2.x += 25;

addChild(circle1);
addChild(circle2);

circle1.addEventListener(MouseEvent.MOUSE_DOWN, click);
circle2.addEventListener(MouseEvent.MOUSE_DOWN, click);

function click(e) {
    trace(e.target.name + " clicked."); // trace name
   
    // Выключаем/включаем реакцию circle2 на события от мышки
    circle2.mouseEnabled = !circle2.mouseEnabled;
}
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 26.10.2006, 12:53
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 67  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 73. Свойство mouseChildren

Новое свойство mouseChildren (flash.display.DisplayObjectContainer.mouseChildren) позволяет включать и выключать возможность реагировать на события от мышки для всех вложенных мувиклипов. Присвоить mouseChildren=false аналогично, если присвоить mouseEnabled=false для всех вложенных мувиклипов, после этого никто из вложенных мувиклипов не будет реагировать на события от мышки.
Это может быть полезно, если вы создаете свою кнопку наследуясь от MovieClip или Sprite со вложенными мувиклипами. По умолчанию в обработчике события такой кнопки Event.target будет не сама кнопка, а вложенный в нее мувиклип. Пример:
Код:
// Сама кнопка
var spriteButton:Sprite = new Sprite();
spriteButton.name = "spriteButton";
spriteButton.mouseChildren = true;

// Рисунок внутри кнопки
var spriteGraphics:Sprite = new Sprite();
spriteGraphics.name = "spriteGraphics";
spriteGraphics.graphics.beginFill(0x4080A0);
spriteGraphics.graphics.drawCircle(50, 50, 25);

// добавляем на экран
spriteButton.addChild(spriteGraphics);
addChild(spriteButton);

// слушаем событие click
spriteButton.addEventListener(MouseEvent.CLICK, click);
function click(evt:MouseEvent):void {
    trace(evt.target.name);
}
Если mouseChildren = true; (по умолчанию)
Код:
//output
spriteButton
Если mouseChildren = false;
Код:
// output
 spriteGraphics
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 26.10.2006, 13:25
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 68  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 74. Различия между rollOver/rollOut и mouseOver/mouseOut

Любой интерактивный объект (flash.display.InteractiveObject) имеет две пары очень похожих событий rollOver/rollOut и mouseOver/mouseOut. Оба они реагируют на то когда мышка входит в область объекта или покидает ее. Различия в поведении этих событий возникают только тогда, когда есть вложенные мувиклипы. События rollOver и rollOut не обращают внимание на наличие вложенных мувиклипов, когда мышка войдет в область объекта сработает rollOver, и только когда мышка покинет объект сработает rollOut. События mouseOver и mouseOut будут срабатывать на перемещение мышки над вложенными мувиклипами. mouseOver сработает когда мышка войдет в область объекта, если при дальнейшем движении курсор мышки войдет в область вложенного мувиклипа сработает mouseOut, когда мышка покинет вложенный объект вновь сработает mouseOver, хотя при этих перемещениях курсор мыши фактически не покидал области объекта. События mouseOver и mouseOut будут вести себя аналогично rollOver и rollOut если установить mouseChildren=false;
Лучше всего посмотреть пример:
Код:
// Основная кнопка
var spriteButton:Sprite = new Sprite();
spriteButton.name = "spriteButton";
spriteButton.graphics.beginFill(0xFF0000);
spriteButton.graphics.drawCircle(50,50, 50);
//spriteButton.mouseChildren=false;

// Вложенный в кнопку Sprite
var spriteGraphics:Sprite = new Sprite();
spriteGraphics.name = "childrenSprite";
spriteGraphics.graphics.beginFill(0x00FF00);
spriteGraphics.graphics.drawCircle(50,50, 15);

// Добавляем на экран
spriteButton.addChild(spriteGraphics);
addChild(spriteButton);

// События
spriteButton.addEventListener(MouseEvent.ROLL_OVER, evnt);
spriteButton.addEventListener(MouseEvent.ROLL_OUT, evnt);
spriteButton.addEventListener(MouseEvent.MOUSE_OVER, evnt);
spriteButton.addEventListener(MouseEvent.MOUSE_OUT, evnt);

function evnt(e:MouseEvent):void {
    trace(e.type, "on", e.target.name);
}
При однократном проведении мышки через всю кнопку:
Код:
// output
rollOver on spriteButton
mouseOver on spriteButton
mouseOut on spriteButton
mouseOver on childrenSprite
mouseOut on childrenSprite
mouseOver on spriteButton
mouseOut on spriteButton
rollOut on spriteButton
Если убрать комментарий со строки spriteButton.mouseChildren=false; то различий в поведении событий roll и mouse не будет.
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 26.10.2006, 13:36
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 69  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 75. DisplayObjectContainer contains()

Метод contains (flash.display.DisplayObjectContainer.contains()) позволяет определить является ли указанный мувиклип вложенным в этот мувиклип (причем не важно в какой степени вложенности).
Пример:
Код:
var king:Sprite = new Sprite();
var queen:Sprite = new Sprite();
var jack:Sprite = new Sprite();
var joker:Sprite = new Sprite();

queen.addChild(jack);
king.addChild(queen);
addChild(king);
addChild(joker);

// В итоге получилась такая вложенность
// king
//   queen
//     jack
// joker
// проверяем:

trace(king.contains(queen)); // true
trace(king.contains(jack)); // true
trace(king.contains(joker)); // false
Если нужно проверить только первый уровень вложенности, то можно просто сравнить свойство parent.
Код:
trace(queen.parent == king); // true
trace(jack.parent == king); // false
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Старый 27.10.2006, 12:32
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 70  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
По умолчанию 76. Освобождение слушателей событий при удалении с экрана

Когда имеете дело с отображаемыми объектами (display objects) в ActionScript 3 важно помнить, что они могут существовать даже если не добавлены на экран (display list) и при этом продолжают получать и обрабатывать события на которые подписаны (очевидно, кроме событий от мышки). К примеру, событие enterFrame будет продолжать вызываться, и после удаления объекта с экрана. Это существенное отличие от ActionScript 1 и 2, т.к. там удаление мувиклипа с экрана означало и удаление всех событий.
Если вы хотите, чтобы событие типа enterFrame не вызывалось, когда объект удален с экрана, вы должны самостоятельно удалять подобные события. Сделать это просто, достаточно прописать обработчики событий Event.ADDED (вызывается когда объект добавлен к другому отображаемому объекту) и Event.REMOVED (вызывается когда объект удаляется от родителя).
Код:
var sprite:Sprite = new Sprite();
sprite.addEventListener(Event.ADDED, addEnterFrame);
sprite.addEventListener(Event.REMOVED, removeEnterFrame);

// Добавляем/удаляем обработчик события enter frame 
function addEnterFrame(evt:Event):void {
    trace("added");
    sprite.addEventListener(Event.ENTER_FRAME, enterFrame);
}
function removeEnterFrame(evt:Event):void {
    trace("removed");
    sprite.removeEventListener(Event.ENTER_FRAME, enterFrame);
}
function enterFrame(evt:Event):void {
    trace("Time: " + getTimer());
}

// Добавляем/удаляем объект по клику мышки
stage.addEventListener(MouseEvent.CLICK, addRemove);
function addRemove(evt:Event):void {
    if (this.contains(sprite)) {
        this.removeChild(sprite);
    }else{
        this.addChild(sprite);
    }
}
Код:
// output
added
Time: 813
Time: 927
removed
added
Time: 2509
Time: 2597
removed
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.

Создать новую тему Ответ Часовой пояс GMT +4, время: 18:15.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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