rotating centered content - apache-flex

Ok, so I've been trying to get this concept to work for the day now and have had zero luck. I am not so good with math, so any help will be appreciated. I am trying to rotate a centered container from it's center. The problem with this code is when I use the rotatePicture method, it doesn't rotate from the center, instead it rotates from the box's top-left corner. Here's the code...
import mx.effects.Rotate;
private function init():void
{
calculateCoordinates();
}
private function rotateBox():void
{
var m:Matrix = myBox.transform.matrix;
var centerX:Number = myBox.width / 2;
var centerY:Number = myBox.height / 2;
var centerPoint:Point = new Point(centerX, centerY);
var transformPoint:Point= m.transformPoint(centerPoint);
m.translate(-transformPoint.x, -transformPoint.y);
m.rotate(90 * Math.PI / 180);
m.translate(transformPoint.x, transformPoint.y);
myBox.transform.matrix = m;
this.callLater(calculateCoordinates);
//calculateCoordinates();
}
private function calculateCoordinates():void
{
var x : Number = (myBox.parent.width - myBox.width) / 2;
x = x < 0 ? 0 : x;
var y : Number = (myBox.parent.height - myBox.height) / 2;
y = y < 0 ? 0 : y;
myBox.move(x, y);
}

Ok, this was a bit tricky and i'm working out a couple of details, but in case anyone had a similar issue, I found the general answer. Just took a movie break to refresh the brain...
I had to place a variable for how many turns the canvas had rotated which was easy since I was restricting the degrees to only 90. Then I place in a switch statement that tested the turns variable and recalculated the (x,y) coordinates based off of the turns. Since I knew that the Rotate class would create a cooler effect and end with the same result, I ended up using that instead.
Cheers!

I don't know what your background is, but in my experience this is a classic case of "out-thinking yourself".
You've written quite a bit of code to do something that is actually native to the Flash display API's.
Since you seem to be using Flex I'll just tell you that the simple way to achieve this is to dynamically reposition your display clip contents so that the center of your contents is at the 0,0 point of your clip.
This gets harder the more content you have, but if you just have something like an image or a button or what have you, it's really easy to just calculate the height and width, then divide by 2 and subtract.
Then the rotation property will work just fine.
In Flash it's even easier because you can just make a new clip, bind your class to the clip, and place all yours contents in the Flash authoring tool positioned properly for rotation to work as expected.
Yeah, what Back2Dos said.

Personally, I'd wrap the container in another sprite, position it so its center is at (0,0) in that sprites coordinate space, and then just rotate the sprite ... it's simple and robust ...

I'd like to use <s:Rotate> to rotate center. Hope useful to you.

Related

How to get current facing direction vector 2D?

So I am developing a game in 2D in Godot and I want to see a line from the center of my sprite to its facing position. I have the sprite rotating and moving along the rotation direction but when I try to create vector out of that its very wrong. For example the vector line is going from the center of the sprite to near (0,0) position on the screen.
public override void _Draw()
{
Vector2 rotationDirection = new Vector2(Mathf.Cos(sprite.GlobalRotation) , Mathf.Sin(sprite.GlobalRotation)) - sprite.GlobalPosition;
DrawLine(sprite.GlobalPosition, rotationDirection, Colors.Red, 2f);
}
EDIT:
Fixed it it works now.
public override void _Draw()
{
DrawLine(sprite.GlobalPosition, sprite.GlobalPosition + new Vector2(Mathf.Cos(sprite.GlobalRotation), Mathf.Sin(sprite.GlobalRotation)) * 50f, Colors.Red, 2f);
}
A simpler solution would have been to add a Line2D child node. You can see the effect right away in the editor, and there's no need for any maths.
This might also be more efficient, because custom _draw functions don't play nice with Godot's geometry batching.

compute mouse position within video with object-fit:contain

