动画 — 补间动画和时间轴

本指南讨论如何使用 Corona 动画 插件在特定时间段内移动、旋转、淡出或缩放显示对象/组。它还概述了如何使用 时间轴 来构建复杂的多插值一个或多个显示对象/组之间的动画。

插件功能

补间动画

可以使用以下其中一个函数启动一个基本的补间动画

这些函数的基本语法是

animation.to( target, properties, params )
animation.from( target, properties, params )

补间动画目标

任一函数中的第一个参数target最常是 显示对象显示组,你想对它进行动画处理。然而,对于更多特殊情况,它还可以是 RectPath 点用于 四边形变形RGB+A用于 Paint 填充的颜色通道或 fill.effect 属性。

对象属性

第二个参数properties是一个键值对表格。在此表中,指定要更改的每个所需的属性以及它的最终值(如果使用则为animation.from()起始值)。

插值 属性(键) 说明
移动 x, y 将对象移到/从特定xy坐标。
旋转 旋转 将对象从一个角度旋转到/另一个角度。
淡入/淡出 alpha 将对象从一个 alpha 值淡入/淡出到另一个 alpha 值。
上/下缩放 xScaleyScale 将对象从/缩放特定x比例或y比例到特定x比例或y比例。
字体大小 size 仅当targetTextObject时才适用。这会对文本对象的字体大小进行补间。
调整大小 widthheight 将对象从/调整到特定宽度/高度大小。
变形 x1y1x2y2x3y3x4y4 仅当targetRectPath时才适用,适用于ShapeObject。有关详细信息,请此处
颜色通道 rgba 仅当targetShapeObject.fill表格时才适用。
填充效果 (各种) 仅当target为对象fill.effect属性时才适用。在这种情况下,属性(键)表示与特定滤镜效果关联的效果属性。有关每个滤镜效果应用哪些滤镜参数的详细信息,请此处
锚点 anchorXanchorY 移动对象的xy锚点
遮罩位置 maskXmaskY 对于遮罩图像/组,移动遮罩的xy位置。
遮罩缩放 maskScaleXmaskScaleY 对于遮罩图像/组,移动遮罩的xy缩放比例。

某些对象在补间期间或之后的表现可能与预期不符。例如,许多小组件不支持缩放或后声明调整大小,因此你不应尝试对xScaleyScalewidthheight补间。另一个例子是物理体——如果你使用补间缩放或调整物理对象的尺寸,实际的物理体不会随该补间缩放。

如有疑问,请查看与该对象或库关联的文档,以确认它没有任何与补间相关的属性限制。

控制参数

第三个参数params,也对键值对。在此表格中,指定补间的适当控制参数

控件 说明
时间 指定补间的持续时间(以毫秒为单位)。
延迟 指定补间开始前的延迟时间(以毫秒为单位)。默认值为0(无)。
缓动 指定用于补间的缓动函数。有关详细信息,请参阅缓动函数
速度缩放 调整补间的相对速度比例。它必须是大于 0 的正数。默认情况下,速度比例为 1(正常速度)。大于 1 的值会增加速度,而小于 1 的值会减慢速度。
标签 允许您对补间进行分类并一起控制的字符串值。
id 分配给补间的可选识别字符串。可以通过补间事件监听器函数从其上检索,其中(见以下内容)。
迭代次数 补间应重复的次数(整数)。使用 0-1 使其无限期重复。
反映 对于具有多个迭代次数的补间,指定是否反映交替的迭代次数(以相反方向播放)。默认值为 false
增量 指定非控制参数是作为最终结束值解释还是作为值的变化。默认值为 false
constantRate + constantRateProperty 如果使用,则必须同时指定这两个参数。有关详细信息,请参阅 文档

缓动函数

默认情况下,补间从开始到结束以一致的线性变化率发生。但是,您可能希望使用缓动效果来达到不同的结果,例如,使对象在开始时快速移动,并随着到达目的地而逐渐减慢速度。此行为可以通过在动画调用中与 缓动 函数结合使用来实现。

要在补间上设置缓动效果,只需在 params 表中提供 easing 键,其值等于其中一个 缓动 库函数。例如

-- Tween the object using outward quadratic interpolation
animation.to( myObject,
    { y=100 },
    {
        time = 2000,
        easing = easing.outQuad
    }
)
-- Tween the object using inward and then outward exponential interpolation
animation.to( myObject,
    { y=100 },
    {
        time = 2000,
        easing = easing.inOutExpo
    }
)

尽管 40+ 个内置 缓动 函数将满足大多数开发人员的需求,但可以创建自定义缓动函数并在补间中使用它们。有关详细信息,请参阅以下 自定义缓动函数

补间动画事件

补间还支持以下列出的全系列补间事件。它们应指定为键值params 表中的对。当事件发生时,关联的监听器函数将接收到对 补间 对象的引用。

