QML用径向渐变做波纹效果

要做波纹效果,用径向渐变是最简单的。QML中有两个RadialGradient径向渐变,一个是QtGraphicalEffects模块中的,另一个是QtQuick.Shapes模块中的(Shapes是Qt5.10开始引入的模块)。

Effects的径向渐变默认效果就没有锯齿感,Shapes的径向渐变抗锯齿设置更麻烦(暂时还没实现和Effects一样的效果,或许可以配合Shader来实现)。所以实际应用中,这种简单的波纹我准备用QtGraphicalEffects模块的径向渐变。

下面的Demo代码我实现了两个波纹以及一个点击效果(GIF不流畅):

代码有四个文件,使用Qt5.12版本编写及测试

 //ClickWave.qml

import QtQuick 2.12
import QtGraphicalEffects 1.0

Item {
    id: control
    implicitWidth: 100
    implicitHeight: 100
    visible: false
    property double wave_offset: 0.0
    property color wave_color: "red"

    RadialGradient{
        id: gradient
        anchors.fill: parent
        //horizontalRadius: 0
        //verticalRadius: 0
        //horizontalOffset: 0
        //verticalOffset: 0

        gradient: Gradient{
            GradientStop{
                position: (control.wave_offset>0.1)?(control.wave_offset-0.1):0
                color: "transparent"
            }
            GradientStop{ position: control.wave_offset+0.09; color: control.wave_color }
            GradientStop{ position: control.wave_offset+0.11; color: "transparent" }
        }
    }
    PropertyAnimation{
        id: animation
        target: control
        property: "wave_offset"
        from:0
        to:0.4
        duration: 400
        running: false
        onStarted: control.visible=true
        onFinished: control.visible=false
    }

    function click(ptx,pty){
        animation.stop()
        control.x=ptx-control.width/2
        control.y=pty-control.height/2
        animation.start()
    }
}

 //EffectsWave.qml

import QtQuick 2.12
import QtGraphicalEffects 1.0

Item {
    id: control
    implicitWidth: 150
    implicitHeight: 150
    property double wave_offset: 0.0
    property color wave_color: "red"
    property alias running: animation.running

    RadialGradient{
        id: gradient
        anchors.fill: parent
        //horizontalRadius: 0
        //verticalRadius: 0
        //horizontalOffset: 0
        //verticalOffset: 0

        //待改进,根据参数来设置波纹数量
        gradient: Gradient{
            //很遗憾,不能用Repeater
            GradientStop{ position: 0; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.001; color: control.wave_color }
            GradientStop{ position: control.wave_offset+0.01; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.07; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.1; color: control.wave_color }
            GradientStop{ position: control.wave_offset+0.11; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.17; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.2; color: control.wave_color }
            GradientStop{ position: control.wave_offset+0.21; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.27; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.3; color: control.wave_color }
            GradientStop{ position: control.wave_offset+0.31; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.37; color: "transparent" }
            GradientStop{ position: control.wave_offset+0.4; color: control.wave_color }
            GradientStop{ position: control.wave_offset+0.41; color: "transparent" }
        }
    }
    PropertyAnimation{
        id: animation
        target: control
        property: "wave_offset"
        from:0
        to:0.1
        duration: 1000
        running: control.visible
        loops: Animation.Infinite
    }
}

Shape用起来没Effects简单,但功能也更多。还要注意的是,ShapePath要围起来他才会填充,这里我用一个透明边框围了一个矩形框。有一点不同的是,Effects径向范围到0.5就到矩形边上了,Shapes径向范围为1才到矩形边上。

//ShapesWave.qml

import QtQuick 2.12
import QtQuick.Shapes 1.12

Item {
    id: control
    implicitWidth: 150
    implicitHeight: 150
    property double wave_offset: 0.0
    property color wave_color: "red"
    property alias running: animation.running

    Shape {
        anchors.fill: parent
        //这些设置感觉没效果
        //多重采样抗锯齿
        //layer.enabled: true
        //layer.smooth: true
        //layer.samples: 8
        //平滑处理
        //smooth: true
        //反走样抗锯齿
        //antialiasing: true

        ShapePath{
            startX:0
            startY: 0
            strokeColor: "transparent"
            //需要圈起来他才会填充渐变色
            PathLine {x: control.width;y: 0}
            PathLine {x: control.width;y: control.height}
            PathLine {x: 0;y: control.height}
            PathLine {x: 0;y: 0}

            fillGradient: RadialGradient {
                //ShapeGradient.PadSpread	该区域将填充最接近的停止色。
                //ShapeGradient.RepeatSpread	在渐变区域外重复渐变。
                //ShapeGradient.ReflectSpread	渐变会反射到渐变区域之外。
                //spread: ShapeGradient.PadSpread
                centerRadius: control.width/2
                //对于简单的径向渐变,应该将focusRadius设置为0(默认值)
                centerX: control.width/2 //中心
                centerY: control.height/2
                focalX: centerX  //焦点
                focalY: centerY
                //待改进,根据参数来设置波纹数量, 很遗憾,不能用Repeater
                GradientStop{ position: 0; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.001; color: control.wave_color }
                GradientStop{ position: control.wave_offset+0.01; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.15; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.2; color: control.wave_color }
                GradientStop{ position: control.wave_offset+0.21; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.35; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.4; color: control.wave_color }
                GradientStop{ position: control.wave_offset+0.41; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.55; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.6; color: control.wave_color }
                GradientStop{ position: control.wave_offset+0.61; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.75; color: "transparent" }
                GradientStop{ position: control.wave_offset+0.8; color: control.wave_color }
                GradientStop{ position: control.wave_offset+0.81; color: "transparent" }
            }
        }
    }

    PropertyAnimation{
        id: animation
        target: control
        property: "wave_offset"
        from:0
        to:0.2
        duration: 1000
        running: control.visible
        loops: Animation.Infinite
    }
}

 //main.qml

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    visible: true
    width: 720
    height: 520
    title: qsTr("Hello World")

    color: "black"

    EffectsWave{
        width: 200
        height: 200
        x:100
        y:100
    }

    ShapesWave{
        width: 200
        height: 200
        x:300
        y:100
    }

    ClickWave{
        id: click_wave
        width: 100
        height: 100
        x:100
        y: 300
    }

    MouseArea{
        anchors.fill: parent
        onClicked: {
            click_wave.click(mouse.x,mouse.y)
        }
    }
}

(完结~~) 

发布了95 篇原创文章 · 获赞 26 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/gongjianbo1992/article/details/103302740