😃 给大家分享6个简约的加载动画,这是第一季,后续陆续上架 😃
这是最终效果
一共只有三个文件,可以直接编译运行
//main.cpp
#include "LoadingAnimWidget.h"
#include <QApplication>
#include <QVBoxLayout>
#include <QPushButton>
#include <QGridLayout>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.setWindowTitle("加载动画 第一季");
QGridLayout * mainLayout = new QGridLayout;
SpotsCircle * anim1 = new SpotsCircle;
mainLayout->addWidget(anim1,0,0);
SpotsShrinkCircle * anim2 = new SpotsShrinkCircle;
mainLayout->addWidget(anim2,0,1);
auto* anim3 = new TextCircle("Loading...");
mainLayout->addWidget(anim3,1,0);
auto* anim4 = new StickCircle();
mainLayout->addWidget(anim4,1,1);
TubeCircle * anim5 = new TubeCircle;
mainLayout->addWidget(anim5,0,2);
TubeBallCircle * anim6 = new TubeBallCircle;
mainLayout->addWidget(anim6,1,2);
QPushButton * btn = new QPushButton("start");
mainLayout->addWidget(btn,2,1);
w.setLayout(mainLayout);
QObject::connect(btn,&QPushButton::clicked,anim1,&SpotsCircle::exec);
QObject::connect(btn,&QPushButton::clicked,anim2,&SpotsShrinkCircle::exec);
QObject::connect(btn,&QPushButton::clicked,anim3,&TextCircle::exec);
QObject::connect(btn,&QPushButton::clicked,anim4,&StickCircle::exec);
QObject::connect(btn,&QPushButton::clicked,anim5,&TubeCircle::exec);
QObject::connect(btn,&QPushButton::clicked,anim6,&TubeBallCircle::exec);
QObject::connect(btn,&QPushButton::clicked,btn,[=](){
if(btn->text() == "start") btn->setText("stop");
else btn->setText("start");
});
w.show();
return a.exec();
}
//LoadingAnimWidget.h
#ifndef LOADINGANIMWIDGET_H
#define LOADINGANIMWIDGET_H
#include <QPropertyAnimation>
#include <QWidget>
class LoadingAnimBase:public QWidget
{
Q_OBJECT
public:
LoadingAnimBase(QWidget* parent=nullptr);
virtual ~LoadingAnimBase();
public slots:
virtual void exec();
virtual void start();
virtual void stop();
protected:
QPropertyAnimation mAnim;
};
class SpotsShrinkCircle:public LoadingAnimBase{//32个球均匀分布在四周,绕着中心转圈,球越来越小
Q_OBJECT
Q_PROPERTY(qreal angle READ angle WRITE setAngle)
public:
explicit SpotsShrinkCircle(QWidget * parent = nullptr);
qreal angle()const;
void setAngle(qreal an);
protected:
void paintEvent(QPaintEvent *event);
signals:
public slots:
private:
qreal mAngle;
};
class SpotsCircle : public LoadingAnimBase//8个紧挨着的球绕着中心转圈,每个球大小一样
{
Q_OBJECT
Q_PROPERTY(qreal angle READ angle WRITE setAngle)
public:
explicit SpotsCircle(QWidget *parent = nullptr);
qreal angle()const;
void setAngle(qreal an);
protected:
void paintEvent(QPaintEvent *event);
public slots:
private:
qreal mAngle;
};
class StickCircle:public LoadingAnimBase//12根小棒分布周围,三根小棒是深色的,其他都是淡色的,深色小棒循环占取淡色小棒的位置
{
Q_OBJECT
Q_PROPERTY(qreal angle READ angle WRITE setAngle)
public:
explicit StickCircle(QWidget* parent = nullptr);
qreal angle()const;
void setAngle(qreal an);
void setShrinkStick(bool shrink);
protected:
void paintEvent(QPaintEvent *event);
public slots:
private:
qreal mAngle;
bool mShrink;
};
class TubeCircle:public LoadingAnimBase //一根管子绕着中心旋转
{
Q_OBJECT
Q_PROPERTY(qreal angle READ angle WRITE setAngle)
public:
explicit TubeCircle(QWidget* parent = nullptr);
qreal angle()const;
void setAngle(qreal an);
protected:
void paintEvent(QPaintEvent *event);
public slots:
private:
qreal mAngle;
};
class TextCircle:public LoadingAnimBase{ //一串文本绕着中心旋转
Q_OBJECT
Q_PROPERTY(qreal angle READ angle WRITE setAngle)
public:
explicit TextCircle(const QString & txt = "Loading...",QWidget* parent = nullptr);
qreal angle()const;
void setAngle(qreal an);
protected:
void paintEvent(QPaintEvent* event);
private:
QString mText;
qreal mAngle;
};
class TubeBallCircle:public LoadingAnimBase //一根封闭的管子,中间有个小球沿着管子滚动
{
Q_OBJECT
Q_PROPERTY(qreal angle READ angle WRITE setAngle)
public:
explicit TubeBallCircle(QWidget* parent = nullptr);
qreal angle()const;
void setAngle(qreal an);
protected:
void paintEvent(QPaintEvent *event);
public slots:
private:
qreal mAngle;
};
#endif // LOADINGANIMWIDGET_H
//LoadingAnimWidget.cpp
#include "LoadingAnimWidget.h"
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
LoadingAnimBase::LoadingAnimBase(QWidget* parent):QWidget(parent){}
LoadingAnimBase::~LoadingAnimBase(){}
void LoadingAnimBase::exec(){
if(mAnim.state() == QAbstractAnimation::Stopped){
start();
}
else{
stop();
}
}
void LoadingAnimBase::start(){
mAnim.setStartValue(0);
mAnim.setEndValue(360);
mAnim.start();
}
void LoadingAnimBase::stop(){
mAnim.stop();
}
SpotsCircle::SpotsCircle(QWidget *parent) : LoadingAnimBase(parent)
{
mAnim.setPropertyName("angle");
mAnim.setTargetObject(this);
mAnim.setDuration(2000);
mAnim.setLoopCount(-1);//run forever
mAnim.setEasingCurve(QEasingCurve::Linear);
resize(200,200);
setFixedSize(200,200);
mAngle = 0;
}
void SpotsCircle::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
int x = width();
int y = height();
painter.setPen(Qt::NoPen);
painter.translate(x/2,y/2);
QColor color = QColor("black");
qreal alpha = color.alphaF();
painter.rotate(mAngle);
for(int i = 0;i<16;++i){//16个小球
qreal rw = 1.0/8*x;
qreal r = rw/2;
painter.setBrush(QBrush(color));
alpha *= 0.8;
color.setAlphaF(alpha);
painter.drawEllipse(0,x/2-rw,r,r);
auto transform = painter.transform();
transform.rotate(-2);
painter.setTransform(transform);
}
}
qreal SpotsCircle::angle()const{
return mAngle;
}
void SpotsCircle::setAngle(qreal an){
mAngle = an;
update();
}
SpotsShrinkCircle::SpotsShrinkCircle(QWidget *parent) : LoadingAnimBase(parent)
{
mAnim.setPropertyName("angle");
mAnim.setTargetObject(this);
mAnim.setDuration(3000);
mAnim.setLoopCount(-1);//run forever
mAnim.setEasingCurve(QEasingCurve::Linear);
resize(200,200);
setFixedSize(200,200);
mAngle = 0;
}
void SpotsShrinkCircle::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
int x = width();
int y = height();
qreal ang = mAngle;
painter.setPen(Qt::NoPen);
painter.translate(x/2,y/2);
QColor color = QColor("black");
qreal alpha = color.alphaF();
painter.rotate(ang);
qreal rw = 1.0/7*x;
qreal r = rw/2;
for(int i = 0;i<12;++i){
painter.setBrush(QBrush(color));
alpha *= 0.9;
color.setAlphaF(alpha);
painter.drawEllipse(0,x/2-rw,r,r);
r *= 0.95;
auto transform = painter.transform();
transform.rotate(-360/18);
painter.setTransform(transform);
}
}
qreal SpotsShrinkCircle::angle()const{
return mAngle;
}
void SpotsShrinkCircle::setAngle(qreal an){
mAngle = an;
update();
}
void StickCircle::setShrinkStick(bool shrink){
mShrink = shrink;
}
StickCircle::StickCircle(QWidget *parent) : LoadingAnimBase(parent)
{
mAnim.setPropertyName("angle");
mAnim.setTargetObject(this);
mAnim.setDuration(2000);
mAnim.setLoopCount(-1);//run forever
mAnim.setEasingCurve(QEasingCurve::Linear);
resize(200,200);
setFixedSize(200,200);
mAngle = 0;
mShrink = false;
}
void StickCircle::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
int x = width();
int y = height();
qreal ang = mAngle;
painter.setPen(Qt::NoPen);
painter.translate(x/2,y/2);
QColor lightColor = QColor("black");
lightColor.setAlphaF(0.1);
const int stickw = 10;//小棍子的宽度
qreal stickl = x / 4;//小棍子的长度
QColor highlight = QColor("black");
const int startIdx = ang / 30;//开头的深色小棍子的索引号
const int arr[14] = {0,1,2,3,4,5,6,7,8,9,10,11,0,1};
QList<int> hightlightList{arr[startIdx],arr[startIdx+1],arr[startIdx+2]};
QList<qreal> alphaList{0.5,0.75,0.99};//三根深色的小棍子的透明度
for(int i = 0;i < 12;++i){
if(hightlightList.contains(i)){
auto hc = highlight;
hc.setAlphaF(alphaList[0]);
painter.setBrush(QBrush(hc));
alphaList.pop_front();
}
else {
painter.setBrush(QBrush(lightColor));
}
painter.drawRoundedRect(QRectF(-stickw/2,0.375*y -stickl/2-1,stickw,stickl),stickw/2,stickw/2);
auto transform = painter.transform();
transform.rotate(30);
painter.setTransform(transform);
}
}
qreal StickCircle::angle()const{
return mAngle;
}
void StickCircle::setAngle(qreal an){
mAngle = an;
update();
}
TextCircle::TextCircle(const QString & txt,QWidget* parent):mText(txt),LoadingAnimBase(parent){
mAnim.setPropertyName("angle");
mAnim.setTargetObject(this);
mAnim.setDuration(2000);
mAnim.setLoopCount(-1);//run forever
mAnim.setEasingCurve(QEasingCurve::Linear);
//resize(200,200);
setFixedSize(200,200);
mAngle = 0;
}
qreal TextCircle::angle()const{return mAngle;}
void TextCircle::setAngle(qreal an){
mAngle = an;
update();
}
void TextCircle::paintEvent(QPaintEvent* event){
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
int x = width();
int y = height();
QPen pen("black");
pen.setWidth(4);
painter.setPen(pen);
painter.translate(x/2,y/2);
painter.rotate(mAngle);
for(int i = 0;i < mText.length();++i){
const QString s = QString(mText[i]);
painter.drawText(QRect(-10,y/2-22,20,20),Qt::AlignTop,s);//中下方画一个字符
painter.rotate(-8);//每个字符之间间距8度
}
}
TubeCircle::TubeCircle(QWidget *parent) : LoadingAnimBase(parent)
{
mAnim.setPropertyName("angle");
mAnim.setTargetObject(this);
mAnim.setDuration(2000);
mAnim.setLoopCount(-1);//run forever
mAnim.setEasingCurve(QEasingCurve::Linear);
resize(200,200);
setFixedSize(200,200);
mAngle = 0;
}
void TubeCircle::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
int x = width();
int y = height();
qreal ang = mAngle;
QPen pen(QColor("black"));
pen.setWidth(x/20);
pen.setCapStyle(Qt::RoundCap);
painter.setPen(pen);
painter.translate(x/2,y/2);
painter.rotate(ang);
const int adjust = x/20;
auto rect = this->rect().adjusted(adjust,adjust,-adjust,-adjust);
rect.translate(-x/2,-y/2);
painter.drawArc(rect,30*16,-300*16);
}
qreal TubeCircle::angle()const{
return mAngle;
}
void TubeCircle::setAngle(qreal an){
mAngle = an;
update();
}
TubeBallCircle::TubeBallCircle(QWidget *parent) : LoadingAnimBase(parent)
{
mAnim.setPropertyName("angle");
mAnim.setTargetObject(this);
mAnim.setDuration(2000);
mAnim.setLoopCount(-1);//run forever
mAnim.setEasingCurve(QEasingCurve::Linear);
resize(200,200);
setFixedSize(200,200);
mAngle = 0;
}
void TubeBallCircle::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
int x = width();
int y = height();
qreal ang = mAngle;
QColor co("gray");
co.setAlphaF(0.3);
QPen pen(co);
const int penw = x/8;
pen.setWidth(penw);
pen.setCapStyle(Qt::RoundCap);
painter.setPen(pen);
painter.translate(x/2,y/2);
painter.rotate(ang);
const int adjust = penw/2;
auto rect = this->rect().adjusted(adjust,adjust,-adjust,-adjust);
rect.translate(-x/2,-y/2);
painter.drawArc(rect,30*16,360*16);//画轨道
painter.setPen(Qt::NoPen);
painter.setBrush(QColor("black"));
painter.drawEllipse(QPoint(0,y/2-penw/2),penw/2,penw/2);//画小球
}
qreal TubeBallCircle::angle()const{
return mAngle;
}
void TubeBallCircle::setAngle(qreal an){
mAngle = an;
update();
}