一步一步学习使用FireMonkey动画(4) 使用Delphi的基本动画组件类,路径和位图列表动画 弹跳小球和奔跑的小人示例

在《一步一步学习使用FireMonkey动画(3)》中,介绍了TAnimation的多数子类,本节将对TRectAnimation、TPathAnimation和TBitmapListAnimation这3个子类进行介绍。

本节将介绍的主题如下:

  1. 使用TPathAnimation创建路径跟随的小球。
  2. 使用TBitmapListAnimation打造奔跑的小人动画
  3. 使用TRectAnimation打造内外边距移动动画

1. 使用TPathAnimation创建路径动画

TPathAnimation动画允许我们将目标控件沿一段矢量路径进行动画。在本系列的《一步一步学习使用FireMonkey动画(1)》中,演示了如何使用TPathAnimation的Path属性进行路径的绘制,例如类传如下的代码:

Pascal 复制代码
  PathAnimation1.Path.MoveTo(PointF(0, 0));

TPathAnimation 并不从 TCustomPropertyAnimation 继承,尽管它处理了目标对象的一些属性。处理的属性( Position 和 RotationAngle )只是硬编码到动画对象中。

TPathAnimation的Path属性接收矢量图形数据,可以在网站上找一些svg的矢量素材来使用,比如:

https://www.svgviewer.dev/

这个网站提供了很多的素材,可以复制Path路径中的路径数据,如下图所示:

下面以TPath组件为例,它的Path属性与TPathAnimation类似,它提供了一个可视化的编辑器,可以实时的查看矢量路径。

还可以使用svg编辑工具,比如InkScape,它完全免费且开源,可以在如下的网址下载:

https://inkscape.org/

可以使用这个工具绘制矢量图形,导出为svg格式的文件,这个文件是一个XML格式的文件,用记事本打开,复制其中的矢量路径到TPath或TPathAnimation的Path属性即可。

比如我在InkSacpe中使用钢笔工具随便画了一段线条:

接下来将其导出为svg文件,用记事本打开这个文件,将其d部分的属性值拷贝到TPath的Data属性中:

这样成功的得到了一条路径。

注意:FireMonkey 支持通过多个组件(如 TPath 、 TPath3D 和 TLabelPath )使用可缩放矢量图形(SVG)。这些组件都使用一个内部数据结构( TPathData ,定义在 FMX.Graphics 中),该结构可以解析和使用来自 SVG 定义的图形数据。

接下来新建一个Multi Deivce应用程序,使用空白模板,在主窗体上放一个TPath,然后将我们在《一步一步学习使用FireMonkey动画(3)》中创建的弹跳小球复制到本项目中。为弹跳小球添加一个TPathAnimation动画。

Structure结构如下所示:

分别为TPathAnimation的Path属性以及TPath的Data属性指定如下的路径数据:

M3.84500002861023,3.47300004959106 C4.83799982070923,24.6110000610352 26.2040004730225,34.9749984741211 42.875,30.8320007324219 C69.8730010986328,24.121000289917 82.1620025634766,-9.76099967956543 74.6009979248047,-37.4169998168945 C63.992000579834,-76.2160034179688 23.7210006713867,-93.3140029907227 -9.33600044250488,-80.4909973144531 C-52.2709999084473,-63.8380012512207 -70.8339996337891,-8.08600044250488 -55.2200012207031,37.6059989929199 C-35.9000015258789,94.1429977416992 24.3759994506836,118.28099822998 73.6240005493164,96.3960037231445 C132.567993164063,70.2020034790039 157.505996704102,-7.92000007629395 133.664993286133,-71.5500030517578 C105.81600189209,-145.880996704102 25.3040008544922,-177.113998413086 -40.0859985351563,-146.054992675781 C-95.6880035400391,-119.646003723145 -129.975997924805,-55.0750007629395 -127.064002990723,11.4790000915527

Path Designer窗口如下所示:

最后,在属性面板设置TPathAnimation动画属性:

除了AnimationType和Interpolation暂时还未详细介绍外,这里还有一个Rotate属性,该属性的意思是:

指定动画过程中对象是否旋转。使用 Rotate 属性可设定父控件在动画期间是否进行旋转。若将 Rotate 设置为 True,控件将进行旋转:正向动画时控件底部朝向路径方向,反向动画时控件顶部朝向路径方向。

运行动画,可以看到弹跳小球已经按照路径在运动。

仔细观察可以看到小球实际上是在旋转的。

最后来一个画蛇添足,为小球的运动添加一些轨迹,这里需要响应TPathAnimation的OnProcess事件,这个事件在每一次动画间隔(也就是每一帧刷新时)需要刷新动画显示时触发。

Pascal 复制代码
private
    { Private declarations }
    FDotPosition:TPointF; // 声明一个私有字段,用于存储上一次记录的点位置(TPointF类型,包含X和Y坐标)
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.fmx}

