![]() |
|
||||||||||
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Если в классе наследнике от 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];
}
}
}
}
В начале getMyVar возвращает null, поскольку переменная «MyVar», еще не определена. После записи при помощи setMyVar, getMyVar возвращает записанное значение. |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В 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);
}
}
}
}
Пример: // 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; |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В класс TextField (flash.text.TextField) добавлен новый метод appendText (flash.text.TextField.appendText()), который добавляет новый текст в конец существующего в текстовом поле (обычный текст, не html). Этот метод аналог TextField.text += newText, но работает гораздо быстрее.
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 3 оставлена директива include для вставки кода из другого файла, только изменился синтаксис, теперь не нужно писать символ #
Храните подключаемые внешние файлы вне папки class path чтобы они не интерпретировались как классы. |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 1 и 2 можно было объявить одну переменную дважды в одной области видимости и это не вызывало ошибки. Например:
В ActionScript 3 так нельзя. Вы можете только один раз объявить переменную в одной области видимости. Так же нельзя изменить тип переменной. // ActionScript 3 var i:Number = 1; var i:String = 2; // ERROR: duplicate definition or undefined property // Это НЕВЕРНО для 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";
}
// ПРАВИЛЬНО для 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";
}
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В 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;
}
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Новое свойство 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 = false; |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Любой интерактивный объект (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);
}
Если убрать комментарий со строки spriteButton.mouseChildren=false; то различий в поведении событий roll и mouse не будет. |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Метод 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 |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Когда имеете дело с отображаемыми объектами (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);
}
}
|
![]() |
![]() |
Часовой пояс GMT +4, время: 18:15. |
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | |
| Опции просмотра | |
|
|