模仿echarts的迁徙图效果
用到了前2篇制作的散点(涟漪效果)和两年前的路径动画类;然尾迹效果未依附路径,有待优化。
动态演示效果
静态展示图片
核心代码
#pragma once
#include "Item/AbstractGeoItem.h"
#include "DataStruct/GeoData.h"
/*
* 迁徙图-移动图元
*/
class QWHAnimationPath;
class MigrationMoveItem : public AbstractGeoItem
{
public:
explicit MigrationMoveItem(const GeoCoord ¢er, const GeoCoord &target, QGraphicsItem *parent = nullptr);
~MigrationMoveItem();
// 更新地理位置
virtual void updateGeoPos();
// 设置路径位置百分比
void setPercent(qreal percent);
protected:
virtual QRectF boundingRect() const override;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
private:
void updatePath();
private:
GeoCoord m_targetPos;
QWHAnimationPath *m_animatePath;
};
#include "MigrationMoveItem.h"
#include <QPainterPath>
#include <QPainter>
#include <QtMath>
#include <QLinearGradient>
#include "Utility/QWHAnimationPath.h"
MigrationMoveItem::MigrationMoveItem(const GeoCoord ¢er, const GeoCoord &target, QGraphicsItem *parent /*= nullptr*/)
: AbstractGeoItem(parent)
{
setZValue(302);
m_lon = center.lon;
m_lat = center.lat;
m_targetPos = target;
m_animatePath = new QWHAnimationPath(false);
m_animatePath->setType(QWHAnimationPath::SLOPE);
m_animatePath->setTarget(QWHAnimationPath::ITEM);
m_animatePath->setItem(this);
updatePath();
}
MigrationMoveItem::~MigrationMoveItem()
{
}
void MigrationMoveItem::updateGeoPos()
{
updatePath();
}
void MigrationMoveItem::setPercent(qreal percent)
{
m_animatePath->setCurPercent(percent);
}
QRectF MigrationMoveItem::boundingRect() const
{
return QRectF(-20, -20, 40, 100);
}
void MigrationMoveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
// 飞机
QPainterPath path;
path.moveTo(0, -20);
path.lineTo(-4, -16);
path.lineTo(-4, -4);
path.lineTo(-20, 4);
path.lineTo(-4, 4);
path.lineTo(-4, 16);
path.lineTo(-8, 20);
path.lineTo(8, 20);
path.lineTo(4, 16);
path.lineTo(4, 4);
path.lineTo(20, 4);
path.lineTo(4, -4);
path.lineTo(4, -16);
path.closeSubpath();
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::green);
painter->drawPath(path);
// 尾迹
QPainterPath path2;
path2.moveTo(-4, 20);
path2.lineTo(0, 60);
path2.lineTo(0, 60);
path2.lineTo(4, 20);
QLinearGradient lg(0, 20, 0, 60);
lg.setColorAt(0, Qt::white);
lg.setColorAt(1, Qt::transparent);
painter->setBrush(lg);
painter->drawPath(path2);
}
void MigrationMoveItem::updatePath()
{
QPainterPath path;
QPointF centerPos = sceneCoordFromGeoCoord(m_lon, m_lat);
QPointF targetPos = sceneCoordFromGeoCoord(m_targetPos.lon, m_targetPos.lat);
QPointF pos = targetPos - centerPos;
double k = qAtan2(-pos.y(), pos.x());
double cx = 0.5 * (centerPos.x() + targetPos.x());
double cy = 0.5 * (centerPos.y() + targetPos.y());
double ctrlx = cx - qCos(M_PI / 2 - k) * 70;
double ctrlY = cy - qSin(M_PI / 2 - k) * 70;
path.moveTo(centerPos);
path.quadTo(QPointF(ctrlx, ctrlY), targetPos);
m_animatePath->setPath(path);
}