动画属性与多个动画的属性绑定
Posted
技术标签:
【中文标题】动画属性与多个动画的属性绑定【英文标题】:Property Binding on Animated Property vs Multiple Animations 【发布时间】:2017-03-06 15:48:06 【问题描述】:考虑这个例子:
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
s 具有相同的可观察行为:单击时,它们的不透明度和大小都会消失。
在内部,Animation
s 的数量不同,它们同时运行 - 1 或 3:
到目前为止,我主要使用rect1
的模式形式,并且仅在绑定变得不必要的复杂rect2
的情况下使用。但是我想知道,如果动画系统有一些魔法,可以优化单个属性的动画,而绑定可能会降低性能。
在哪些用例中使用模式rect1
是有益的,什么时候使用rect2
的方法更明智?
EDIT 还有第三个选项,可以通过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'
EDIT 2 解决 Ansh Kumar 的答案:
这是QML Profiler
的摘录。您可以看到,在 rect2
的动画期间,既没有绑定也没有运行 javascript,这与 height
和 width
被(有效地)绑定到 opacity
的时候不同rect1
或 width
(有效地)绑定到 rect3
中的 height
。
此外,动画源几乎没有JS
的踪迹。我无法深入研究它,但似乎只有ScriptAction
得到QQMLScriptString
,其余的只有将输入从var
转换为正确类型的成本(如果类型是使用具体动画指定,例如NumberAnimation
)。
此外,据我所见,每个动画都没有循环,但所有动画都具有某种update()
-function 左右,由单个循环调用(在运行/注册时)(AnimationTimer
)。但这是我已经不确定的地方。
现在问题仍然存在:动画的实现是否比优化的 JS 环境更有效,尤其是在创建多个对象和填充时。
【问题讨论】:
【参考方案1】:QML 中有两种类型的绑定:优化的绑定和非优化的绑定。保持绑定表达式尽可能简单是个好主意,因为 QML 引擎使用了优化的绑定表达式求值器,它可以求简单的绑定表达式,而无需切换到完整的 JavaScript 执行环境。这些优化的绑定比更复杂的(非优化的)绑定的评估效率更高。绑定优化的基本要求是每个被访问的符号的类型信息必须在编译时就知道。
当他们知道他们正在使用的对象和属性的类型时,绑定是最快的。为属性设置动画将导致重新评估引用该属性的任何绑定。通常,这是所需要的。 rect2
中的 opacity
、height
和 width
被重新评估为完整的 JavaScript 执行环境,而在 rect1
中; width
和 height
经过优化的绑定表达式求值器并经过优化以提供更有效的绑定,因为它们的对象类型在编译时是已知的。查看binding 和animations 了解更多详情。
编辑
关于在 C++ 环境中进行评估是正确的。我找到了以下信息。
渲染引擎应达到每秒 60 帧的一致刷新率。 60 FPS 意味着每帧之间大约有 16 毫秒(正好 16.6667 毫秒)可以进行处理,其中包括将绘制图元上传到图形硬件所需的处理。 This 显示动画与垂直刷新同步,因此每 16.66 毫秒一次,并且恰好是 pr 帧一次。
while (animationIsRunning)
processEvents();
advanceAnimations();
paintQMLScene();
swapAndBlockForNextVSync();
所以,在rect1
中,您设置了duration: 1000
并将height
与opacity
(height: 300 * opacity
) 类似地width
与opacity
绑定,所以绑定应该被调用大约60 次?如果您看到statistics
的QML profiler
输出,您会发现以下内容
正如预期的那样,调用次数约为 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
是最好的用法,因为调用次数减少了。
【讨论】:
为什么height
和width
会在完整的JS环境中重新评估?我没有声明中间变量,没有访问var
,没有调用任何 JS 函数,没有构造闭包或函数,避免在直接评估范围之外使用所有属性,也没有发出副作用。所以这应该在 优化模式 afaik. 下运行
@derM 因为Behavior on
会为您服务,即使您没有明确执行任何操作。
但是我使用了专门的NumberAnimation
,它提供了更有效的实现。所以我认为它应该在优化的 C++ 环境中运行属性更改。这就是为什么我假设NumberAnimation
可能比更通用的优化绑定更有效。
所以基本上问题是:什么更优化:更有效的动画实现: NumberAnimation
或 优化 binding
@derM 我已经通过更多研究更新了我的答案。以上是关于动画属性与多个动画的属性绑定的主要内容,如果未能解决你的问题,请参考以下文章