1

如何扩展下面的简单函数以确定预期的运动方向并将运动锁定到该轴?

换句话说,用户打算向下平移,但由于他们是人类,所以他们向下平移但也略微向右平移,比例为 6:1 我如何推断预期方向并锁定它?

这是我简洁的小锅功能:

function onPan(e:TransformGestureEvent):void
{
    e.target.x += e.offsetX;
    e.target.y += e.offsetY;
}
4

3 回答 3

2

虽然上面 Shaun Husain 的建议很接近,但据我所知,AS3 中的手势不提供起点和终点。为了解决这个问题,我从 GESTURE_PAN 事件中抽取了 5 个触发点的样本,并使用 Levenshtein 距离计算的变体来确定预期方向。以下是此问题的有效解决方案:

var onPanPointer:Number;
var onPanLevString:String;
var onPanLevSampleSize:Number;

onPanLevSampleSize = 5;

function onPan(e:TransformGestureEvent):void
{

    if (Math.abs(e.offsetX) > Math.abs(e.offsetY))
    {
        // Looks like we intended to move on the X axis
        if (e.offsetX > 0)
        {
            if (onPanLevString == null)
            {
                onPanLevString = "r"
            }
            else
            {
                onPanLevString = onPanLevString + "r"
            }
        }
        else
        {
            if (onPanLevString == null)
            {
                onPanLevString = "l"
            }
            else
            {
                onPanLevString = onPanLevString + "l"
            }
        }
    }
    else
    {
        // Looks like we intended to move on the Y axis
        if (e.offsetY > 0)
        {
            if (onPanLevString == null)
            {
                onPanLevString = "d"
            }
            else
            {
                onPanLevString = onPanLevString + "d"
            }
        }
        else
        {
            if (onPanLevString == null)
            {
                onPanLevString = "u"
            }
            else
            {
                onPanLevString = onPanLevString + "u"
            }
        }
    }

    if (onPanPointer < onPanLevSampleSize)
    {
        onPanPointer += 1;
    }
    else
    {
        //trace("Pointer Value has reached the desired count of: " + onPanPointer);
        //trace("The Levenshtein String is: " + onPanLevString);

        if (levenshteinDistance(onPanLevString,repeatString("u",onPanLevSampleSize)) <= ((onPanLevSampleSize/2)+1))
        {
            e.target.y += e.offsetY*onPanLevSampleSize;
            //trace("Panning Up");
        }
        else if (levenshteinDistance(onPanLevString,repeatString("d",onPanLevSampleSize)) <= ((onPanLevSampleSize/2)+1))
        {
            e.target.y += e.offsetY*onPanLevSampleSize;
            //trace("Panning Down");
        }
        else if (levenshteinDistance(onPanLevString,repeatString("l",onPanLevSampleSize)) <= ((onPanLevSampleSize/2)+1))
        {
            e.target.x += e.offsetX*onPanLevSampleSize;
            //trace("Panning Left");
        }
        else
        {
            e.target.x += e.offsetX*onPanLevSampleSize;
            //trace("Panning Right");
        }


        onPanPointer = 1;
        onPanLevString = null;
    }

    //trace("X Offset = " + e.offsetX);
    //trace("Y Offset = " + e.offsetY);
}

正在使用的 levenshteinDistance 函数(如下)由 mircea16 在 Snipplr 上编写,可以在此处找到

function levenshteinDistance(s1:String,s2:String):int
{
    var m:int=s1.length;
    var n:int=s2.length;
    var matrix:Array=new Array();
    var line:Array;
    var i:int;
    var j:int;
    for (i=0;i<=m;i++)
    {
        line=new Array();
        for (j=0;j<=n;j++)
        {
            if (i!=0)line.push(0)
            else line.push(j);
        }
        line[0]=i
        matrix.push(line);
    }
    var cost:int;
    for (i=1;i<=m;i++)
    for (j=1;j<=n;j++)
    {
        if (s1.charAt(i-1)==s2.charAt(j-1)) cost=0
        else cost=1;
        matrix[i][j]=Math.min(matrix[i-1][j]+1,matrix[i][j-1]+1,matrix[i-1][j-1]+cost);
    }
    return matrix[m][n];
}

使上述示例工作所需的最后一个函数是我使用的 repeatString 函数。(这是使您能够使用 onPanLevSampleSize var 更改样本大小而无需更改任何其他内容所必需的)

function repeatString(string:String, numTimes:uint):String
{
    var output:String = "";
    for(var i:uint = 0; i < numTimes; i++)
        output += string;
    return output;
}

您需要更改以调整使用的样本大小的唯一数字是 onPanLevSampleSize,所有计算都使用该数字作为基础执行。

希望这对将来的人有所帮助!

于 2012-06-09T17:25:17.553 回答
1

还没有尝试过,但我认为他会更喜欢这样的事情:

        private var startX:Number;
        private var startY:Number;
        private function onPan(e:TransformGestureEvent):void
        {
            var currentX:Number = e.localX;
            var currentY:Number = e.localY;
            if(Math.pow(currentX-startX,2) > Math.pow(currentY - startY,2))
            {
                e.target.x = currentX;
            }
            else
            {
                e.target.y = currentY;
            }
        }

我只是省略了你想要设置 startX 和 startY 的部分。我还没有使用 TransformGestureEvent,但我认为它有一个初始的向下事件,你可以标记 startX/startY。基本上我只是说看看 X 的变化是否大于 Y 的变化,如果调整 X,否则调整 Y。所以这就像粘性平移。

于 2012-06-08T03:56:42.840 回答
0

奇怪的问题,但我想我明白你在找什么。

function onPan(e:TransformGestureEvent):void
{
    e.target.x += e.offsetX + (e.offsetY/6); // use ratio from offsetY
    e.target.y += e.offsetY;
}
于 2012-06-08T03:45:04.600 回答