前言
目前见的比较多的轮播图有平移和旋转两种方式。平移类似淘宝那种切换幻灯片一样的效果,旋转一般是近大远小,看起来有点3D的感觉。本文代码实现旋转轮播图效果如下:
完整代码链接: https://github.com/gongjianbo/MyTestCode/tree/master/Qt/TestQt_20211029_Swiper
设计思路思路 1.计算坐标可以现在 3D 场景中设计效果,图片是绕着 Y 轴旋转的,如下图:
由于我们的观察点是固定的,就能拆分成两个平面进行处理:
一个是 xz 组成的旋转轨迹平面,x 对应绘制时的坐标点 x 分量,z 对应绘制时的前后顺序,近大远小,同时 z 值更大的堆叠在上层。可以根据球圆上点坐标的方式根据旋转角度计算 x 和 z 的值。
另一个是绘制时的 xy 屏幕坐标系,可以直接将 y 在图上居中,x 取上一步获取到的 x 值。要注意的是 Qt 绘制时,原点在左上角,右下角为正方向。
2.切换动画切换动画可以用 QPropertyAnimation 属性动画来做。
要注意的一个点就是头尾切换时。如果第一个切换到最后一个,可以将当前 index 设置为最后一个 index+1,这样再去减 1 动画就能正常过渡;或者最后一个切换到第一个,可以将当前 index 设置为第一个 index-1,这样再去加 1 动画就能正常过渡。否则可能出现从头逐个切换到最后或者反过来,这明显就破坏了旋转的连续性。
主要实现代码#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
Q_PROPERTY(double curIndex READ getCurIndex WRITE setCurIndex NOTIFY curIndexChanged)
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
double getCurIndex() const;
void setCurIndex(double index);
protected:
bool event(QEvent *e) override;
void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private:
//计算图片位置
void calcImagePos();
//计算按钮位置
void calcBtnPath();
//切换到下一个图
void toPrev();
//切换到上一个图
void toNext();
signals:
void curIndexChanged();
private:
Ui::MainWindow *ui;
struct ImageNode{
QImage img;
double xf{0};
double yf{0};
double zf{0};
};
//当前图片列表
QVector imageList;
//按钮位置
QVector btnList;
//图片z堆叠顺序
QVector drawList;
//当前设置的index
int setIndex{0};
//属性动画绘制用到的index
double curIndex{0.0};
//旋转动画
QPropertyAnimation animation;
//自动切换定时器
QTimer swipTimer;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setMouseTracking(true);
//界面上放了两个按钮用来前进后退,切换当前图片
connect(ui->btnPrev,&QPushButton::clicked,this,&MainWindow::toPrev);
connect(ui->btnNext,&QPushButton::clicked,this,&MainWindow::toNext);
//随便搞五个色块image当作图片
int alpha=255;
QList colors=QList{
QColor(255,0,0,alpha),
QColor(0,255,0,alpha),
QColor(0,0,255,alpha),
QColor(255,255,0,alpha),
QColor(0,255,255,alpha) };
for(int i=0;itype()) {
case QEvent::HoverMove:{
QHoverEvent *hover = static_cast(e);
if(hover){
//放到哪个按钮上就切换到对应图片
for(int i=0;ipos()))
{
setIndex=i;
animation.stop();
animation.setStartValue(getCurIndex());
animation.setEndValue((double)setIndex);
animation.start();
break;
}
}
}
}
break;
default:
break;
}
return QMainWindow::event(e);
}
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
painter.fillRect(rect(),Qt::white);
if(imageList.isEmpty())
return;
//切换两种效果
if(!ui->checkBox->isChecked())
{
painter.save();
//平移到中心点绘制,便于计算
painter.translate(width()/2,height()/2);
for(int i=0;i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?