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);
}
}
}