














地图组件中标注点在所有覆盖物中,使用场景是最大的,就是在地图上显示个图片图标,然后可以显示提示文字信息,这个标注点还可以轨迹移动,轨迹回放和实时轨迹都要用到这个覆盖物,所以涉及一个尽可能满足现有各种需求场景的类非常重要,最开始的时候做的很简单,就是绘制一个图片,在Qt中直接用qpainter的drawimage即可,这里涉及到一个问题,有些图标是水滴状,有些是圆形的,一般来说,用户希望的是水滴状的显示在坐标的顶部,圆形的图标显示在坐标的中间,甚至还有些其他的图标,这样展示会显示的更合理。于是多了一个参数,需要设置图片在位置的哪个方位,支持左侧、右侧、上侧、下侧、中间、左上角、右上角、左下角、右下角共9个位置,这样涵盖了所有可能的情况。
有了图标还是不够的,一般还需要有提示文本,这个提示文本也需要有9个方位可控,然后就是支持背景颜色和透明度,一般来说是半透明更好看,还支持边框颜色和粗细设置。当然还包括字体名称和大小的参数。后面发现尽管是在对应位置绘制的文本,靠的太近也不大好看,还增加文本位置的偏移值参数,也就是尽量离图标远一点,不要紧挨着。写完所有的参数,专门做了个标注的示例,可以动态调整各个参数。

#include "overlaymarker.h"
OverlayMarker::OverlayMarker(qreal lng, qreal lat, int zoom_min, int zoom_max)
: OverlayShape(lng, lat, QSizeF(0, 0), zoom_min, zoom_max)
{
m_movie = NULL;
this->setOverlayType(OverlayType_Marker);
}
OverlayMarker::~OverlayMarker()
{
this->stop();
}
QPixmap OverlayMarker::image() const
{
return m_image;
}
void OverlayMarker::setImage(const QPixmap &image)
{
m_image = image;
this->setSizePx(m_image.size());
}
void OverlayMarker::setImage(const QString &filename, const QPixmap &image)
{
//存在文件路径则优先取文件
if (!filename.isEmpty()) {
this->stop();
this->setImage(QPixmap(filename));
//如果是动图则取出每一帧进行绘制
if (filename.endsWith(".gif")) {
m_movie = new QMovie(filename);
connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged(int)));
m_movie->start();
}
} else if (!image.isNull()) {
this->stop();
this->setImage(image);
}
}
void OverlayMarker::draw(QPainter *painter, const RectWorldCoord &backbuffer_rect, int cur_zoom)
{
//先判断是否在主图画布的区域里面
RectWorldCoord pixmap_rect_coord(boundingBox(cur_zoom));
if (backbuffer_rect.rawRect().intersects(pixmap_rect_coord.rawRect())) {
//计算标注点图片绘制区域
PointWorldPx top_left = getPointPx(pixmap_rect_coord.topLeftCoord(), cur_zoom);
PointWorldPx bottom_right = getPointPx(pixmap_rect_coord.bottomRightCoord(), cur_zoom);
RectWorldPx pixmap_rect_px(top_left, bottom_right);
QRectF pixmap_rect = pixmap_rect_px.rawRect();
QPointF pixmap_center = pixmap_rect_px.centerPx().rawPoint();
QPointF pixmap_point = QPointF(-pixmap_rect.width() / 2.0, -pixmap_rect.height() / 2.0);
//平移坐标系/绘制标注点图片
painter->translate(pixmap_center);
painter->rotate(rotation());
painter->drawPixmap(pixmap_point, m_image);
//图标所在区域
//painter->fillRect(QRectF(pixmap_point, sizePx()), Qt::red);
//恢复坐标系
painter->rotate(-rotation());
painter->translate(-pixmap_center);
//绘制显示的文本
if (!m_text.isEmpty()) {
QSizeF text_size = OverlayShape::initText(painter);
this->drawText(painter, pixmap_rect, text_size, m_text);
}
//绘制编辑状态
if (m_edit) {
this->drawHand(painter, m_point_coord, cur_zoom);
}
}
}
void OverlayMarker::stop()
{
if (m_movie) {
m_movie->deleteLater();
m_movie = NULL;
}
}
void OverlayMarker::frameChanged(int)
{
//取出动图的每一张图片
m_image = m_movie->currentPixmap();
emit requestRedraw();
}
OverlayBase *OverlayHelper::addMarker(MapWidget *map, const QString &flag, const QPointF &point, const QString &image, const QPixmap &pixmap, int rotate, int align)
{
OverlayMarker *marker = new OverlayMarker(point.x(), point.y());
marker->setOverlayFlag(flag);
marker->setImage(image, pixmap);
marker->setRotation(rotate);
marker->setAlignType(AlignType(align));
map->addOverlay(marker, redraw);
return marker;
}
void OverlayHelper::updateMarker(OverlayBase *overlay, const QPointF &point, const QString &image, const QPixmap &pixmap, int rotate, int align)
{
OverlayMarker *marker = (OverlayMarker *)overlay;
OverlayHelper::updateColor(marker, QColor(), 0);
marker->setImage(image, pixmap);
if (!point.isNull()) {
marker->setCoord(PointWorldCoord(point.x(), point.y()));
}
if (rotate >= 0) {
marker->setRotation(rotate);
}
if (align >= 0) {
marker->setAlignType(AlignType(align));
}
}
void OverlayHelper::updateMarker(MapWidget *map, const QString &flag, const QPointF &point, const QString &image, const QPixmap &pixmap, int rotate, int align)
{
foreach (OverlayBase *overlay, map->getOverlays()) {
if (overlay->overlayFlag() == flag && overlay->overlayType() == OverlayType_Marker) {
OverlayHelper::updateMarker(overlay, point, image, pixmap, rotate, align);
}
}
}
QPointF OverlayHelper::getMarkerPara(OverlayBase *overlay, QPixmap *image, int *rotate, int *align)
{
OverlayMarker *marker = (OverlayMarker *)overlay;
if (image) {
(*image) = marker->image();
}
if (rotate) {
(*rotate) = marker->rotation();
}
if (align) {
(*align) = (int)marker->alignType();
}
return marker->coord().rawPoint();
}
QPointF OverlayHelper::getMarkerPara(MapWidget *map, const QString &flag, QPixmap *image, int *rotate, int *align)
{
QPointF coord;
foreach (OverlayBase *overlay, map->getOverlays()) {
if (overlay->overlayFlag() == flag && overlay->overlayType() == OverlayType_Marker) {
coord = OverlayHelper::getMarkerPara(overlay, image, rotate, align);
break;
}
}
return coord;
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。