Flash AS3 - Как центрировать объект вокруг точки после масштаба - PullRequest
0 голосов
/ 27 октября 2011

Я создал mc, который работает как моя карта и контролирует его, позволяя перемещать карту и перемещаться по ключевым точкам и увеличивать их при различных уровнях масштабирования.

I 'm используя scaleX и scaleY для масштабирования карты mc и список позиций x и y для правильного позиционирования карты для каждой ключевой точки.

Когда я хочу перейти в определенную область, я выполняю этот расчет (offsetX иoffsetY - центр экрана):

newX = posX * scale + offsetX;
newY = posY * scale + offsetY;

Затем я изменяю положение и масштаб карты, чтобы плавно масштабировать и переместить карту в правильное положение:

var tween = new TweenLite(_background, EASING_SPEED, {x:newX, y:newY,scaleX:scale.getScale(),scaleY:scale,ease:EASING_TYPE,onComplete:moveToComplete,onCompleteParams:[room]});

IТеперь нужно реализовать функцию увеличения / уменьшения масштаба, и это то, с чем я борюсь.Масштаб должен использовать центр экрана в качестве точки обзора для шкалы, поэтому я пытался что-то вроде следующего, чтобы получить правильное позиционирование:

var newX = offsetX - (offsetX - _background.x) * scale;
var newY = offsetY - (offsetY - _background.y) * scale;

Так что, на мой взгляд, этополучает расстояние от текущей позиции карты относительно центральной точки экрана (offsetX, offsetY), а затем масштабирует это расстояние до нового масштаба.

Однако, это явно неправильно, потому что это не работает, а расположение карты неверно.

Я также пытался использовать матрицу преобразования, чтобы получить правильные значения, но я знаю даже меньшео них и не получил правильных результатов.

function scale(target:MovieClip, center:Point, scale:Number):Point {
    var m:Matrix = new Matrix();
    m.translate(-center.x, -center.y);//move the center into (0,0)
    m.scale(scale, scale);//scale relatively to (0,0) (which is where our center is now)
    m.translate(center.x, center.y);//move the center back to its original position
    return m.transformPoint(new Point());//transform (0,0) using the whole transformation matrix to calculate the destination of the upper left corner
}

Если бы кто-то мог пролить свет на то, где я иду не так, я был бы очень благодарен!

Ответы [ 4 ]

4 голосов
/ 19 января 2012
function scaleAroundPoint (object:DisplayObject, offsetX:Number, offsetY:Number, absScaleX:Number, absScaleY:Number ):void {
    var relScaleX:Number = absScaleX / object.scaleX;
    var relScaleY:Number = absScaleY / object.scaleY;
    var AC:Point = new Point( offsetX, offsetY );
    AC = object.localToGlobal( AC );
    AC = object.parent.globalToLocal( AC );
    var AB:Point = new Point( object.x, object.y );
    var CB:Point = AB.subtract( AC );
    CB.x *= relScaleX;
    CB.y *= relScaleY;
    AB = AC.add( CB );
    object.scaleX *= relScaleX;
    object.scaleY *= relScaleY;
    object.x = AB.x;
    object.y = AB.y;
}

С http://timwhitlock.info/blog/2008/04/13/scale-rotate-around-an-arbitrary-centre/

Пример использования вышеуказанной функции:

var currentScale:Number = 1;
mc.addEventListener(MouseEvent.CLICK, onClick);

function onClick (e:MouseEvent):void {
    var point:Point = new Point(e.localX, e.localY);
    currentScale += .1;
    scaleAroundPoint(mc, point.x, point.y, currentScale, currentScale);
}
2 голосов
/ 28 октября 2011

У меня была похожая проблема, когда я хотел, чтобы изображение вращалось по центру изображения, когда я менял поворот изображения, но вместо этого изображение поворачивалось вокруг точки 0,0.

В обоих случаях (у вас и у меня) есть два способа обойти это.
Первым подходом было бы установить его с помощью математики при изменении масштаба.

var newX = stage.width/2 - _background.width/2
var newY = stage.height/2- _background.height/2

