![]() |
|
||||||||||
|
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 3 больше нет метода duplicateMovieClip, но его можно частично воспроизвести. Например, такая функция:
package com.senocular.display {
import flash.display.DisplayObject;
import flash.geom.Rectangle;
/**
* duplicateDisplayObject
* Создает дубликат DisplayObject,
* аналогично методу duplicateMovieClip из AVM1
* @param target Дублируемый объект
* @param autoAdd Если true, то созданный дубликат будет добавлен
* на сцену туда же, где и оригинал
* @return возвращает ссылку на дубликат
*/
public function duplicateDisplayObject(target:DisplayObject, autoAdd:Boolean = false):DisplayObject {
// Создаем дубликат (constructor в кавычках, чтобы компилятор не ругался в strict mode)
var targetClass:Class = target["constructor"];
var duplicate:DisplayObject = new targetClass();
// Дублируем свойства
duplicate.transform = target.transform;
duplicate.filters = target.filters;
duplicate.cacheAsBitmap = target.cacheAsBitmap;
duplicate.opaqueBackground = target.opaqueBackground;
if (target.scale9Grid) {
var rect:Rectangle = target.scale9Grid;
// Баг, Flash 9 возвращает scale9Grid в 20 раз больше чем на самом деле
rect.x /= 20, rect.y /= 20, rect.width /= 20, rect.height /= 20;
duplicate.scale9Grid = rect;
}
// Добавить дубликат к target.parent
// если autoAdd установлен в true
if (autoAdd && target.parent) {
target.parent.addChild(duplicate);
}
return duplicate;
}
}
Замечание: на данный момент во Flash Player 9 есть баг, некорректно возвращается свойство scale9Grid, эта функция исправляет ошибку, но когда баг в плеере исправят, строчку: нужно будет удалить. Пример использования функции: Учтите, эта функция не является полным аналогом duplicateMovieClip, т.к. не может продублировать что-то динамически нарисованное, только объекты, имеющие свой класс. |
|
|||||
|
Регистрация: 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
|
Новое свойство 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
|
Когда имеете дело с отображаемыми объектами (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);
}
}
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Обработчик события в ActionScript 3 может определить фазу события (см. предыдущий совет о фазах событий) по свойству eventPhase, которое может принимать три значения:
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
circle.addEventListener(MouseEvent.CLICK, clickCircle);
circle.addEventListener(MouseEvent.CLICK, clickCircle, true);
stage.addEventListener(MouseEvent.CLICK, clickStage);
stage.addEventListener(MouseEvent.CLICK, clickStage, true);
function clickCircle(evt:MouseEvent):void {
trace("clickCircle: " + getPhaseName(evt.eventPhase));
}
function clickStage(evt:MouseEvent):void {
trace("clickStage: " + getPhaseName(evt.eventPhase));
}
function getPhaseName(phase:int):String {
switch(phase) {
case EventPhase.CAPTURING_PHASE:
return "Capturing Phase";
case EventPhase.AT_TARGET:
return "At Target Phase";
case EventPhase.BUBBLING_PHASE:
return "Bubbling Phase";
}
return "Error: No Phase Detected";
}
Кликнув вне круга: |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 1 и 2 имелись события onMouseDown и onMouseUp, которые вызывались во всех объектах не зависимо от того, где находилась мышка. В ActionScript 3 такие события распространяются только на те объекты, над которыми находится мышка в момент клика. К примеру, если ваш мувиклип обрабатывает события MOUSE_DOWN и MOUSE_UP, а пользователь нажал кнопку мыши над мувиклипом, отвел мышку в сторону и отпустил кнопку, то событие MOUSE_UP ваш мувиклип не получит. Для обработки события глобально в ActionScript 3 нужно добавлять обработчик события к Stage. Поскольку именно к stage добавляются все отображаемые объекты, то через него проходят все события.
Одна маленькая, но важная деталь. Что если вы добавили обработчик события к stage, а какой-то мувиклип использовал предотвращение распространения события (см. предыдущий совет), в этом случае ваш обработчик события вызван не будет. Значит нужно добавлять обработчик события к stage на фазу захвата (capture). Но если пользователь кликнет по пустому месту, где нет никаких объектов, то целью события в этом случае будет stage и ваш обработчик события на фазу захвата (capture) вызван не будет, поскольку stage в данном случае участвует только в фазе обработка (targeting). Получается, для того чтобы поймать событие глобально в любом случае, нужно добавить два обработчика события к stage на фазе захвата (capture) и на фазе обработка (targeting). Поскольку нельзя поставить обработчик события только на фазу обработка (targeting), то нужно будет фазу подъема (bubbling) игнорировать в обработчике. Пример: var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
// Используем stage для глобальной обработки mouse up
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp, true);
function mouseUp(evt:MouseEvent):void {
// обрабатываем только фазы capturing и target
if (evt.eventPhase == EventPhase.BUBBLING_PHASE) return;
trace("global mouseUp");
}
// пусть мувиклип circle предотвращает распространение события mouse up
circle.addEventListener(MouseEvent.MOUSE_UP, mouseUpCircle);
function mouseUpCircle(evt:MouseEvent):void {
trace("mouseUpCircle");
evt.stopPropagation();
}
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 3 нет события onReleaseOutside, но его можно реализовать самостоятельно. Поскольку события mouseDown и mouseUp привязаны к объекту, то узнать о том, что кнопка мышки была отпущена за пределами объекта можно только слушая событие mouseUp глобально (см. предыдущий совет). Единственное, нужно добавить проверку отпустили кнопку мыши над тем же объектом (тогда это будет просто mouseUp) или над другим (тогда это будет onReleaseOutside).
Пример: // в этой переменной запоминаем ссылку на объект по которому кликнули
var clicked:DisplayObject;
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
function mouseDown(evt:MouseEvent):void {
trace("mouseDown");
clicked = circle;
}
function mouseUp(evt:MouseEvent):void {
trace("mouseUp");
}
function mouseUpOutside(evt:MouseEvent):void {
trace("mouseUpOutside");
}
// обработчик события на клик мышкой по объекту circle
circle.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
// обработчики событий для глобального mouseUp (подробнее см. предыдущий совет)
stage.addEventListener(MouseEvent.MOUSE_UP, captureMouseUp);
stage.addEventListener(MouseEvent.MOUSE_UP, captureMouseUp, true);
function captureMouseUp(evt:MouseEvent):void {
if (evt.eventPhase == EventPhase.BUBBLING_PHASE) return;
// убедимся, что кликнули по нужному нам объекту
if (clicked == circle) {
clicked = null; // очищаем ссылку для следующих кликов
var target:Sprite = evt.target as Sprite;
// отпустили кнопку над circle
if (target == circle) {
mouseUp(evt);
}else{
// отпустили кнопку мыши вне circle
mouseUpOutside(evt);
}
}
}
Нажать и отпустить кнопку мыши над кругом (объект circle): Нажать кнопку мыши над кругом, а отпустить в другом месте: Примечание: вместо того чтобы использовать переменную clicked, можно было бы в обработчике клика мышки mouseDown прописать слушателей на глобальный mouseUp, а в обработчике captureMouseUp удалить их. |
|
|||||
|
Регистрация: Apr 2014
Сообщений: 18
|
Цитата:
![]() Вот класс package { import flash.display.Sprite; import flash.display.MovieClip; import flash.events.*; public class Provod extends MovieClip { public var pArr:Array= new Array(); public var x1:Number,y1:Number,R1,smotrit; public function Provod(Num:int,x1,y1,R1:int,smotrit:int):void { //создаю части верёвки и заношу их в массив //сам провод //наконечник провода //остальная часть провода for (var i:int = 1; i <Num; i++) {var L:MovieClip= new p(); L.x = 0;L.y = i-Num;addChild(L);pArr[i] = L; } var Z:MovieClip= new z();Z.x = 0;Z.y = -Num;addChild(Z);Z.rotation=R1;pArr[0] = Z; //при движении мыши двигаю провод pArr[0].addEventListener(MouseEvent.MOUSE_DOWN,fun); pArr[0].addEventListener(MouseEvent.MOUSE_UP,funny); } public function fun(e:Event):void { pArr[0].startDrag(false); stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove); } public function funny(f:Event):void { pArr[0].stopDrag(); pArr[0].x=pArr[1].x; pArr[0].y=pArr[1].y; stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove); } public function stage_mouseMove(e:MouseEvent):void { //сначала выствляем провод от первого звена (которое в координатах мыши) //до последнего pArr[0].x = mouseX; pArr[0].y = mouseY; for (var i:int = 1; i < pArr.length; i++) { var p1:Sprite = pArr[i-1];//предыдущее звено var p2:Sprite = pArr[i];//текущее звено var ang:Number = Math.atan2(p1.y - p2.y, p1.x - p2.x); var dx:Number = p1.x - p2.x; var dy:Number = p1.y - p2.y; var dist:Number = Math.sqrt(dx * dx + dy * dy); p2.rotation = ang * 180 / Math.PI; if (dist > 1) { p2.x += (dist-1)*(dx/dist); p2.y += (dist-1)*(dy/dist); } } //перебераем звенья в обратном порядке, от фиксированного конца, до начального звена //фиксирую последее звено pArr[pArr.length - 1].x = x1; pArr[pArr.length - 1].y = y1; //цикл начинаю с предпоследнего звена, ведь последнее звено зафиксировано for (i=pArr.length-2; i >= 0; i--) { p1 = pArr[i+1];//звено следующее (в сторону начала провода) p2 = pArr[i];// текущее звено ang = Math.atan2(p1.y - p2.y, p1.x - p2.x); dx = p1.x - p2.x; dy = p1.y - p2.y; dist = Math.sqrt(dx * dx + dy * dy); p2.rotation = ang * 180 / Math.PI; if (dist > 1) { p2.x += (dist-1)*(dx/dist); p2.y += (dist-1)*(dy/dist); } } } } } не могли бы вы подсказать в чем проблема? |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 3 можно назначить свой класс (Document class) для главного timeline, который фактически будет являться root для всех отображаемых объектов. Назначить Document class можно в панели Property Inspector для документа (когда ничего не выделено) или же в диалоге ActionScript 3 Settings который расположен: File > Publish Settings > Flash [закладка] > Settings... [кнопка для ActionScript 3]. Просто впишите в поле "Document class" название вашего класса.
Document Class обязательно должен наследоваться от Sprite (flash.display.Sprite) или его потомков. Если будете использовать главную timeline, то document class лучше наследовать от MovieClip (flash.display.MovieClip) т.к. MovieClip поддерживает фреймы. Document Class обязательно должен быть публичным (public). Пример: package {
import flash.events.Event;
import flash.display.MovieClip;
public class CustomDocument extends MovieClip {
public function CustomDocument() {
addEventListener(Event.ADDED, checkChildren);
checkChildren(new Event("initialize"));
}
private function checkChildren(evt:Event):void {
// Позволяем добавить только один объект на root
if (numChildren > 1) {
throw (new Error("This movie can have only one child instance"));
}
}
}
}
|
![]() |
![]() |
Часовой пояс GMT +4, время: 05:12. |
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | |
| Опции просмотра | |
|
|