When I use QGraphicsItemAnimation::setRotationAt() function to rotate a QGraphicsItem for an animation, the original point is always left top point of the item.
So I tried QGraphicsItem::setTransformOriginPoint() to make the rotation point to be at right top. But it still doesn't work. Is there any way to rotate the item itself at the right top?
for (int i = 0; i < 1000; ++i){
mAnimation->setTranslationAt(i / 1000.0, size.w, 0);
mAnimation->setRotationAt(i / 1000.0, qreal(i / 1000.0 * angle));
mAnimation->setTranslationAt(i / 1000.0, -size.w, 0);
}
Here is the answer i found, when set frames of the item, need to translate the original point before rotation, and translate it back.
Related
In my Flutter app, I have drawn a rectangle in one coordinate system on a Google Map and I want to rotate this coordinate system around the coordinate (0,0). How this can be done is described here: Rotation matrix. I have implemented the rotation of coordinates like this in my app:
class Coordinate {
Coordinate(this.x, this.y);
double x;
double y;
void rotate(double angle) {
// angle is in degrees, convert to radians
final double angleInRadians = angle * (math.pi / 180);
final double oldX = x;
final double oldY = y;
final double newX = oldX * math.cos(angleInRadians) - oldY * math.sin(angleInRadians);
final double newY = oldX * math.sin(angleInRadians) + oldY * math.cos(angleInRadians);
x = newX;
y = newY;
}
}
Using this to rotate four corners of a rectangle works fine for some places in the world, like Australia and a place near (0,0). In this picture, you can see the rotation of the red rectangle on the top around the point (0,0) (bottom left) to the rotated red rectangle on the bottom right:
Please ignore all the markers and non-red lines. The next to images show a rectangle like the one in the picture above which I again rotate around (0,0) using the code above, but as you can see in the second image, the red rectangle is not a rectangle anymore, but a parallelogram instead.
I cannot find an explanation for this. The questions I ask myself are: Why does the code work for some places but not for others? Why does the rectangle transform to a perfect parallelogram instead of whatever other shape with the points possibly all around the world? As it is working for some locations, the problem cannot be that I have mixed up some of the coordinates or something like that, it has to do something with the calculation of the edges of the rotated rectangle. But I cannot find out what I did wrong here.
REMINDER: IGNORE ALL MARKERS AND NON-RED LINES
What I'm doing
I'm using anime.js to animate some circles along paths in an svg. I create paths using Vue as I'd like the circle on the top to end up on the bottom, so it can't just be a static SVG.
What I expect
I expect the circles to start at one end of the svg path, and finish at the other end.
What's actually happening
I have a demo here:
https://codepen.io/EightArmsHQ/pen/paVxpd
When I click animate, the circles are jumping to a different position, then animating almost correctly, before finishing in the wrong place.
This is the code I am using for anime.js:
for(var c = 0; c < this.coins.length; c++){
var path = anime.path('#path-'+ c);
anime({
targets: document.getElementById(this.coins[c].ref),
translateX: path('x'),
translateY: path('y'),
rotate: path('angle'),
duration: 1000,
delay : this.coins.length * 100 - (100 * c),
easing: 'easeInOutQuad',
rotation: 0,
});
}
I know its almost definitely to do with transform-origin and the rotation transform that is applied to the circles, but I can't get my head around it.
I found after some experimenting the issue was that I was altering the transformX and transformY properties, which, while it sort of worked and would work better for DOM elements, I should have been using cx and cy attributes. I also removed the rotation as well.
for(var c = 0; c < this.coins.length; c++){
var path = anime.path('#path-'+ c);
anime({
targets: document.getElementById(this.coins[c].ref),
cx: path('x'),
cy: path('y'),
duration: 1000,
delay : this.coins.length * 100 - (100 * c),
easing: 'easeInOutQuad',
rotation: 0,
});
}
Here is a demo:
https://codepen.io/EightArmsHQ/pen/aqKXrQ?editors=1010
I want to rotate a pixmap from its xAxis, but it just rotates from top left corner.(I want it to be rotated from the center) here is my code:
QTransform *X = new QTransform();
X->translate(pixmap().size().width() / 2, pixmap().size().height() / 2);
X->rotate(rtn, Qt::XAxis); //rtn is an angle
setTransform(*X);
It seems that the translate method does not change the origin point to the center of my pixmap.
Now I want some help to solve this problem.
ok, the problem was that I didn't translate back my transformation after rotate method, this is the appropriate rotation from center on xAxis:
setTransform(QTransform().translate(pixmap().size().width() / 2, pixmap().size().height() / 2).rotate(rtn, Qt::XAxis).translate(-pixmap().size().width() / 2, -pixmap().size().height() / 2));
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
My application is using Qt.
I have a class which is inheriting QGraphicsPixmapItem.
When applying transformations on these items (for instance, rotations), the origin of the item (or the pivot point) is always the top left corner.
I'd like to change this origin, so that, for instance, when setting the position of the item, this would put actually change the center of the pixmap.
Or, if I'm applying a rotation, the rotation's origin would be the center of the pixmap.
I haven't found a way to do it straight out of the box with Qt, so I thougth of reimplementing itemChange() like this :
QVariant JGraphicsPixmapItem::itemChange(GraphicsItemChange Change, const QVariant& rValue)
{
switch (Change)
{
case QGraphicsItem::ItemPositionHasChanged:
// Emulate a pivot point in the center of the image
this->translate(this->boundingRect().width() / 2,
this->boundingRect().height() / 2);
break;
case QGraphicsItem::ItemTransformHasChanged:
break;
}
return QGraphicsItem::itemChange(Change, rValue);
}
I thought this would work, as Qt's doc mentions that the position of an item and its transform matrix are two different concepts.
But it is not working.
Any idea ?
You're overthinking it. QGraphicsPixmapItem already has this functionality built in. See the setOffset method.
So to set the item origin at its centre, just do setOffset( -0.5 * QPointF( width(), height() ) ); every time you set the pixmap.
The Qt-documentation about rotating:
void QGraphicsItem::rotate ( qreal angle )
Rotates the current item
transformation angle degrees clockwise
around its origin. To translate around
an arbitrary point (x, y), you need to
combine translation and rotation with
setTransform().
Example:
// Rotate an item 45 degrees around (0, 0).
item->rotate(45);
// Rotate an item 45 degrees around (x, y).
item->setTransform(QTransform().translate(x, y).rotate(45).translate(-x, -y));
You need to create a rotate function, that translate the object to the parent's (0, 0) corner do the rotation and move the object to the original location.