事件 参数(键) 描述(值)
开始 onStart 在补间开始之前要调用的监听器函数。
完成 onComplete 在补间完成后要调用的监听器函数。
暂停 onPause 在补间暂停时要调用的监听器函数。
恢复 onResume 在补间恢复时要调用的监听器函数。
取消 onCancel 在补间被取消时要调用的监听器函数。
重复 onRepeat 在补间在重复周期中完成一次迭代时要调用的监听器函数。
位置更改 onPositionChange 当补间通过 object:setPosition()animation.setPosition() 手动更改其播放位置时要调用的监听器函数。

在下例中,当补间完成时,将调用 tweenListener() 函数

local myObject = display.newRect( 0, 0, 100, 100 )

local function tweenListener( obj )
    print( "Tween completed; ID: " .. obj.id )
end

animation.to( myObject,
    { alpha=0 },
    {
        time = 2000,
        id = "tween1",
        onComplete = tweenListener
    }
)

时间轴

时间线是一种构建一个或多个显示对象/组间复杂多插值动画的强大方式。它们使用 animation.newTimeline() 命令构建

animation.newTimeline( timelineParams )

对于此函数,timelineParams 参数是一个 ,其中指定了时间线的补间、标记和其他参数。

时间轴补间动画

至少 timelineParams 表必须包含一个子表 tweens,其中包含将参与时间线的所有补间

local newTimeline = animation.newTimeline(
{
    tweens = {},
})

