qml animation trail on object



  • I'm trying to leave a trail behind an image that's moved from one position to the next, similar to when swipe keyboard when you drag your finger from one spot to the next. Basically I want a way to show where an object has been. I'm only moving the image (which is just a dot so I could change it to a Ellipse) in a horizontal line so it shouldn't be too hard.

    I've looked at using a ParticleSystem, a TrailEmitter and adjusting gravity to pull the particles to where I want them but the TrailEmitter only seems to work until the particle gets to the first gravity spot. There is no subsequent trail when moving to the next gravity spot.

    I feel like there should be an easier way than having two ellipses with a rectangle in between and having a changing the opaque level based on position.

    Cheers.



  • I once played around trying to create an old phosphor oscilloscope look...

    I came up with this:
    scope
    although it does look better in its native 60FPS than as a captured GIF.

    Tricks I used:

    • Rendering a line rather than a dot (otherwise you just end up with a collection of dots).
    • Recursive shader to fade the trail with time.
    • Bit of Glow effect to stop it looking too much like a jagged collection of line segments.

    Maybe some ideas can be used to get whatever look you're trying to get.

    Code (runs in Qt 5.9.1's qmlscene on OSX):

    import QtQuick 2.2
    import QtGraphicalEffects 1.0
    
    Item {
      id: main
      width: 640
      height: 480
    
      Rectangle {
        id: bg
        anchors.fill: parent
        color: '#50593a'
        visible: false
      }
    
      Rectangle
      {
        id: phosphor
        anchors.fill: parent
        color: '#00000000'
    
        property real timebase: 0.0
    
        NumberAnimation on timebase {
          duration: 1000
          from: 0.0
          to: 1.0
          loops: Animation.Infinite
        }
    
        onTimebaseChanged: trace.advance(timebase)
    
        Item {
          id: trace
          anchors.fill: parent
    
          property real cycles: 0.0
          property real noise: 0.0
    
          function advance(t) {
            if (t<spot.x1) cycles+=1.0
            spot.x0=spot.x1
            spot.x1=t
    
            var signal=0.2+0.6*Math.pow(0.5+0.5*Math.cos(2.0*Math.PI*(cycles+t)*0.8),16)
            noise+=(Math.random()-0.5)*0.01-0.01*noise
    
            spot.y0=spot.y1
            spot.y1=1.0-signal-noise
          }
    
          ShaderEffect {
            id: spot
            anchors.fill: parent
            blending: true
    
            property real x1: 0.0
            property real y1: 0.0
            property real x0: 0.0
            property real y0: 0.0
            property color col: '#7fffa7'
    
            vertexShader: "
              uniform highp mat4 qt_Matrix;
              attribute highp vec4 qt_Vertex;
              attribute highp vec2 qt_MultiTexCoord0;
              varying highp vec2 coord;
              void main() {
                coord=qt_MultiTexCoord0;
                gl_Position=qt_Matrix*qt_Vertex;
              }"
            fragmentShader: "
              uniform highp float x0;
              uniform highp float y0;
              uniform highp float x1;
              uniform highp float y1;
              uniform lowp vec4 col;
              varying highp vec2 coord;
              void main() {
                highp float k=1.0/distance(vec2(x1,y1),vec2(x0,y0));
                highp float r=0.0001+0.00005*k;
                highp vec2 n=normalize(vec2(x1,y1)-vec2(x0,y0));
                highp float p=dot(coord,n)-dot(vec2(x0,y0),n);
                highp float q=p*k;
                highp float d=distance(coord,vec2(x0,y0)+p*n);
                highp float d0=distance(coord,vec2(x0,y0));
                highp float d1=distance(coord,vec2(x1,y1));
                if (x1<x0)
                  gl_FragColor=vec4(0.0,0.0,0.0,0.0);
                else if (0.0<=q && q<=1.0 && d<r)
                  gl_FragColor=col*(1.0-d/r);
                else if (q<0.0 && d0<r)
                  gl_FragColor=col*(1.0-d/r);
                else if (q>1.0 && d1<r)
                  gl_FragColor=col*(1.0-d/r);
                else
                  gl_FragColor=vec4(0.0,0.0,0.0,0.0);
              }"
          }
        }
        ShaderEffectSource {
          id: base
          anchors.fill: parent
          live: true
          sourceItem: trace
          hideSource: true
        }
    
        ShaderEffectSource {
          id: buffer
          anchors.fill: parent
          live: true
          recursive: true
          sourceItem: buffer
          wrapMode: ShaderEffectSource.ClampToEdge
          smooth: false
    
          ShaderEffect {
            anchors.fill: parent
            blending: false
            property variant src0: buffer
            property variant src1: base
            vertexShader: "
              uniform highp mat4 qt_Matrix;
              attribute highp vec4 qt_Vertex;
              attribute highp vec2 qt_MultiTexCoord0;
              varying highp vec2 coord;
              void main() {
                coord=qt_MultiTexCoord0;
                gl_Position=qt_Matrix*qt_Vertex;
              }"
            fragmentShader: "
              uniform sampler2D src0;
              uniform sampler2D src1;
              varying highp vec2 coord;
              void main() {
                highp vec4 src0=texture2D(src0,coord);
                highp vec4 src1=texture2D(src1,coord);
                gl_FragColor=floor(255.0*0.975*src0)/255.0+src1;
              }"
          }
        }
      }
    
    
      Glow {
        id: glow
        anchors.fill: parent
        radius: 16
        samples: 32
        spread: 0.75
        color: '#7fffa7'
        source: phosphor
      }
    
      Blend {
        anchors.fill: parent
        source: bg
        foregroundSource: glow
        mode: 'addition'
      }
    
      Grid {
        id: graticule
        columns: 8
        rows: 6
        spacing: 0
        Repeater {
          model: parent.rows*parent.columns
          Rectangle {
            width: 80
            height: 80
            color: '#00000000'
            border.width: 1
            border.color: '#66000000'
          }
        }
      }
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.