JGuang

机器人头像

Bot Avatars · Libraries.dev

交互预览
npm install bot-avatars@0.2.2

机器人头像

Libraries.dev 的独立组件,请不要替换为 JGuang UI/Base UI 的同名 API。

安装

npm install bot-avatars@0.2.2

安装包后使用它自己的导出组件,支持 React 18+。Canvas/WebGL 组件需要浏览器环境;提供静态降级,并尊重减少动画偏好。声音预览使用模拟信号,不会自动申请麦克风。

使用与验证

在左侧选择组件,在预览中操作它的状态;使用“查看代码”检查真实源码。安装后执行类型检查和构建,再验证键盘焦点、手机布局与深浅色主题。

来源

https://github.com/Jakubantalik/Libraries.dev/tree/b7f44b8744f4e09ff088d824719636a513110e2a MIT 许可证;不包括付费内容。下方提供上游英文参考内容,中文使用指南已适配;上游详细参考暂保留英文。


适用场景

为智能体配置动画头像;本地示例默认使用较轻量的 crisp 材质。

关键原生参数

参数说明
type选择 18 种公开形状;path 可替换轮廓,但不会替换 type 决定的面部位置。
statedefault、working、sleeping 是视觉状态,不是任务完成事件。
shading可选 crisp/smooth/plastic/flat/fabric。fabric 毛发参数可能较重,不要未经测量就同时放置大量头像。
paused冻结动作。interactive 开启指针互动;暂停动画不会让画布成为具有完整语义的按钮。
theme显式同步应用深浅色;size 和 aria-label 保持原生画布 API。

交互与状态检查

检查状态、形状/材质切换、暂停/继续和指针互动。提供可访问名称,避免离屏头像持续累积。

业务接入边界

不包含智能体身份、图片上传、聊天传输或认证。装饰和公开预设属于 npm API,不代表可以复制付费 Studio 内容。

示例文件与宿主配置

从源码面板复制 examples 下的组件文件和 shared.tsx,保留它们的相对位置;不是只复制原生上游实现。先安装固定版本 npm 包,在浏览器组件中使用它自己的导出。示例不需要 Tailwind 或新的主题 Provider,采用宿主 html 的语言和主题,并提供减少动画与图形不可用降级。原生实现参考仅供阅读,通过 npm 导入,不要求手工复制内部引擎。示例场景名称不是新增的原生组件属性。下方上游详细参考保留英文,不宣称全文中文化。

可运行用法

以下代码使用资源原生 API;不是把其他设计系统的同名组件替换进来。

"use client";
import { useState } from "react";
import { BotAvatar, type BotAvatarType, type BotAvatarState, type BotAvatarShading } from "bot-avatars";
import { DemoFrame, GraphicsGuard, control, demoTheme, t } from "./shared";
export default function Example({ variant = "Default" }: { variant?: string }) {
  const shapes: BotAvatarType[] = ["clover", "flower", "triangle", "square", "blob", "ghost", "circle", "drop", "star", "droid", "mech", "alien", "hexagon", "cat", "cloud", "pill", "pebble", "puddle"];
  const [type, setType] = useState<BotAvatarType>("clover"), [state, setState] = useState<BotAvatarState>(variant === "Working" ? "working" : variant === "Sleeping" ? "sleeping" : "default"), [shading, setShading] = useState<BotAvatarShading>("crisp"), [paused, setPaused] = useState(variant === "Paused");
  return <DemoFrame status={`type=${type}, state=${state}, shading=${shading}, paused=${paused}`} controls={<>
    <label>{t("Shape", "形状")} <select style={control} aria-label={t("Avatar shape", "头像形状")} value={type} onChange={e => setType(e.target.value as BotAvatarType)}>{shapes.map(s => <option key={s}>{s}</option>)}</select></label>
    <label>{t("State", "状态")} <select style={control} aria-label={t("Avatar state", "头像状态")} value={state} onChange={e => setState(e.target.value as BotAvatarState)}>{["default", "working", "sleeping"].map(s => <option key={s}>{s}</option>)}</select></label>
    <label>{t("Material", "材质")} <select style={control} aria-label={t("Avatar material", "头像材质")} value={shading} onChange={e => setShading(e.target.value as BotAvatarShading)}>{["crisp", "smooth", "plastic", "flat", "fabric"].map(s => <option key={s}>{s}</option>)}</select></label>
    <button type="button" style={control} aria-pressed={paused} onClick={() => setPaused(!paused)}>{paused ? t("Resume", "继续动画") : t("Pause", "暂停动画")}</button>
  </>}><GraphicsGuard><BotAvatar type={type} state={state} shading={shading} size={100} color="#2F67FF" theme={demoTheme()} paused={paused} aria-label={t(`Demo ${type} avatar, ${state}`, `演示 ${type} 头像,${state}`)} /></GraphicsGuard></DemoFrame>;
}