tweens 表内,通过接受以下内容的基本 Lua 表配置各个补间键值

  • startTime — 时间线进度中(以毫秒为单位)补间应开始的可选 数字。默认值为 0(时间线的开始)。
  • tween — 配置补间的必需 。应与任何基本补间类似地配置该表(参见上面的 补间.
  • useFrom — 可选 布尔 属性,如果将其设置为 true,则会让补间表现得如同由 animation.from() 而不是由 animation.to() 声明的那样。

例如,此 tweens 表配置了时间线的两个独立补间

local newTimeline = animation.newTimeline(
{
    tweens = {
        { startTime=0, tween={ object1, { x=400 }, { time=4000, iterations=5, reflect=true } } },
        { startTime=1000, tween={ object1, { y=400 }, { time=4000, easing=easing.outQuad } } }
    },
})

时间轴标记

为了提高控制水平,可以在时间线持续期间内指定任意多個 标记。这些标记在可选 markers 表内指定,允许你指定跳转至时间线内的点。每个标记应定义为一个 ,其中包含以下属性

  • name — 与标记关联的 字符串 名称。此名称应是 唯一的(你不应在同一个时间线内使用重复的标记名称)。
  • time — 在时间线进度中(以毫秒为单位)设置标记的 数字
  • params — 可选 ,其中可以包含自定义信息;此表将传递到 onMarkerPass 侦听器函数(详细信息)。

例如,此 markers 表为时间线配置了三个时间标记

local newTimeline = animation.newTimeline(
{
    tweens = {
        { startTime=0, tween={ object1, { x=400 }, { time=4000, iterations=5, reflect=true } } },
        { startTime=1000, tween={ object1, { y=400 }, { time=4000, easing=easing.outQuad } } }
    },
    markers = {
        { name="marker_start", time=0 },    -- Start of the timeline
        { name="marker_2000", time=2000 },  -- 2 seconds into the timeline
        { name="marker_3000", time=3000 }   -- 3 seconds into the timeline
    },
})

一旦配置完成后,你可使用标记名称跳转至其关联的位置。有关详细内容,请参阅 object:setPosition()animation.setPosition()

其他参数

时间线接受多种其他参数(可选),这些参数可用于微调设置并控制。这些应被指定为键值timelineParams 表内的

参数(键) 说明
布尔 值,如果为 true,则会立即让时间线播放。默认值为 false
标签 字符串,表示时间线标签。动画插件可以暂停、恢复、取消、设置位置或改变具有相同标签的时间线的速度缩放。
id 要分配给时间线的可选识别字符串。这可以从任何时间线事件侦听器函数中作为 obj.id 检索(请参见下文)。
延迟 数字,表示在时间线开始播放之前(以毫秒为单位)的延迟。默认值为 0
速度缩放 调整时间轴的相对速度刻度。这必须是大于 0 的正 number。默认情况下,速度刻度为 1(正常速度)。大于 1 的值将增加速度,而低于 1 的值将降低速度。
autoCancel 当为 true 时,Boolean 值将导致在时间轴完成后取消所有子补间动画。仅当您不打算在第一次播放后再次播放时间轴时才应执行此操作。默认为 false

时间轴事件

时间轴还支持以下列出的完整 时间轴事件。这些应指定为键值timelineParams 表内的成对。当事件发生时,关联的侦听器函数将收到对 Timeline 对象的引用。

事件 参数(键) 描述(值)
开始 onStart 在时间轴开始之前直接调用的侦听器函数。
完成 onComplete 在时间轴中所有补间动画完成时间轴中最终标记(以先发生者为准)后调用的侦听器函数。
暂停 onPause 时间轴暂停时调用的侦听器函数。
恢复 onResume 时间轴恢复时调用的侦听器函数。
取消 onCancel 时间轴取消时调用的侦听器函数。
位置更改 onPositionChange 通过 object:setPosition()animation.setPosition() 手动更改时间轴播放位置时调用的侦听器函数。
marker passed onMarkerPass 当到达或通过时间轴中的标记时调用的侦听器函数。此函数将接收包含对关联 Timeline 对象(timeline)的引用、name 属性以及分配给特定标记的可选 params 表的 table,而不是仅接收对 Timeline 对象的引用。

在以下示例中,每当时间轴中每个补间动画的每次迭代完成后,将调用 timelineListener() 函数

local object1 = display.newRect( 50, 50, 100, 100 )

local function timelineListener( obj )
    print( "Timeline completed; ID: " .. obj.id )
end

-- Create a timeline object
local newTimeline = animation.newTimeline(
{
    tweens = {
        { startTime=0, tween={ object1, { x=400 }, { time=4000, iterations=5, reflect=true } } },
        { startTime=1000, tween={ object1, { y=400 }, { time=4000, easing=easing.outQuad } } }
    },
    id = "timeline1",
    onComplete = timelineListener
})

-- Set the timeline playing
newTimeline:resume()

控制补间动画/时间轴

可以通过各种方法控制补间动画和时间轴。您可以通过 animation 插件使用库命令(通过)或在 Tween 对象或 Timeline 对象上使用对象命令

库命令的一个好处是,根据传递的参数,您可以通过一次调用影响多个补间动画和/或时间轴(这里,* 表示 pauseresumecancelsetPositionsetSpeedScale)。

参数 语法 范围
(无) animation.*() 影响所有补间动画/时间轴。
tween 引用 (Tween) animation.*( tweenObject ) 影响指定的引用 tween (tweenObject)。
时间线 引用 (Timeline) animation.*( timelineObject ) 影响指定的引用时间线 (timelineObject)。
标签名称 (String) animation.*( "tagName" ) 影响共享相同标签名称的所有 tween/时间线。
对象引用 (DisplayObject) animation.*( DisplayObject ) 影响指定显示对象/组上的所有 tween。

任何以 Timeline 内特定子 tween 为目标的控制方法都会被忽略。时间线 tween 由父时间线控制,因此您应该控制时间线本身。例如,如果时间线内的一个 tween 影响到一个名为 object1 的对象,则您不能通过调用暂停特定 tweenanimation.pause( object1 )这是因为时间线拥有其所有子 tween,并且应该将它视为一个集合动画序列。

补间动画/时间轴状态

如有需要,您可以通过以下调用获取特定 tween 或时间线的状态

状态 对象命令
已暂停/未暂停 Tween:getIsPaused()  /  Timeline:getIsPaused()
当前位置 Tween:getPosition()  /  Timeline:getPosition()
当前速度缩放 Tween:getSpeedScale()  /  Timeline:getSpeedScale()
持续时间 Tween:getDuration()  /  Timeline:getDuration()

自定义缓动函数

如果内置的 easing 函数不包含针对您的项目必要的非常具体的插值模式,则可以创建自定义 easing 函数,并将其用作 tween 的 easing 属性。

自定义 easing 函数应遵循其他 easing 函数的模式,例如 easing.linear

easing.linear = function( t, tMax, start, delta )
    return delta * t / tMax + start
end

实际上,只要自定义 easing 函数能接受 ttMaxstartdelta 属性,则任何在另一端输出的数字都是有效的(尽管通常应该返回一个介于 01 之间的数字).

在编写了自己的 easing 函数后,只需将其引用为 tween 的 easing 参数即可。例如

local myObject = display.newRect( 0, 0, 100, 100 )

local function myLinearEasing( t, tMax, start, delta )
    return delta * t / tMax + start
end

animation.to( myObject,
    { x=500 },
    {
        time = 2000,
        easing = myLinearEasing
    }
)
注意

大多数 easing 函数设计为当 t=0 时返回 0,当 t=1 时返回 1。但是,这未必总能令人满意。例如,出场退场easing 函数(例如 easing.continuousLoop)在 t=0 时返回 0,但在 t=1 时也返回 0。换句话说,结束值与开始值相同。如果您的自定义 easing 函数是这样的,则必须设置easingEndIsStart = true作为 tween 的一个参数,否则它在完成后和重复迭代时会表现异常。例如

animation.to( myObject,
    { x=500 },
    {
        time = 2000,
        easing = myContinuousEasing,
        easingEndIsStart = true
    }
)