前文链接:QGraphicsView实现简易地图15『测量面积』
一种简单的爆炸波扩散效果
动态演示效果:
静态展示图片:
核心代码:
#pragma once
#include "../AbstractGeoItem.h"
#include "DataStruct/GeoData.h"
/*
* 爆炸扩散效果-静态
*/
class ExplosiveDiffusionItem : public AbstractGeoItem
{
public:
ExplosiveDiffusionItem(const GeoCoord &geoCoord, int radius, QGraphicsItem *parent = nullptr);
~ExplosiveDiffusionItem();
// 更新地理位置
virtual void updateGeoPos();
protected:
virtual QRectF boundingRect() const override;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
// 设置半径(单位:米)
void setRadius(int radius);
// 获取半径(单位:米)
int radius();
protected:
int m_radius; // 半径(单位:米)
double m_rw; // 基于指定经纬度处的椭圆横轴半径
double m_rh; // 基于指定经纬度处的椭圆竖轴半径
};
#include "ExplosiveDiffusionItem.h"
#include <QRadialGradient>
#include <QPainter>
#include "Utility/MapUtility.h"
ExplosiveDiffusionItem::ExplosiveDiffusionItem(const GeoCoord &geoCoord, int radius, QGraphicsItem *parent /*= nullptr*/) : AbstractGeoItem(parent)
{
setZValue(300);
setGeoPos(geoCoord.lon, geoCoord.lat);
m_radius = radius;
}
ExplosiveDiffusionItem::~ExplosiveDiffusionItem()
{
}
void ExplosiveDiffusionItem::updateGeoPos()
{
AbstractGeoItem::updateGeoPos();
prepareGeometryChange();
}
QRectF ExplosiveDiffusionItem::boundingRect() const
{
return QRectF(-m_rw, -m_rh, 2 * m_rw, 2 * m_rh);
}
void ExplosiveDiffusionItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QRadialGradient gr(0, 0, m_rw, 0, 0);
gr.setColorAt(0.0, QColor(255, 255, 255, 0));
gr.setColorAt(0.90, QColor(255, 255, 255, 10));
gr.setColorAt(0.94, QColor(255, 255, 255, 40));
gr.setColorAt(0.99, QColor(185, 225, 240, 255));
gr.setColorAt(1, QColor(185, 225, 240, 128));
painter->setRenderHint(QPainter::Antialiasing);
painter->setBrush(gr);
painter->setPen(Qt::NoPen);
painter->drawEllipse(boundingRect());
}
void ExplosiveDiffusionItem::setRadius(int radius)
{
m_radius = radius;
GeoCoord right = MapUtility::geoCoordByDisAndBearing(m_lon, m_lat, 90, m_radius);
GeoCoord top = MapUtility::geoCoordByDisAndBearing(m_lon, m_lat, 0, m_radius);
QPointF rightPos = sceneCoordFromGeoCoord(right.lon, right.lat);
QPointF topPos = sceneCoordFromGeoCoord(top.lon, top.lat);
QPointF centerPos = sceneCoordFromGeoCoord(m_lon, m_lat);
m_rw = rightPos.x() - centerPos.x();
m_rh = centerPos.y() - topPos.y();
prepareGeometryChange();
}
int ExplosiveDiffusionItem::radius()
{
return m_radius;
}
此处提供的动态效果,是利用QPropertyAnimation制作而成,后面文章的动态效果也是采用这种方法,后续将不再展示代码,参考此处即可。
#pragma once
#include "ExplosiveDiffusionItem.h"
/*
* 爆炸扩散效果-动态扩散
*/
class QPropertyAnimation;
class ExplosiveDiffusionAnimateItem : public QObject, public ExplosiveDiffusionItem
{
Q_OBJECT
Q_PROPERTY(int m_radius WRITE setRadius READ radius)
public:
ExplosiveDiffusionAnimateItem(const GeoCoord &geoCoord, int radius, QGraphicsItem *parent = nullptr);
~ExplosiveDiffusionAnimateItem();
void start(int msecs = 1000);
private:
QPropertyAnimation *m_animation;
};
#include "ExplosiveDiffusionAnimateItem.h"
#include <QPropertyAnimation>
ExplosiveDiffusionAnimateItem::ExplosiveDiffusionAnimateItem(const GeoCoord &geoCoord, int radius, QGraphicsItem *parent /*= nullptr*/)
: ExplosiveDiffusionItem(geoCoord, radius, parent)
{
m_animation = new QPropertyAnimation(this, "m_radius", this);
m_animation->setEasingCurve(QEasingCurve::InOutQuad);
connect(m_animation, &QAbstractAnimation::finished, this, &ExplosiveDiffusionAnimateItem::finished);
}
ExplosiveDiffusionAnimateItem::~ExplosiveDiffusionAnimateItem()
{
}
void ExplosiveDiffusionAnimateItem::start(int msecs/* = 1000*/)
{
if (m_animation->state() != QAbstractAnimation::Stopped)
m_animation->stop();
m_animation->setDuration(msecs);
m_animation->setStartValue(0);
m_animation->setEndValue(m_radius);
m_animation->start();
}