可用状态与示例

待机、工作中、休眠、暂停动画

组件中的状态与数据为演示用途,不包含后端接口。接入实际项目时请检查源码中的公开参数,再连接业务数据。

bot-avatars

Animated bot avatars for React. Eighteen simple 3D shapes with living faces — round eyes that blink and glance, an optional mouth — and three states an agent can be in: idle, working and sleeping. Each one turns its head, looks around, hops and flips, and every state change is a cross-animation. Vector shapes drawn on a 2D canvas as a lit, inflated body in plush faux fur (or glossy plastic): no WebGL, no runtime dependencies.

Live demo · Repository · Report an issue

Install

npm install bot-avatars

Quick start

import { BotAvatar } from 'bot-avatars';

function Agent({ busy }: { busy: boolean }) {
  return <BotAvatar type="clover" state={busy ? 'working' : 'default'} />;
}

Types

Eighteen bodies, each with its own colour:

<BotAvatar type="clover" />    {/* sky */}
<BotAvatar type="flower" />    {/* green */}
<BotAvatar type="triangle" />  {/* magenta */}
<BotAvatar type="square" />    {/* sky */}
<BotAvatar type="blob" />      {/* green */}
<BotAvatar type="ghost" />     {/* white */}
<BotAvatar type="circle" />    {/* lavender */}
<BotAvatar type="drop" />      {/* teal */}
<BotAvatar type="star" />      {/* yellow */}
<BotAvatar type="droid" />     {/* pale, antenna ball, round ears */}
<BotAvatar type="mech" />      {/* slate, wide head, two antennae */}
<BotAvatar type="alien" />     {/* lime, wide brow, narrow chin */}
<BotAvatar type="hexagon" />   {/* coral nut */}
<BotAvatar type="cat" />       {/* apricot, round head, two ears */}
<BotAvatar type="cloud" />     {/* pale sky, five puffs */}
<BotAvatar type="pill" />      {/* indigo, a wide capsule */}
<BotAvatar type="pebble" />    {/* sage, a wide flat stone */}
<BotAvatar type="puddle" />    {/* pink, a taller lumpy blob */}

Your own shape

path takes SVG path data for the body outline, in a 100×100 box centred on (50, 50), in place of the type's own. It is inflated, lit and animated like any stock shape. The type still sets where the face sits, the default colour and the label, so keep the outline solid round the face.

const heart = 'M50 88C50 88 12 64 12 38C12 24 23 14 35 14C42 14 47 18 50 23C53 18 58 14 65 14C77 14 88 24 88 38C88 64 50 88 50 88Z';

<BotAvatar type="circle" path={heart} color="#ff5c8a" />

The stock outlines are exported as botAvatarShapes, a good place to start from.

Faces

The eyes alone by default. face="mouth" adds a small mouth that changes with the state:

<BotAvatar type="clover" face="mouth" />

States

<BotAvatar state="default" />   {/* idle: turns to look around, blinks, a jump with a full turn now and then */}
<BotAvatar state="working" />   {/* busy: hopping — every third hop a spin — with a wide smile and the odd laugh */}
<BotAvatar state="sleeping" />  {/* head down, lids shut, slow breaths and the odd nod */}

Every state is a resting pose plus its own motion. The pose is a small rig — yaw, pitch, roll, position, squash, eyes — and a state switch eases from the old targets to the new ones on a timed curve (soft start, soft finish), so it never snaps or creeps. With prefers-reduced-motion: reduce (or paused) the still pose of the state is drawn instead.

Colour

<BotAvatar type="blob" color="#ff5c8a" />          {/* any body colour */}
<BotAvatar type="clover" color="#111" />            {/* the ink turns light on a dark body */}
<BotAvatar type="star" ink="#4D7CFF" />             {/* or pick the ink yourself */}
<BotAvatar type="drop" brightness={1.25} />          {/* lighter body; below 1 darker */}
<BotAvatar type="drop" saturation={0.7} />           {/* duller body; the default is 1.5 (or the type's own), more vivid than the palette */}
<BotAvatar type="clover" saturation={2.2} />         {/* past 1.5 (up to 2.5) more vivid: richer colour, richer shade, coloured light */}
<BotAvatar type="clover" paused pose={{ yaw: 0.8, pitch: -0.2 }} />  {/* held turned round, as a 3D viewer would */}
<BotAvatar type="clover" shading="plastic" />       {/* glossy plastic instead of the default plush fur */}
<BotAvatar type="square" shading="crisp" />         {/* a lit rim with a clean edge */}
<BotAvatar type="square" shading="smooth" />        {/* soft shadow and highlight, no edge */}
<BotAvatar type="square" shading="flat" />          {/* keep the depth, drop the lighting */}

