# 动画效果 2.B 提供了专门的动画接口,允许你用短短几行就可以做出一个效果不错的动画。本节主要讲述的是 UI 中的动画。 ## 定义动画属性 我们以一个自定义 UI 为例,来讲述如何编写一段动画。自定义 UI 参考[此指南](./new-ui.md)和[此教程](../../guide/ui.md)。 假设自定义 UI 在 `packages-user/client-modules/src/render/ui` 文件夹下,我们需要引入 `transitioned` 接口,并调用它定义动画属性: ```tsx {8-13} // 引入接口,如果文件夹不同,注意路径关系 import { transitioned } from '../use'; // 从 mutate-animate 库中引入速率曲线函数 import { hyper } from 'mutate-animate'; // UI 模板及如何编写 UI 参考 “新增 UI” 需求指南,这里只给出必要的修改部分,模板部分不再给出 export const MyCom = defineComponent(() => { // 定义动画属性 const value = transitioned( 1, // 初始值是 1 500, // 动画时长 500ms hyper('sin', 'out') // 速率曲线是双曲正弦函数(此曲线观感较好) )!; // 上一行的感叹号为非空断言,因为此接口在组件或 UI 外调用会返回 null, // 而我们在 UI 内,因此我们需要断言其不可能为 null return () => ; }); ``` 注意 `transitioned` 只能在 UI 或组件的顶层调用,不能在 UI 的函数内调用,也不可在 UI 外调用,在其他地方调用会返回 `null`! ## 添加到元素属性 定义属性后,我们需要把属性添加到元素上,直接使用 `value.ref.value` 即可,这里以不透明度 `alpha` 属性为例: ```tsx {9} // UI 模板及如何编写 UI 参考 “新增 UI” 需求指南,这里只给出必要的修改部分,模板部分不再给出 export const MyCom = defineComponent(() => { // 定义动画属性 const value = transitioned(1, 500, hyper('sin', 'out'))!; return () => ( {/* 将 value.ref.value 赋值给 alpha 属性 */} ); }); ``` ## 执行动画 最后,在我们需要的时候执行动画即可,使用 `value.set`: ```tsx export const MyCom = defineComponent(() => { // 定义动画属性 const value = transitioned(1, 500, hyper('sin', 'out'))!; // 例如在 UI 挂载完毕后执行 onMounted(() => { // 动画属性调成 0,效果就是矩形逐渐从不透明变成完全透明 value.set(0); }); return () => ( ); }); ``` ## 拓展-颜色动画 除了一般数值的动画外,样板还支持颜色动画,使用 `transitionedColor` 接口,用法与 `transitioned` 基本一致: ```tsx {23} // 引入接口,如果文件夹不同,注意路径关系 import { transitionedColor } from '../use'; // [!code ++] // 从 mutate-animate 库中引入速率曲线函数 import { hyper } from 'mutate-animate'; export const MyCom = defineComponent(() => { // 定义颜色动画 const color = transitionedColor( '#fff', // 初始颜色,设定为白色 // [!code ++] 1000, // 动画时长 1s hyper('sin', 'out') // 动画速率曲线 )!; // 例如在 UI 挂载完毕后执行 onMounted(() => { // 颜色调成纯黑 color.set('#000'); // [!code ++] }); return () => ( {/* 将 fillStyle 赋值为 color.ref.value */} ); }); ``` 颜色目前仅支持输入 `#RGB` `#RGBA` `#RRGGBB` `#RRGGBBAA` `rgb(r,g,b)` `rgba(r,g,b,a)` 几种格式的字符串。 ## 拓展-配合交互 我们可以配合交互实现以下几种功能: ### 鼠标移入移出 当鼠标移入时高亮,当移出时恢复: ```tsx {8-11,19-20} import { transitionedColor } from '../use'; import { hyper } from 'mutate-animate'; export const MyCom = defineComponent(() => { // 初始颜色为灰色 const color = transitionedColor('#aaa', 200, hyper('sin', 'out'))!; /** 鼠标移入时变成白色 */ const enter = () => color.set('#fff'); /** 鼠标移出时恢复为灰色 */ const leave = () => color.set('#aaa'); return () => ( ); }); ``` ### 点击切换状态 鼠标点击或触碰点击后高亮,再次点击恢复: ```tsx {8-15,23} import { transitionedColor } from '../use'; import { hyper } from 'mutate-animate'; export const MyCom = defineComponent(() => { // 初始颜色为灰色 const color = transitionedColor('#aaa', 200, hyper('sin', 'out'))!; let highlight = false; /** 点击时触发 */ const click = () => { // 如果已经高亮,那么恢复为灰色,否则高亮为白色 color.set(highlight ? '#aaa' : '#fff'); // 切换状态 highlight = !highlight; }; return () => ( ); }); ``` ## 拓展-API 参考 参考[此 API 文档](../../api/user-client-modules/functions.md#transitioned)。