procedure TfrmMain.PathAnimation1Process(Sender: TObject);
const CircleSize = 4; // 定义常量,表示绘制圆点的大小
begin
  if FDotPosition.Distance(CircleBall.Position.Point) > CircleSize then // 判断当前球位置与上次记录点之间的距离是否大于圆点尺寸
  begin
    FDotPosition := CircleBall.Position.Point/2; // 计算新位置:将球当前位置坐标除以2(可能是为了缩小轨迹)
    var LDot := TCircle.Create(Self); // 动态创建一个圆形控件(TCircle实例)
    try
      LDot.Parent := Self; // 设置圆形的父容器为当前窗体,使其显示在窗体上
      LDot.Height := CircleSize; // 设置圆形的高度为预设的圆点尺寸
      LDot.Width := CircleSize; // 设置圆形的宽度为预设的圆点尺寸
      LDot.Position.Point := FDotPosition; // 将圆形定位到计算得到的新坐标位置
      LDot.Position.Point.Offset(-CircleSize/2,-CircleSize/2); // 调整位置:将圆心偏移(-半径值),使绘制点以中心为基准(通常用于居中显示)
    except
      LDOt.Free; // 异常处理:如果创建或设置过程中发生错误,则释放已创建的圆形对象
    end;
  end;
end;

这样当弹跳小球沿路径运动时,会显示一个轨迹:

通过这个轨迹,可以发现,每一次动画的刷新时间似乎并不固定,这是由于不同的插值设置所影响的。

在后续的内容中会介绍动画的一些属性和事件的作用,敬请关注。

2. 使用TBitmapListAnimation打造奔跑的小人动画

这个控件让我们可以将一系列的连续的静态图片动起来,比如有下面的一幅图片:

TBitmapListAnimation通过将多个动画帧组合在一个图像条带中,然后按顺序快速切换这些帧来实现动画播放,非常适合处理那些不适合用矢量路径或属性插值实现的复杂动画(例如角色动画、特效等)。

它具有如下的一些新的属性:

  • AnimationBitmap 设置源图像,包含所有动画帧的长条带状位图。
  • AnimationCount 指定动画的总帧数。
  • AnimationRowCount 指定源图像中动画的行数,常用于打包多组动画。
  • PropertyName 指定要动画化的目标属性,对于序列帧动画,这通常是 Bitmap。

上面的图中,一共有5行图片,总共是30帧。

下面拉一个TRectangle控件到窗体,然后放一个TBitmapListAnimation在其上面,使TBitmapListAnimation的Parent指向TRectangle。

为TBitmapListAnimation的AnimationBitmap指定上面的图片,设置 AnimationCount为30,AnimationRowCount为5。

现在运行这个示例,可以看到小人已经在奔跑了。

是不是有一些电影小视频的效果了。

3. 使用TRectAnimation创建内外边距动画。

RectAnimation 是为了处理 FMX 视觉对象的 Padding 和 Margins 属性而引入的常见情况。这里涉及到的数据结构是 TBounds (定义在 FMX.Types 单元中),它是 FMX 中边距和填充的实际类型。

  • Padding:是指控件的内边距,是控件边缘和内部的子元素之间的距离。
  • Margins:是指控件的外边距,是控件的外边缘和其容器的边缘之间的距离。

它们均为TBound类型,具有Left、Top、Bottom、Right 4个属性,通过使用TRectAnimation,则可以创建内外边距的移动效果。

请在主窗体上拖一个TRectangle控件,拖一个TRectAnimation以它作为父项,在其内部再放一个TRectangle,指定其Align为Client,占满整个矩形。

为TRectAnimation设置如下的属性:

Pascal 复制代码
      AnimationType = InOut
      AutoReverse = True
      Enabled = True
      Duration = 2
      Interpolation = Exponential
      Loop = True
      PropertyName = 'Padding'
      StopValue.Left = 50
      StopValue.Top = 50
      StopValue.Right = 50
      StopValue.Bottom = 50

这里StartValue保持了默认的全是0,StopValue全部设置为50,PropertyName只能选择Margins和Padding,这里选择了Margins,现在运行动画,可以看到内边距果然产生了动画效果。

总结

本章介绍了3个有意思也是特别有创意的控件,一个是矢量路径动画TPathAnimation,一个是位图动画控件TBitmapListAnimation,还有一个内外边距变化的TRectAnimation控件,它们都可以创造出令人惊叹的动画效果。对于程序员来说,可能并不缺动画工具,而是缺那么一丝丝创意了。

相关推荐
lincats4 小时前
一步一步学习使用FireMonkey动画(6) 用实例理解动画的运行状态
ide·delphi·livebindings·delphi 12.3·firemonkey
lincats11 小时前
一步一步学习使用FireMonkey动画(5) 动画图解11种动画插值类型
ide·移动开发·delphi 12.3·firedac·firemonkey
lincats1 天前
一步一步学习使用FireMonkey动画(3) 使用Delphi的基本动画组件类
ide·delphi·delphi 12.3·firemonkey
lincats1 天前
一步一步学习使用FireMonkey动画(2) 使用TAnimator类创建动画
ide·delphi 12.3·firedac·firemonkey
lincats2 天前
一步一步学习使用FireMonkey动画(1) 使用动画组件为窗体添加动态效果
android·ide·delphi·livebindings·delphi 12.3·firemonkey
lincats6 天前
一步一步学习使用LiveBindings(16)使用代码创建LiveBindings绑定
delphi·livebindings·delphi 12.3·firedac·firemonkey
lincats8 天前
一步一步学习使用LiveBindings(15)TListView进阶使用(3),创建自定义的列表项打造天气预报程序
delphi 12.3·firedac·firemonkey·tlistview
lincats9 天前
一步一步学习使用LiveBindings(14)TListView进阶使用(2),打造天气预报程序
delphi·livebindings·delphi 12.3·firedac·firemonkey·tlistview
lincats10 天前
一步一步学习使用LiveBindings(13) TListView的进阶使用(1)
delphi·livebindings·delphi 12.3·firemonkey·tlistview