The palette is exported as botAvatarPalette (type → colour), with botAvatarPresets carrying each type's face and label (and, for a few, their own brightness and saturation).

Shading

fabric is the default, a plush fur (below); plastic is a real material, shaded per pixel: the outline is baked once into a pillow height field (lobes become domes, rays become tubes, the cusps between them fall into shadow), and every frame a lit sphere is evaluated for the head's pose — wrap-around diffuse, a tight hot spot and a broad sheen, a Fresnel rim under a sky, a window reflection, saturated shadows — and mapped onto it. fabric dresses the same form in a plush faux fur, like a toy's, under a strong studio light: a key from the upper left, low and from round the side, with a clear terminator and a real shade side (the colour deepened, never grey, with a saturated band where the key turns into shade), a dim fill, the floor's shade under the body, and a back light from behind the toy that the fibres carry through to a bright rim over the top and the side away from the key, the edge's hairs glowing. Single fibres catch the key as highlights along the locks where it grazes them. backLight sets where the light behind comes from, lightFront how far round to the front the key sits, shine the fibres' highlights, backSoftness how soft the back light is (crisp hairs to an even glow), sheen the smooth satin light over the edge (0 for a matte pile), and rim the back light's strength. The fur is a volume, not a texture: tapered locks lie on the curved body, each a lit mound with a shaded side and a contact shadow under the tip of the one above, made of fine strands with dark roots and lighter tips that cast thin shadows into the pile, gathered into tufts with darker partings between them; it covers the whole body as one continuous pile, round the sides and the back as it turns, its gaps a deep shade of the body's own colour. The silhouette is a soft halo: a haze of fine hairs lit toward their tips, broken into tufts, laid round the whole turned body, so a side view or a flip is as fuzzy as the front. Fabric has its own default light (shadow 1.15, highlight 1.45, light 295, rim 0.6, spread 1.6, lightFront 32, shine 0, sheen 0, backSoftness 1).

Both are drawn on an inflated body: thickest in the middle and rounding off to nothing at the outline all round, like a cushion or a plush toy, so a turn shows a round side rather than the wall of an extruded shape, smooth all the way round to a side view. roundness (0–1, default 1) bends that profile toward a slab with soft edges. crisp lights a rim round the front with a clean edge, smooth lays a soft shadow and highlight over the whole form, flat keeps only the depth. The light itself is adjustable:

<BotAvatar
  shadow={1.4}      // 0–2, strength of the shadow side (default 1.15 in fabric, 0.35 in the others)
  highlight={0.6}   // 0–2, strength of the lit side (default 1.45 in fabric, 1.3 in the others)
  light={265}       // degrees clockwise from the top (default 295 in fabric, 300 in the others: the upper left)
  depth={1.5}       // 0.2–2, thickness shown when the head turns (default 0.65)
  roundness={0.5}   // 0–1, plastic and fabric: a cushion at 1, toward a slab at 0 (default 1)
  rim={1.5}         // 0–2, strength of the back light in fabric, of the Fresnel rim in plastic, rim width in crisp (default 0.6 in fabric, 0.5 in the others)
  spread={0.7}      // 0.4–2.5, how far the light wraps round in fabric, width of the highlight in plastic, reach of the soft shading in smooth (default 1.6 in fabric, 1.55 in the others)
/>

The plush pile has a style of its own:

<BotAvatar
  furLength={2}     // 0.3–2.5, length of the pile (default 1)
  furDensity={1}    // 0.3–2, how many fibres (default 1.6)
  furFuzz={0.5}     // 0–1, the haze of hairs at the silhouette (default 0.9)
  furClumps={0.7}   // 0–1, how much the fibres gather into tufts (default 0.4)
  furCurl={0.5}     // 0–1, straight to wavy (default 0.7)
  furGravity={0.4}  // 0–1, how much it hangs: combed down from the top, hanging off the sides (default 0.9)
/>

Each style is baked once per shape on idle time and shared by every avatar that wears it.

Wear

