Search code examples
cssqtanimationqmlqt-quick

How can we make an element animate with glow pulsating effect in QML?


I have a css action which I want to replicate in qml, How can I make a button (or any other element) animate in QML to have a pulsating effect, like the following CSS:

@import "bourbon";

$n:6;
$w:20px;//dot size
$e:4;//dot margin factor
$hsl:160;//start color
$bg:#333;

html{
    background:$bg;
  height: 100%;
  backface-visibility: hidden;
}   

#c{
    position: absolute;
    top:50%;
    left:50%;   
    margin-left: -(($n - 1)*($w + $w*$e))/2 - ($w/2);
}

@mixin shadow($b,$s,$sm,$c){
    box-shadow:
        0 0 8px 6px $c,
        0 0 $b $s $bg,
        0 0 $b ($s + $sm) $c;
}

.s{
    width: $w;
    height: $w;
    border-radius: 50%;
    cursor:pointer;
    float: left;
  @include transition(all .2s);
    &:nth-child(n+2){
        margin-left: $w*$e;
    }
}   
    
@for $i from 0 to $n {
    $c:hsl($hsl+(10*$i),100%,55%);
  $c2:hsl((6*$i),100%,55%);
    
    .s:nth-child(#{$i+1}){          
        background: lighten($c,5%); 
        @include animation(r+$i 2s ($i/4)+s ease-out  infinite);         &:hover{
      background: lighten($c2,5%);      
      @include animation(r2+$i .5s .4s  ease-out  infinite);
    }
    }
    @include keyframes(r+$i) {
    0%{@include shadow(0px,0px,0px,rgba($c,0));}
        10%{@include shadow(12px,10px,4px,$c);}
        100%{@include shadow(0px,40px,0px,rgba($c,0));}
    }
  @include keyframes(r2+$i) {
        from{@include shadow(12px,10px,4px,$c2);}
        to{@include shadow(4px,40px,1px,rgba($c2,0));}
    }
}

I have tried using StyleEngine and external css till now, but it didn't workout for me!


Solution

  • You can animate gradient to make some glow effect. Since 5.10 there is RadialGradient so you can use it for that. I'm not good in painting but the idea as the folowing:

    import QtQuick 2.10
    import QtQuick.Window 2.2
    import QtQuick.Shapes 1.0
    
    Window {
        id: window
        title: "Test"
        visible: true
        width: 400
        height: 400
    
        Shape {
            width: 100
            height: 100
            anchors.centerIn: parent
            ShapePath {
                strokeWidth: 2
                strokeColor: "transparent"
                startX: 50; startY: 0
    
                fillGradient: RadialGradient {
                    id: gradient
                    property real pos: 0.3
                    centerX: 50;
                    centerY: 50
                    centerRadius: 50
                    focalX: centerX; focalY: centerY
                    GradientStop { position: 0; color: "#33ffbb" }
                    GradientStop { position: 0.2; color: "#33ffbb" }
                    GradientStop { position: 0.25; color: "transparent" }
                    GradientStop { position: gradient.pos - 0.1; color: "transparent" }
                    GradientStop { position: gradient.pos; color: "#33ffbb" }
                    GradientStop { position: gradient.pos + 0.1; color: "transparent" }
                }
                PathArc {
                    x: 50
                    y: 100
                    radiusX: 50
                    radiusY: 50
                    useLargeArc: true
                }
                PathArc {
                    x: 50
                    y: 0
                    radiusX: 50
                    radiusY: 50
                    useLargeArc: true
                }
            }
    
            PropertyAnimation {
                target: gradient
                property: "pos"
                from: 0.3
                to: 0.9
                duration: 1500
                loops: Animation.Infinite
                easing.type: Easing.OutQuad
                running: true
            }
        }
    }
    

    You can play with values to get the effect close to your example.