I am trying to convert a mouse event to pixel coordinates within a video. By pixel coordinates, I mean coordinates relative to the original video resolution.
My video element has object-fit: contain, which means that the top left corner of the video is not necessarily located at position (0,0), as this picture shows:
If I click on the top-left corner of the white section in this video then I want to get (0,0), but in order to do this I need to discover the offset of the video content (white area) relative to the video element (black border).
How can I recover this offset?
I am already aware of width, height, videoWidth, and videoHeight, but these only let me account for the scaling, not the offset.
The offset can be deduced. I think this kind of code should do the trick:
if(videoHeight/height > videoWidth/width){
scale = videoHeight/height;
offsetX = (videoWidth - width*scale)/2;
offsetY = 0;
}
else{
scale = videoWidth/width;
offsetY = (videoHeight - height*scale)/2;
offsetX = 0;
}
I was also interested in getting the actual pixel positions from mouse or touch events when using object-fit, and this is the only result I found when searching. Although I suspect it is probably too late to be helpful to you, I thought I'd answer in case anybody else comes across this in future like I did.
Because I'm working on code with other people, I needed a robust solution that would work even if someone changed or removed the object-fit or object-property in the css
The approach that I took was:
Implement the cover, contain etc algorithms myself, just functions doing math, not dependent on the DOM
Use getComputedStyle to get the element's objectFit and objectPosition properties
Use .getBoundingClientRect() to get the DOM pixel size of the element
Pass the element's current objectFit, objectPosition, its DOM pixel size and it's natural pixel size to my function to figure out where the fitted rectangle sat within the element
You then have enough information to transform the event point to a pixel location
There's more code than would comfortably fit here, but getting the size of the fitted rectangle for cover or contain is something like:
if ( fitMode === 'cover' || fitMode === 'contain' ) {
const wr = parent.width / child.width
const hr = parent.height / child.height
const ratio = fitMode === 'cover' ? Math.max( wr, hr ) : Math.min( wr, hr )
const width = child.width * ratio
const height = child.height * ratio
const size = { width, height }
return size
}
// handle other object-fit modes here
Hopefully this gives others a rough idea of how to solve this problem themselves, alternately I have published the code at the link below, it supports all object-fit modes and it includes examples showing how to get the actual pixel point that was clicked:
https://github.com/nrkn/object-fit-math

Image Rotate 3D in Flex, but display another image on back of this image?

i want to rotate 3D an Image called img1 in Flex. I want to rotate it around y axis 180 degree. I can do this by using 3D effect already built in Flex but i want to do a bit more different.
I want during rotating, there's another image called img2 appear on back of img1 (in default case, the image appear on the back is img1) and when rotating finish, the image will be img2.
How can i do this ?
Thank you.
If you need no perspective effect, it's quite easy to do. A rough implementation (not tested!):
// Event.ENTER_FRAME event listener
void on_enter_frame(event:Event):void
{
// m_angle is a member of the class/flex component where on_enter_frame is declared
// ANGLE_DELTA is just a constant
m_angle += ANGLE_DELTA;
// Angle clamping to the range [0, PI * 2)
m_angle %= Math.PI * 2;
if (m_angle < 0)
m_angle += Math.PI * 2;
// If we currently look at the front side...
if (m_angle < Math.PI)
{
img1.visible = true;
img2.visible = false;
img1.scaleX = Math.cos(m_angle);
}
else
{
img1.visible = false;
img2.visible = true;
// If you omit negation, the back-side image will be mirrored
img2.scaleX = -Math.cos(m_angle);
}
}
So every frame we increase the rotation angle, clamp it to the range [0, PI * 2). Then depending on the value of the rotation angle, we hide/show the pair of your images, and then perform x-scaling of the visible image.
Thank you, now i found a solution. Please check it here, it's very easy to do.
http://forums.adobe.com/thread/921258

Rotate a drawn rectangle in flex