A hat, glasses, headphones and a bow tie, each a small 3D object built from lit surfaces and placed on the body's own shape — the hat seated where the head is wide enough to hold it, the headphones on its widest row with the band resting on the head, the glasses over the eyes, the bow tie under the face — and turned with the head, so it tips, turns and flips with the body. They are lit from the body's light and cast a soft shadow where they sit. Each surface is built once per shape and size and painted a strip at a time with the light carried along it, so a hat is a few dozen canvas fills — about 0.2–0.8 ms a frame at 120 px.

<BotAvatar type="clover" hat="beret" />
<BotAvatar type="triangle" glasses="round" bowTie />
<BotAvatar type="flower" headphones accessoryColor="#f4efe6" />
  • hat: none (default), beret (pleated felt with a leather binding and a stalk), beanie (knit stitch by stitch, with a ribbed cuff and a yarn pompom), party (a striped paper cone with a foil trim and tinsel) or crown (gold, with ridged points, pearls, cut stones, a velvet cap and an orb and cross)
  • the headphones are over-ear: leather cushions, brushed metal rings and yokes, a stitched padded band; the glasses are acetate with rounded rims and reflecting lenses; the bow tie is satin, or felt on a plush body
  • glasses: none (default), round, square or shades
  • headphones, bowTie: booleans
  • accessoryColor: the hat's, the headphones' and the bow tie's colour, a soft black by default (the crown stays gold)

Other props

<BotAvatar
  type="star"
  size={40}            // px, or any CSS length; default 64
  speed={1.5}          // multiplier on every animation
  paused={false}       // freeze on the current frame
  seed={0.3}           // 0–1: offsets the blink and glance loops; auto by default
  interactive={false}  // no pointer following, no hop on click
  theme="light"        // the surface the avatar sits on; auto by default
  aria-label="Talent scout, working"  // overrides the per-state default
/>

All other <canvas> props (className, style, onClick, data-*, …) pass through. The canvas draws a little larger than its box and pulls itself back with negative margins, so a hop or a flip is never clipped while the layout stays exactly size square.

Drawing it yourself

The rig and the renderer are exported for custom uses — a filmstrip, a sprite sheet, another canvas:

import { BotAvatarSim, drawBotAvatarFrame, botAvatarShapes, botAvatarPresets, autoInk, BOT_AVATAR_OVERSCAN } from 'bot-avatars';

const sim = new BotAvatarSim(0.5, 'working');
sim.update(1 / 60); // advance a frame
drawBotAvatarFrame(ctx, 64, sim.pose, {
  path: new Path2D(botAvatarShapes.clover),
  ...botAvatarPresets.clover, // face, faceX, faceY, faceScale, color
  ink: autoInk(botAvatarPresets.clover.color),
  shading: 'plastic',
  typeKey: 'clover', // names the outline for the material caches, the key warmBotAvatarPlastic takes
  dpr: devicePixelRatio, // the scale the context is set to (optional; else read from the context)
  sides: 'auto', // plastic's side slices: 'vector' fills, or 'sprite' blits (what WebKit gets by default)
}); // on a canvas 64 * BOT_AVATAR_OVERSCAN * devicePixelRatio px square; the body's centre sits BOT_AVATAR_RISE * 64 below its middle

In plastic and fabric the first frame of a new type bakes its form (a few ms, done on idle time when an animation loop is running; the smooth look stands in until then). warmBotAvatarPlastic(type, path, devicePx) bakes ahead of time; warmBotAvatarPlastic(type, path, devicePx, depth, true) also queues fabric's pile, in small steps on idle time.

The idle look

Idle, the head looks to a corner, stays a few seconds and swings across to the opposite one. turn scales how far it goes to the side:

<BotAvatar turn={1.4} />   {/* 0–2; 1 as the library has it, 0 faces forward */}

The jump

Now and then in the idle state, and on every click, the avatar jumps and turns right round. Its numbers are props:

<BotAvatar
  jumpHeight={32}    // body units; the body is 100 tall (default 26)
  jumpTime={0.8}     // seconds in the air (0.68)
  jumpStretch={1.3}  // stretch in the air, 0–2 (1)
  jumpSquash={1.4}   // squash on the ground, before take-off and on landing, 0–2 (1.15)
  jumpSquashTime={0.3}     // seconds the landing squash takes (0.37)
  jumpSquashEase="bouncy"  // sharp | pulse | soft | bouncy (pulse)
  jumpGroundTime={0.2}     // seconds held at the deepest squash on the ground (0.11; 0 for none)
  jumpGroundEase="bouncy"  // how the weight settles through it: sharp | pulse | soft | bouncy (pulse)
  jumpRiseTime={0.5}       // seconds from the deepest squash back to shape (0.33)
  jumpRiseEase="bouncy"    // how it rises: sharp | pulse | soft | bouncy (pulse)
  jumpClickSquashTime={0.8}  // seconds a click's jump takes for its crouch and landing squash (0.24)
  jumpSpin={2}       // whole turns in the air, 0–2 (1)
  jumpLean={10}      // degrees of lean into it (6)
  jumpEvery={5}      // seconds between idle jumps, give or take 40 %; 0 for none (8)
  jumpLand={-0.08}   // when the landing squash begins: seconds before (negative) or after touch-down (0, at contact)
