一、简述
前几天在群里看见有个小伙伴用的一款gif录屏软件有一个类似水滴的点击效果。于是想了想,便开始了Code。思路也很简单,就是借助Qt的动画类QVariantAnimation然后不断重绘达到点击的动画效果,先看一下效果图。
二、代码之路
WaterDrop.h
#include <QtWidgets/QWidget>
#include <QVariantAnimation>
class WaterDrop : public QWidget
{
Q_OBJECT
public:
WaterDrop(QWidget *parent = Q_NULLPTR);
~WaterDrop();
void show();
void move(const QPoint &point);
void setColor(QColor color);
private:
void paintEvent(QPaintEvent *event);
public slots:
void onRaduisChanged(QVariant value);
private:
QVariantAnimation* m_waterDropAnimation;
// 水滴变化的半径;
int m_animationRadius;
// 水滴的颜色;
QColor m_waterDropColor;
};
WaterDrop.cpp
#include "WaterDrop.h"
#include <QPainter>
// 水滴的半径;
#define WATER_DROP_RADIUS 15
WaterDrop::WaterDrop(QWidget *parent)
: QWidget(parent)
, m_waterDropAnimation(NULL)
, m_animationRadius(0)
, m_waterDropColor(QColor(255, 120, 0, 150)) // 默认为橘黄色;
{
this->setFixedSize(QSize(WATER_DROP_RADIUS * 2, WATER_DROP_RADIUS *2));
this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
this->setAttribute(Qt::WA_TranslucentBackground);
// 控件显示完关闭后自动删除;
this->setAttribute(Qt::WA_DeleteOnClose);
m_waterDropAnimation = new QVariantAnimation(this);
}
WaterDrop::~WaterDrop()
{
}
void WaterDrop::move(const QPoint &point)
{
// 这里要把鼠标点击的点转换为圆心点坐标;
QPoint translatePoint = point - QPoint(WATER_DROP_RADIUS, WATER_DROP_RADIUS);
__super::move(translatePoint);
}
void WaterDrop::show()
{
__super::show();
// 通过动画类不断进行重绘;
m_waterDropAnimation->setStartValue(0);
m_waterDropAnimation->setEndValue(WATER_DROP_RADIUS);
m_waterDropAnimation->setDuration(350);
connect(m_waterDropAnimation, &QVariantAnimation::valueChanged, this, &WaterDrop::onRaduisChanged);
connect(m_waterDropAnimation, &QVariantAnimation::finished, this, &WaterDrop::close);
m_waterDropAnimation->start();
}
// 设置水滴的颜色;
void WaterDrop::setColor(QColor color)
{
m_waterDropColor = color;
}
// 绘制鼠标的水滴点击效果;
void WaterDrop::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(m_waterDropColor));
// 思路就是先绘制一个固定大小的圆A,然后绘制同一圆心的透明的圆B,然后通过动画类是圆B的半径从0增长到WATER_DROP_RADIUS,以致覆盖固定的圆A;
QPainterPath waterDropPath;
waterDropPath.addEllipse(QPoint(WATER_DROP_RADIUS, WATER_DROP_RADIUS), WATER_DROP_RADIUS, WATER_DROP_RADIUS);
QPainterPath hidePath;
hidePath.addEllipse(QPoint(WATER_DROP_RADIUS, WATER_DROP_RADIUS), m_animationRadius, m_animationRadius);
waterDropPath -= hidePath;
painter.drawPath(waterDropPath);
}
void WaterDrop::onRaduisChanged(QVariant value)
{
// 不断增加圆B的半径值,并重绘;
m_animationRadius = value.toInt();
update();
}
测试代码
// 新建一窗口类,重写mousePressEvent事件即可;
void MyWidget::mousePressEvent(QMouseEvent *event)
{
QPoint cursorPos = event->pos();
qDebug() << "mousePressEvent" << cursorPos;
WaterDrop* waterDrop = new WaterDrop();
waterDrop->move(this->mapToGlobal(cursorPos));
waterDrop->setColor(Qt::green);
waterDrop->show();
}
尾
后续会继续分享Qt动画类做出的一些动画特效,敬请期待哈O(∩_∩)O!
支持一下,请点个赞吧!!!