Add record/vinyl look to now playing screen
This commit is contained in:
@@ -1,16 +1,18 @@
|
||||
#include "spinningalbumart.h"
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QMouseEvent>
|
||||
#include <QRadialGradient>
|
||||
#include <QLinearGradient>
|
||||
|
||||
SpinningAlbumArt::SpinningAlbumArt(const QString& imagePath, int size, QWidget* parent)
|
||||
: QWidget(parent), size_(size)
|
||||
{
|
||||
artLabel_ = new QLabel(this);
|
||||
artLabel_->setAlignment(Qt::AlignCenter);
|
||||
|
||||
setFixedSize(size, size);
|
||||
|
||||
// Load and crop square
|
||||
// Load album art and square-crop it
|
||||
QPixmap pix(imagePath);
|
||||
QPixmap scaled = pix.scaled(size, size,
|
||||
Qt::KeepAspectRatioByExpanding,
|
||||
@@ -24,33 +26,121 @@ SpinningAlbumArt::SpinningAlbumArt(const QString& imagePath, int size, QWidget*
|
||||
side
|
||||
);
|
||||
|
||||
// Mask into circle
|
||||
discArt_ = createCircularDisc(square, size);
|
||||
artLabel_->setPixmap(discArt_);
|
||||
// Build full realistic vinyl disc with grooves + sheen + hole + label
|
||||
disc_ = buildRecord(square, size);
|
||||
|
||||
artLabel_->setPixmap(disc_);
|
||||
|
||||
// Setup spin timer
|
||||
timer_ = new QTimer(this);
|
||||
timer_->setInterval(16);
|
||||
connect(timer_, &QTimer::timeout, this, &SpinningAlbumArt::updateRotation);
|
||||
}
|
||||
|
||||
QPixmap SpinningAlbumArt::createCircularDisc(const QPixmap& src, int size)
|
||||
QPixmap SpinningAlbumArt::buildRecord(const QPixmap& src, int size)
|
||||
{
|
||||
QPixmap disc(size, size);
|
||||
disc.fill(Qt::transparent);
|
||||
|
||||
QPointF center(size / 2.0, size / 2.0);
|
||||
|
||||
QPainter p(&disc);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
QPainterPath path;
|
||||
path.addEllipse(0, 0, size, size);
|
||||
p.setClipPath(path);
|
||||
//
|
||||
// 1. Base vinyl gradient
|
||||
//
|
||||
QRadialGradient vinylGrad(center, size / 2);
|
||||
vinylGrad.setColorAt(0.0, QColor(55, 55, 55));
|
||||
vinylGrad.setColorAt(1.0, QColor(10, 10, 10));
|
||||
p.setBrush(vinylGrad);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(0, 0, size, size);
|
||||
|
||||
p.drawPixmap(0, 0, src);
|
||||
//
|
||||
// 2. Grooves (2px spacing, soft alpha)
|
||||
//
|
||||
p.setPen(QPen(QColor(255, 255, 255, 22), 1));
|
||||
int labelRadius = size * 0.35;
|
||||
for (int r = labelRadius; r < size / 2; r += 2)
|
||||
p.drawEllipse(center, r, r);
|
||||
|
||||
//
|
||||
// 3. Directional sheen (angled elliptical gradient)
|
||||
//
|
||||
QPixmap sheen(size, size);
|
||||
sheen.fill(Qt::transparent);
|
||||
{
|
||||
QPainter sp(&sheen);
|
||||
sp.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QLinearGradient lg(0, size * 0.25, size, size * 0.75);
|
||||
lg.setColorAt(0.0, QColor(255, 255, 255, 40));
|
||||
lg.setColorAt(0.5, QColor(255, 255, 255, 5));
|
||||
lg.setColorAt(1.0, QColor(0, 0, 0, 0));
|
||||
|
||||
sp.setBrush(lg);
|
||||
sp.setPen(Qt::NoPen);
|
||||
sp.drawEllipse(0, 0, size, size);
|
||||
}
|
||||
p.drawPixmap(0, 0, sheen);
|
||||
|
||||
//
|
||||
// 4. Recessed label shadow
|
||||
//
|
||||
QRadialGradient labelGrad(center, size * 0.36);
|
||||
labelGrad.setColorAt(0.0, QColor(0, 0, 0, 80));
|
||||
labelGrad.setColorAt(1.0, Qt::transparent);
|
||||
p.setBrush(labelGrad);
|
||||
p.drawEllipse(center, size * 0.36, size * 0.36);
|
||||
|
||||
//
|
||||
// 5. Album art masked to label circle
|
||||
//
|
||||
QPixmap label = buildLabelMask(src, size);
|
||||
p.drawPixmap(0, 0, label);
|
||||
|
||||
//
|
||||
// 6. Spindle hole (cutout)
|
||||
//
|
||||
int holeDiameter = size * 0.17;
|
||||
QPainterPath hole;
|
||||
hole.addEllipse(
|
||||
(size - holeDiameter) / 2,
|
||||
(size - holeDiameter) / 2,
|
||||
holeDiameter,
|
||||
holeDiameter
|
||||
);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Clear);
|
||||
p.fillPath(hole, Qt::transparent);
|
||||
|
||||
return disc;
|
||||
}
|
||||
|
||||
QPixmap SpinningAlbumArt::buildLabelMask(const QPixmap& src, int size)
|
||||
{
|
||||
QPixmap label(size, size);
|
||||
label.fill(Qt::transparent);
|
||||
|
||||
QPainter p(&label);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
int labelDiameter = size * 0.70;
|
||||
|
||||
QPainterPath mask;
|
||||
mask.addEllipse(
|
||||
(size - labelDiameter) / 2,
|
||||
(size - labelDiameter) / 2,
|
||||
labelDiameter,
|
||||
labelDiameter
|
||||
);
|
||||
|
||||
p.setClipPath(mask);
|
||||
p.drawPixmap(0, 0, src);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
void SpinningAlbumArt::start()
|
||||
{
|
||||
timer_->start();
|
||||
@@ -63,7 +153,7 @@ void SpinningAlbumArt::stop()
|
||||
|
||||
void SpinningAlbumArt::updateRotation()
|
||||
{
|
||||
rotationAngle_ += 0.6;
|
||||
rotationAngle_ += 0.5;
|
||||
|
||||
QPixmap frame(size_, size_);
|
||||
frame.fill(Qt::transparent);
|
||||
@@ -76,7 +166,7 @@ void SpinningAlbumArt::updateRotation()
|
||||
p.rotate(rotationAngle_);
|
||||
p.translate(-size_ / 2, -size_ / 2);
|
||||
|
||||
p.drawPixmap(0, 0, discArt_);
|
||||
p.drawPixmap(0, 0, disc_);
|
||||
|
||||
artLabel_->setPixmap(frame);
|
||||
}
|
||||
|
||||
@@ -4,14 +4,15 @@
|
||||
#include <QLabel>
|
||||
#include <QPixmap>
|
||||
#include <QTimer>
|
||||
#include <QMouseEvent>
|
||||
|
||||
class SpinningAlbumArt : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SpinningAlbumArt(const QString& imagePath, int size = 250, QWidget* parent = nullptr);
|
||||
explicit SpinningAlbumArt(const QString& imagePath,
|
||||
int size = 250,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
@@ -20,18 +21,20 @@ public slots:
|
||||
signals:
|
||||
void artClicked();
|
||||
|
||||
private slots:
|
||||
void updateRotation();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
|
||||
private:
|
||||
QPixmap discArt_; // circular-masked album image
|
||||
QLabel* artLabel_; // widget that displays the spinning frame
|
||||
QTimer* timer_; // animation timer
|
||||
qreal rotationAngle_ = 0;
|
||||
int size_; // final diameter of the disc
|
||||
private slots:
|
||||
void updateRotation();
|
||||
|
||||
QPixmap createCircularDisc(const QPixmap& src, int size);
|
||||
private:
|
||||
QPixmap buildRecord(const QPixmap& src, int size);
|
||||
QPixmap buildLabelMask(const QPixmap& src, int size);
|
||||
|
||||
QLabel* artLabel_;
|
||||
QPixmap disc_; // final assembled vinyl-only disc (with grooves + sheen + hole + label)
|
||||
QTimer* timer_;
|
||||
|
||||
qreal rotationAngle_ = 0;
|
||||
int size_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user