#include "CircularReveal.h" #include #include #include CircularReveal::CircularReveal(QQuickItem *parent) : QQuickPaintedItem(parent) { m_target = nullptr; m_radius = 0; _anim = new QPropertyAnimation(this, "radius", this); _anim->setDuration(333); _anim->setEasingCurve(QEasingCurve::OutCubic); setVisible(false); connect(_anim, &QPropertyAnimation::finished, this, [=]() { update(); setVisible(false); Q_EMIT animationFinished(); }); connect(this, &CircularReveal::radiusChanged, this, [=]() { update(); }); } void CircularReveal::paint(QPainter *painter) { painter->save(); painter->drawImage(QRect(0, 0, static_cast(width()), static_cast(height())), _source); QPainterPath path; path.moveTo(_center.x(), _center.y()); path.addEllipse(QPointF(_center.x(), _center.y()), m_radius, m_radius); painter->setCompositionMode(QPainter::CompositionMode_Clear); if (m_darkToLight) { painter->fillPath(path, Qt::white); } else { QPainterPath outerRect; outerRect.addRect(0, 0, width(), height()); outerRect = outerRect.subtracted(path); painter->fillPath(outerRect, Qt::black); } painter->restore(); } [[maybe_unused]] void CircularReveal::start(int w, int h, const QPoint ¢er, int radius) { if (_anim->state() == QAbstractAnimation::Running) { _anim->stop(); int currentRadius = m_radius; _anim->setStartValue(currentRadius); _anim->setEndValue(m_darkToLight ? 0 : radius); } else { if (m_darkToLight) { _anim->setStartValue(radius); _anim->setEndValue(0); } else { _anim->setStartValue(0); _anim->setEndValue(radius); } } _center = center; _grabResult = m_target->grabToImage(QSize(w, h)); connect(_grabResult.data(), &QQuickItemGrabResult::ready, this, &CircularReveal::handleGrabResult); } void CircularReveal::handleGrabResult() { _grabResult.data()->image().swap(_source); update(); setVisible(true); Q_EMIT imageChanged(); _anim->start(); }