跳到主要内容

Animations

隐式动画

使用隐式动画,可以通过设置控件属性的目标值来动画控件属性;每当目标值更改时,控件将从旧值动画到新值。动画将在给定的持续时间内生成旧值和新值之间的插值。默认情况下,动画将线性地增加动画值,但是可以应用曲线来更改动画值的增加方式。例如,easeOutCubic 曲线将快速增加动画值,然后慢慢达到目标值。

每个 Control 都提供了一些 animate_{something} 属性,以启用其外观的隐式动画:

  • animate_opacity
  • animate_rotation
  • animate_scale
  • animate_offset
  • animate_position
  • animate (Container)

animate_* 属性可以具有以下值之一:

  • animation.Animation 类的实例 - 允许配置动画的持续时间(以毫秒为单位)和曲线,例如 animate_rotation=ft.animation.Animation(duration=300, curve="bounceOut")。请参阅 Flutter 文档中的 Curves 以获取可能的值。默认为 linear
  • 整数值 - 启用具有指定持续时间(以毫秒为单位)和 linear 曲线的动画。
  • 布尔值 - 启用具有 1000 毫秒持续时间和 linear 曲线的动画。

不透明度动画

将控件的 animate_opacity 设置为 True、数字或 animation.Animation 类的实例(见上文),以启用控件的不透明度动画。

import flet as ft

def main(page: ft.Page):

c = ft.Container(
width=150,
height=150,
bgcolor="blue",
border_radius=10,
animate_opacity=300,
)

def animate_opacity(e):
c.opacity = 0 if c.opacity == 1 else 1
c.update()

page.add(
c,
ft.ElevatedButton(
"Animate opacity",
on_click=animate_opacity,
),
)

ft.app(target=main)

旋转动画

将控件的 animate_rotation 设置为 True、数字或 animation.Animation 类的实例(见上文),以启用控件的旋转动画。

from math import pi
import flet as ft

def main(page: ft.Page):

c = ft.Container(
width=100,
height=70,
bgcolor="blue",
border_radius=5,
rotate=ft.transform.Rotate(0, alignment=ft.alignment.center),
animate_rotation=ft.animation.Animation(300, ft.AnimationCurve.BOUNCE_OUT),
)

def animate(e):
c.rotate.angle += pi / 2
page.update()

page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.spacing = 30
page.add(
c,
ft.ElevatedButton("Animate!", on_click=animate),
)

ft.app(target=main)

缩放动画

将控件的 animate_scale 设置为 True、数字或 animation.Animation 类的实例(见上文),以启用控件的缩放动画。

import flet as ft

def main(page: ft.Page):

c = ft.Container(
width=100,
height=100,
bgcolor="blue",
border_radius=5,
scale=ft.transform.Scale(scale=1),
animate_scale=ft.animation.Animation(600, ft.AnimationCurve.BOUNCE_OUT),
)

def animate(e):
c.scale = 2
page.update()

page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.spacing = 30
page.add(
c,
ft.ElevatedButton("Animate!", on_click=animate),
)

ft.app(target=main)

偏移动画

将控件的 animate_offset 设置为 True、数字或 animation.Animation 类的实例(见上文),以启用控件的偏移动画。

offset 属性是一个 transform.Offset 类的实例,指定控件相对于其大小的水平 x 和垂直 y 偏移。例如,偏移 transform.Offset(-0.25, 0) 将导致控件水平平移一个四分之一宽度。

偏移动画用于各种滑动效果:

import flet as ft

def main(page: ft.Page):

c = ft.Container(
width=150,
height=150,
bgcolor="blue",
border_radius=10,
offset=ft.transform.Offset(-2, 0),
animate_offset=ft.animation.Animation(1000),
)

def animate(e):
c.offset = ft.transform.Offset(0, 0)
c.update()

page.add(
c,
ft.ElevatedButton("Reveal!", on_click=animate),
)

ft.app(target=main)

位置动画

将控件的 animate_position 设置为 True、数字或 animation.Animation 类的实例(见上文),以启用控件的位置动画。

请注意,控件位置仅在 Stack 控件中生效。

import flet as ft

def main(page: ft.Page):

c1 = ft.Container(width=50, height=50, bgcolor="red", animate_position=1000)

c2 = ft.Container(
width=50, height=50, bgcolor="green", top=60, left=0, animate_position=500
)

c3 = ft.Container(
width=50, height=50, bgcolor="blue", top=120, left=0, animate_position=1000
)

def animate_container(e):
c1.top = 20
c1.left = 200
c2.top = 100
c2.left = 40
c3.top = 180
c3.left = 100
page.update()

page.add(
ft.Stack([c1, c2, c3], height=250),
ft.ElevatedButton("Animate!", on_click=animate_container),
)

ft.app(target=main)

动画容器

Container.animate 设置为 True、数字或 animation.Animation 类的实例(见上文),以启用容器属性的隐式动画,如大小、背景颜色、边框样式、渐变。

import flet as ft

def main(page: ft.Page):

c = ft.Container(
width=150,
height=150,
bgcolor="red",
animate=ft.animation.Animation(1000, ft.AnimationCurve.BOUNCE_OUT),
)

def animate_container(e):
c.width = 100 if c.width == 150 else 150
c.height = 50 if c.height == 150 else 150
c.bgcolor = "blue" if c.bgcolor == "red" else "red"
c.update()

page.add(c, ft.ElevatedButton("Animate container", on_click=animate_container))

ft.app(target=main)

动画内容切换器

AnimatedSwitcher 允许在新控件和 AnimatedSwitcher 中的控件之间进行动画过渡。

import time

import flet as ft

def main(page: ft.Page):

i = ft.Image(src="https://picsum.photos/150/150", width=150, height=150)

def animate(e):
sw.content = ft.Image(
src=f"https://picsum.photos/150/150?{time.time()}", width=150, height=150
)
page.update()

sw = ft.AnimatedSwitcher(
i,
transition=ft.AnimatedSwitcherTransition.SCALE,
duration=500,
reverse_duration=500,
switch_in_curve=ft.AnimationCurve.BOUNCE_OUT,
switch_out_curve=ft.AnimationCurve.BOUNCE_IN,
)

page.add(
sw,
ft.ElevatedButton("动画!", on_click=animate),
)

ft.app(target=main)

动画结束回调

所有具有 animate_* 属性的控件都有 on_animation_end 事件处理程序,当动画完成时调用,可用于链接多个动画。

事件对象 data 字段包含动画的名称:

  • opacity(不透明度)
  • rotation(旋转)
  • scale(缩放)
  • offset(偏移)
  • position(位置)
  • container(容器)

例如:

 c = ft.Container(
ft.Text("动画我!"),
# ...
animate=ft.animation.Animation(1000, "bounceOut"),
on_animation_end=lambda e: print("容器动画结束:", e.data)
)