【问题标题】:How to scale rotated objects properly in Actionscript 3?如何在 Actionscript 3 中正确缩放旋转对象?
【发布时间】:2010-03-17 12:00:52
【问题描述】:

不幸的是,这是一个需要解释的相当复杂的问题,所以请不要因文字墙而气馁——它的存在是有原因的。 ;)

我正在开发一个用于 Flash 的转换管理器,使用 Actionscript 3 编写。用户可以在屏幕上放置对象,例如矩形。

然后可以选择并转换此矩形:移动、缩放或旋转。

因为默认情况下 flash 围绕对象的左上角旋转,并且我希望它围绕中心旋转,所以我为每个显示对象(例如矩形)创建了一个包装器设置。

这是包装器的设置方式:

//the position wrapper makes sure that we do get the top left position when we access x and y
var positionWrapper:Sprite = new Sprite();
positionWrapper.x = renderObject.x;
positionWrapper.y = renderObject.y;

//set the render objects location to center at the rotation wrappers top left
renderObject.x = 0 - renderObject.width / 2;
renderObject.y = 0 - renderObject.height / 2;

//now create a rotation wrapper, at the center of the display object
var rotationWrapper:Sprite = new Sprite();
rotationWrapper.x = renderObject.width / 2;
rotationWrapper.y = renderObject.height / 2;

//put the rotation wrapper inside the position wrapper and the render object inside the rotation wrapper
positionWrapper.addChild(rotationWrapper);
rotationWrapper.addChild(renderObject);

现在,可以直接访问和设置对象的 x 和 y:mainWrapper.x 或 mainWrapper.y。可以从这个主包装器的子级设置和访问旋转:mainWrapper.getChildAt(0).rotation。最后,可以通过获取旋转包装器的孩子并直接访问显示对象来获取和设置显示对象的宽度和高度。

我如何访问它们的示例:

//get wrappers and render object
var positionWrapper:Sprite = currentSelection["render"];
var rotationWrapper:Sprite = positionWrapper.getChildAt(0) as Sprite;
var renderObject:DisplayObject = rotationWrapper.getChildAt(0);

这适用于所有初始转换:移动、缩放和旋转。

但是,当您首先旋转对象(例如 45 度)然后对其进行缩放时,就会出现问题。缩放后的对象变形,无法按应有的方式缩放。

例如,当您向左缩放时会发生这种情况。向左缩放基本上是为对象添加 n 宽度,然后将位置包装器的 x 坐标也减少 n:

renderObject.width -= diffX;
positionWrapper.x += diffX;

这在对象未旋转时有效。但是,当它是时,位置包装器将不会旋转,因为它是旋转包装器的父级。这将使位置包装器水平向左移动,同时对象的宽度沿对角线增加。

我希望这有任何意义,如果没有,请告诉我,我会尝试详细说明。

现在,问题是:我应该使用不同类型的设置、系统还是结构?我是否应该使用矩阵,如果是这样,旋转后如何保持静态宽度/高度?或者如何修复当前的包装系统以在旋转后进行缩放?任何帮助表示赞赏。

【问题讨论】:

  • 您可能希望将值除以 2 得到的值四舍五入 - 如果它们的大小是奇数,那么您最终会得到半像素位置的对象(这可能会导致搞笑抗锯齿)。这可能是也可能不是您想要的。
  • 通过缩放,您的意思是这里通常不均匀缩放?例如,方形凸轮变成任何矩形?
  • 卡梅伦,谢谢。 AB,是的,没错。

标签: actionscript-3 algorithm rotation transform scaling


【解决方案1】:

看起来您应该使用变换矩阵
看看这篇很棒的帖子
http://gasi.ch/blog/zooming-in-flash-flex/

【讨论】:

  • 我尝试使用矩阵类。问题是矩阵类在改变旋转后对象的宽高xy。
【解决方案2】:

这个呢:

positionWrapper.width -= diffX;
positionWrapper.x += diffX;

另外,您可以踢出rotationWrapper 并直接在positionWrapper 上执行旋转。

除此之外,我建议你看看senocular's tranformtoolsephiroth's modifications

编辑:您基本上要寻找的是具有任意中心的任意向量的比例变换。有了这个,剩下的就变得微不足道了。对于第一个问题:创建一个矩阵 M 将中心移动到 0.0 并将向量旋转到 x 轴上。通过向量的长度和 M 的倒数将 M 与 x 尺度相结合,得到的矩阵应该可以满足您的需要。当然你可以直接用笔和纸计算得到的矩阵,但这应该已经足够了

【讨论】:

  • renderObject 必须围绕中心旋转时,如何退出 rotationWrapper?这就是旋转包装器的用途,然后位置包装器确保位置仍然在左上角而不是中心。
  • @Tom:我这边的小错误。但是,是的,你可以把它踢出去。您也可以在 positionWrapper 中居中渲染对象,然后旋转 positionWrapper 本身。在帖子中更新了它。
  • 尝试为 positionWrapper 设置宽度,它不起作用,因为 positionWrapper 没有旋转,因此即使对象旋转了 45 度,它也会水平改变宽度。
  • 无论包装器是否已旋转,您都不能仅将其在 x 坐标中向后移动 n 个像素,因为旋转的对象不会移动那么远。也许这需要一些正弦计算?
  • @Tom:您也许应该定义所需的行为。如果不是水平缩放,“向左缩放”到底是什么意思?在 renderObject 坐标中是“向左缩放”吗?另外,您查看我提供的链接了吗?
猜你喜欢
  • 2019-03-07
  • 2018-04-19
  • 2020-10-20
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
  • 2015-07-20
  • 2012-10-14
相关资源
最近更新 更多