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)
)