/>

Pointer play

By default an avatar's eyes and head follow a pointer that comes within a few head widths, and a click makes it hop and turn right round, in any state. Turn it off with interactive={false}; your own onClick still runs either way.

The whirl

Off by default. With whirl set, a spin — the idle jump, a click, the working spin hop — draws a puff of motion round the body: one tapered trail on a tilted ring, made of the body's own material as a translucent plastic tube, lit from the same light, passing behind the body on the far side and over the face on the near side, where it casts a soft shadow. It is only there while the turn is under way, and it is already moving when it appears.

<BotAvatar
  whirl={1}           // 0–2 strength; off by default
  whirlSize={1.1}     // 0.6–1.6 ring size
  whirlWidth={0.8}    // 0.4–2 trail thickness
  whirlLength={1.3}   // 0.4–1.6 trail length round the ring
  whirlTilt={1.4}     // 0.5–1.8, how open the ring is seen
/>

A row of them

Each instance seeds its own blink timing from its React id, so a roster never blinks in unison. Pass the same seed to two avatars to make them move in step.

{agents.map((a) => (
  <BotAvatar key={a.id} type={a.avatar} state={a.busy ? 'working' : 'default'} size={32} />
))}

Accessibility & performance

  • role="img" with a per-state aria-label ("Clover bot, working") out of the box.
  • prefers-reduced-motion: reduce keeps the pose and drops the motion.
  • One shared animation frame loop for every avatar on the page; each one pauses when scrolled offscreen or when the tab is hidden. Device-pixel-ratio capped at 2.
  • In crisp, smooth and flat the body is seventeen copies of its outline stacked through the depth with a pillow profile; in plastic and fabric it is slices through an inflated height field, each in the side's own light, with the lit front laid over them — a rounded solid that turns and flips, in plain 2D canvas fills, about 1 ms of main thread a frame (fabric a little more: its fur is baked once per shape on idle time and laid over the whole body in one pass). Cheap enough for a whole roster at once.
  • Server rendering works: the canvas paints on the client, after mount.

License

MIT © Jakub Antalik

源码参数参考

以下实现签名和类型从本地固定版本源码生成。保留可选属性、原生继承类型、联合分支和 never 限制;不会将其他设计系统的 API 混入。forwardRef 实现中的 ref 属于 React 引用,不是新增业务属性。此区域是原始类型参考,不是上游说明的全文翻译。

BotAvatar({
    type = 'clover',
    path,
    face,
    state = 'default',
    size = 64,
    color,
    ink,
    brightness: brightnessProp,
    saturation: saturationProp,
    speed = 1,
    paused = false,
    seed,
    shading = 'fabric',
    hat = 'none',
    glasses = 'none',
    headphones = false,
    bowTie = false,
    accessoryColor = '#27272b',
    shadow,
    highlight,
    depth = 0.65,
    roundness = 1,
    furLength = 1,
    furDensity = 1.6,
    furFuzz = 0.9,
    furClumps = 0.4,
    furCurl = 0.7,
    furGravity = 0.9,
    light,
    rim,
    spread,
    backLight,
    lightFront,
    shine,
    sheen,
    backSoftness,
    pose: heldPose,
    interactive = true,
    turn = 1,
    theme = 'auto',
    whirl = 0,
    whirlSize = 1,
    whirlWidth = 1,
    whirlLength = 1,
    whirlTilt = 1,
    jumpHeight = 26,
    jumpTime = 0.68,
    jumpStretch = 1,
    jumpSpin = 1,
    jumpLean = 6,
    jumpEvery = 8,
    jumpLand = 0,
    jumpSquash = 1.15,
    jumpSquashTime = 0.37,
    jumpSquashEase = 'pulse',
    jumpGroundTime = 0.11,
    jumpGroundEase = 'pulse',
    jumpRiseTime = 0.33,
    jumpRiseEase = 'pulse',
    jumpClickSquashTime = 0.24,
    className,
    style,
    'aria-label': ariaLabel,
    ...rest
  }, ref)