i wrote the following code for drawing a rotate rectangle
var s:UIComponent = new UIComponent();
s.graphics.lineStyle(1, 0x0000FF);
s.graphics.drawRect(50, 50, 200, 200);
s.rotation = 30;
template.addChild(s);
where template is a canvas. Its rotate nicely but the problem is the position is not in right place. i.e. it is not in (50,50) after rotate. How can i solve this problem?
Thanks in advance.
What you're seeing is the default rotation around the origin in Flex (in your case the X,Y coordinates of 50,50) I am assuming that you want to rotate around the center (as I recently had to do). There is the jury rig way to do it, by adjusting the origin point based on rotation angle. Then there is the rotate effect:
import mx.effects.Rotate;
var s:UIComponent = new UIComponent();
var rotator:Rotate = new Rotate(s);
s.graphics.lineStyle(1, 0x0000FF);
s.graphics.drawRect(50, 50, 200, 200);
rotator.angleFrom = 0;
rotator.angleTo = 30;
rotator.originX = s.width/2;
rotator.originY = s.height/2;
template.addChild(s);
rotator.play();
Now I've noticed some problems with this that required me to set the width and height of the rotated object again after the play() method, but other than that I get the ideal rotation situation.
Another downside to this is that it's an effect, which means it visually rotates the object. I will post back when I correct that, if you don't want to see the object rotate.
The Answer is duration
just by adding rotator.duration = 1 before play it happens so quick the user won't see it. 1 being 1 millisecond. I tried 0, but that resulted in no rotation occurring. Obviously if you want to see the effect in action you can increase that length of time by using any value in milliseconds.

how to do 3D rotation around center in AS3 using matrix3D?

I am trying to rotate a Sprite in three dimensions around its centerpoint, and I am struggling to understand some of the behavior of matrix3D.
Ive overridden the set rotationX, rotationY, and rotationZ methods of the Sprite as follows:
override public function set rotationX (_rotationX:Number) : void {
this.transform.matrix3D.prependTranslation(this.width/2.0, this.height/2.0, 0);
this.transform.matrix3D.prependRotation(-this.rotationX, Vector3D.X_AXIS);
this.transform.matrix3D.prependRotation(_rotationX, Vector3D.X_AXIS);
this.transform.matrix3D.prependTranslation(-(this.width/2.0), -(this.height/2.0), 0);
}
override public function set rotationY (_rotationY:Number) : void {
this.transform.matrix3D.prependTranslation(this.width/2.0, this.height/2.0, 0);
this.transform.matrix3D.prependRotation(-this.rotationY, Vector3D.Y_AXIS);
this.transform.matrix3D.prependRotation(_rotationY, Vector3D.Y_AXIS);
this.transform.matrix3D.prependTranslation(-(this.width/2.0), -(this.height/2.0), 0);
}
override public function set rotationZ (_rotationZ:Number) : void {
this.transform.matrix3D.prependTranslation(this.width/2.0, this.height/2.0, 0);
this.transform.matrix3D.prependRotation(-this.rotationZ, Vector3D.Z_AXIS);
this.transform.matrix3D.prependRotation(_rotationZ, Vector3D.Z_AXIS);
this.transform.matrix3D.prependTranslation(-(this.width/2.0), -(this.height/2.0), 0);
}
I am using prependTranslation to correct the centerpoint of the rotation, and the first prependRotation to cancel out any previously-applied rotation.
Testing it out, rotationX works exactly as expected, and the Sprite rotates around its horizontal axis.
rotationY and rotationZ also appear to work fine. However, there is one problem: whenever rotationY or rotationZ are set, all of the other rotation values change as well. This is not a problem with rotationX -- if I set rotationX, nothing else changes. But if I set rotationY or rotationZ all the rotation values change, which is a problem for my app (which is trying to save and restore values).
I think I am just lacking some understanding about what is going on with matrix3D. How can I implement this so there is no interdependence between the values?
Another easy solution is to add the object and center it within a container sprite and do the 3D transformations on the containing sprite.
I know nothing about AS3 etc. But just looking at your code, I wonder why you translate on the z-axis using what I understand to be x and y values (width and height). Shouldn't the z-axis be translated using something like "depth"?
This is very simple, you can try use the following code:
var matrix3d:Matrix3D = s.transform.matrix3D;
matrix3d.appendRotation( -1, Vector3D.Z_AXIS , new Vector3D( 390, 360, 0 ) );
while s is your sprite, the third parameter, Vector3D indicate your sprite's center position.
The Above code will make the sprite s rotate more -1 degree.

Resources