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

Вернуться   Форум Flasher.ru > Блоги > Psycho Tiger

Оценить эту запись

cacheAsBitmap/filter vs mask. Девочки, сверкаем!

Запись от Psycho Tiger размещена 14.09.2010 в 14:46
Обновил(-а) Psycho Tiger 14.09.2010 в 16:50

Маленький интродакшн: при непустом массиве filters cacheAsBitmap сразу ставится в true, поэтому по сути фильтры здесь не причем, но тем не менее, как использующее это свойство они всё таки затрагиваются.
Код AS3:
package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.filters.BevelFilter;
 
	public class Tile extends Sprite
	{
 
		public function Tile()
		{
			super();
			var _bitmapData:BitmapData = new BitmapData(100,100,false, 0xFF00);
			super.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			var bmp:Bitmap = new Bitmap(_bitmapData);
			super.addChild(bmp);
			//super.cacheAsBitmap = true;
			var _maskShape:Shape = new Shape();
			_maskShape.graphics.beginFill(0);
			_maskShape.graphics.drawRect(0, 0, 50, 50);
			_maskShape.graphics.endFill();
			super.mask = _maskShape;
 
		}
 
		private function onMouseDown(event:MouseEvent):void
		{
			trace("Click");
		}
 
	}
 
}
Давайте добавим одну Tile:
Код AS3:
var tile:Tile = new Tile();
super.addChild(tile);
Появилась, всё хорошо. Даже реагирует на события мышки и мы радостно видим в окошке Click.
Добавим ей подружку:
Код AS3:
var tile:Tile = new Tile();
super.addChild(tile);	
tile = new Tile();
super.addChild(tile);
tile.x = 100;
Запускаем... Но вторую подружку мы не увидим.
Убираем маску: она отчетливо видна.

