今天和大家分享一个文本风格的加载动画, 有两类,其中一个可以设置文本内容和文本颜色,演示了两份. 共三个动画, 效果如下:
一共三个文件,可以直接编译 , 如果对您有所帮助的话 , 不要忘了点赞呢.
//main.cpp
#include "LoadingAnimWidget.h"
#include <QApplication>
#include <QGridLayout>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.setWindowTitle("加载动画 第8季");
QGridLayout * mainLayout = new QGridLayout;
auto* anim1= new TextInBouncingBox("正在加载");
mainLayout->addWidget(anim1,0,0);
auto* anim2 = new TextInBouncingBox("正在加载中");
anim2->setBoxColor("slateblue");
anim2->setTextColor("white");
mainLayout->addWidget(anim2,0,1);
auto* anim3 = new ExpandingScroll;
mainLayout->addWidget(anim3,0,2);
w.setLayout(mainLayout);
w.show();
anim1->start();
anim2->start();
anim3->start();
return a.exec();
}
//LoadingAnimWidget.h
#ifndef LOADINGANIMWIDGET_H
#define LOADINGANIMWIDGET_H
#include <QPropertyAnimation>
#include <QWidget>
class LoadingAnimBase:public QWidget
{
Q_OBJECT
Q_PROPERTY(qreal angle READ angle WRITE setAngle)
public:
LoadingAnimBase(QWidget* parent=nullptr);
virtual ~LoadingAnimBase();
qreal angle()const;
void setAngle(qreal an);
public slots:
virtual void exec();
virtual void start();
virtual void stop();
protected:
QPropertyAnimation mAnim;
qreal mAngle;
};
class TextInBouncingBox:public LoadingAnimBase{//显示装在上下跳动的盒子里的字符
public:
TextInBouncingBox(const QString & str,QWidget* parent = nullptr);
void setTextColor(const QColor& color);
void setBoxColor(const QColor& color);
protected:
void paintEvent(QPaintEvent*);
private:
QString mText;
QColor mTextColor;
QColor mBoxColor;
};
class ExpandingScroll:public LoadingAnimBase{//一个圆环转动两圈之后像卷轴一样展示"正在加载"
public:
ExpandingScroll(QWidget* parent = nullptr);
protected:
void paintEvent(QPaintEvent*);
};
#endif
//LoadingAnimWidget.cpp
#include "LoadingAnimWidget.h"
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
#include <QtMath>
#include <QRandomGenerator>
LoadingAnimBase::LoadingAnimBase(QWidget* parent):QWidget(parent){
mAnim.setPropertyName("angle");
mAnim.setTargetObject(this);
mAnim.setDuration(2000);
mAnim.setLoopCount(-1);//run forever
mAnim.setEasingCurve(QEasingCurve::Linear);
setFixedSize(200,200);
mAngle = 0;
}
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();
}
qreal LoadingAnimBase::angle()const{ return mAngle;}
void LoadingAnimBase::setAngle(qreal an){
mAngle = an;
update();
}
TextInBouncingBox::TextInBouncingBox(const QString& str,QWidget* parent ):LoadingAnimBase (parent),
mText(str),mBoxColor("darkslategray"),mTextColor("yellow"){
setFont(QFont("Microsoft YaHei",16,2));
}
void TextInBouncingBox::setTextColor(const QColor& color){
if(mTextColor != color){
mTextColor = color;
update();
}
}
void TextInBouncingBox::setBoxColor(const QColor& color){
if(mBoxColor != color){
mBoxColor = color;
update();
}
}
void TextInBouncingBox::paintEvent(QPaintEvent*){
const int len = mText.size();
if(len <= 0) return;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QFontMetrics fm(font());
const int txtH = fm.height();
const int rectH = txtH + 4;
const int rectW = fm.horizontalAdvance("w")+4;
const qreal x = width();
const qreal y = height();
painter.translate(0.1*x,0.6*y);
painter.setBrush(QBrush(mBoxColor));
const qreal amplitude = rectH*0.3;
const qreal offset = M_PI / len / 2;
for(int i = 0;i < len;++i){
QRectF rct( i*rectW,-rectH - amplitude*qSin(-2*M_PI / 360 * mAngle + offset*i) ,rectW,rectH);
painter.setPen(Qt::NoPen);
painter.drawRect(rct); //画一个小盒子
painter.setPen(mTextColor);
painter.drawText(rct,Qt::AlignCenter,QString(mText[i])); //画一个字符
}
}
ExpandingScroll::ExpandingScroll(QWidget* parent):LoadingAnimBase (parent){
setFont(QFont("Microsoft YaHei",16,2));
mAnim.setDuration(4000);
}
void ExpandingScroll::paintEvent(QPaintEvent*){
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
qreal x = width();
qreal y = height();
painter.translate(x/2,y/2);
painter.setBrush(Qt::NoBrush);
QPen pen("black");
static const qreal penWidth = 4;
pen.setWidthF(penWidth);
painter.setPen(pen);
x -= 4;
y -= 4;
const auto ang = mAngle;
const int arr[9] = {20,30,60,90,150,180,210,275,345};//9个时间节点,分割下面10个分支
if(ang < arr[0]){//中间的竖线转变为半圆弧线
const qreal h = 0.25*x;
painter.drawLine(0,h/2 - ang/arr[0] * h,0,-h/2);
painter.drawArc(QRectF(0,-1.5*h,2*h,2*h),180*16,-180*16*ang/arr[0]);
}
else if(ang < arr[1]){//半圆弧线转变为四分之一圆弧和右侧的小竖线
const qreal h = 0.25*x;
const qreal ratio = (ang-arr[0])/(arr[1] - arr[0]);
qreal start = 180 - 90*ratio;
painter.drawArc(QRectF(0,-1.5*h,2*h,2*h),start*16,-start*16);
painter.drawLine(x/2,-h/2,x/2,-h/2+h/2*ratio);
}
else if(ang < arr[2]){//剩下的上方的四分之一圆弧转为大的下方的八分之一圆弧
const qreal h = 0.25*x;
const qreal ratio = (ang - arr[1]) / (arr[2] - arr[1]);
qreal start = 90 - 90 * ratio;
painter.drawArc(QRectF(0,-1.5*h,2*h,2*h),start*16,-start*16);
painter.drawLine(x/2,-h/2,x/2,0);
painter.drawArc(QRectF(-x/2,-y/2,x,y),0,-45*16*ratio);
}
else if(ang < arr[3]){//小竖线转为下方的大的八分之一圆弧
const qreal h = x/8;
qreal ratio = (ang-arr[2]) / (arr[3] - arr[2]);
painter.drawLine(x/2,-h*(1-ratio),x/2,0);
painter.drawArc(QRectF(-x/2,-y/2,x,y),0,-(45+45*ratio)*16);
}
else if(ang < arr[4]){//大圆弧转两圈
qreal ratio = (ang - arr[3]) / (arr[4] - arr[3]);
painter.rotate(720*ratio);
painter.drawArc(QRectF(-x/2,-y/2,x,y),0,-90*16);
}
else if(ang < arr[5]){//大圆弧转为竖线
qreal ratio = (ang-arr[4]) / (arr[5] - arr[4]);
painter.drawArc(QRectF(-x/2,-y/2,x,y),-90*ratio*16,-90*(1-ratio)*16);
painter.drawLine(0,y/2,0,y/2 - 0.625*ratio*y);
}
else if(ang < arr[6]){//竖线缩小一下
qreal ratio = (ang - arr[5]) / (arr[6] - arr[5]);
painter.drawLine(0,y/2 - 0.375*y*ratio,0,-0.125*y);
}
else if(ang < arr[7]){//展开卷轴
qreal ratio = (ang - arr[6]) / (arr[7] - arr[6]);
QPainterPath pp;
pp.addRect(QRectF(-0.375*x*ratio,-0.125*y,0.75*x*ratio,y/4).adjusted(
penWidth/-2,penWidth/-2,penWidth/2,penWidth/2));
painter.setClipPath(pp);
const auto rct = QRectF(-0.375*x,-0.125*y,0.75*x,y/4);
painter.setBrush(QBrush("burlywood"));
painter.drawRoundedRect(rct,4,4);
painter.drawText(rct,Qt::AlignCenter,"正在加载");
}
else if(ang < arr[8]){//展示一小段时间
const auto rct = QRectF(-0.375*x,-0.125*y,0.75*x,y/4);
painter.setBrush(QBrush("burlywood"));
painter.drawRoundedRect(rct,4,4);
painter.drawText(rct,Qt::AlignCenter,"正在加载");
}
else{//收起卷轴
qreal ratio = (ang - arr[8])/(360 - arr[8]);
QPainterPath pp;
pp.addRect(QRectF(-0.375*x* (1-ratio),-0.125*y,0.75*x*(1-ratio),y/4).adjusted(
penWidth/-2,penWidth/-2,penWidth/2,penWidth/2));
painter.setClipPath(pp);
const auto rct = QRectF(-0.375*x,-0.125*y,0.75*x,y/4);
painter.setBrush(QBrush("burlywood"));
painter.drawRoundedRect(rct,4,4);
painter.drawText(rct,Qt::AlignCenter,"正在加载");
}
}