考虑这个例子:
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
id: appWindow
width: 1024
height: 800
visible: true
Rectangle {
id: rect1
property bool active: true
opacity: active ? 1 : 0
height: 300 * opacity
width: 300 * opacity
Behavior on opacity { NumberAnimation { duration: 1000 } }
MouseArea { anchors.fill: parent; onClicked: parent.active = false }
color: 'cornflowerblue'
}
Rectangle {
id: rect2
property bool active: true
x: 305
opacity: active ? 1 : 0
height: active ? 300 : 0
width: active ? 300 : 0
Behavior on opacity { NumberAnimation { duration: 1000 } }
Behavior on height { NumberAnimation { duration: 1000 } }
Behavior on width { NumberAnimation { duration: 1000 } }
MouseArea { anchors.fill: parent; onClicked: parent.active = false }
color: 'steelblue'
}
}
我有两个Rectangle
具有相同的可观察行为:点击后,它们会以不透明度和大小淡化。
在内部,它同时运行的Animation
s的数量不同 - 1或3:
截至目前,我主要使用模式格式rect1
,并且仅在绑定不必要的情况下使用复杂rect2
。但是我想知道,如果动画系统有一些魔力,那么优化单个属性的动画,而绑定可能性能较差。
在哪些用例中使用模式rect1
以及何时使用rect2
的方法更明智?
编辑还有第三个选项可以通过OpacityAnimator
移动到渲染线程。现在我不能再绑定到不透明度,因为它会在动画结束时跳转到0。
Rectangle {
id: rect3
property bool active: true
opacity: active ? 1 : 0
height: active ? 300 : 0
x: 610
width: height
Behavior on opacity { OpacityAnimator { duration: 1000 } }
Behavior on height { NumberAnimation { duration: 1000 } }
MouseArea { anchors.fill: parent; onClicked: parent.active = false }
color: 'dodgerblue'
}
编辑2 要解决 Ansh Kumar 的答案:
这是
QML Profiler
的摘录。您可以看到,rect2
动画期间既没有绑定也没有JavaScript运行,这与height
和width
(有效)绑定的时间不同opacity
中的rect1
或width
(有效)绑定到height
中的rect3
。
此外,动画的来源显示JS
的痕迹很少。我无法将其检查到所有深度,但似乎只有ScriptAction
获得QQMLScriptString
,其余只有将输入从var
转换为右边的成本type(如果通过使用NumberAnimation
等具体动画指定类型。)
此外,据我所知,每个动画都没有循环,但所有动画都有某种update()
- 函数左右,通过单个循环调用(运行/注册时)({ {1}})。但这是我不确定的地方。
现在问题仍然存在:动画的实现是否比优化的JS环境更有效,尤其是在创建多个对象和其他东西时。
答案 0 :(得分:1)
QML中有两种类型的绑定:优化绑定和非优化绑定。保持绑定表达式尽可能简单是一个好主意,因为QML引擎使用优化的绑定表达式求值程序,它可以评估简单的绑定表达式,而无需切换到完整的JavaScript执行环境。与更复杂(非优化)的绑定相比,这些优化的绑定的评估效率更高。优化绑定的基本要求是访问的每个符号的类型信息必须在编译时知道。
当绑定知道它们正在使用的对象和属性的类型时,它们是最快的。动画属性将导致重新评估引用该属性的任何绑定。通常,这是所期望的。 opacity
中的height
,width
和rect2
会重新评估为完整的JavaScript执行环境,而rect1
则会被重新评估。 width
和height
经过优化的绑定表达式求值程序并进行了优化,以提供更高效的绑定,因为它们的对象类型在编译时是已知的。查看binding和animations了解详情。
修改强>
在C ++环境中进行评估是正确的。我找到了以下信息。
渲染引擎应该实现一致的每秒60帧的刷新率。 60 FPS意味着在可以进行处理的每个帧之间有大约16毫秒(正好是16.6667毫秒),其中包括将绘图基元上传到图形硬件所需的处理。 This表示动画与垂直刷新同步,因此每16.66毫秒一次,恰好是一帧帧。
while (animationIsRunning) {
processEvents();
advanceAnimations();
paintQMLScene();
swapAndBlockForNextVSync();
}
因此,在rect1
中,您已设置duration: 1000
并将height
与opacity
height: 300 * opacity
绑定width
opacity
QML profiler
那么绑定应该被调用大约60次?如果您看到statistics
的{{1}}输出,您会找到以下内容
预期的通话次数约为60(正好是63)。现在,如果您将持续时间更改为2000,则呼叫次数将加倍。
由于必须计算300 * opacity
,因此QML
应调用JavaScript环境约60次(duration: 1000
时)
正如预期的那样,大约被召唤了60次。
NumberAnimation
怎么样,是用JavaScript还是C ++实现的?当然,你用C ++实现它是正确的,Here是它的声明的链接。因此,在rect1
中我们曾使用NumberAnimation
一次,而rect2
我们已经使用了3次。因此,应创建总共4个NumberAnimation
个实例。
因此,rect1
总共有大约120个绑定和JavaScript调用,而在rect2
中没有绑定和JavaScript调用,因此rect2
的动画应该更快,但是问题是,会有任何重大改进吗?由于QtCreator的免费版本没有配备CPU分析器,我无法研究问题的这一部分(CPU Usage Qt)。如果有人有Qt的商业版,请更新我的假设。我认为rect2
最适合使用,因为呼叫次数减少了。