260 lines
9.7 KiB
C++
260 lines
9.7 KiB
C++
#include "ElaPromotionCard.h"
|
|
|
|
#include <QMouseEvent>
|
|
#include <QPainter>
|
|
#include <QPainterPath>
|
|
#include <QPropertyAnimation>
|
|
#include <QRadialGradient>
|
|
#include <QtMath>
|
|
|
|
#include "ElaPromotionCardPrivate.h"
|
|
#include "ElaTheme.h"
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, int, BorderRadius)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QPixmap, CardPixmap)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QString, CardTitle)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QString, PromotionTitle)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QString, Title)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QString, SubTitle)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QColor, CardTitleColor)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QColor, PromotionTitleColor)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QColor, PromotionTitleBaseColor)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QColor, TitleColor)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, QColor, SubTitleColor)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, int, CardTitlePixelSize)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, int, PromotionTitlePixelSize)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, int, TitlePixelSize)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaPromotionCard, int, SubTitlePixelSize)
|
|
ElaPromotionCard::ElaPromotionCard(QWidget* parent)
|
|
: QWidget{parent}, d_ptr(new ElaPromotionCardPrivate())
|
|
{
|
|
Q_D(ElaPromotionCard);
|
|
d->q_ptr = this;
|
|
d->_pBorderRadius = 5;
|
|
d->_pPressRadius = 0;
|
|
d->_pHoverOpacity = 0;
|
|
d->_pHorizontalCardPixmapRatio = 1;
|
|
d->_pVerticalCardPixmapRatio = 1;
|
|
d->_pCardTitle = "";
|
|
d->_pPromotionTitle = "";
|
|
d->_pTitle = "";
|
|
d->_pSubTitle = "";
|
|
d->_pCardTitleColor = Qt::white;
|
|
d->_pPromotionTitleColor = Qt::white;
|
|
d->_pTitleColor = Qt::white;
|
|
d->_pSubTitleColor = Qt::white;
|
|
d->_pPromotionTitleBaseColor = QColor(0, 0, 0, 120);
|
|
d->_pCardTitlePixelSize = 22;
|
|
d->_pPromotionTitlePixelSize = 12;
|
|
d->_pTitlePixelSize = 25;
|
|
d->_pSubTitlePixelSize = 16;
|
|
setMouseTracking(true);
|
|
setObjectName("ElaPromotionCard");
|
|
setStyleSheet("#ElaPromotionCard{background-color:transparent;}");
|
|
d->_hoverGradient = new QRadialGradient();
|
|
d->_hoverGradient->setRadius(170);
|
|
d->_hoverGradient->setColorAt(0, QColor(0xFF, 0xFF, 0xFF, 40));
|
|
d->_hoverGradient->setColorAt(1, QColor(0xFF, 0xFF, 0xFF, 0));
|
|
|
|
d->_pressGradient = new QRadialGradient();
|
|
d->_pressGradient->setRadius(170);
|
|
d->_pressGradient->setColorAt(0, QColor(0xFF, 0xFF, 0xFF, 0));
|
|
d->_pressGradient->setColorAt(1, QColor(0xFF, 0xFF, 0xFF, 40));
|
|
}
|
|
|
|
ElaPromotionCard::~ElaPromotionCard()
|
|
{
|
|
Q_D(const ElaPromotionCard);
|
|
delete d->_hoverGradient;
|
|
delete d->_pressGradient;
|
|
}
|
|
|
|
void ElaPromotionCard::setHorizontalCardPixmapRatio(qreal pixmapRatio)
|
|
{
|
|
Q_D(ElaPromotionCard);
|
|
if (pixmapRatio > 0 && pixmapRatio <= 1)
|
|
{
|
|
Q_EMIT pHorizontalCardPixmapRatioChanged();
|
|
d->_pHorizontalCardPixmapRatio = pixmapRatio;
|
|
}
|
|
}
|
|
|
|
qreal ElaPromotionCard::getHorizontalCardPixmapRatio() const
|
|
{
|
|
Q_D(const ElaPromotionCard);
|
|
return d->_pHorizontalCardPixmapRatio;
|
|
}
|
|
|
|
void ElaPromotionCard::setVerticalCardPixmapRatio(qreal pixmapRatio)
|
|
{
|
|
Q_D(ElaPromotionCard);
|
|
if (pixmapRatio > 0 && pixmapRatio <= 1)
|
|
{
|
|
Q_EMIT pVerticalCardPixmapRatioChanged();
|
|
d->_pVerticalCardPixmapRatio = pixmapRatio;
|
|
}
|
|
}
|
|
|
|
qreal ElaPromotionCard::getVerticalCardPixmapRatio() const
|
|
{
|
|
Q_D(const ElaPromotionCard);
|
|
return d->_pVerticalCardPixmapRatio;
|
|
}
|
|
|
|
bool ElaPromotionCard::event(QEvent* event)
|
|
{
|
|
Q_D(ElaPromotionCard);
|
|
switch (event->type())
|
|
{
|
|
case QEvent::MouseButtonPress:
|
|
{
|
|
QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(event);
|
|
QPropertyAnimation* opacityAnimation = new QPropertyAnimation(d, "pPressOpacity");
|
|
connect(opacityAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
|
update();
|
|
});
|
|
connect(opacityAnimation, &QPropertyAnimation::finished, this, [=]() {
|
|
d->_isPressAnimationFinished = true;
|
|
});
|
|
opacityAnimation->setDuration(300);
|
|
opacityAnimation->setEasingCurve(QEasingCurve::InQuad);
|
|
opacityAnimation->setStartValue(1);
|
|
opacityAnimation->setEndValue(0);
|
|
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
|
|
QPropertyAnimation* pressAnimation = new QPropertyAnimation(d, "pPressRadius");
|
|
connect(pressAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
|
d->_pressGradient->setRadius(value.toReal());
|
|
});
|
|
pressAnimation->setDuration(300);
|
|
pressAnimation->setEasingCurve(QEasingCurve::InQuad);
|
|
pressAnimation->setStartValue(30);
|
|
pressAnimation->setEndValue(d->_getLongestDistance(mouseEvent->pos()) * 1.8);
|
|
pressAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
d->_isPressAnimationFinished = false;
|
|
d->_pressGradient->setFocalPoint(mouseEvent->pos());
|
|
d->_pressGradient->setCenter(mouseEvent->pos());
|
|
//点击后隐藏Hover效果
|
|
d->_startHoverOpacityAnimation(false);
|
|
break;
|
|
}
|
|
case QEvent::MouseButtonRelease:
|
|
{
|
|
Q_EMIT promotionCardClicked();
|
|
break;
|
|
}
|
|
case QEvent::MouseMove:
|
|
{
|
|
QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(event);
|
|
if (d->_pHoverOpacity < 1 && d->_isPressAnimationFinished)
|
|
{
|
|
d->_startHoverOpacityAnimation(true);
|
|
}
|
|
if (d->_isPressAnimationFinished)
|
|
{
|
|
d->_hoverGradient->setCenter(mouseEvent->pos());
|
|
d->_hoverGradient->setFocalPoint(mouseEvent->pos());
|
|
}
|
|
update();
|
|
break;
|
|
}
|
|
case QEvent::Enter:
|
|
{
|
|
d->_startHoverOpacityAnimation(true);
|
|
break;
|
|
}
|
|
case QEvent::Leave:
|
|
{
|
|
d->_startHoverOpacityAnimation(false);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return QWidget::event(event);
|
|
}
|
|
|
|
void ElaPromotionCard::paintEvent(QPaintEvent* event)
|
|
{
|
|
Q_D(ElaPromotionCard);
|
|
QPainter painter(this);
|
|
painter.save();
|
|
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
|
painter.setPen(Qt::NoPen);
|
|
//阴影绘制
|
|
eTheme->drawEffectShadow(&painter, rect(), d->_shadowBorderWidth, d->_pBorderRadius);
|
|
QRect foregroundRect(d->_shadowBorderWidth, d->_shadowBorderWidth, width() - 2 * d->_shadowBorderWidth, height() - 2 * d->_shadowBorderWidth);
|
|
QPainterPath path;
|
|
path.addRoundedRect(foregroundRect, d->_pBorderRadius, d->_pBorderRadius);
|
|
painter.setClipPath(path);
|
|
//背景图片绘制
|
|
if (!d->_pCardPixmap.isNull())
|
|
{
|
|
//源区域计算
|
|
QRect pixSourceRect = d->_pCardPixmap.rect();
|
|
qreal horizontalOffset = d->_pCardPixmap.width() * (1 - d->_pHorizontalCardPixmapRatio) / 2;
|
|
qreal verticalOffset = d->_pCardPixmap.height() * (1 - d->_pVerticalCardPixmapRatio) / 2;
|
|
pixSourceRect.adjust(horizontalOffset, verticalOffset, -horizontalOffset, -verticalOffset);
|
|
painter.drawPixmap(foregroundRect, d->_pCardPixmap, pixSourceRect);
|
|
}
|
|
//文字绘制
|
|
painter.save();
|
|
QFont font = painter.font();
|
|
//卡片标题
|
|
font.setWeight(QFont::Bold);
|
|
font.setPixelSize(d->_pCardTitlePixelSize);
|
|
painter.setFont(font);
|
|
painter.setPen(d->_pCardTitleColor);
|
|
painter.drawText(QRect(25, 25, foregroundRect.width() - 25, foregroundRect.height()), Qt::AlignLeft | Qt::AlignTop | Qt::TextSingleLine, d->_pCardTitle);
|
|
//标题
|
|
font.setWeight(QFont::Bold);
|
|
font.setPixelSize(d->_pTitlePixelSize);
|
|
painter.setFont(font);
|
|
painter.setPen(d->_pTitleColor);
|
|
int titleTextHeight = painter.fontMetrics().height();
|
|
QRect titleRect(25, (height() - titleTextHeight) / 2, foregroundRect.width() - 25, titleTextHeight);
|
|
painter.drawText(titleRect, Qt::AlignLeft | Qt::AlignBottom | Qt::TextSingleLine, d->_pTitle);
|
|
//推广标题
|
|
if (!d->_pPromotionTitle.isEmpty())
|
|
{
|
|
font.setWeight(QFont::Normal);
|
|
font.setPixelSize(d->_pPromotionTitlePixelSize);
|
|
painter.setFont(font);
|
|
int promotionTitleTextWidth = painter.fontMetrics().horizontalAdvance(d->_pPromotionTitle);
|
|
int promotionTitleTextHeight = painter.fontMetrics().height();
|
|
QRect promotionTitleTextRect(32, titleRect.top() - promotionTitleTextHeight - 5, foregroundRect.width() / 2 - 25, promotionTitleTextHeight);
|
|
//背景绘制
|
|
painter.setPen(Qt::NoPen);
|
|
painter.setBrush(d->_pPromotionTitleBaseColor);
|
|
painter.drawRoundedRect(QRect(25, promotionTitleTextRect.top() - 2, promotionTitleTextWidth + 14, promotionTitleTextHeight + 4), 8, 8);
|
|
//文字绘制
|
|
painter.setPen(d->_pPromotionTitleColor);
|
|
painter.drawText(promotionTitleTextRect, Qt::AlignLeft | Qt::AlignBottom | Qt::TextSingleLine, d->_pPromotionTitle);
|
|
}
|
|
//副标题
|
|
font.setWeight(QFont::Medium);
|
|
font.setPixelSize(d->_pSubTitlePixelSize);
|
|
painter.setFont(font);
|
|
painter.setPen(d->_pSubTitleColor);
|
|
painter.drawText(QRect(25, titleRect.bottom(), foregroundRect.width() / 2 - 25, height() / 2), Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, d->_pSubTitle);
|
|
|
|
painter.restore();
|
|
//效果阴影绘制
|
|
if (d->_isPressAnimationFinished)
|
|
{
|
|
//覆盖阴影绘制
|
|
painter.setOpacity(d->_pHoverOpacity);
|
|
painter.setBrush(*d->_hoverGradient);
|
|
painter.drawEllipse(d->_hoverGradient->center(), d->_hoverGradient->radius(), d->_hoverGradient->radius());
|
|
}
|
|
else
|
|
{
|
|
//点击阴影绘制
|
|
painter.setOpacity(d->_pPressOpacity);
|
|
painter.setBrush(*d->_pressGradient);
|
|
painter.drawEllipse(d->_pressGradient->center(), d->_pPressRadius, d->_pPressRadius / 1.1);
|
|
}
|
|
painter.restore();
|
|
}
|