qml 实现老虎机的样式

qml实现的老虎机的样式


qml 因为封装了很多控件,只要使用简单的设置就可以达到效果。
为了实现老虎机的滚动样式,曾试过ListView,Column,PathView和相关的过渡效果,但实际效果并不理想,最后才想到用代码设置项目的 y的值和透明度,得到的结果也算不错。

效果图

在这里插入图片描述

qml代码

//main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15

Item {
    width: 640
    height: 480
    property var btns: []   // 保存按钮
    property int btnSpace: 5
    property int btnSize: 30
    property int btnsLength: (btnSpace+btnSize)*10

    function rollOffset(ofs){
        // console.log("=========rollOffset==========")
        for(let i = 0; i < btns.length;++i){
            btns[i].y -= ofs
            if(btns[i].y < -(btnSize + btnSpace)*4){
                btns[i].y += (btnSize + btnSpace)*10
            }

            var opacity =Math.abs(btns[i].y + (btnSize/2) - rect.height/2)/(btns.length * (btnSize+btnSpace)/2)
            opacity = 1 - opacity*2;
            btns[i].opacity = opacity;
            console.log(i,opacity.toFixed(1))
        }
    }

    function setOpencity(centIdx){
        for(let v = 0 ; v < btns.length;++v){
            var midf = centIdx - 5;
            var idx = (v + midf);
            btns[(idx+10)%10].opacity = (1-2*Math.abs(idx-centIdx)/5).toFixed(1);
            btns[(idx+10)%10].y = rect.height/2 + (idx-centIdx)*(btnSize+btnSpace)-(btnSize/2)
            console.log(v,(idx+10)%10,btns[(idx+10)%10].opacity);
        }
    }

    Rectangle {
        id: rect
        width: 60; height: 150;
        anchors.centerIn: parent
        border.color: "black"
        color: "#333333"
        clip: true
        objectName: "rect"

        // 中间指示器
        Rectangle{
            width: rect.width
            height: btnSize+5
            anchors.centerIn: parent
            color: "transparent"
            border.color: "green"
            border.width: 2
            z : 2
        }
        // 10个按钮
        Repeater {
            id:rep
            objectName: "rep"
            model: 10

            Button {
                width: btnSize
                height: btnSize
                anchors.horizontalCenter: parent.horizontalCenter
                text: index
                Component.onCompleted: {
                    btns.push(this);
                }
                onClicked: rollOffset(btnSize+btnSpace);
            }
        }

        // 指定 中间的按钮,并指定所有按钮的位置
        Component.onCompleted: {
            console.log("==========onCompleted=============")
            var centerIndex = 9;
            setOpencity(centerIndex)
        }
    }

    // 控制按钮
    Button {
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        text: "Start";
        onClicked: {
            if(timer.running){
                timer.speed = -0.3
                text = "Start"
            }
            else {
                timer.start();
                text = "Stop"
            }
        }
    }

    // 定时器
    Timer {
        id: timer
        interval: 20
        repeat: true
        property real offset: 0
        property real speed : 0.3

        onTriggered: {
            offset += speed;                // 速度
            offset = Math.min(offset,55);   // 最大的偏移距离

            // 停止逻辑 ====>
            if(offset < 0) {
                speed = 0.3;
                stop();
                console.log('================================')
                var max = 0;
                for(var v = 0 ; v < btns.length;++v){
                    if(btns[v].opacity > btns[max].opacity)
                        max = v;
                }

                console.log("max: ",max)

                var yf = btns[max].y + btnSize/2 - rect.height/2;
                for(v = 0 ; v < btns.length;++v){
                    btns[v].y -= yf
                    var midf = max - 5;
                    var idx = (v + midf);
                    console.log(v,(idx+10)%10, (1-Math.abs(idx-max)/5).toFixed(1));
                }
                setOpencity(max);
                return;
            } // 停止逻辑  <====

            rollOffset(offset);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值