Play animated SVG with QML

Viewed 3552

I would like to play an animated SVG file with QML. I already tried AnimatedImage, but SVG stays static and is not animated.

AnimatedImage {
      id: loader
      source: "qrc:/Assets/Images/loader"
      height: 30
      width: 30
}

Any advice would be highly appreciated, thank you.

2 Answers

While I couldn't find a way to do this purely in QML, I got it to work with a custom QML type defined in C++ as described here.

import Svg 1.0

    Svg{
        width:50
        height:50
        file: ":/res/icons/spinning.svg"
    }

in C++

//svg.h
class Svg : public QQuickPaintedItem {
    Q_OBJECT
    Q_PROPERTY(QString file READ file WRITE setFile NOTIFY fileChanged)
    QML_ELEMENT

   public:
    explicit Svg(QQuickItem* parent = 0);
    void paint(QPainter* painter) override;
    const QString& file();

   public slots:
    void setFile(const QString& filepath);

   signals:
    void fileChanged(const QString& filepath);

   private:
    QSvgRenderer* m_renderer;
    QTimer* m_timer;
    QString m_path;
    int m_refreshRate;
};

// svg.cpp
#include <svg.h>

Svg::Svg(QQuickItem *parent) : QQuickPaintedItem(parent) {
    m_refreshRate = 1 / 60 * 1000;  // 60hz
    setAntialiasing(true);

    m_timer = new QTimer{this};
    connect(m_timer, &QTimer::timeout, [this] {
        if (m_renderer->isValid()) {
            update(boundingRect().toRect());
        }
    });        
}

void Svg::paint(QPainter *painter) { m_renderer->render(painter); }

const QString &Svg::file() { return m_path; }

void Svg::setFile(const QString &path) {
    m_path = path;
    m_renderer = new QSvgRenderer(path, this);
    emit fileChanged(path);
    m_timer->start(m_refreshRate);
}

In .pro file add the following:

QT += svg
CONFIG += qmltypes
QML_IMPORT_NAME = Svg
QML_IMPORT_MAJOR_VERSION = 1
Related