200 lines
7.8 KiB
QML
200 lines
7.8 KiB
QML
// ==============================================
|
|
// =============== 加载中 动态图标 ===============
|
|
// ==============================================
|
|
|
|
import QtQuick 2.15
|
|
import QtGraphicalEffects 1.15 // 阴影
|
|
|
|
Item {
|
|
id: lRoot
|
|
property string text: "OCR..."
|
|
property real time: 700 // 动画间隔时间,毫秒
|
|
width: size_.smallText * 6
|
|
height: width
|
|
clip: true
|
|
property bool running: false // 是否运行动画
|
|
|
|
onVisibleChanged: {
|
|
if(visible) {
|
|
image.init()
|
|
cRoot.init()
|
|
running = qmlapp.enabledEffect // 启动动画
|
|
}
|
|
else {
|
|
running = false // 停止动画
|
|
}
|
|
}
|
|
|
|
// 主体
|
|
Panel {
|
|
anchors.fill: parent
|
|
color: theme.bgColor
|
|
|
|
// 图标
|
|
Item {
|
|
anchors.fill: parent
|
|
anchors.margins: size_.spacing * 2
|
|
anchors.topMargin: size_.spacing
|
|
Image {
|
|
id: image
|
|
source: "../../images/icons/dango_right.png"
|
|
mipmap: true // 启用高质量缩放
|
|
fillMode: Image.Stretch
|
|
property real p1x
|
|
property real p1y
|
|
property real pw
|
|
property real ph
|
|
property real sw
|
|
property real sh
|
|
property real p1w
|
|
property real p1h
|
|
property real p2x
|
|
property real p2y
|
|
property real p2w
|
|
property real p2h
|
|
property real pt: lRoot.time * 0.5
|
|
// 预计算变形动画参数
|
|
Component.onCompleted: {
|
|
// 父组件大小
|
|
pw=parent.width, ph=parent.height
|
|
// 图片原始大小
|
|
sw=sourceSize.width, sh=sourceSize.height
|
|
// 最高点
|
|
p1h=ph*0.9, p1w=p1h*(sw/sh)*0.9, p1y=0, p1x=(pw-p1w)*0.5
|
|
// 最低点
|
|
p2h=p1h*0.9, p2w=p1h*(sw/sh)*1.1, p2x=(pw-p2w)*0.5, p2y=ph-p2h
|
|
}
|
|
// 恢复初始状态
|
|
function init() {
|
|
if(qmlapp.enabledEffect) {
|
|
x=p2x, y=p2y
|
|
width=p2w, height=p2h
|
|
}
|
|
else {
|
|
height=ph, width=ph*(sw/sh)
|
|
y=0, x=(pw-width)*0.5
|
|
}
|
|
}
|
|
// 串行动画
|
|
SequentialAnimation{
|
|
id: animation
|
|
running: lRoot.running
|
|
loops: Animation.Infinite
|
|
ParallelAnimation {
|
|
NumberAnimation{ target:image; property:"x"; to:image.p1x; duration:image.pt; easing.type:Easing.OutCubic}
|
|
NumberAnimation{ target:image; property:"y"; to:image.p1y; duration:image.pt; easing.type:Easing.OutCubic}
|
|
NumberAnimation{ target:image; property:"width"; to:image.p1w; duration:image.pt; easing.type:Easing.OutCubic}
|
|
NumberAnimation{ target:image; property:"height"; to:image.p1h; duration:image.pt; easing.type:Easing.OutCubic}
|
|
}
|
|
ParallelAnimation {
|
|
NumberAnimation{ target:image; property:"x"; to:image.p2x; duration:image.pt; easing.type:Easing.InCubic}
|
|
NumberAnimation{ target:image; property:"y"; to:image.p2y; duration:image.pt; easing.type:Easing.InCubic}
|
|
NumberAnimation{ target:image; property:"width"; to:image.p2w; duration:image.pt; easing.type:Easing.InCubic}
|
|
NumberAnimation{ target:image; property:"height"; to:image.p2h; duration:image.pt; easing.type:Easing.InCubic}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 下方文字动画
|
|
Item {
|
|
id: cRoot
|
|
anchors.bottom: parent.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
// anchors.margins: size_.smallSpacing
|
|
height: size_.smallText
|
|
property var chars: []
|
|
property int time: lRoot.time
|
|
|
|
Component.onCompleted: {
|
|
let l = []
|
|
for(let i in lRoot.text)
|
|
l.push(lRoot.text[i])
|
|
chars = l
|
|
textTimer.max = l.length
|
|
}
|
|
// 恢复初始状态
|
|
function init() {
|
|
textTimer.now = 0
|
|
}
|
|
Timer {
|
|
id: textTimer
|
|
property int now: 0
|
|
property int max: 0
|
|
interval: cRoot.time
|
|
running: lRoot.visible
|
|
repeat: true
|
|
onTriggered: {
|
|
if(now===max-1)
|
|
now = 0
|
|
else
|
|
now++
|
|
}
|
|
}
|
|
|
|
Row {
|
|
anchors.bottom: parent.bottom
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
spacing: size_.smallText * 0.1
|
|
|
|
Repeater {
|
|
model: cRoot.chars
|
|
Text_ {
|
|
id: charT
|
|
property bool charShow: textTimer.now===index
|
|
font.pixelSize: size_.smallText
|
|
text: modelData
|
|
color: theme.specialTextColor
|
|
property real minOpa: 0.5
|
|
opacity: minOpa
|
|
property real sp: size_.smallSpacing
|
|
property real spMax: size_.smallSpacing * 1.5
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: sp
|
|
height: size_.smallText
|
|
|
|
onCharShowChanged: {
|
|
if(lRoot.running) {
|
|
if(charShow) caShow.running = true
|
|
else caHide.running = true
|
|
}
|
|
else {
|
|
anchors.bottomMargin = charShow ? spMax : sp
|
|
opacity = charShow ? 1 : minOpa
|
|
}
|
|
}
|
|
ParallelAnimation {
|
|
id: caShow
|
|
running: false
|
|
NumberAnimation {
|
|
target:charT; properties: "anchors.bottomMargin";
|
|
from: charT.sp; to: charT.spMax; duration:cRoot.time * 0.5;
|
|
easing.type:Easing.OutCubic;
|
|
}
|
|
NumberAnimation {
|
|
target:charT; properties: "opacity";
|
|
from: minOpa; to: 1; duration:cRoot.time * 0.5;
|
|
easing.type:Easing.OutCubic;
|
|
}
|
|
}
|
|
ParallelAnimation {
|
|
id: caHide
|
|
running: false
|
|
NumberAnimation {
|
|
target:charT; properties: "anchors.bottomMargin";
|
|
from: charT.spMax; to: charT.sp;
|
|
easing.type:Easing.InQuart; duration:cRoot.time;
|
|
}
|
|
NumberAnimation {
|
|
target:charT; properties: "opacity";
|
|
from: 1; to: minOpa; duration:cRoot.time;
|
|
easing.type:Easing.InQuart;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |