AS3 удерживает объект при масштабировании / панорамировании с помощью GestureEvent / MouseEvent

То, что я хочу сделать, это не допустить, чтобы мой MovieClip (который больше, чем область просмотра) не имел видимых границ. Как и многие другие приложения, например, Clash of Clans.

Таким образом, если вы увеличиваете и уменьшаете масштаб или панорамируете, вы никогда не увидите сцену под ним.

Если бы я только панорамировал, а не увеличивал масштаб, это было бы легко, потому что мне просто нужно было рассчитать, находится ли мой прямоугольник MC в пределах моей сцены, и если да, я бы просто

mc.x = 0 + mc.width / 2;
//or
mc.x = stage.StageWidth - (mc.width/2);
//or .... The same for y

Теперь большая проблема, когда я тоже увеличиваю! И каждый раз, когда я придумываю какой-то код, он не работает хорошо. Есть много примеров для увеличения с помощью GestureEvent в Интернете, но никто из них не держит MC ограниченным, поэтому вы не видите сцену под ним.

Может кто-нибудь, пожалуйста, приведите пример для меня. Допустим, сцена - 480x720, а mc - 1080x720!

Вы должны панорамировать и масштабировать, всегда покрывая сцену, и масштаб mc останется в пределах 1-1,5.


Вот мой текущий код:

Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener(TransformGestureEvent.GESTURE_PAN, onPan);
stage.addEventListener(MouseEvent.CLICK, gotoBox);

var isInBox: Boolean = false;
table.x = 203.1;
table.y = 360;
table.scaleX = 1;
table.scaleY = 1;

var mouseTimer: Timer;

function onPan(event: TransformGestureEvent): void
{
    if (!isInBox)
    {
        if (event.phase == GesturePhase.BEGIN)
        {
        stage.removeEventListener(MouseEvent.CLICK, gotoBox);
        trace("noClick");
        }

        table.x += event.offsetX;
        table.y += event.offsetY;
        if (table.x > (table.width / 2))
        {
        table.x = table.width / 2;
        }
        if (table.x < stage.stageWidth - (table.width / 2))
        {
            table.x = stage.stageWidth - (table.width / 2)
        }
        if (table.y > (table.height / 2))
        {
            table.y = table.height / 2;
        }
        if (table.y < stage.stageHeight - (table.height / 2))
        {
            table.y = stage.stageHeight - (table.height / 2)
        }

        if (event.phase == GesturePhase.END)
        {
            if (mouseTimer !== null)
            {
                if (mouseTimer.running)
                {
                    mouseTimer.stop();
                    mouseTimer.removeEventListener(TimerEvent.TIMER, enableClick);
                }
            }
            mouseTimer = new Timer(250);
            mouseTimer.addEventListener(TimerEvent.TIMER, enableClick);
            mouseTimer.start();
            trace("start");
        }
    }
}
function enableClick(e: TimerEvent)
{
    mouseTimer.stop();
    trace("stop");
    mouseTimer.removeEventListener(TimerEvent.TIMER, enableClick);
    stage.addEventListener(MouseEvent.CLICK, gotoBox);
    trace("nowClick");
}
function gotoBox(e: MouseEvent)
{
// here it goes to another frame
}

Я не могу добавить функцию масштабирования, потому что это полная катастрофа; Я использовал что-то похожее на функцию onZoom в этой ссылке FlashAndMath

Потому что мне нужно было увеличивать и уменьшать точку, и это главная проблема, так как мне нужно двигать mc вокруг, чтобы сделать эту точку в центре, пока я должен переместить его, чтобы сделать мой целый MC на определенной границе, чтобы покрыть сцену! Эти движения тоже действуют друг против друга. Если эта последняя часть не ясна, попросите меня объяснить больше, пожалуйста:)

Получив правильный ответ от LDMS, я обновил этот вопрос, чтобы избежать дискуссий в чате:)

1 ответ

Решение

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

