j123b567
j123b567

Reputation: 3439

QML continuouse infinite moving text

I need to implement infinite moving text but before it wraps around, same text should be displayed at the end.

There is already a solved question QML Moving text with timer, but my problem is different.

Example:

My text is "some text" and I want achive animation like this

Frame    I need this     Regular NumberAnimation
0        |some text |    |some text |
10       |ome text  |    |ome text  |
20       |me text   |    |me text   |
30       |e text   s|    |e text    |
40       | text   so|    | text     |
50       |text   som|    |text      |
60       |ext   some|    |ext       |
70       |xt   some |    |xt        |
80       |t   some t|    |t         |
90       |   some te|    |          |
100      |  some tex|    |         s|
110      | some text|    |        so|
120      |some text |    |       som|
130      |ome text  |    |      some|
140      |me text   |    |     some |
150      |e text   s|    |    some t|
160      | text   so|    |   some te|
170      |text   som|    |  some tex|
180      |ext   some|    | some text|
190      |xt   some |    |some text |
200      |t   some t|    |ome text  |

Is there an easy way how to do this in QML?

Upvotes: 4

Views: 3377

Answers (1)

dtech
dtech

Reputation: 49289

You can do it without any animation whatsoever, simply compose the display string by cutting the source string at a specific step:

  Item {
    property string text: "some text"
    property string spacing: "      "
    property string combined: text + spacing
    property string display: combined.substring(step) + combined.substring(0, step)
    property int step: 0

    Timer {
      interval: 200
      running: true
      repeat: true
      onTriggered: parent.step = (parent.step + 1) % parent.combined.length
    }

    Text {
      text: parent.display
    }
  }

This is lighter than doing position animation, plus it has a more "organic" look IMO.

But if you still insist on animation, you can simply have two text elements in a row to fake wrapping over. But that will be heavier than the previous solution, as it will involve many more reevaluations for sub-pixel animation, two text elements and also the graphics clipping that will be necessary to hide the "offscreen" text:

  Item {
    id: root
    property alias text: t1.text
    property int spacing: 30
    width: t1.width + spacing
    height: t1.height
    clip: true

    Text {
      id: t1
      text: "some text"
      NumberAnimation on x { running: true; from: 0; to: -root.width; duration: 3000; loops: Animation.Infinite }

      Text {
        x: root.width
        text: t1.text
      }
    }
  }

The two implementations side by side:

enter image description here

Upvotes: 11

Related Questions