QT实现弹幕和webp格式礼物动效
Demo:https://download.csdn.net/download/wu110112/21628782?spm=1001.2014.3001.5501
动效礼物可支持各位为:gif和webp格式
20210830-155059
20210827-162020
BulletCrtan.h
#pragma once
#include <QWidget>
#include <QVector>
#include <QString>
#include <QStringList>
#include <QPoint>
#include <QFont>
#include <QTimer>
#include <QMovie>
#include <QLabel>
/************************************************************************
*作者:wujianhua
*时间:2021/08/26
*类介绍:弹幕类【支持文案飘屏、礼物动效展示】
************************************************************************/
namespace Bullet_Curtain{//弹幕信息结构typedef struct tag_Bullet_Curtain_Info {QString content; //内容数据QColor rgba; //文本显示颜色QPoint pt; //坐标int step; //弹幕步进tag_Bullet_Curtain_Info(){rgba = QColor(255, 255, 255, 230);}}BULLET_CURTAIN_INFO, *LPBULLET_CURTAIN_INFO;
};class BulletCurtain : public QWidget
{Q_OBJECTpublic:BulletCurtain(QWidget *parent);~BulletCurtain();/*************************************************************************作者:wujianhua*时间:2021/08/26*函数:发送弹幕*参数:* info:弹幕信息*返回值:* 无************************************************************************/void sendBulletCurtain(Bullet_Curtain::BULLET_CURTAIN_INFO info);/*************************************************************************作者:wujianhua*时间:2021/08/27*函数:发送动效礼物*参数:* path:礼物路径*返回值:* 无************************************************************************/void sendGift(const QString &path);/*************************************************************************作者:wujianhua*时间:2021/08/30*函数:获取弹幕最大显示行数*参数:* 无*返回值:* 返回弹幕支持最大的弹幕行数************************************************************************/int getBulletCurtainMaxRow();/*************************************************************************作者:wujianhua*时间:2021/08/30*函数:显示弹幕行数*参数:* maxRow:弹幕最大行数*返回值:* 无************************************************************************/void showMaxCurtainMaxRow(unsigned int maxRow=1);/*************************************************************************作者:wujianhua*时间:2021/08/30*函数:显示弹幕*参数:* 无*返回值:* 无************************************************************************/void showBulletCurtain();/*************************************************************************作者:wujianhua*时间:2021/08/30*函数:隐藏弹幕*参数:* 无*返回值:* 无************************************************************************/void hideBulletCurtain();/*************************************************************************作者:wujianhua*时间:2021/08/30*函数:显示礼物*参数:* 无*返回值:* 无************************************************************************/void showGift();/*************************************************************************作者:wujianhua*时间:2021/08/30*函数:隐藏礼物*参数:* 无*返回值:* 无************************************************************************/void hideGift();protected:virtual void paintEvent(QPaintEvent * event);private:/*************************************************************************作者:wujianhua*时间:2021/08/26*函数:回执弹幕文本数据*参数:* drawInfo:弹幕绘制信息*返回值:* 绘制成功返回true,绘制失败返回false【失败也可以理解当前弹幕内容已经轮播一次结束不在绘制了】************************************************************************/bool drawText(Bullet_Curtain::LPBULLET_CURTAIN_INFO drawInfo);/*************************************************************************作者:wujianhua*时间:2021/08/27*函数:播放礼物动效*参数:* path:礼物物理路径*返回值:* 无************************************************************************/void playerGift(const QString &path);
private:QVector<Bullet_Curtain::LPBULLET_CURTAIN_INFO> m_vecInfoQueue; //弹幕信息队列QTimer *m_timerReflush = nullptr; //定时刷新QFont * m_font = nullptr; //弹幕字体unsigned int m_currentRow = 0; //当前弹幕行号unsigned int m_maxRow = 1; //最大显示弹幕行数//播放礼物动效QTimer *m_timeGift = nullptr;QStringList m_giftList;QLabel *m_webpLabel = nullptr;QMovie *m_webpMovie = nullptr;bool m_curGiftFinished = true; //当前礼物播放完成bool m_showBulletCurtain = true; //弹幕显示标志bool m_showGift = true; //礼物显示标志
};
BulletCrtan.cpp
#include "BulletCurtain.h"
#include <QPainter>
#include <QTime>
#include <QDebug>
#include <QHBoxLayout>using namespace Bullet_Curtain;
BulletCurtain::BulletCurtain(QWidget *parent): QWidget(parent)
{setObjectName("BulletCrtan");//设置背景透明setAttribute(Qt::WA_TranslucentBackground);//创建播放礼物动效对象QHBoxLayout *layout = new QHBoxLayout(this);layout->setSpacing(0);layout->setContentsMargins(0, 0, 0, 0);m_webpLabel = new QLabel();m_webpLabel->setAlignment(Qt::AlignCenter);m_webpLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);m_webpLabel->setBackgroundRole(QPalette::Shadow);//m_webpLabel->setAutoFillBackground(true);layout->addWidget(m_webpLabel);setLayout(layout);m_webpMovie = new QMovie(this);m_webpMovie->setCacheMode(QMovie::CacheAll);connect(m_webpMovie, &QMovie::frameChanged, this, [=](int frameNumber) {int count = m_webpMovie->frameCount()-1;if(frameNumber == count ){m_webpMovie->stop();m_webpLabel->clear();m_curGiftFinished = true;}});//定时刷新弹幕m_timerReflush = new QTimer(this);connect(m_timerReflush, &QTimer::timeout, this, [=]() {update();});m_timerReflush->setInterval(50);m_timerReflush->start();//随机生成种子 弹幕步进使用qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));//设置字体m_font = new QFont("微软雅黑", 10, 10);m_font->setBold(true);m_font->setPointSize(12);connect(m_webpMovie, &QMovie::finished, this, [=]() {m_webpMovie->stop();m_webpLabel->clear();m_curGiftFinished = true;});//定时检测礼物m_timeGift = new QTimer(this);connect(m_timeGift, &QTimer::timeout, this, [=]() {while (m_giftList.size() && m_curGiftFinished && m_showGift) {playerGift(m_giftList.at(0));m_giftList.removeAt(0);}});m_timeGift->setInterval(100);m_timeGift->start();
}BulletCurtain::~BulletCurtain()
{m_timeGift->stop();delete m_timeGift, m_timeGift = nullptr;m_timerReflush->stop();delete m_timerReflush, m_timerReflush = nullptr;delete m_font, m_font = nullptr;m_webpMovie->stop();delete m_webpLabel, m_webpLabel = nullptr;delete m_webpMovie, m_webpMovie = nullptr;QVector<LPBULLET_CURTAIN_INFO>::iterator it = m_vecInfoQueue.begin();while (it != m_vecInfoQueue.end()){LPBULLET_CURTAIN_INFO &pInfo = *it;if (pInfo) {delete pInfo, pInfo = nullptr;}it++;}m_vecInfoQueue.clear();
}void BulletCurtain::sendBulletCurtain(BULLET_CURTAIN_INFO info)
{if (!m_showBulletCurtain)return;LPBULLET_CURTAIN_INFO drawInfo = new BULLET_CURTAIN_INFO;drawInfo->content = info.content;QFontMetrics metrics(*m_font); //获取弹幕字体可以得到内容占用的x坐标长度metrics.width(info.content);int conentHeight = metrics.height();int yPix = m_currentRow * conentHeight+20;//10 + 30;drawInfo->pt = QPoint(size().width(), yPix);drawInfo->rgba = info.rgba;drawInfo->step = qrand() % 5+4; //随机弹幕步进m_vecInfoQueue.push_back(drawInfo);m_currentRow++;int maxRow = getBulletCurtainMaxRow();if(m_maxRow >0 && m_maxRow < maxRow){maxRow = m_maxRow;}if(m_currentRow >= maxRow)m_currentRow = 0;
}void BulletCurtain::sendGift(const QString &path)
{m_giftList.push_back(path);
}int BulletCurtain::getBulletCurtainMaxRow()
{QFontMetrics metrics(*m_font); metrics.width("TEST ROW");int conentHeight = metrics.height();QSize size = this->size();int maxRow = qAbs(size.height() / conentHeight);return maxRow;
}void BulletCurtain::showMaxCurtainMaxRow(unsigned int maxRow/*=1*/)
{m_maxRow = maxRow;
}void BulletCurtain::showBulletCurtain()
{m_showBulletCurtain = true;
}void BulletCurtain::hideBulletCurtain()
{m_showBulletCurtain = false;m_currentRow = 0;QVector<LPBULLET_CURTAIN_INFO>::iterator it = m_vecInfoQueue.begin();while (it != m_vecInfoQueue.end()){LPBULLET_CURTAIN_INFO &pInfo = *it;if (pInfo) {delete pInfo, pInfo = nullptr;}it++;}m_vecInfoQueue.clear();}void BulletCurtain::showGift()
{m_showGift = true;
}void BulletCurtain::hideGift()
{m_showGift = false;m_giftList.clear();m_webpMovie->stop();m_webpLabel->clear();m_curGiftFinished = true;
}
void BulletCurtain::paintEvent(QPaintEvent * event)
{//弹幕滚屏qDebug() << "bulletcurtain queue size:" << m_vecInfoQueue.size();QVector<LPBULLET_CURTAIN_INFO>::iterator it = m_vecInfoQueue.begin();while (it != m_vecInfoQueue.end()){LPBULLET_CURTAIN_INFO &pInfo = *it;if (!pInfo) {it = m_vecInfoQueue.erase(it);}else {if (!drawText(pInfo)) {delete pInfo, pInfo = nullptr;it = m_vecInfoQueue.erase(it);}else {it++;}}}
}bool BulletCurtain::drawText(LPBULLET_CURTAIN_INFO drawInfo)
{if(drawInfo && m_showBulletCurtain){QPainter painter(this);painter.save();QPen pen(drawInfo->rgba); //自定义画笔的样式,让文字周围有边框QFontMetrics metrics(*m_font); //获取弹幕字体可以得到内容占用的x坐标长度int conentPix = metrics.width(drawInfo->content);//计算X坐标偏移int x = drawInfo->pt.x() - drawInfo->step;if(x+conentPix <0){x = size().width();return false;}painter.setRenderHint(QPainter::Antialiasing);drawInfo->pt.setX(x);painter.setPen(pen);painter.setFont(*m_font);painter.drawText(drawInfo->pt.x(), drawInfo->pt.y(), drawInfo->content);painter.restore();return true;}return false;
}void BulletCurtain::playerGift(const QString &path)
{m_webpMovie->stop();m_webpLabel->clear();m_webpLabel->setMovie(m_webpMovie);m_webpMovie->setFileName(path);m_webpMovie->start();if(m_webpMovie->isValid()){m_curGiftFinished = false;}
}
QT实现弹幕和webp格式礼物动效相关推荐
- 记录一次礼物动效的设计与实现过程
实现礼物动效可以使用ViewGroup的方式也可以使用自定义View的方式.本文使用的是自定义View方式,不会讨论关于ViewGroup的实现方式. 数据模型 数据源列表使用mList 数据源列表使 ...
- 直播间赠送礼物动效、选礼物列表、赠送数量,礼物连发排队处理,Vue项目
1.可以选择送的是礼物列表的哪一个.可以选择送的数量x1x2x3 2.礼物做了排队展示的处理,可以解决礼物连续发送.监听到别人发送礼物接口数据回调的排队问题,不会冲刷掉礼物动效 下面是一个完整的送礼物 ...
- 动效给程序员用什么格式_UI动效敲砖篇
UI其实并不仅仅是静态,还包括动效设计!!!作为一个程序员,每天除了撸各种干燥无味的代码,我觉得大家有必要了解一下这个润滑产品,期间的滋味只有试了的人才懂! 我们这一代人还是清楚移动设备的演化:大哥大 ...
- 动效给程序员用什么格式_动效,一种属于前端程序员的浪漫,无与伦比的体验...
一.初见 动效顾名思义就是动画效果.网页中为什么需要动效呢?简单来说就是为了有趣. 如果把网页和用户的关系比做正在恋爱的情侣,很显然网页的 UI 是颜值,而动效在我看来则是情侣之间的小浪漫.可能和颜值 ...
- 如何让动效又快又好落地?我分析了这5种格式的优缺点
动效设计,可以提升界面的趣味性和引导性,让用户浏览过程中不会太枯燥,获得更好的体验. 最近做的金山知了(后面改名为金山知识库)官网,头图元素加入了缓动效果,第一眼挺新颖的.金山协作新年许愿活动,许愿按 ...
- js svg语音波动动画_让动效更酷炫!4 个常见且常用的 SVG 交互动画方法
本文介绍了 4 种常见的 SVG 交互动画方法,帮你了解 SVG 交互动画的原理和简单方法. 优秀的人机交互和舒适合理的动画,一直是 UX 设计师孜孜不倦追求的目标.但 UX 设计师每天都遇到能做出效 ...
- 怎么用class引入svg_让动效更酷炫!4 个常见且常用的 SVG 交互动画方法
本文介绍了 4 种常见的 SVG 交互动画方法,帮你了解 SVG 交互动画的原理和简单方法. 优秀的人机交互和舒适合理的动画,一直是 UX 设计师孜孜不倦追求的目标.但 UX 设计师每天都遇到能做出效 ...
- 动效素材极速交付: 腾讯PAG动效组件技术揭秘
编者按:音视频产品中的动效素材需求是源源不断的,例如贴纸花字,转场特效,照片和视频模板等,并且对它们的产量,上线速度,以及视觉效果都有比较高的要求.但在传统工作流中的交付成本却非常高,需要通过代码来手 ...
- 499张WEBP格式动漫图片
499张WEBP格式动漫图片 Lan 2020-05-10 19:13 185 人阅读 0 条评论 用处多多,即可当网站背景,还可以配合WE当桌面壁纸 本资源转载于网络,如有问题请联系E- ...
最新文章
- Spark HistoryServer日志解析清理异常
- 机器学习基石13-Hazard of Overfitting
- 【小夕精选】多轮对话之对话管理(Dialog Management)
- Android开发笔记(三十一)SQLite游标及其数据结构
- python怎么读取excel-python 读取 Excel
- 公布中秋福利中奖名单
- fatal error: libmemcached/memcached.h: No such file or directory
- 电脑telnet工具如何开启
- 阻容感基础03:电阻器分类(1)-片式电阻器
- python把两张图片合成一张_怎么合成图片-利用Python将两张图片合成为一张图
- 带你走进springboot
- 源码下载地址及各类资源站点
- 方差分析结果如何看?指标怎么计算?
- 视频号怎么赚钱?视频号有什么功能?
- 探索 nunustudio 开发3D模型 第二弹:根据矢量图制作动画效果
- php js 对象追加元素,JS添加元素新节点
- 高品质回音消除 模块 : F-23
- The Armijo Goldstein line search scheme
- Azure-900【定义云模型】
- C#数字转化为货币金钱格式,元角分。