Так что если вы сделали функцию под названием forceBoundsпросто вызовите его в любое время, когда вы масштабируете или меняете х / у:

        function forceBounds():void {
            //figure out the bounds to constrain to
            //the x, should be the farthest left it can go without the edge being seen on the right. To get this value just subtract the smaller width (stage) from the larger width (mc) - this should be a negative number
            var bounds:Rectangle = (stage.stageWidth - mc.width, stage.stageHeight - mc.height, mc.width - stage.stageWidth, mc.height - stage.stageHeight);

            if (mc.x > bounds.x + bounds.width) {
                mc.x = bounds.x + bounds.width;
            }
            else if (mc.x < bounds.x) {
                mc.x= bounds.x;
            }

            if (mc.y > bounds.y + bounds.height) {
                mc.y = bounds.y + bounds.height;
            }
            else if (mc.y < bounds.y) {
                mc.y = bounds.y;
            }
        }

Вот полный пример, который я сделал во FlashPro: (с объектом на сцене с именем экземпляра mc это больше, чем границы сцены.

Код увеличения взят из FlashAndMath.com

import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
import flash.events.TransformGestureEvent;
import fl.motion.MatrixTransformer;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.events.GesturePhase;

Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener(TransformGestureEvent.GESTURE_PAN, onPan);
stage.addEventListener(TransformGestureEvent.GESTURE_ZOOM, onZoom);

forceBounds();

function onPan(e:TransformGestureEvent):void {
    trace("PAN");
    if(e.phase == GesturePhase.BEGIN){
        stage.removeEventListener(TransformGestureEvent.GESTURE_ZOOM, onZoom);
    }

    //localToGlobal is a helper method that converts a point to global coordinates
    var p:Point = DisplayObject(e.target).localToGlobal(new Point(e.offsetX, e.offsetY));
    //conversely, global to local does the opposite
    p = mc.globalToLocal(p);

    mc.x = p.x;
    mc.y = p.y;

    forceBounds();

    if(e.phase == GesturePhase.END){
        stage.addEventListener(TransformGestureEvent.GESTURE_ZOOM, onZoom);
    }
}

function onZoom(event:TransformGestureEvent):void {
    trace("ZOOM");
    var container:MovieClip = mc;
    var locX:Number=event.localX;
    var locY:Number=event.localY;
    var stX:Number=event.stageX;
    var stY:Number=event.stageY;
    var prevScale:Number=container.scaleX;
    var mat:Matrix;
    var externalPoint=new Point(stX,stY);
    var internalPoint=new Point(locX,locY);

    container.scaleX *= (event.scaleX + event.scaleY) * .5;

    if(event.scaleX > 1 && container.scaleX > 6){
        container.scaleX=prevScale;
    }
    if(event.scaleY > 1 && container.scaleY > 6){
        container.scaleX=prevScale;
    }
    if(event.scaleX < 1 && container.scaleX < 0.8){
        container.scaleX=prevScale;
    }
    if(event.scaleY < 1 && container.scaleY < 0.8){
        container.scaleX=prevScale;
    }

    if(container.scaleX < 1) container.scaleX = 1;
    if(container.scaleX > 1.5) container.scaleX = 1.5;
    container.scaleY = container.scaleX;

    mat=container.transform.matrix.clone();
    MatrixTransformer.matchInternalPointWithExternal(mat,internalPoint,externalPoint);
    container.transform.matrix=mat;

    forceBounds();
}

function forceBounds():void {
    //figure out the bounds to constrain to
    //the x, should be the farthest left it can go without the edge being seen on the right. To get this value just subtract the smaller width (stage) from the larger width (mc) - this should be a negative number
    var bounds:Rectangle = new Rectangle(stage.stageWidth - mc.width, stage.stageHeight - mc.height, mc.width - stage.stageWidth, mc.height - stage.stageHeight);

    if (mc.x > bounds.x + bounds.width) {
        mc.x = bounds.x + bounds.width;
    }
    else if (mc.x < bounds.x) {
        mc.x= bounds.x;
    }

    if (mc.y > bounds.y + bounds.height) {
        mc.y = bounds.y + bounds.height;
    }
    else if (mc.y < bounds.y) {
        mc.y = bounds.y;
    }
}
Другие вопросы по тегам