Чешем репу. Вспоминаем, что к Bitmap нельзя выполнять обрезку маской.
Думаем. Понимаем, что маску мы применили к Tile`у, а не Bitmap и первый тайл очень даже образался. Делаем лицо лопатой и ждём гуру. Мне не понятно такое поведение - один раз не лоботряс.

UPD: благодаря комментариям нашли проблему: Это потому что addChild забыли сделать. В итоге маска имеет координаты (0;0), а после addChild она попадает в контейнер, который маскирует, и следовательно её глобальные координаты меняются на координаты контейнера.

Расскоментиваем строчку cacheAsBitmap=true и запускаем. О, чудо! Мы видим вторую битмапу, которая не обрезана. Ну ладно бы там маска. Это дело не реагирует на события мыши. Если убрать добавление маски, то, конечно же, событие мышки мы получаем.

Будьте внимательнее.
Всего комментариев 32

Комментарии

Старый 14.09.2010 15:55 switcher! вне форума
switcher!
интересное дело. Похоже на баг.
Не понятны слова:
Цитата:
Мы видим вторую битмапу, которая, конечно же, не обрезана
сказано так, будто это рядовой эффект.

и
Цитата:
Выходит cacheAsBitmap преобразует картинку в такое представление растра, которому тоже неподвластна маска
на чем основано данное утверждение? Если первый тайл, к которому так же применяется cacheAsBitmap=true, не только адекватно отображается, но и реагирует на действия мыши.

Кстати, это характерно не только для битмап. Если использовать только graphics - будет тот же эффект.
Старый 14.09.2010 16:13 iNils вне форума
iNils
 
Аватар для iNils
Код AS3:
addChild (_maskShape)
Старый 14.09.2010 16:18 switcher! вне форума
switcher!
да, момент адекватной "обрезки" объектов это решает. Но все кроме первого по-прежнему не интерактивны.
Старый 14.09.2010 16:25 -De- вне форума
-De-
 
Аватар для -De-
Это ещё связанно с забагованностью маски, которая не добавлена в дисплей лист. Я лично во-первых не люблю маску из-за тормознутости, а во-вторых всегда добавляю в контейнер с маскируемым обьектом. Так - работает.
Код AS3:
public function Tile()
        {
            var _bitmapData:BitmapData = new BitmapData(100,100,false, 0xFF00);
            addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            var fooSprite:Sprite = new Sprite();
            addChild(fooSprite);
            var bmp:Bitmap = new Bitmap(_bitmapData);
            fooSprite.addChild(bmp);
            fooSprite.cacheAsBitmap = true;
            var _maskShape:Shape = new Shape();
            _maskShape.graphics.beginFill(0);
            _maskShape.graphics.drawRect(0, 0, 50, 50);
            _maskShape.graphics.endFill();
            fooSprite.mask = _maskShape;
            //fooSprite.addChild(_maskShape);//клики не работают
            addChild(_maskShape);//всё ок
        }
Старый 14.09.2010 16:28 iNils вне форума
iNils
 
Аватар для iNils
Цитата:
Это ещё связанно с забагованностью маски, которая не добавлена в дисплей лист
Просто ее глобальные координаты имеют значение (0,0), и если объект сдвинут, под маску он не попадает.
Старый 14.09.2010 16:32 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
iNils, ты хочешь сказать что при становлении маской она теряет свою принадлежность к контейнеру в этом примере?

@switcher!: кстати да, удалю пока этот кусок сообщения. Требуется более тщательный анализ.
Старый 14.09.2010 16:41 iNils вне форума
iNils
 
Аватар для iNils
Цитата:
ты хочешь сказать что при становлении маской она теряет свою принадлежность к контейнеру в этом примере?
Можно перевод на человеческий?
Я хочу сказать, что у первого тайла координаты (0,0) поэтому он под свою маску попал, а у второго тайла координаты (100,0), тогда как у маски (0,0), так как она не в его дисплей листе находится. А вот когда ты сделал addChild, маска сразу принимает координаты тайла.
Старый 14.09.2010 16:48 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Забавненько. Спасибо, не думал что маска вне дисплай листа контейнера имеет глобальные координаты.
Но ещё забавней что маска перестаёт накладываться после второго cacheAsBitmap. Статью переправил обычным добавлением UPD, чтобы прослеживалась нить странности с отсутствием маски на втором cacheAsBitmap.
Обновил(-а) Psycho Tiger 14.09.2010 в 16:52
Старый 14.09.2010 16:53 iNils вне форума
iNils
 
Аватар для iNils
Цитата:
Спасибо, не думал что маска вне дисплай листа контейнера имеет глобальные координаты.
А где она должна быть? И с чего вдруг? Это же не avm1, где новый объект был намертво привязан к тому объекту, в котором его создавали.
Старый 14.09.2010 16:56 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Ну да, прав.
Старый 14.09.2010 17:13 switcher! вне форума
switcher!
а что насчет интерактивности - почему для этого требуется "прослойка", как в примере -De- ?
Старый 14.09.2010 17:33 i.o. вне форума
i.o.
 
Аватар для i.o.
Код AS3:
            //fooSprite.addChild(_maskShape);//клики не работают
            addChild(_maskShape);//всё ок
Это давно ли народ пытается маску всунуть в тот объект, который мы пытаемся замаскировать?
Маска и маскируемый объект должны лежать в одном контейнере, рядышком, чтобы у них одна система координат была.
С 5-го, если не раньше, флэша так было. Так собственно и осталось.
Старый 14.09.2010 17:51 iNils вне форума
iNils
 
Аватар для iNils
Цитата:
Это давно ли народ пытается маску всунуть в тот объект, который мы пытаемся замаскировать?
А в чем проблема?
Старый 14.09.2010 18:06 i.o. вне форума
i.o.
 
Аватар для i.o.
Цитата:
А в чем проблема?
//клики не работают
Старый 14.09.2010 18:14 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Код AS3:
	addEventListener(Event.ADDED_TO_STAGE, onAdded);
 
...
 
		private function onAdded(event:Event):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, onAdded);
			parent.addChild(_maskShape);
		}
Сори за быдлокод.
Результат один и тот же. Клик не работает, второй объект не маскируется. (при cachAsBitmap=true)
Старый 14.09.2010 18:33 iNils вне форума
iNils
 
Аватар для iNils
Если маска прямоугольная, то можно использовать за место нее scrollRect.
Старый 14.09.2010 19:01 incoob вне форума
incoob
А зачем используется super в приведенном примере?
Старый 14.09.2010 19:04 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Потому что свойства и методы определенны в супер-классе.
Это мой стиль написания.
Старый 14.09.2010 19:11 incoob вне форума
incoob
Цитата:
Результат один и тот же. Клик не работает, второй объект не маскируется. (при cachAsBitmap=true)
А у меня почему-то все работает.
Что-то мне подсказывает, что ты запускаешь сам Tile вместо
Код AS3:
var tile:Tile = new Tile();
super.addChild(tile);	
tile = new Tile();
super.addChild(tile);
tile.x = 100;
Старый 14.09.2010 19:17 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Повезло. Не забудь раскомментировать строчку //super.cacheAsBitmap = true;
Старый 14.09.2010 20:19 incoob вне форума
incoob
И правда пропустил. Оба объекта при этом все так же визуализируются. Но вот события не работают.
Все верно гоорит i.o. Если маску добавлять не в маскируемый объект а в родителя, то проблема исчезнет и события заработают.
Старый 14.09.2010 21:06 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Хорошо, даже если так: почему работает первый контейнер?
Обновил(-а) Psycho Tiger 14.09.2010 в 21:22
Старый 14.09.2010 21:20 iNils вне форума
iNils
 
Аватар для iNils
Цитата:
Хорошо, даже если так: почему работает первый контейнер?
Та же самая причина. Сдвинь контейнер на 25 пикселей в право. Левая половина будет работать, а правая нет.
Старый 14.09.2010 21:23 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Я не совсем о том: события мыши доступны, когда маска находится в себе в случае с первым контейнером.
Старый 14.09.2010 21:41 iNils вне форума
iNils
 
Аватар для iNils
Баг .
Старый 14.09.2010 21:50 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Ага, понятно. Примерно это я и ожидал услышать.
Старый 15.09.2010 01:50 TERRORist вне форума
TERRORist
 
Аватар для TERRORist
а _maskShape.mouseEnabled = false не помогает?
Старый 15.09.2010 17:42 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Тут суть скорее в том, что при одинаковом коде первый раз себя ведёт не так, как второй и следующий. С мышкой разобрались как получать события.
Старый 15.09.2010 18:49 iNils вне форума
iNils
 
Аватар для iNils
Цитата:
Тут суть скорее в том, что при одинаковом коде первый раз себя ведёт не так, как второй и следующий
Ты опять ничего не понял. Дело не в последовательности, а в положении. Смести первый клип, а не второй и он не будет работать, а второй будет.
Тут баг с hitArea. Причем создание новой области, и внутри Tile проблему не решает.

Но проблема не страшная, выходы есть.
Старый 15.09.2010 18:57 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Тьфу ты. У меня голова другим забита. Описался: хотел написать что разобрались с маскированием.

Обходные пути всегда есть - например я создаю ещё один спрайт, в него кладу битмапу и на него же кладу маску. Тут важно понять, где кончается баг и начинается собственная глупость.
Старый 15.09.2010 19:00 iNils вне форума
iNils
 
Аватар для iNils
Не только, как я уже говорил, для прямоугольной маски можно использовать scrollRect.
А маска сама по себе глючная. Собственный scale9Grid она также игнорирует.
Старый 15.09.2010 19:46 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Да, мне тоже кажется что scrollRect удачней. Прямоугольная маска была выбрана исключительно ради примера.
 

 


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


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