How to animate a widget like discord 'zoom animation'
-
wrote on 16 Jan 2023, 01:51 last edited by
How to create this kind of animation in qt?
I mean the 'zoom-out' animation when I click on the 'User Settings' button and at the Esc button
https://youtu.be/Z6Q-QUDLZ8EThe animation at a slower speed:
https://youtu.be/bcPs_kILo10 -
wrote on 16 Jan 2023, 05:44 last edited by
https://doc.qt.io/qt-5/animation-overview.html
The video looks like a combination of opacity and scale animations.
-
wrote on 17 Jan 2023, 11:33 last edited by
What properties is used to create scale?
-
@Marcia3x In the link @jeremy_k gave you there is an example:
QPushButton button("Animated Button"); button.show(); QPropertyAnimation animation(&button, "geometry"); animation.setDuration(10000); animation.setStartValue(QRect(0, 0, 100, 30)); animation.setEndValue(QRect(250, 250, 100, 30)); animation.start();
Just do not change x/y, only change width/height.
-
@Marcia3x In the link @jeremy_k gave you there is an example:
QPushButton button("Animated Button"); button.show(); QPropertyAnimation animation(&button, "geometry"); animation.setDuration(10000); animation.setStartValue(QRect(0, 0, 100, 30)); animation.setEndValue(QRect(250, 250, 100, 30)); animation.start();
Just do not change x/y, only change width/height.
wrote on 19 Jan 2023, 01:07 last edited by Marcia3x@jsulm said in How to animate a widget like discord 'zoom animation':
@Marcia3x In the link @jeremy_k gave you there is an example:
QPushButton button("Animated Button"); button.show(); QPropertyAnimation animation(&button, "geometry"); animation.setDuration(10000); animation.setStartValue(QRect(0, 0, 100, 30)); animation.setEndValue(QRect(250, 250, 100, 30)); animation.start();
Just do not change x/y, only change width/height.
After a lot of search and effort, I did something:
// stackedwidget.h class StackedWidget : public QStackedWidget { Q_OBJECT public: enum QEasingCurve::Type m_animationtype = QEasingCurve::Type::OutQuart; int m_speed = 1000; int m_now; int m_next; bool animation_active = false; QPoint m_pnow; QParallelAnimationGroup* animgroup; StackedWidget(QWidget* parent) : QStackedWidget(parent) { QWidget* widget = new QWidget(); QGridLayout* widget_layout = new QGridLayout(); widget->setLayout(widget_layout); QPushButton* button; for (size_t i = 0; i < 10; i++) { button = new QPushButton(); button->setText("Button " + QString::number(i)); button->setStyleSheet(R"( background-color: #3c3f45; border-radius: 4px; color: rgba(255, 255, 255, 0.4); font-size: 15px; font-weight: 600; )"); widget_layout->addWidget(button); } button->setText("Change Page"); connect(button, &QPushButton::clicked, [=] { animimateToPage(1); }); QWidget* widget_2 = new QWidget(); QGridLayout* widget_layout_2 = new QGridLayout(); widget_2->setLayout(widget_layout_2); for (size_t i = 0; i < 10; i++) { button = new QPushButton(); button->setText("================ " + QString::number(i)); button->setStyleSheet(R"( background-color: #3c3f45; border-radius: 4px; color: rgba(255, 255, 255, 0.4); font-size: 15px; font-weight: 600; )"); widget_layout_2->addWidget(button); } button->setText("return"); connect(button, &QPushButton::clicked, [this] { animimateToPage(0); }); addWidget(widget); addWidget(widget_2); } void animimateToPage(int index) { if (animation_active) return; animation_active = true; int now = currentIndex(); int next = indexOf(widget(index)); int offsetx = frameRect().width(); int offsety = frameRect().height(); widget(next)->setGeometry(0, 0, offsetx, offsety); QPoint pnext = widget(next)->pos(); QPoint pnow = widget(now)->pos(); m_pnow = pnow; //widget(next)->move(pnext.x() - offsetx, pnext.y() - offsety); QRect rnext = widget(next)->geometry(); QRect rnow = widget(now)->geometry(); int addw = 300; int addh = 100; widget(next)->show(); widget(next)->raise(); QPropertyAnimation* animnow = new QPropertyAnimation(widget(now), "geometry"); animnow->setDuration(m_speed); animnow->setEasingCurve(m_animationtype); animnow->setStartValue(QRect(0, 0, rnow.width(), rnow.height())); animnow->setEndValue(QRect(0, 0, rnow.width() - addw, rnow.height() - addh)); QGraphicsOpacityEffect* animnow_op_eff = new QGraphicsOpacityEffect(); widget(now)->setGraphicsEffect(animnow_op_eff); QPropertyAnimation* animnow_op = new QPropertyAnimation(animnow_op_eff, "opacity"); animnow_op->setDuration(m_speed); animnow_op->setStartValue(1); animnow_op->setEndValue(0); QPropertyAnimation* animnext = new QPropertyAnimation(widget(next), "geometry"); animnext->setDuration(m_speed); animnext->setEasingCurve(m_animationtype); animnext->setStartValue(QRect(0, 0, rnext.width() - addw, rnext.height() - addh)); animnext->setEndValue(QRect(0, 0, rnext.width(), rnext.height())); QGraphicsOpacityEffect* animnext_op_eff = new QGraphicsOpacityEffect(); animnext_op_eff->setOpacity(0); widget(next)->setGraphicsEffect(animnext_op_eff); QPropertyAnimation* animnext_op = new QPropertyAnimation(animnext_op_eff, "opacity"); animnext_op->setDuration(m_speed); animnext_op->setStartValue(0); animnext_op->setEndValue(1); animgroup = new QParallelAnimationGroup; animgroup->addAnimation(animnow); animgroup->addAnimation(animnext); animgroup->addAnimation(animnow_op); animgroup->addAnimation(animnext_op); QObject::connect(animgroup, &QParallelAnimationGroup::finished, this, &StackedWidget::animationDoneSlot); m_next = next; m_now = now; animgroup->start(QAbstractAnimation::DeleteWhenStopped); } void animationDoneSlot() { setCurrentIndex(m_next); widget(m_now)->hide(); widget(m_now)->move(m_pnow); widget(m_now)->setGraphicsEffect(nullptr); widget(m_next)->setGraphicsEffect(nullptr); animation_active = false; } };
#include "stackedwidget.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); ui.centralWidget->setStyleSheet("#centralWidget { background-color: #36393f; }"); QGridLayout* layout = new QGridLayout(); ui.centralWidget->setLayout(layout); StackedWidget* stacked_widget = new StackedWidget(this); layout->addWidget(stacked_widget); return; }
I have added some random buttons which colors similar to those seen in discord just to help check if the
animation is 'correct'.Looks like there's any kind of flickering in the animation, and I'm struggling with how to calculate the values to use in
start/end of the geometry animation.The animation I'm referring to:
https://i.imgur.com/fC2cTCY.gif (i reduced the speed of the animation, also, click on the image to enlarge it)
https://imgur.com/a/nUuOGSn (default speed)
5/5