HumanBreak/docs/guide/implements/animate.md
2025-08-22 18:14:18 +08:00

5.6 KiB
Raw Blame History

动画效果

2.B 提供了专门的动画接口,允许你用短短几行就可以做出一个效果不错的动画。本节主要讲述的是 UI 中的动画。

定义动画属性

我们以一个自定义 UI 为例,来讲述如何编写一段动画。自定义 UI 参考此指南此教程

假设自定义 UI 在 packages-user/client-modules/src/render/ui 文件夹下,我们需要引入 transitioned 接口,并调用它定义动画属性:

// 引入接口,如果文件夹不同,注意路径关系
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 () => <container></container>;
});

注意 transitioned 只能在 UI 或组件的顶层调用,不能在 UI 的函数内调用,也不可在 UI 外调用,在其他地方调用会返回 null

添加到元素属性

定义属性后,我们需要把属性添加到元素上,直接使用 value.ref.value 即可,这里以不透明度 alpha 属性为例:

// UI 模板及如何编写 UI 参考 “新增 UI” 需求指南,这里只给出必要的修改部分,模板部分不再给出
export const MyCom = defineComponent(() => {
    // 定义动画属性
    const value = transitioned(1, 500, hyper('sin', 'out'))!;

    return () => (
        <container>
            {/* 将 value.ref.value 赋值给 alpha 属性 */}
            <g-rect rect={[0, 0, 100, 100]} alpha={value.ref.value} />
        </container>
    );
});

执行动画

最后,在我们需要的时候执行动画即可,使用 value.set

export const MyCom = defineComponent(() => {
    // 定义动画属性
    const value = transitioned(1, 500, hyper('sin', 'out'))!;

    // 例如在 UI 挂载完毕后执行
    onMounted(() => {
        // 动画属性调成 0效果就是矩形逐渐从不透明变成完全透明
        value.set(0);
    });

    return () => (
        <container>
            <g-rect rect={[0, 0, 100, 100]} alpha={value.ref.value} />
        </container>
    );
});

拓展-颜色动画

除了一般数值的动画外,样板还支持颜色动画,使用 transitionedColor 接口,用法与 transitioned 基本一致:

// 引入接口,如果文件夹不同,注意路径关系
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 () => (
        <container>
            {/* 将 fillStyle 赋值为 color.ref.value */}
            <g-rect rect={[0, 0, 100, 100]} fillStyle={color.ref.value} />
        </container>
    );
});

颜色目前仅支持输入 #RGB #RGBA #RRGGBB #RRGGBBAA rgb(r,g,b) rgba(r,g,b,a) 几种格式的字符串。

拓展-配合交互

我们可以配合交互实现以下几种功能:

鼠标移入移出

当鼠标移入时高亮,当移出时恢复:

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 () => (
        <container>
            <g-rect
                rect={[0, 0, 100, 100]}
                fillStyle={color.ref.value}
                // 监听 enter  leave 事件
                onEnter={enter}
                onLeave={leave}
            />
        </container>
    );
});

点击切换状态

鼠标点击或触碰点击后高亮,再次点击恢复:

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 () => (
        <container>
            <g-rect
                rect={[0, 0, 100, 100]}
                fillStyle={color.ref.value}
                // 监听 click 事件
                onClick={click}
            />
        </container>
    );
});

拓展-API 参考

参考此 API 文档