#include "ElaPromotionCard.h" #include #include #include #include #include #include #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(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(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(); }