J'ai écrit la méthode suivante (en actionscript 3, il est une application flash) qui retourne ce type de transformation est nécessaire pour la position de la souris par rapport à une position d'élément donné.
Un élément peut être déplacé, mis à l'échelle et pivoté. Cette méthode retourne si l'une de ces transformations est applicable avec les coordonnées données:
(ne vous inquiétez pas, vous n'avez pas besoin de déboguer cette méthode, ça marche - je l'ai juste ajouté ici pour que vous compreniez ce que je fais)
//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;
}
Une élaboration de tous les paramètres requis:
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
Si aucune transformation est applicable, elle renvoie null.
Le problème
Maintenant, ma fonction semble fonctionner à merveille. Le problème se pose maintenant que j'introduis la rotation aux éléments qui doivent être transformés.
Lorsque vous faites pivoter un élément, les coins se déplacent vers une position différente. Le curseur doit maintenant être à différentes positions pour obtenir les mêmes types de transformation en fonction de la situation, tout comme ma méthode ci-dessus (s'il n'y a pas de rotation):
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
La question
Mon la méthode le fait parfaitement, s'il n'y a pas de rotation. Cependant, comment modifier cette fonction pour prendre en compte la rotation, par exemple le changement de coordonnées des coins?
Mise à jour pour Justin
//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)
{
//...
}
Comme vous pouvez le voir, la rotation est réglée et a reçu de l'enfant de l'objet rendu. C'est parce que l'objet réel est un positionWrapper et à l'intérieur de ce wrapper il y a un rotateWrapper (auquel la rotation est définie) et à l'intérieur de ce wrapper, l'élément visible reste. Les valeurs x, y, width et height du wrapper de position sont toujours égales à celles de l'objet d'affichage visible, cela ne devrait donc pas poser de problème.
Maintenant, ce sont les résultats:
- Sans rotation, tout fonctionne comme prévu
- Avec environ 45 rotation, quand je souris sur au objet affichage visuel de:
- centre en bas: il retourne "scalerLeft", alors qu'il devrait retourner "scalerDown"
- right center: il renvoie scalerDown, alors qu'il devrait retourner scalerRight
- centre supérieur: il retourne scalerRight, alors qu'il doit retourner scalerUp
- centre gauche: il retourne scalerUp, alors qu'il devrait revenir scalerLeft (notez le modèle décalé ici)
- le moteur semble revenir assez exactement
- le RO- semble retourner au fond direct d'un coin, pas où il devrait
- le mesureur bottomLeft semble retourner dans le coin inférieur droit, je pense que ce même décalage est le problème et est probablement le même pour tous les autres scalers aussi
Ceci est un bugger à déboguer, mais peut-être que cela aidera.
Mise à jour # 2 pour Justin alt text http://feedpostal.com/transformBug.gif Le décalage/bug semble se renforcer plus la rotation est. Avec 0 rotation, ce bug n'apparaît pas.
Est-ce que cela a du sens pour vous ou quelqu'un d'autre? Merci d'avance.
Ajouté bounty vaut 150 réputation à la question, je sais que ma question est assez complexe! – Tom
J'ai peur de m'être réjouie trop tôt. Il y a un bug notable que j'ai expliqué dans ma question mise à jour. Je sais que j'ai déjà accepté une réponse mais j'apprécierais vraiment que quelqu'un puisse donner un coup d'oeil à ce bug, car je n'ai aucune idée de ce qui pourrait le provoquer. – Tom
Mise à jour: nevermind, c'était un bug dans mon code interne qui l'a causé. Fixé maintenant Merci. – Tom