export type BotAvatarType =
  | 'clover'
  | 'flower'
  | 'triangle'
  | 'square'
  | 'blob'
  | 'ghost'
  | 'circle'
  | 'drop'
  | 'star'
  | 'droid'
  | 'mech'
  | 'alien'
  | 'hexagon'
  | 'cat'
  | 'cloud'
  | 'pill'
  | 'pebble'
  | 'puddle';

export type BotAvatarFace = 'eyes' | 'mouth';

export type BotAvatarState = 'default' | 'working' | 'sleeping';

export type BotAvatarSquashEase = 'sharp' | 'pulse' | 'soft' | 'bouncy';

export type BotAvatarShading = 'crisp' | 'smooth' | 'plastic' | 'flat' | 'fabric';

export type BotAvatarHat = 'none' | 'beret' | 'beanie' | 'party' | 'crown';

export type BotAvatarGlasses = 'none' | 'round' | 'square' | 'shades';

export interface BotAvatarProps
  extends Omit<CanvasHTMLAttributes<HTMLCanvasElement>, 'color' | 'ref'> {
  /** Body shape. Default `clover`. */
  type?: BotAvatarType;
  /**
   * A custom body outline: SVG path data in the 100×100 body box, centred
   * on (50, 50), replacing the type's own (and its antennae). The type
   * still sets the face's place, the default colour and the label, so keep
   * the outline solid round the face. Default: the type's outline.
   */
  path?: string;
  /** Face kind. Defaults to the type's own. */
  face?: BotAvatarFace;
  /** What the bot is doing: `default` (idle), `working` (hopping, spinning) or `sleeping`. */
  state?: BotAvatarState;
  /** Rendered size in px, or any CSS length. Default `64`. */
  size?: number | string;
  /** Body colour. Defaults to the type's palette colour. */
  color?: string;
  /** Face ink. Defaults to dark, or light on a dark body. */
  ink?: string;
  /**
   * Lightness of the body colour: 1 as the palette has it, below 1 darker,
   * above 1 lighter (0.5–1.5 is the useful range). Default `1`, or the
   * type's own (the star's is `1.1`).
   */
  brightness?: number;
  /**
   * Saturation of the body colour: 1 as the palette has it, below 1
   * duller, above 1 more vivid, 0.5–2.5. Past 1.5, where most of the
   * palette is already as saturated as a screen shows it, the colour is
   * pushed along its own hue toward its most vivid shade (deepening by at
   * most 15% where the screen cannot show it brighter), the shade side
   * grows richer, and `plastic` and `fabric` keep
   * more of it in the light — highlights, sheen, rim and fur tips stay
   * coloured rather than paling toward white. Default `1.5`, or the
   * type's own (the star's is `1.84`).
   */
  saturation?: number;
  /** Multiplier on every animation's speed. Default `1`. */
  speed?: number;
  /** Freeze every animation on its current frame. */
  paused?: boolean;
  /**
   * 0–1. Offsets the blink and glance timing so a row of avatars does not
   * blink in unison. Defaults to a value derived from the instance id.
   */
  seed?: number;
  /** How the body is lit: `fabric` (default), `plastic`, `crisp`, `smooth`
   * or `flat`. `true` and `false` mean crisp and flat. */
  shading?: BotAvatarShading | boolean;
  /** A hat, sitting on the top of the head and turning with it: `beret`,
   * `beanie`, `party` or `crown`. Default `none`. */
  hat?: BotAvatarHat;
  /** Glasses over the eyes: `round`, `square` or `shades`. Default `none`. */
  glasses?: BotAvatarGlasses;
  /** Headphones over the head, a cup on either side. Default `false`. */
  headphones?: boolean;
  /** A bow tie under the face. Default `false`. */
  bowTie?: boolean;
  /** Colour of the hat, the headphones and the bow tie. Default a soft black. */
  accessoryColor?: string;
  /** Strength of the shadow side, 0–2. Default `0.35` (`1.15` for `fabric`). */
  shadow?: number;
  /** Strength of the lit side, 0–2. Default `1.3` (`1.45` for `fabric`). */
  highlight?: number;
  /** Thickness of the body, 0.2–2: what shows when it turns or flips. Default `0.65`. */
  depth?: number;
  /**
   * `plastic` and `fabric`: the body's profile through its depth, 0–1. At
   * `1` (default) it is inflated like a cushion or a plush toy — thickest in
   * the middle and rounding off to nothing at the outline all round, so a
   * turn shows a round side; toward `0` it becomes a slab with soft edges.
   */
  roundness?: number;
  /** `fabric`: length of the pile, 0.3–2.5. Default `1`. */
  furLength?: number;
  /** `fabric`: how many fibres, 0.3–2. Default `1.6`. */
  furDensity?: number;
  /** `fabric`: softness of the silhouette — the haze of fine hairs standing past it, 0–1. Default `0.9`. */
  furFuzz?: number;
  /** `fabric`: how much the fibres gather into tufts, 0–1. Default `0.4`. */
  furClumps?: number;
  /** `fabric`: how wavy the fibres are, 0 (straight) – 1. Default `0.7`. */
  furCurl?: number;
  /**
   * `fabric`: how much the pile hangs, 0–1 — combed down from a parting at
   * the top, lying over the top edge and hanging off the sides and bottom,
   * rather than standing out evenly all round. Default `0.9`.
   */
  furGravity?: number;
  /** Where the light comes from, in degrees clockwise from the top. Default `300` (`295` for `fabric`): from the upper left, like a studio key light. */
  light?: number;
  /** Width of the lit rim in `crisp` shading, strength of the Fresnel rim in `plastic`, of the back light in `fabric` — the bright rim it wraps round the top and sides, and the glow of the edge's hairs — 0–2. Default `0.5` (`0.6` for `fabric`). */
  rim?: number;
  /** `fabric`: where the back light comes from, in degrees clockwise from the top. Default: above the toy, toward the side away from `light`. */
  backLight?: number;
  /** `fabric`: how far round to the front the key light sits, in degrees — `0` grazes the toy from the side (dramatic), `85` lights it nearly from the camera (flat). Default `32`. */
  lightFront?: number;
  /** `fabric`: strength of the highlights along single fibres where the key grazes the pile, 0–2. Default `0` (off: a soft, matte pile). */
  shine?: number;
  /** `fabric`: the smooth, satin sheen over the body's edge — the key's sheen and the back light's band as even gradients, a material shine rather than the fur's own — 0 (matte, only the fibres shine) – 2. Default `0`. */
  sheen?: number;
  /** `fabric`: how soft the back light is, 0–1 — `0` a small source caught on single fibres as crisp bright hairs, `1` a large one, an even glow reaching further in from the edge and fading out gently. Default `1`. */
  backSoftness?: number;
  /** Reach of the soft shading in `smooth`, width of the highlight in `plastic`, how far the light wraps round in `fabric`, 0.4–2.5. Default `1.55` (`1.6` for `fabric`). */
  spread?: number;
  /**
   * Holds the body at this orientation, in radians — `yaw` turns it to the
   * viewer's right, `pitch` tips it to look up, `roll` tilts it — in the
   * state's rest pose, overriding the animation's turns, hops and glances
   * (and pointer play) while it is set. For turning an avatar round by
   * hand, as a 3D viewer does; usually with `paused`.
   */
  pose?: { yaw?: number; pitch?: number; roll?: number };
  /**
   * Pointer play: the eyes and head follow a pointer that comes near, and
   * a click makes the avatar hop and turn right round. Default `true`.
   */
  interactive?: boolean;
  /**
   * The surface the avatar sits on, for touches that have to read against
   * it. `auto` (default) reads an ancestor `data-theme` attribute or
   * `dark` / `light` class, then `prefers-color-scheme`.
   */
  theme?: 'auto' | 'dark' | 'light';
  /**
   * How far the head turns from side to side while idle, 0–2: `1` as the
   * library has it, `0` keeps it facing forward. Default `1`.
   */
  turn?: number;
  /** The whirl round a spin: its strength, 0–2. Off by default (`0`); `1` turns it on. */
  whirl?: number;
  /** Size of the whirl's ring, 0.6–1.6. Default `1`. */
  whirlSize?: number;
  /** Thickness of the whirl's trail, 0.4–2. Default `1`. */
  whirlWidth?: number;
  /** Length of the trail round the ring, 0.4–1.6. Default `1`. */
  whirlLength?: number;
  /** How flat the ring is seen, 0.5–1.8 (higher is more open). Default `1`. */
  whirlTilt?: number;
  /** The jump (an idle flip, a click): how high, in body units — the body is 100 tall. Default `26`. */
  jumpHeight?: number;
  /** Seconds the jump spends in the air. Default `0.68`. */
  jumpTime?: number;
  /** How much the body stretches in the air, 0–2. Default `1`. */
  jumpStretch?: number;
  /** How much the body squashes on the ground, before take-off and on landing, 0–2. Default `1.15`. */
  jumpSquash?: number;
  /** Seconds the landing squash takes, from contact to recovered. Default `0.37`. */
  jumpSquashTime?: number;
  /**
   * How the landing squash plays out: `sharp` (all at once, then eases
   * off), `pulse` (a quick press that recovers without a wobble, the
   * default), `soft` (eases in and out), `bouncy` (overshoots into a
   * stretch and settles).
   */
  jumpSquashEase?: BotAvatarSquashEase;
  /** Seconds a jump holds its deepest squash on the ground before recovering. Default `0.11`. */
  jumpGroundTime?: number;
  /**
   * How the weight settles through that hold, in the same shapes as
   * `jumpSquashEase`: the body presses a little deeper and comes back to
   * the held depth, `sharp` at once, `pulse` quickly, `soft` in the
   * middle, `bouncy` with a wobble. Default `pulse`.
   */
  jumpGroundEase?: BotAvatarSquashEase;
  /** Seconds the body takes to rise from its deepest squash back to its own shape. Default `0.33`. */
  jumpRiseTime?: number;
  /**
   * How it rises: `sharp` lets go at once and eases in to rest, `pulse`
   * leaves quickly with a long settle, `soft` eases out of the squash and
   * into rest, `bouncy` passes rest into a slight stretch and settles
   * back. Default `pulse`.
   */
  jumpRiseEase?: BotAvatarSquashEase;
  /** Seconds a click's jump takes for its landing squash (an idle jump's uses `jumpSquashTime`). Default `0.24`. */
  jumpClickSquashTime?: number;
  /** Whole turns made in the air, 0–2. Default `1`. */
  jumpSpin?: number;
  /** Degrees of lean into a jump. Default `6`. */
  jumpLean?: number;
  /** Seconds between idle jumps, give or take 40 %; 0 for none. Default `8`. */
  jumpEvery?: number;
  /** When the landing squash begins: seconds before touch-down (negative, bracing for the ground) or after it. Default `0`, the moment of contact. */
  jumpLand?: number;
  className?: string;
  style?: CSSProperties;
}