Другой способ, который после загрузки не потребует дополнительного кода.
Добавьте еще один мувиклип внутри _background в этот мувиклип, и изображение перейдет. Это изображение будет расположено с центральной точкой в ​​точке 0,0 вместо того, чтобы верхняя точка изображения была 0,0. Так что в основном

image.x = -(image.width/2)
image.y = -(image.height/2)

Это будет работать для масштабирования и поворота изображения с центром в центре изображения.

[EDIT]
Итак, вам нужно начать новый проект и создать что-то вроде этой диаграммы.
enter image description here

Поместите изображение в видеоклип контейнера.
Изображение и контейнер будут иметь одинаковую высоту и ширину
Переместите изображение так, чтобы его центр находился в 0,0 точке мувиклипа
Поставьте контейнер на сцену. 2 кнопки на событии щелчка добавляют .1 другую, чтобы вычесть .1 к шкале на контейнере.
Теперь запустите тест
Как вы можете видеть масштабирование по центру изображения
Теперь для теста 2 откройте контейнер и перетащите изображение влево Запустите тест снова.
Вы видите, что изображение теперь масштабируется вправо от центра (напротив того места, куда вы перетаскивали).

Таким образом, чтобы подвести итог, смещение является обратным движением от центра изображения. (+ 2 балла, если вы это понимаете)

image.x = -(image.width/2) - offsetX
image.y = -(image.height/2) - offsetY


ПРИМЕЧАНИЕ: масштабирование будет применяться к контейнеру, а не к изображению напрямую, где в качестве движения изображения все еще будут image.x и image.y

1 голос
/ 27 октября 2011

Когда вы масштабируете объект, точка фокуса должна сохранять те же координаты.Поскольку вы масштабируете объект, вам, вероятно, следует использовать координаты этой точки относительно размера карты.

Так как эта точка остается в той же позиции на стадии, тогда должна быть возможность рассчитать координаты карты относительно этого фиксированного значения.

//Pseudo Code
   // the point you want to zoom in
   // Record Mouse Click Coordinates , store in variable
   var origin:Point = new Point ( mouseX , mouseY );

   //calculate these coordinates as percentage of 
   //the map's width & height
    //store in variable 
    var percent:Object = { x% , y%}

   //during scaling, calculate the point's 
    //position using the "percent" values and
   //tween back to original ( var origin ) position 

хорошо, я не пробовал, но этомой первый подход:)

Надеюсь, это поможет!

Допустим, ваша карта в соотношении 1: 1 составляет 800x400.Центр будет тогда в (400, 200).Если вы масштабируете карту, скажем, 1600x800, центральная точка будет перемещена в (800, 400).Затем вам нужно будет прокрутить карту, чтобы вернуть эту точку к (400, 200), это создаст впечатление, что центральная точка осталась на месте.

Пример, который я вам дал, был основан наПредставьте, что переменная «zoom in» указывает на переменную, где бы ни щелкала мышь, например.Если это не так, вам следует просто переместить точку регистрации в центр:)

0 голосов
/ 29 декабря 2014

Люди, я думаю, что это просто математическая задача.Вы можете изменить положение x, y, одновременно делая масштаб в анимации:

public function FadeInWithGrowth(_obj:*, _timeSec:Number=DEFAULT_TIMESEC_FADE_IN, _ease:Ease=null):void{
        var _endAlpha:int = _obj.alpha;
        var _startScaleX:int = _obj.scaleX/2;
        var _startScaleY:int = _obj.scaleY/2;
        var _endScaleX:int = _obj.scaleX;
        var _endScaleY:int = _obj.scaleY;
        var _startX:int = _obj.width/2 -(_startScaleX*_obj.width/2);
        var _startY:int = _obj.height/2 -(_startScaleY*_obj.height/2);
        var _endX:int = _obj.x;
        var _endY:int = _obj.y;
        _ease = _ease ? _ease : Back.easeOut;
        //Para que o scale ocorra centralizado e não a partir do topo
        TweenMax.fromTo(_obj, DEFAULT_TIMESEC_FADE_IN,
            {alpha:0, scaleX:_startScaleX, scaleY:_startScaleY, x:_startX, y:_startY},
            {alpha:_endAlpha, scaleX:_endScaleX, scaleY:_endScaleY, x:_endX, y:_endY, ease:_ease}
        );
    }
...