How to animate a widget like discord 'zoom animation'
-
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 -
https://doc.qt.io/qt-5/animation-overview.html
The video looks like a combination of opacity and scale animations.
-
@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.
@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'.Result:
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)