在更改scaleX和scaleY时保持相对位置?

时间:2015-08-19 07:11:55

标签: actionscript-3 flex actionscript flex4

我正在尝试在地图演示文稿类型应用中实现一个简单的“缩放”功能。用户与NumericStepper进行交互以拨入比例值,然后我使用该值设置地图精灵的scaleXscaleY属性。地图精灵的父级已定义scrollRect,因此地图会在缩放时被裁剪。这一切似乎都很好。

当我改变比例时,可见内容随着精灵变大或变小而移动。我想将内容保持在相对相同的屏幕位置。我已经在下面进行了第一次传球,但这不太对。

问题我是否在正确的轨道上认为我可以通过比较缩放后精灵宽度/高度的变化来确定移动x / y的程度? (正如我写的那样,我想我可以在缩放之前确定精灵的中心,然后重新定位它,使它在该点上保持居中。嗯......)。

        protected function scaleStepper_changeHandler(event:Event):void
        {
            var cX:Number = wrapper.x + (wrapper.width /2);
            var cY:Number = wrapper.y + (wrapper.height /2);

            wrapper.scaleX = scaleStepper.value;
            wrapper.scaleY = scaleStepper.value;

            wrapper.x = cX - (wrapper.width /2);
            wrapper.y = cY - (wrapper.height /2);

        }

2 个答案:

答案 0 :(得分:0)

你是在正确的轨道上,但为了更好的解决方案,你应该使用矩阵来转换你的精灵。使用以下代码来实现您的需求:

private var originalMatrix:Matrix;

private function scaleAroundPoint(target:Sprite, scalePoint:Point, scaleFactor:Number):void 
{ 
    if(originalMatrix == null)
        originalMatrix = target.transform.matrix;

    var matrix:Matrix = originalMatrix.clone();             
    matrix.translate(-scalePoint.x, -scalePoint.y); 
    matrix.scale(scaleFactor, scaleFactor); 
    matrix.translate(scalePoint.x, scalePoint.y); 
    target.transform.matrix = matrix; 
}

您可以这样调用此方法:

scaleAroundPoint(wrapper, new Point(yourWidth/2, yourHeight/2), scaleStepper.value);

希望这有助于解决您的问题。

答案 1 :(得分:0)

  

我是否在正确的轨道上认为我可以通过比较缩放后精灵宽度/高度的变化来确定移动x / y的数量?

是。由于所有值都是已知的,因此您无需在缩放后进行“测试”。你基本上想要均匀地分配边界框边界的移动。

以下是一个维度的示例,比例因子2,X是注册点,|是边界:

before scaling          |--X--|
after  scaling        |----X----|

没问题。现在如果注册点不在中间怎么办?

before scaling          |-X---|
after  scaling         |--X------|

作为最后一个例子,在边界上有注册点的边缘情况:

before scaling          |X----|
after  scaling          |X--------|

注意在缩放之前所有3个示例的边界是否相等,并且在每个示例中,注册点保持不变。

问题已明确确定。现在该如何解决这个问题?

我们知道宽度变化了多少

before scaling          width
after  scaling          width * scaleFactor

从第一个例子我们可以确定缩放后左边界应该在哪里(假设注册点是0,所以对象居中):

before scaling         -width * 0.5
after  scaling         -width * 0.5 * scaleFactor

此值取决于当前注册点在显示对象内相对于左边界的位置。要绕过这种依赖关系,请相互减去这些值,以便知道在缩放后左边界向左移动了多少,同时保持对象居中:

boundary shift          width * 0.5 * (scaleFactor - 1)

在缩放之前和之后进行比较,左边界应该在该数量的左侧更远,右边界应该在该数量的右边进一步。

问题是你无法直接设置左边界或右边界。 您必须设置注册点,这将影响边界的位置。要知道你应该移动注册点的距离,想象两个边缘情况:

before scaling          |X----|
after  scaling          |X--------|
corrected,            |X--------|

before scaling          |----X|
after  scaling      |--------X|
corrected,            |--------X|

在这两种情况下,注册点必须移动边界应移动的量,因为基本上,边界上的注册点,因此行为相同。

中间的任何值都可以通过两种情况之间的线性插值找到:

-[width * 0.5 * (scaleFactor - 1)]  <= value <= +[width * 0.5 * (scaleFactor - 1)]
-[width * 0.5 * (scaleFactor - 1)] * (1-t) + [width * 0.5 * (scaleFactor - 1)] * t

要查找插值t,如果X位于左侧而1位于右侧,则为0:

t = (X - L) / width

-[width * 0.5 * (scaleFactor - 1)] * (1-t) + [width * 0.5 * (scaleFactor - 1)] * t添加到注册点的x位置并缩放对象。

以类似的方式对y做同样的事情。