源码中的解构默认值

只列出直接写在参数或 props 解构中的默认表达式。条件表达式、运行时主题和其他计算值请结合源码;这里不是全部行为的默认值清单。

// BotAvatar
type = 'clover'

// BotAvatar
state = 'default'

// BotAvatar
size = 64

// BotAvatar
speed = 1

// BotAvatar
paused = false

// BotAvatar
shading = 'fabric'

// BotAvatar
hat = 'none'

// BotAvatar
glasses = 'none'

// BotAvatar
headphones = false

// BotAvatar
bowTie = false

// BotAvatar
accessoryColor = '#27272b'

// BotAvatar
depth = 0.65

// BotAvatar
roundness = 1

// BotAvatar
furLength = 1

// BotAvatar
furDensity = 1.6

// BotAvatar
furFuzz = 0.9

// BotAvatar
furClumps = 0.4

// BotAvatar
furCurl = 0.7

// BotAvatar
furGravity = 0.9

// BotAvatar
interactive = true

// BotAvatar
turn = 1

// BotAvatar
theme = 'auto'

// BotAvatar
whirl = 0

// BotAvatar
whirlSize = 1

// BotAvatar
whirlWidth = 1

// BotAvatar
whirlLength = 1

// BotAvatar
whirlTilt = 1

// BotAvatar
jumpHeight = 26

// BotAvatar
jumpTime = 0.68

// BotAvatar
jumpStretch = 1

// BotAvatar
jumpSpin = 1

// BotAvatar
jumpLean = 6

// BotAvatar
jumpEvery = 8

// BotAvatar
jumpLand = 0

// BotAvatar
jumpSquash = 1.15

// BotAvatar
jumpSquashTime = 0.37

// BotAvatar
jumpSquashEase = 'pulse'

// BotAvatar
jumpGroundTime = 0.11

// BotAvatar
jumpGroundEase = 'pulse'

// BotAvatar
jumpRiseTime = 0.33

// BotAvatar
jumpRiseEase = 'pulse'

// BotAvatar
jumpClickSquashTime = 0.24

原生与外部类型

以下外部类型仍由 React 或资源自身依赖定义,没有手工展开为虚构属性。实际可用类型以安装版本的 TypeScript 检查为准。

HTMLCanvasElement
Omit<CanvasHTMLAttributes<HTMLCanvasElement>, 'color' | 'ref'>
CanvasHTMLAttributes<HTMLCanvasElement>
CSSProperties