C

Qt Quick Ultralite Motorcycle Cluster Demo

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial
import QtQuick 2.4
import QtQuickUltralite.Extras 2.0

Item {
    id: root
    property int rpm: 0
    property int gear: 0
    width: 228
    height: 228

    property bool active
    property bool isDayMode

    property color circlesColor: gear === 0 ? Style.neutralGreen : (root.rpm > 13000 ? Style.red : Style.neutralGreen)
    property color ringsColor: Style.white
    property color backgroundColor: gear === 0 ? backgroundColorForNeutral : (root.rpm > 13000 ? Style.red : Style.normalGreen)
    property color fontColor: gear == 0 ? fontColorNeutral : Style.white

    property string gearTextVal: gear == 0 ? "N" : gear
    property color backgroundColorForNeutral: Style.neutralGreen
    property color fontColorNeutral: Style.white

    property image holeInBackgroundImg: "qrc:///images/fuelGauge/hole-in-bg-day.png"
    property image gradientCircleImg: "qrc:///images/fuelGauge/fuel-colored-circle.png"

    states: [
        State {
            name: "dayMode"
            when: isDayMode === true
            PropertyChanges {
                target: root
                holeInBackgroundImg: "qrc:///images/fuelGauge/hole-in-bg-day.png"
            }
            PropertyChanges {
                target: root
                backgroundColorForNeutral: Style.white
            }
            PropertyChanges {
                target: root
                ringsColor: Style.black
            }
            PropertyChanges {
                target: root
                fontColorNeutral: Style.black
            }
            PropertyChanges {
                target: root
                gradientCircleImg: "qrc:///images/fuelGauge/fuel-colored-circle-day.png"
            }

            PropertyChanges {
                target: background
                opacity: 1
            }
            PropertyChanges {
                target: holeInBackground
                opacity: 1
            }
            PropertyChanges {
                target: gradientCircle
                opacity: 1
            }
        },
        State {
            name: "nightMode"
            when: isDayMode !== true
            PropertyChanges {
                target: root
                holeInBackgroundImg: "qrc:///images/fuelGauge/hole-in-bg.png"
            }
            PropertyChanges {
                target: root
                backgroundColorForNeutral: Style.neutralGreen
            }
            PropertyChanges {
                target: root
                ringsColor: Style.white
            }
            PropertyChanges {
                target: root
                fontColorNeutral: Style.white
            }
            PropertyChanges {
                target: root
                gradientCircleImg: "qrc:///images/fuelGauge/fuel-colored-circle.png"
            }

            PropertyChanges {
                target: background
                opacity: 1
            }
            PropertyChanges {
                target: holeInBackground
                opacity: 1
            }
            PropertyChanges {
                target: gradientCircle
                opacity: 1
            }
        }
    ]

    transitions: [
        Transition {
            SequentialAnimation {
                id: dayModeAnimation
                ParallelAnimation {
                    NumberAnimation {
                        target: background
                        duration: 300
                        property: "opacity"
                        to: 0
                        easing.type: Easing.OutCubic
                    }
                    NumberAnimation {
                        target: gradientCircle
                        duration: 300
                        property: "opacity"
                        to: 0
                        easing.type: Easing.OutCubic
                    }
                }
                NumberAnimation {
                    target: holeInBackground
                    property: "opacity"
                    to: 0
                    duration: 300
                    easing.type: Easing.OutCubic
                }
                ScriptAction {
                    script: {
                        holeInBackground.source = holeInBackgroundImg
                    }
                }
                ScriptAction {
                    script: {
                        gradientCircle.source = gradientCircleImg
                    }
                }
                PauseAnimation {
                    duration: 1000
                }
                NumberAnimation {
                    target: holeInBackground
                    property: "opacity"
                    to: 1
                    duration: 300
                    easing.type: Easing.OutCubic
                }

                ParallelAnimation {
                    NumberAnimation {
                        target: gradientCircle
                        property: "opacity"
                        to: 1
                        duration: 300
                        easing.type: Easing.OutCubic
                    }
                    NumberAnimation {
                        target: background
                        property: "opacity"
                        to: 1
                        duration: 300
                        easing.type: Easing.OutCubic
                    }
                }
            }
        }
    ]

    Behavior on circlesColor {
        ColorAnimation {
            duration: 500
            easing.type: Easing.InOutQuad
        }
    }

    Behavior on backgroundColor {
        ColorAnimation {
            duration: 500
            easing.type: Easing.InOutQuad
        }
    }

    Rectangle {
        id: background
        width: holeInBackground.width
        height: holeInBackground.height

        anchors.centerIn: root
        color: backgroundColor
    }

    Image {
        id: holeInBackground
        anchors.centerIn: root
    }

    ColorizedImage {
        id: gradientCircle
        color: root.circlesColor
        anchors.centerIn: root
    }

    Text {
        id: textValue
        font.family: "Barlow-mono"
        font.pixelSize: 105
        color: fontColor
        anchors.centerIn: background
        anchors.verticalCenterOffset: -21//-14
        text: gearTextVal
    }

    Text {
        id: gearText
        font.family: "Barlow-mono"
        font.pixelSize: 30
        color: fontColor
        text: "Gear"
        anchors.centerIn: background
        anchors.verticalCenterOffset: 45
    }

    ColorizedImage {
        id: ring1
        source: "qrc:///images/fuelGauge/ring-2.png"
        width: 195
        height: 195
        anchors.centerIn: root
        color: root.ringsColor
    }

    ColorizedImage {
        id: ring2
        source: "qrc:///images/fuelGauge/ring-2.png"
        anchors.centerIn: root
        property int horizontalCenterOffsetValue
        anchors.horizontalCenterOffset: horizontalCenterOffsetValue
        color: root.ringsColor
    }

    function hideElements() {
        ring1.opacity = 0
        ring2.opacity = 0
        holeInBackground.opacity = 0
        background.opacity = 0
        gradientCircle.opacity = 0

        textValue.opacity = 0
        gearText.opacity = 0
    }

    onActiveChanged: {
        if (active) {
            startAnimation()
        } else {
            hiddingAnimation()
        }
    }

    function startAnimation() {
        startUpAnimation.start()
    }

    function hiddingAnimation() {
        hideAnimation.start()
    }

    SequentialAnimation {
        id: hideAnimation
        NumberAnimation {
            target: background
            property: "opacity"
            to: 0
            duration: 500
            easing.type: Easing.OutCubic
        }
        NumberAnimation {
            target: root
            property: "opacity"
            to: 0
            duration: 500
            easing.type: Easing.OutCubic
        }
        ScriptAction {
            script: hideElements()
        }
    }

    SequentialAnimation {
        id: startUpAnimation
        ScriptAction {
            script: {
                hideElements()
                root.opacity = 1
            }
        }
        ParallelAnimation {
            NumberAnimation {
                target: ring2
                property: "horizontalCenterOffsetValue"
                from: -StartupConfig.ring2TravelDistance
                to: 0
                duration: StartupConfig.ring2TravelDuration
                easing.type: Easing.OutCubic
            }
            NumberAnimation {
                target: ring2
                property: "opacity"
                from: 0
                to: 1
                duration: StartupConfig.ring2OpacityDuration
                easing.type: Easing.OutCubic
            }
        }
        ScriptAction {
            script: {
                holeInBackground.opacity = 1
            }
        }

        SequentialAnimation {
            NumberAnimation {
                target: ring1
                property: "opacity"
                from: 0
                to: 1
                duration: StartupConfig.ring1OpacityDuration
                easing.type: Easing.OutCubic
            }
            NumberAnimation {
                target: gradientCircle
                property: "opacity"
                from: 0
                to: 1
                duration: StartupConfig.backgroundOpacityDuration
                easing.type: Easing.OutCubic
            }
            ParallelAnimation {
                NumberAnimation {
                    target: background
                    property: "opacity"
                    from: 0
                    to: 1
                    duration: StartupConfig.backgroundOpacityDuration
                    easing.type: Easing.OutCubic
                }
                NumberAnimation {
                    target: gearText
                    property: "opacity"
                    from: 0
                    to: 1
                    duration: StartupConfig.backgroundOpacityDuration
                    easing.type: Easing.OutCubic
                }
            }
            NumberAnimation {
                target: textValue
                property: "opacity"
                from: 0
                to: 1
                duration: 500
                easing.type: Easing.OutCubic
            }
        }
    }

    Component.onCompleted: {
        hideElements()
    }
}