状況
特定の要素位置に対する現在のマウス位置に必要な変換タイプを返す次のメソッド (actionscript 3 では、これはフラッシュ アプリケーションです) を作成しました。
要素は、移動、スケーリング、および回転できます。このメソッドは、これらの変換のいずれかが指定された座標に適用できるかどうかを返します。
(心配しないでください。このメソッドをデバッグする必要はありません。機能します。ここに追加して、私が何をしているのかを理解してください)
//returns whether the mouse is at a transforming position
private static function mouseAtTransformPosition(cX:Number, cY:Number, eX:Number, eY:Number, eW:Number, eH:Number, margin:Number):String
{
//initialize the transformation type
var transformType:String = null;
//set the transformation type depending on the given coordinates
if ((cX > eX) && (cX < eX + eW) && (cY > eY) && (cY < eY + eH))
{
transformType = "mover";
}
else if ((cX > eX) && (cX < eX + eW) && (cY <= eY) && (cY >= eY - margin))
{
transformType = "scalerUp";
}
else if ((cX >= eX + eW) && (cX <= eX + eW + margin) && (cY > eY) && (cY < eY + eH))
{
transformType = "scalerRight";
}
else if ((cX > eX) && (cX < eX + eW) && (cY >= eY + eH) && (cY <= eY + eH + margin))
{
transformType = "scalerDown";
}
else if ((cX <= eX) && (cX >= eX - margin) && (cY > eY) && (cY < eY + eH))
{
transformType = "scalerLeft";
}
else if ((cX >= eX - margin) && (cX <= eX) && (cY >= eY - margin) && (cY <= eY))
{
transformType = "scalerUpLeft";
}
else if ((cX >= eX + eW) && (eX <= eX + eW + margin) && (cY >= eY - margin) && (cY <= eY))
{
transformType = "scalerUpRight";
}
else if ((cX >= eX + eW) && (cX <= eX + eW + margin) && (cY >= eY + eH) && (cY <= eY + eH + margin))
{
transformType = "scalerDownRight";
}
else if ((cX >= eX - margin) && (cX <= eX) && (cY >= eY + eH) && (cY <= eY + eH + margin))
{
transformType = "scalerDownLeft";
}
else if ((cX >= eX - margin * 2) && (cX <= eX) && (cY >= eY - margin * 2) && (cY <= eY))
{
transformType = "rotatorTopLeft";
}
else if ((cX >= eX + eW) && (cX <= eX + eW + margin * 2) && (cY >= eY - margin * 2) && (cY <= eY))
{
transformType = "rotatorTopRight";
}
else if ((cX >= eX + eW) && (cX <= eX + eW + margin * 2) && (cY >= eY + eH) && (cY <= eY + eH + margin * 2))
{
transformType = "rotatorBottomRight";
}
else if ((cX >= eX - margin * 2) && (cX <= eX) && (cY >= eY + eH) && (cY <= eY + eH + margin * 2))
{
transformType = "rotatorBottomLeft";
}
//return the found transformation type
return transformType;
}
必要なすべてのパラメーターの詳細:
cX: cursor X position
cY: cursor Y position
eX: element X position
eY: element Y position
eW: element width
eH: element height
margin: how far the cursor can be removed from an exact transformation location to still be applicable
適用可能な変換がない場合は、null が返されます。
問題
今、私の機能はうまく機能しているようです。変換が必要な要素に回転を導入しているため、問題が発生します。
要素を回転すると、角が別の位置に移動します。上記の方法と同じように(回転がない場合)、状況に応じて同じ変換タイプを取得するには、カーソルを異なる位置に配置する必要があります。
cursor is...
inside the element -> move
at top of element -> scale up
at right of element -> scale right
at bottom of element -> scale down
at left of element -> scale left
at top left of element -> scale up-left
at top right of element -> scale up-right
at bottom left of element -> scale down-left
at bottom right of element -> scale down-right
further top left of element -> rotate right/left
further top right of element -> rotate right/left
further bottom right of element -> rotate right/left
further bottom left of element -> rotate right/left
質問
回転がない場合、私の方法はこれを完全に行います。ただし、角の座標の変更など、回転を考慮してこの関数を変更するにはどうすればよいですか?
ジャスティンのアップデート
//checks whether mouse transforming is applicable
private static function checkMouseTransforming(cX:Number, cY:Number, render:Sprite):void
{
//temp disable rotation to get accurate width/height, x and y
var realRotation:Number = render.getChildAt(0).rotation;
render.getChildAt(0).rotation = 0;
var eX:Number = render.x;
var eY:Number = render.y;
var eW:Number = render.width;
var eH:Number = render.height;
var margin:uint = 10;
//restore real rotation
render.getChildAt(0).rotation = realRotation;
cX -= eX + eW / 2;
cY -= eY + eH / 2;
var theta:Number = render.getChildAt(0).rotation * Math.PI / 180;
var newcX:Number = Math.cos(theta) * cX - Math.sin(theta) * cY;
var newcY:Number = Math.sin(theta) * cX + Math.cos(theta) * cY;
newcX += eX + eW / 2;
newcY += eY + eH / 2;
var transformType:String = mouseAtTransformPosition(newcX, newcY, eX, eY, eW, eH, margin);
if (transformType)
{
//...
}
ご覧のとおり、回転はレンダリングされたオブジェクトの子から設定および受信されます。これは、実際のオブジェクトが positionWrapper であり、このラッパー内に (回転が設定されている) rotationWrapper があり、そのラッパー内に実際の可視要素が残っているためです。位置ラッパーの x、y、幅、および高さは、表示される表示オブジェクトのものと常に同じであるため、これによって問題が発生することはありません。
さて、これらは結果です:
- ローテーションがなければ、すべてが期待どおりに機能します
- 約 45 回転で、ビジュアル表示オブジェクトにマウスを合わせると、次のようになります。
- 下中央: 「scalerLeft」を返しますが、「scalerDown」を返す必要があります。
- 右中央: scalerDown を返しますが、scalerRight を返す必要があります
- 上部中央: scalerRight を返しますが、scalerUp を返す必要があります
- 左中央: scalerUp を返しますが、scalerLeft を返す必要があります (ここでオフセット パターンに注意してください)。
- ムーバーはかなり正確に戻ってくるようです
- 回転子は、本来あるべき場所ではなく、コーナーの真下に戻っているようです
- bottomLeft スケーラーは右下隅に戻っているようです。これと同じオフセットが問題であり、おそらく他のすべてのスケーラーでも同じであると思います
これはデバッグするのが面倒ですが、これが役立つかもしれません。
Justin の代替テキストの更新 #2 http://feedpostal.com/transformBug.gif オフセット/バグは、ローテーションが高くなるほど強くなるようです。0 回転では、このバグは発生しません。
これはあなたや他の誰かにとって意味がありますか? 前もって感謝します。