Почему Flash использует всю высоту маскируемого объекта, а не только видимую область? - PullRequest
5 голосов
/ 25 июля 2011

Проблема заключается в том, что я устанавливаю свойство .mask объекта Sprite , Sprite объект все еще возвращает свою полную высоту, когда я вызываю Sprite.height .Поэтому я решил, что простой способ преодолеть это - переопределить метод получения свойства.

Теперь ... хотя это сработало, если я добавлю этот маскированный Sprite объектдругому объекту Sprite , новый объект Sprite сообщит о своей высоте как маскируемый Sprite высота объекта, хотя я переопределил свойство, чтобы оно возвращало только высоту видимой области из-за маски.Таким образом, кажется, что Flash игнорирует тот факт, что не все содержимое является видимым, но все равно автоматически увеличивает высоту нового Sprite объекта, как если бы на маске не было маски Sprite .

Поэтому мне интересно, есть ли обходной путь, чтобы я мог добавить этот маскированный объект к любому другому DisplayObject , зная, что этоизменить размер только на то, что видно в маскированном объекте.

Спасибо за любую помощь.

РЕДАКТИРОВАТЬ

Вот пример кода ..

var content:Bitmap = new Bitmap(new BitmapData(50, 100, false, 0x000000));
var container:Sprite = new Sprite();
var mask:Bitmap = new Bitmap(new BitmapData(50, 50, false, 0x000000));

container.mask = mask;

container.addChild(content);

trace(container.height) // this should return 50 instead of 100

Ответы [ 4 ]

2 голосов
/ 24 сентября 2013

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

2 голосов
/ 27 июля 2011

Так что для тех, кому интересно, мне удалось найти обходной путь. Что меня действительно раздражает, так это то, что DisplayObject.scrollRect не обновляет размеры немедленно, поэтому, пока Adobe не оторвется от своей задницы и не исправит ее, вот что вам нужно сделать.

Проблема с .scrollRect , как я уже упоминал, заключается в том, что он не подстраивается под новые ширину и высоту до тех пор, пока не пройдет кадр или через некоторое время. В любом случае я в основном построил свой класс таким образом, чтобы после установки .scrollRect я создавал таймер, который запускался каждую миллисекунду, проверяя, если .width и .height обновлен до новых значений. После этого я отправляю пользовательское событие READY , которое родительский объект прослушивает перед добавлением класса на сцену.

Теперь одна очень важная вещь, которую вы должны знать об этой арке, является то, что объект, для которого вы устанавливаете свойство .scrollRect , должен быть добавленным на сцену до того, как он попытается обновить значения ширины и высоты до значений, установленных в свойстве .scrollRect . Поэтому, чтобы сделать это как можно более чистым, я передаю объект Stage из моего основного класса в объект, чей .scrollRect я хочу настроить, давайте назовем его MyClass . MyClass устанавливает для его свойства .visible значение false, а затем добавляет сам к сцене. Только после этого теперь я могу запустить таймер на 1 мс, чтобы проверить, правильно ли изменились размеры после того, как я установил .scrollRect .

Так что, как только функция обработки тиков таймера увидит, что измерения успешно изменились, MyClass теперь может отправлять событие MyClass.READY в основной класс, одновременно устанавливая его .visible свойство true и удаление себя со сцены. Когда прослушиватель событий основного класса запускается, он теперь может добавить MyClass куда угодно, зная, что у него будут правильные измерения, как установлено в MyClass.scrollRect .

Это было большой болью для меня и, вероятно, многих других разработчиков, ищущих решения, поэтому я надеюсь, что это помогло вам и пока хватит, пока Adobe не сделает что-то с этим. Спасибо всем, кто писал ранее, кто пытался помочь, я действительно ценю это, спасибо!

0 голосов
/ 24 сентября 2013

ширина и высота могут быть переопределены.Объект всегда будет иметь внутреннюю ширину и высоту, соответствующие тому, что отображается внутри него, и, к сожалению, эта внутренняя ширина и высота никогда не будут учитывать маскированные области.getRect и getBounds также не чувствительны к маскам, поэтому сами по себе они тоже недостаточны.

Что вам нужно сделать, это написать рекурсивный метод с именем что-то вроде «getMaskSensitiveRect», чувствительный к маскам.Вместо того, чтобы пересекать результат getRect для каждого дочернего объекта, вы сначала должны проверить, является ли свойство маски каждого дочернего элемента нулевым, и если оно не равно нулю, вызвать getRect для маски вместо объекта и использовать его в качестве прямоугольника дочернего объекта для пересечения.с остальными дочерними объектами.И вам определенно придется пройти всю иерархию всех детей, внуков и т. Д. До самого глубокого уровня, чтобы получить точную меру, потому что, если даже одна маска не будет учтена, она может взорвать размер.

Не забудьте переопределить установщики для ширины и высоты, потому что изменение ширины или высоты объекта DisplayObject фактически изменяет его масштаб, и это происходит относительно этого внутреннего размера, а НЕ переопределенной ширины и высоты.То, что вам нужно сделать в установщике, - это вызвать метод getMaskSensitiveRect и вычислить масштаб с использованием этой и желаемой ширины, а затем назначить масштаб для свойств scaleX и scaleY.

0 голосов
/ 26 июля 2011

Если вы не можете найти прямого решения, вы можете попробовать следующее:

  1. Нарисуйте дочерний объект (ваш объект DisplayObject, который включает маску и маску) в объект BitmapData.
  2. Разобрать пиксели объекта BitmapData и проверить значение альфа-канала, используя метод getPixel32() BitmapData.
  3. Определите ограничивающий прямоугольник, который ограничивает все ненулевые альфа-пиксели, и используйте эти размеры.

Я бы обернул все это методом getMaskedDimensions(child:DisplayObject):Rectangle. Дайте мне знать, если вам нужно больше деталей. В противном случае, удачи с этим!

...