Лучшим подходом, вероятно, было бы использование кода, размещенного в вопросе, то есть, чтобы развернуть объект, проверить его ширину, а затем повторно повернуть его. И вот почему.
Во-первых, , простота . Понятно, что делается и почему это работает. Любой, кто придет позже, не должен иметь проблем с пониманием.
Второй, Точность . Из любопытства я закодировал все три предложения, которые в настоящее время находятся в этой теме, и я не очень удивился, обнаружив, что для произвольно масштабируемого объекта они дают три несколько разных ответа. Причина этого, в двух словах, заключается в том, что внутренние компоненты рендеринга Flash сильно оптимизированы, и, среди прочего, width
и height
не хранятся внутри как плавающие числа. Они хранятся в виде «твипов» (двадцатых пикселей) на том основании, что дальнейшая точность визуально не имеет значения.
В любом случае, если три метода дают разные ответы, какой из них наиболее точный? За мои деньги самый правильный ответ - то, что Flash думает о ширине объекта, когда он не повернут, что дает нам простой метод. Кроме того, этот метод является единственным, который всегда дает ответы, округленные до ближайшей 1/20, что, как я предполагаю (хотя я предполагаю), означает, что оно, вероятно, равно значению, хранимому внутри, а не вычисляемому значению.
Наконец, скорость . Я предполагаю, что это вас удивит, но когда я закодировал три метода, простой подход был самым быстрым с небольшим отрывом. (Не вдавайтесь в подробности - все они были очень близки, и если вы настроите мой код, другой метод может оказаться в лидерах. Дело в том, что они очень сопоставимы.)
Вы, вероятно, ожидали, что простой метод будет медленнее на том основании, что изменение поворота объекта может привести к пересчету многих других вещей, что приведет к накладным расходам. Но все, что происходит на самом деле сразу, когда вы меняете вращение, это то, что матрица преобразования объекта получает новые значения. Flash на самом деле мало что делает с этой матрицей, пока в следующий раз не нарисует объект на экране. Что касается того, что математика происходит, когда вы читаете ширину / высоту объекта, сказать сложно. Но стоит отметить, что все, что происходит в простом методе, выполняется сильно оптимизированными внутренними компонентами Player, а не в AS3, как алгебраический метод.
В любом случае, я приглашаю вас попробовать пример кода, и я думаю, вы обнаружите, что простой простой метод, по крайней мере, не медленнее, чем любой другой. Это плюс простота делает его тем, с кем я бы пошел.
Вот код, который я использовал:
// init
var clip:MovieClip = new MovieClip();
clip.graphics.lineStyle( 10 );
clip.graphics.moveTo( 12.345, 37.123 ); // arbitrary
clip.graphics.lineTo( 45.678, 29.456 ); // arbitrary
clip.scaleX = .87; // arbitrary
clip.scaleY = 1.12; // arbitrary
clip.rotation = 47.123; // arbitrary
// run the test
var iterations:int = 1000000;
test( method1, iterations );
test( method2, iterations );
test( method3, iterations );
function test( fcn:Function, iter:int ) {
var t0:uint = getTimer();
for (var i:int=0; i<iter; i++) {
fcn( clip, i==0 );
}
trace(["Elapsed time", getTimer()-t0]);
}
// the "simple" method
function method1( m:MovieClip, traceSize:Boolean ) {
var rot:Number = m.rotation;
m.rotation = 0;
var w:Number = m.width;
var h:Number = m.height;
m.rotation = rot;
if (traceSize) { trace([ "method 1", w, h ]); }
}
// the "algebraic" method
function method2( m:MovieClip, traceSize:Boolean ) {
var r:Number = m.rotation * Math.PI/180;
var c:Number = Math.abs( Math.cos( r ) );
var s:Number = Math.abs( Math.sin( r ) );
var denominator:Number = (c*c - s*s); // an optimization
var w:Number = (m.width * c - m.height * s) / denominator;
var h:Number = (m.height * c - m.width * s) / denominator;
if (traceSize) { trace([ "method 2", w, h ]); }
}
// the "getBounds" method
function method3( m:MovieClip, traceSize:Boolean ) {
var r:Rectangle = m.getBounds(m);
var w:Number = r.width*m.scaleX;
var h:Number = r.height*m.scaleY;
if (traceSize) { trace([ "method 3", w, h ]); }
}
И мой вывод:
method 1,37.7,19.75
Elapsed time,1416
method 2,37.74191378925391,19.608455916982187
Elapsed time,1703
method 3,37.7145,19.768000000000004
Elapsed time,1589
Удивительно, а? Но здесь есть важный урок о разработке Flash. Настоящим я крещу Закон лени Фена:
По возможности, избегайте хитрой математики, заставляя визуализатор сделать это за вас.
Это не только ускоряет выполнение, но, по моему опыту, в любом случае это обычно приводит к выигрышу в производительности. Счастливая оптимизация!