Лучший способ масштабировать DropShadows в AS3? - PullRequest
0 голосов
/ 09 ноября 2009

Я создаю флэш-приложение, которое использует как фильтр dropShadow, так и масштабирование различных спрайтов.

И в этом заключается проблема :

Этот фильтр поддерживает этапное масштабирование. Тем не менее, он не поддерживает общие масштабирование, вращение и наклон. Если сам объект масштабируется (если scaleX и ScaleY установлены в значение, отличное от 1.0), фильтр не масштабируется.

По случайности отсутствие поддержки вращения мне выгодно, но мне действительно очень нужно масштабирование для работы. Какой лучший способ сделать это?

Могу ли я расширить объект DropShadow и обновить его?

Должен ли я создать свой собственный объект, который просто воссоздает себя с новым значением .distance, соответствующим уровню масштабирования?

Какой метод лучше всего использовать (учитывая производительность)?

Ответы [ 3 ]

1 голос
/ 29 мая 2013

Имея в виду производительность, вы можете использовать Bitmap и нарисовать контейнер оригинального размера с DropShadowFilter на нем. Таким образом, фильтр будет масштабироваться и Flash даже не придется пересчитывать рендеринг тени.

Пример:

// We need to use this container as the source for the Bitmap.
var sample:Sprite = new Sprite();


// Sample object with DropShadowFilter applied.
var rect:Sprite = new Sprite();
rect.x = rect.y = 10;
rect.graphics.beginFill(0xCC0000);
rect.graphics.drawRect(0, 0, 50, 50);
rect.graphics.endFill();
rect.filters = [new DropShadowFilter()];
sample.addChild(rect);


// Create our Bitmap.
var bitmap:Bitmap = new Bitmap();

bitmap.x = bitmap.y = 100;
bitmap.bitmapData = new BitmapData(sample.width + 20, sample.height + 20, true);
bitmap.bitmapData.draw(sample);
bitmap.scaleX = bitmap.scaleY = 0.5;

addChild(bitmap);
0 голосов
/ 29 мая 2013

Поскольку фильтр не масштабируется, значения его параметров всегда должны соответствовать пиксельным единицам. Следовательно, вы просто должны масштабировать значения фильтра так же, как объект. Для этого просто переведите единичный вектор (длина == 1) в системе координат объектов в глобальную систему координат, и расстояние будет вашим глобальным коэффициентом масштабирования для фильтров объекта.

Каждый раз, когда ваш объект перемещается или масштабируется, изменяйте любые значения фильтра, которые должны масштабироваться, и повторно применяйте фильтры. Вот пример класса документа, показывающий квадрат с фильтрами свечения и тени, масштабируемыми с ним, в то время как он вложен в другой масштабируемый контейнер. Я также добавил слушателя изменения размера сцены, чтобы держать квадрат в центре сцены.

Вставьте это в действия на основной временной шкале нового документа и запустите его. Обратите внимание, что масштаб расстояния и размера тени, а также размытие фильтра свечения также масштабируются. Вы даже можете добавить математику для учета вращения, если у вас есть разные значения размытия x и y.

import flash.display.Sprite;
import flash.filters.GlowFilter;
import flash.events.Event;
import flash.display.StageScaleMode;
import flash.utils.getTimer;
import flash.geom.Point;
import flash.filters.DropShadowFilter;

//Fix the scale of the stage
stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
stage.frameRate = 60;

//Create a small green square centered at the origin
var r:Sprite = new Sprite();
r.graphics.beginFill( 0x00ff00 );
r.graphics.drawRect( -5, -5, 10, 10 );
r.graphics.endFill();

//Nest it in a container
var container:Sprite = new Sprite();
container.addChild( r )
addChild( container );

//Apply a glow filter
var GLOW_BLUR:Number = 10;
var SHADOW_DIST:Number = 5;
var SHADOW_BLUR:Number = 2;
var dropshadow:DropShadowFilter = new DropShadowFilter( SHADOW_DIST, 45, 0, 1, SHADOW_BLUR, SHADOW_BLUR, 1, 3 ); //new GlowFilter( 0x000000, 0.5, GLOW_BLUR, GLOW_BLUR, 2, 3 );
var glow:GlowFilter = new GlowFilter( 0x0000ff, 1, GLOW_BLUR, GLOW_BLUR, 1, 3 ); //new GlowFilter( 0x000000, 0.5, GLOW_BLUR, GLOW_BLUR, 2, 3 );
r.filters = [glow,dropshadow];

addEventListener( Event.ENTER_FRAME, enterFrame, false, 0, true );
addEventListener( Event.RESIZE, stageResized, false, 0, true );
var t:int = getTimer();
stageResized( null );
function enterFrame( e:Event ):void
{
    var cycle_length:Number = 2000;
    var cycle:Number = (((getTimer() - t) % cycle_length) / cycle_length) * Math.PI * 2.0;
    var scale:Number = 2 + Math.sin( cycle );
    r.scaleX = r.scaleY = scale;
    container.scaleX = container.scaleY = scale * 2;
    container.rotation = cycle / (Math.PI / 180);

    var p0:Point = new Point( 0, 0 );
    var p1:Point = new Point( 1, 0 );
    p0 = r.localToGlobal( p0 );
    p1 = r.localToGlobal( p1 );
    var globalScale:Number = Point.distance( p0, p1 );

    dropshadow.blurX = dropshadow.blurY = SHADOW_BLUR * globalScale;
    dropshadow.distance = SHADOW_DIST * globalScale;
    glow.blurX = glow.blurY = GLOW_BLUR * globalScale;
    r.filters = [glow,dropshadow];
}
function stageResized( e:Event ):void
{
    container.x = (stage.stageWidth / 2);
    container.y = (stage.stageHeight / 2);
}
0 голосов
/ 09 ноября 2009

Я использую фильтр dropShadow, как этот, и масштабирую, поворачиваю, наклоняю работает отлично:

var localFilters :Array = new Array();
localFilters.push( dropShadowFilter );

component.filters = localFilters;

после этого, если вы делаете, например:

var m:Matrix = new Matrix();
m.scale( 1.5, 2 );

component.transform.matrix = m;

Фильтр dropShadow будет масштабирован.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...