【问题标题】:How do I get the visual width and height of a rotated component?如何获得旋转组件的视觉宽度和高度?
【发布时间】:2011-03-20 15:33:18
【问题描述】:

我正在玩这样的代码:

<s:Button id="test" label="test" transformX="{Math.floor(test.width/2)}" rotationY="20" x="20" y="20" />

按钮在 Y 轴上旋转,旋转轴在按钮的中间。

这将创建一个看起来像这样的按钮:


(来源:jeffryhouser.com

旋转按钮在视觉上填充的空间与您想象的 x、y、高度和宽度值不同。

我图片中的“A”值是按钮的高度。但是,我想用于计算和放置目的是 B 值。

另外,我想对宽度进行类似的计算;获取从右上角到左下角的宽度。

我该怎么做?


我整理了一个sample 来展示人们建议的各种计算方法。源代码也是available。没有什么能像我预期的那样工作。例如,将 rotationSlider 设置为 85。该按钮实际上是不可见的,但所有方法仍为其指定高度和宽度。

【问题讨论】:

标签: apache-flex actionscript-3 math geometry flex4


【解决方案1】:

我的数学可能有点生疏,但这就是我找到答案的方法:

您可以将一个直角三角形从按钮的右边缘延伸到您所拥有的图表的最底端 (A-B)。然后,您可以使用正弦定理获得三个角度:90'、20' 和 70'(90 将始终存在,然后您的变量 - 第三个角度为 180)。

然后您可以使用以下公式来找到您的答案:

B = ((button.width * sin(button.rotationY)) / (sin(90 -button.rotationY)) + (button.height)

【讨论】:

【解决方案2】:

getBounds(..) 和 getRect(..) 应该是获取变换对象宽度和高度的方法。

尚未在 Flex 4 中尝试过它们,但它们在 Flex 3 中总是为我工作。

【讨论】:

  • 在纸上;这听起来正是我正在寻找的。但是,他们似乎没有按照我期望的方式工作。 没有转换。宽度为 70,高度为 21。 var bounds1 : Rectangle = test2.getRect(this.test2); bounds1 宽度为 72,高度为 23。如果我开始旋转项目;结果似乎更不正确。
  • 我整理了一个示例来展示人们建议的各种方法:flextras.com/labs/DisplaySize/DisplaySize.html
  • 詹姆斯发布的博客看起来很有希望,但如果 getBounds 没有返回正确的边界,我真的认为这是一个错误......
【解决方案3】:

答案在 James Ward 的其中一个问题上,位于blog post

博文没有说的一件事是,在许多情况下,相关类的 transform 属性的 perspectiveProjection 属性将为空。链接到的示例通过将maintainProjectionCenter 属性设置为true 来解决这个问题。但是,您也可以像这样创建一个新的 perspectiveProjection 对象:

object.transform.perspectiveProjection = new PerspectiveProjection();

我将 evtimmy 中的函数封装到一个类中:

/**
 * DotComIt/Flextras 
 * Utils3D.as
 * Utils3D
 * jhouser
 * Aug 5, 2010
 */
package com.flextras.coverflow
{
    import flash.geom.Matrix3D;
    import flash.geom.PerspectiveProjection;
    import flash.geom.Rectangle;
    import flash.geom.Utils3D;
    import flash.geom.Vector3D;

    public class TransformUtilities
    {
        public function TransformUtilities()
        {
        }


    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  projectBounds
    //----------------------------------
    // info from 
    // http://evtimmy.com/2009/12/calculating-the-projected-bounds-using-utils3dprojectvector/

    /**
     * Method retrieved from  
     * http://evtimmy.com/2009/12/calculating-the-projected-bounds-using-utils3dprojectvector/
     * 
     * @param bounds:  The rectangle that makes up the object
     * @param matrix The 3D Matrix of the item
     * @param the projection of the item's parent.
     */
    public static function projectBounds(bounds:Rectangle,
                                         matrix:Matrix3D, 
                                         projection:PerspectiveProjection):Rectangle
    {
        // Setup the matrix
        var centerX:Number = projection.projectionCenter.x;
        var centerY:Number = projection.projectionCenter.y;
        matrix.appendTranslation(-centerX, -centerY, projection.focalLength);
        matrix.append(projection.toMatrix3D());

        // Project the corner points
        var pt1:Vector3D = new Vector3D(bounds.left, bounds.top, 0); 
        var pt2:Vector3D = new Vector3D(bounds.right, bounds.top, 0) 
        var pt3:Vector3D = new Vector3D(bounds.left, bounds.bottom, 0);
        var pt4:Vector3D = new Vector3D(bounds.right, bounds.bottom, 0);
        pt1 = Utils3D.projectVector(matrix, pt1);
        pt2 = Utils3D.projectVector(matrix, pt2);
        pt3 = Utils3D.projectVector(matrix, pt3);
        pt4 = Utils3D.projectVector(matrix, pt4);

        // Find the bounding box in 2D
        var maxX:Number = Math.max(Math.max(pt1.x, pt2.x), Math.max(pt3.x, pt4.x));
        var minX:Number = Math.min(Math.min(pt1.x, pt2.x), Math.min(pt3.x, pt4.x));
        var maxY:Number = Math.max(Math.max(pt1.y, pt2.y), Math.max(pt3.y, pt4.y));
        var minY:Number = Math.min(Math.min(pt1.y, pt2.y), Math.min(pt3.y, pt4.y));

        // Add back the projection center
        bounds.x = minX + centerX;
        bounds.y = minY + centerY;
        bounds.width = maxX - minX;
        bounds.height = maxY - minY;
        return bounds;
    }

    }

}

虽然这是我问题的答案,但我不确定这是否是我问题的解决方案。谢谢大家!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多