【问题标题】:maintaining relative position when changing scaleX and scaleY?更改 scaleX 和 scaleY 时保持相对位置?
【发布时间】:2015-11-12 08:31:49
【问题描述】:

我正在尝试在地图演示类型应用程序中实现一个简单的“缩放”功能。用户与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);

        }

【问题讨论】:

    标签: actionscript-3 apache-flex actionscript flex4


    【解决方案1】:

    我是否在正确的轨道上认为我可以通过比较缩放后精灵的宽度/高度的变化来确定 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在左边为0,在右边为1:

    t = (X - L) / width
    

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

    以类似的方式对 y 执行相同的操作。

    【讨论】:

      【解决方案2】:

      您在正确的轨道上,但为了获得更好的解决方案,您应该使用矩阵来转换您的 Sprite。使用下面的代码来实现你所需要的:

      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);
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-09
        • 2020-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多