跳到正文

过渡与动画

用 .Transition(...) 为样式变化添加动画。每一帧都不会重新运行组件。

#悬停过渡

把过渡写在基础样式上,这样指针进入和离开时都会生效。

func HoverAction() *ui.Element {
	return ui.Button().Child("Continue").
		Padding(12).
		BorderRadius(8).
		BackgroundColor("#334155").
		TextColor("white").
		Opacity(0.85).
		Transition("background-color 160ms ease-out, opacity 160ms ease-out").
		Hover(func(s ui.StyleBuilder) ui.StyleBuilder { return s.BackgroundColor("#2563eb").Opacity(1) })
}

同样的写法也适用于 Active、Focus、Expanded 和 DragOver。

#状态驱动的动画

用信号或 .When 改变目标值。动画进行时保持该节点挂载。

func AnimatedSelection() *ui.Element {
	selected, setSelected := ui.CreateSignal(false)
	return ui.View().FlexCol().Gap(12).Children(
		ui.Button().Child("Toggle emphasis").OnClick(func() { setSelected(!selected()) }),
		ui.View().Child("Your selection").
			Padding(20).
			BorderRadius(12).
			BackgroundColor("#334155").
			TextColor("white").
			Opacity(0.6).
			Transition("background-color 180ms ease-out, opacity 180ms ease-out").
			When(selected, ui.Style().BackgroundColor("#2563eb"), ui.Style().Opacity(1)),
	)
}

过渡中途反向时,会从当前可见值继续。

#时长与帧率

多个属性共用同一套时间时,使用 ui.TransitionDeclaration。

func CappedTransition() *ui.Element {
	return ui.Button().Child("Hover me").Padding(12).BackgroundColor("#334155").TextColor("white").Opacity(0.8).
		Transition(ui.TransitionDeclaration{
			Properties: []string{"background-color", "opacity"},
			Duration:   180 * time.Millisecond,
			Easing:     "ease-out",
			MaxFps:     30,
		}).
		Hover(func(s ui.StyleBuilder) ui.StyleBuilder { return s.BackgroundColor("#2563eb").Opacity(1) })
}
字段用法
.TransitionProperty(...)属性名,逗号分隔的字符串或 []string。
.TransitionDuration(...)毫秒数、time.Duration,或 "180ms" / "0.18s"。时长限制为 0–10 秒。
.TransitionEasing(...)"linear"、"ease"、"ease-in"、"ease-out" 或 "ease-in-out"。
.TransitionMaxFps(...)可选的帧率上限。省略则跟随显示器。

一个节点对所选属性共用同一套时长、缓动和帧率上限。不支持延迟、cubic-bezier() 以及按属性分别计时。

ui.Style().Transition(180 * time.Millisecond) 会为背景、边框和文本颜色添加动画。"all" 包含所有支持的绘制属性。"none" 会移除该简写。

#支持的属性

过渡名称样式方法
background-color 或 background.BackgroundColor(...) 或纯色 .Background(...)
border-color.BorderColor(...)
border-width.BorderWidth(...)
border-radius.BorderRadius(...)
color.TextColor(...)
opacity.Opacity(...)
transform.Transform(...)
box-shadow.BoxShadow(...)

宽度、高度、内边距和渐变色标不会插值。滑动开关的滑块请使用 .Transform("translateX(20px)") 配合 .Transition("transform 160ms ease-out")。

#挂载与减少动态效果

过渡只对已存在节点上的变化做动画。ui.Show 会立即移除子节点,不会等待淡出。透明度为零的节点仍会参与布局并接收输入。

对话框用 EnterDuration 和 ExitDuration 控制关闭内容保持挂载的时间。见 Dialog。

过渡会遵循系统的「减少动态效果」设置。可用 native.WindowOptions.ReduceMotion 为单个窗口覆盖该设置。

#动态图像

把 GIF 或 WebP 路径传给 ui.Image。播放由文件本身决定,不需要定时器。

func AnimatedImage(path string) *ui.Element {
	return ui.Image().Value(path).
		Width(96).Height(96).ObjectFit("contain")
}

用 CLI 的 resources 选项打包文件。见打包资源和 Image。