QGraphicsView实现简易地图19『迁徙图』

发布于:2024-06-02 ⋅ 阅读:(90) ⋅ 点赞:(0)

模仿echarts的迁徙图效果
用到了前2篇制作的散点(涟漪效果)和两年前的路径动画类;然尾迹效果未依附路径,有待优化。
动态演示效果

静态展示图片
在这里插入图片描述

核心代码

#pragma once
#include "Item/AbstractGeoItem.h"
#include "DataStruct/GeoData.h"

/*
 * 迁徙图-移动图元
 */

class QWHAnimationPath;

class MigrationMoveItem : public AbstractGeoItem
{
public:
	explicit MigrationMoveItem(const GeoCoord &center, 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 &center, 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);
}