• 简体中文
  • 平滑化

    流式文本通常是成批到达的:有时只收到几个字,有时一次收到一整段。平滑化把接收和显示分开,让内容按更连贯的节奏出现在页面上。

    看见缓冲区

    下面的演示模拟大小不同的文本片段陆续到达。正常颜色是已经显示的内容,另一种颜色是已收到、仍在等待显示的缓冲内容。实际应用中,缓冲区里的文字暂时不可见。

    已上屏缓冲区

    新片段到达时,缓冲区先增长,显示边界再逐步跟上。可以暂停观察两者的位置,或重新播放,比较每次收到内容时的变化。

    弹簧如何调整节奏

    内置的 spring 调度器用显示位置和待显示内容之间的距离调整速度。积压内容较多时,输出加快;接近末尾时,速度逐步收敛。它保留前一帧的速度,让后续更新衔接起来。

    调度器按经过的时间计算进度,再把不足一个字符的部分留到下一次更新。这样,文字可以在两次网络更新之间继续显示,也不需要为每个字符设置固定延时。上面的演示使用与 Smooth mapper 相同的 SpringSmoothScheduler。

    在应用中使用

    选择对应框架查看代码。Core 示例中的 mappers 传入 Core 输入,只生成内容与效果标记,视觉呈现由渲染器完成;组件已内置对应渲染器。

    开启 streaming 就会使用默认的弹簧平滑化:

    import type { MapperPluggable } from '@fluxdown/core';
    import { Smooth } from '@fluxdown/core-plugins/plugins/mapper/smooth';
    import { Scale } from '@fluxdown/core-plugins/plugins/mapper/scale';
    import { MutableState, toClosure } from 'stative';
    
    const isStreaming = MutableState.of(true);
    const active = toClosure(isStreaming);
    
    const mappers: MapperPluggable[] = [
      [Smooth, { enabled: active }],
      [Scale, { enabled: active }],
    ];

    也可以显式指定调度器,并配合动画效果使用:

    import type { MapperPluggable } from '@fluxdown/core';
    import {
      RafSmoothTicker,
      Smooth,
      SpringSmoothScheduler,
    } from '@fluxdown/core-plugins/plugins/mapper/smooth';
    import { Shad } from '@fluxdown/core-plugins/plugins/mapper/shad';
    
    const mappers: MapperPluggable[] = [
      [
        Smooth,
        {
          enabled: true,
          ticker: RafSmoothTicker,
          scheduler: SpringSmoothScheduler,
        },
      ],
      [Shad, { enabled: true }],
    ];

    text 始终传入已经收到的完整内容。将 streaming 设为 false 后,剩余缓冲会立即显示;如果希望保留收尾过程,可以让平滑化继续开启。

    Core 使用同一个 Smooth mapper,输出经过截取的内容块,渲染层无需自己安排逐字更新。接入方式见 Core 状态与更新,完整选项见各框架的配置文档:React、Vue、Svelte、Angular、React Native、Lynx、Solid、Taro。

    Core 示例用 MutableState 保存接收状态;完成时调用 isStreaming.next(false),销毁 Core 后再调用 active.destroy() 和 isStreaming.destroy() 清理外部状态。