在位置更新时在QML中使MapQuickItem动画化

问题描述 投票:1回答:1

我有一个QAbstractListModel对象,该对象维护要在地图上显示的项目列表。这些项目的位置每隔几秒钟更改一次,很容易在将来的60秒内计算出非常准确的位置。我要做的是设置物品在获得新位置时的位置(该零件工作正常),然后立即将其移向计算出的将来位置。

没有动画的代码看起来像这样,可以正常工作:

    Component {
       id: drawTarget

       MapQuickItem {
           id: marker

           coordinate: data.coords

           sourceItem: Item {
               id: item
               ...

data对象具有一个属性,该属性在将来60秒内返回该项目的估计位置,因此我尝试了此操作:

    Component {
       id: drawTarget

       MapQuickItem {
           id: marker

           coordinate: data.coords

           CoordinateAnimation {
               id:anim
               property: "coordinate"
           }

           onCoordinateChanged: {
               anim.stop()
               anim.from = data.coords
               anim.to = data.coordsIn60sec
               anim.duration = 60000
               anim.start()
           }           

           sourceItem: Item {
               id: item
               ...

但是,尽管在每次位置更新时都会正确更新对象的位置,但是指向将来估计位置的动画完全不起作用。

人们将如何做这样的事情?

qt animation qml coordinates
1个回答
1
投票

在其代码中,它制作了一个绑定coordinate: data.coords,其中指出“坐标”采用“坐标”的值,但同时又说“坐标”取决于动画,这不是矛盾的吗?好吧,这是矛盾的。

这个想法不是执行绑定coordinate: data.coords,而是仅通过动画来更新属性。

以下代码是可行的示例:

main.qml

import QtQuick 2.14
import QtQuick.Window 2.14
import QtLocation 5.6
import QtPositioning 5.6

Window {
    visible: true
    width: 640
    height: 480
    Plugin {
        id: mapPlugin
        name: "osm"
    }
    Map {
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(59.91, 10.75) // Oslo
        zoomLevel: 10
        MapItemView{
            model: datamodel
            delegate: MapQuickItem{
                id: item
                // begin configuration
                property var position: model.position
                property var nextposition: model.nextposition
                onPositionChanged: restart();
                onNextpositionChanged: restart();
                function restart(){
                    anim.stop()
                    anim.from = position
                    anim.to = nextposition
                    anim.start()
                }
                CoordinateAnimation {
                    id: anim
                    target: item
                    duration: 60 * 1000
                    property: "coordinate"
                }
                // end of configuration
                anchorPoint.x: rect.width/2
                anchorPoint.y: rect.height/2
                sourceItem: Rectangle{
                    id: rect
                    color: "green"
                    width: 10
                    height: 10
                }
            }
        }
    }
}

datamodel.h

#ifndef DATAMODEL_H
#define DATAMODEL_H

#include <QAbstractListModel>
#include <QGeoCoordinate>
#include <QTimer>
#include <random>

#include <QDebug>

struct Data{
    QGeoCoordinate position;
    QGeoCoordinate nextposition;
};

static QGeoCoordinate osloposition(59.91, 10.75); // Oslo;

class DataModel : public QAbstractListModel
{
    Q_OBJECT
    QList<Data> m_datas;
public:
    enum PositionRoles {
        PositionRole = Qt::UserRole + 1,
        NextPositionRole
    };
    explicit DataModel(QObject *parent = nullptr)
        : QAbstractListModel(parent)
    {
        init();
    }
    int rowCount(const QModelIndex &parent = QModelIndex()) const override{
        return parent.isValid() ? 0: m_datas.count();
    }
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
        if (!index.isValid() || index.row() < 0 || index.row() >= m_datas.count())
            return QVariant();
        const Data &data = m_datas[index.row()];
        if (role == PositionRole)
            return QVariant::fromValue(data.position);
        else if (role == NextPositionRole)
            return QVariant::fromValue(data.nextposition);
        return QVariant();
    }
    QHash<int, QByteArray> roleNames() const override{
        QHash<int, QByteArray> roles;
        roles[PositionRole] = "position";
        roles[NextPositionRole] = "nextposition";
        return roles;
    }
private:
    void init(){
        for(int i=0; i< 10; ++i){
            Data data;
            data.position = osloposition;;
            data.nextposition = data.position;
            m_datas << data;
        }
        QTimer *timer = new QTimer(this);
        QObject::connect(timer, &QTimer::timeout, this, &DataModel::updateData);
        timer->start(60 * 1000);
        updateData();
    }
    void updateData(){
        qDebug() << __PRETTY_FUNCTION__;
        static std::default_random_engine e;
        static std::uniform_real_distribution<> dis(-.1, .1);
        for(int i=0; i < m_datas.count(); ++i){
            Data & data = m_datas[i];
            QModelIndex ix = index(i);
            data.position = data.nextposition;
            data.nextposition = QGeoCoordinate(osloposition.latitude() + dis(e),
                                           osloposition.longitude() + dis(e));
            Q_EMIT dataChanged(ix, ix, {PositionRole, NextPositionRole});
        }
    }
};

#endif // DATAMODEL_H

以下link是完整示例

© www.soinside.com 2019 - 2024. All rights reserved.