Ant Design Blazor Avatar 头像组件完全指南:图片、图标、字符展示与头像组实战

原创2026-10-10 02:53:011,625 阅读
文章标签:前端UI组件设计系统

Ant Design Blazor Avatar 头像组件完全指南:图片、图标、字符展示与头像组实战

导读

Avatar 是 Ant Design Blazor 中用于"代表用户或事物"的数据展示组件,它同时支持图片、图标、字符三种内容形态,并提供方形/圆形两种形状与多种尺寸规格;配套的 AvatarGroup 则可将多个头像组合展示,在超出上限时自动折叠为"+N"气泡。本指南将以组件官方文档 index.zh-CN.md 为主线,结合组件源码(Avatar.razor.cs、AvatarGroup.razor.cs)与官方示例,完整讲解全部 API 参数、四种典型场景的写法,以及图片加载失败 fallback、字符自动缩放等底层原理,读完即可在 Blazor 项目中直接落地使用。

一、快速上手:最基本的头像

官方示例 Basic.razor 展示了头像的三种尺寸(默认、大、小)与两种形状(圆形、方形):

<div>
  <div>
    <Avatar Size="@("5rem")" Icon="@IconType.Outline.User" />
    <Avatar Size="AvatarSize.Large" Icon="@IconType.Outline.User" />
    <Avatar Icon="@IconType.Outline.User" />
    <Avatar Size="AvatarSize.Small" Icon="@IconType.Outline.User" />
  </div>
  <div>
    <span @onclick="()=> size++ ">
      <Avatar Shape="AvatarShape.Square" Size="@size.ToString()" Icon="@IconType.Outline.User" />
    </span>
    <Avatar Shape="AvatarShape.Square" Size="AvatarSize.Large" Icon="@IconType.Outline.User" />
    <Avatar Shape="AvatarShape.Square" Icon="@IconType.Outline.User" />
    <Avatar Shape="AvatarShape.Square" Size="AvatarSize.Small" Icon="@IconType.Outline.User" />
  </div>
</div>

@code {
  int size = 64;
}

要点说明:

  • 尺寸的两种传法:Size 既可以是枚举 AvatarSize.Large / AvatarSize.Small(默认 AvatarSize.Default),也可以直接传 CSS 长度字符串,例如 "5rem",甚至支持 @size.ToString() 绑定动态数值,每次点击外层 <span> 都会让头像尺寸递增。
  • 形状枚举:Shape 接受 AvatarShape.Square(方形)或 AvatarShape.Circle(圆形,默认),枚举定义见 AvatarShape.cs。
  • 尺寸枚举:Default、Large、Small 三种,定义见 AvatarSize.cs。

二、三种内容类型:图片、图标与字符

示例 Type.razor 完整演示了三种形态:

<div>
    <Avatar Icon="user" />
    <Avatar>U</Avatar>
    <Avatar>USER</Avatar>
    <Avatar Src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
    <Avatar Style="color: #f56a00; background-color: #fde3cf; ">U</Avatar>
    <Avatar Style="background-color: #87d068" Icon="user" />
</div>

从渲染模板 Avatar.razor 可以看出三种内容的渲染优先级与共存规则:

@if (_hasIcon)
{
    <Icon Type="@Icon" />
}
@if (_hasSrc)
{
    <img src="@Src" srcset="@SrcSet" alt="@Alt" @onerror="ImgError" />
}
@if (_hasText)
{
    <span class="ant-avatar-string" @ref="TextEl" style="@_textStyles">
        ...
    </span>
}

在 Avatar.razor.cs 的 OnParametersSet 中,三个开关的计算规则是:

  • _hasText = string.IsNullOrEmpty(Src) && (!string.IsNullOrEmpty(_text) || _childContent != null):字符/内容仅在未设置 Src 时展示;
  • _hasIcon = string.IsNullOrEmpty(Src) && !string.IsNullOrEmpty(Icon):图标同样仅在未设置 Src 时展示;
  • _hasSrc = !string.IsNullOrEmpty(Src):设置 Src 后图片优先占据展示位。

也就是说:Src 图片优先,图片缺席时再依次考虑 Icon 与字符内容。字符型头像与图标型头像都可以通过 Style 自定义前景色与背景色,如上例中的 color: #f56a00; background-color: #fde3cf。

三、尺寸与形状深入:OneOf 机制与 CSS 长度解析

Size 参数在源码中的类型是 OneOf<AvatarSize, string>(见 Avatar.razor.cs),这意味着两种赋值方式并存:

  1. 枚举方式:AvatarSize.Default / AvatarSize.Large / AvatarSize.Small,对应渲染为 CSS 类 ant-avatar、ant-avatar-lg、ant-avatar-sm(见 SetClassMap);
  2. 字符串方式:任意合法的 CSS 长度,如 "5rem"、"64px"、"20vw"。

字符串尺寸的解析在 SetSizeStyle 中完成,通过 CssSizeLength.TryParse 校验后生成内联样式:

_sizeStyles = $"width:{cssSize};height:{cssSize};line-height:{cssSize};";
_sizeStyles += $"font-size:calc({cssSize} / 2);";

可见字体大小自动取头像尺寸的一半,且宽高、行高同步一致,保证字符垂直居中。

形状的映射由 _shapeMap 完成(Avatar.razor.cs):AvatarShape.Square → square、AvatarShape.Circle → circle,最终渲染为 ant-avatar-square / ant-avatar-circle 样式类。相关样式文件位于 components/avatar/style/,主题样式可参考 avatar.less 等 less 文件。

四、字符型头像的自动缩放:字体自适应原理

官方示例 Dynamic.razor 演示了字符型头像的"自动调整字符大小"能力——当字符串较长时,字体大小会根据头像宽度自动缩放:

<div>
    <Avatar Style="@($"background-color: {color}; vertical-align: middle;")" Size="AvatarSize.Large">
        @user
    </Avatar>
    <Button
        Size="ButtonSize.Small"
        Style="margin:0 16px; vertical-align: middle;"
        OnClick="_=>changeUser()"
    >
        Change
    </Button>
</div>

@code
{
    private static string[] userList = {"U", "Lucy", "Tom", "Edward"};
    private static string[] colorList = {"#f56a00", "#7265e6", "#ffbf00", "#00a2ae"};

    private string user { get; set; } = userList[0];
    private string color { get; set; } = colorList[0];

    private void changeUser()
    {
        var index = Array.IndexOf(userList, user);
        user = index < userList.Length - 1 ? userList[index + 1] : userList[0];
        color = index < colorList.Length - 1 ? colorList[index + 1] : colorList[0];
    }
}

点击 Change 按钮后,头像内的用户名会在 U、Lucy、Tom、Edward 之间轮换,背景色同步变化;当名字变长时字符会自动缩小以完整容纳。

该能力由源码中的 CalcStringSize 实现,其核心算法为:

var childrenWidth = (await JsInvokeAsync<HtmlElement>(JSInteropConstants.GetDomInfo, TextEl))?.OffsetWidth ?? 0;
var avatarWidth = (await JsInvokeAsync<DomRect>(JSInteropConstants.GetBoundingClientRect, Ref))?.Width ?? 0;
var scale = childrenWidth != 0 && avatarWidth - 8 < childrenWidth
    ? (avatarWidth - 8) / childrenWidth
    : 1;

_textStyles = $"transform: scale({new CssSizeLength(scale, true)}) translateX(-50%);";

原理可概括为:

  1. 通过 JS Interop 读取字符容器的实际渲染宽度(OffsetWidth)与头像容器的宽度(GetBoundingClientRect);
  2. 当字符宽度超过"头像宽度 − 8px"的安全边距时,按两者比值计算缩放系数;
  3. 用 transform: scale(...) translateX(-50%) 让字符按比例缩小并保持居中,不改变 DOM 布局,只做视觉缩放。

Text 变更时会置位 _waitingCalcSize,并在下一次渲染后触发重新计算(Avatar.razor.cs),因此动态替换字符内容也能获得正确的缩放结果。

五、带徽标的头像:消息提醒场景

示例 Badge_.razor 展示了头像与 Badge 徽标的组合用法,通常用于消息提醒、未读计数等场景:

<div>
    <span class="avatar-item">
        <Badge Count="1">
            <Avatar Shape="AvatarShape.Square" Icon="@IconType.Outline.User" />
        </Badge>
    </span>
    <span>
        <Badge Dot>
            <Avatar Shape="AvatarShape.Square" Icon="@IconType.Outline.User" />
        </Badge>
    </span>
</div>
<style>
    /* tile uploaded pictures */
    .avatar-item {
        margin-right: 24px;
    }

    [class*='-col-rtl'] .avatar-item {
        margin-right: 0;
        margin-left: 24px;
    }
</style>

Badge 的 Count 用于展示具体数字,Dot 则只显示一个小圆点(不显示数值)。头像自身作为徽标的锚点容器,实现"头像右上角挂角标"的典型效果,style 中同时考虑了 RTL 布局下边距的镜像调整。

六、头像组 AvatarGroup:组合展示与溢出折叠

6.1 基本组合

示例 Group.razor 展示了头像组的两种形态:

<AvatarGroup>
    <Avatar Src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
    <Avatar Style="background-color: #f56a00">K</Avatar>
    <Tooltip Title="Ant User" Placement="Placement.Top">
        <Unbound>
            <Avatar Style="background-color: #87d068;" Icon="user" RefBack="@context"/>
        </Unbound>
    </Tooltip>
    <Avatar Style="background-color: #1890ff;" Icon="ant-design" />
</AvatarGroup>
<Divider />
<AvatarGroup MaxCount="2" MaxStyle="color: #f56a00; background-color:#fde3cf;">
    <Avatar Src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
    <Avatar Style="background-color: #f56a00">K</Avatar>
    <Tooltip Title="Ant User" Placement="Placement.Top" >
        <Unbound>
            <Avatar Style="background-color: #87d068;" Icon="user" RefBack="@context"/>
        </Unbound>
    </Tooltip>
    <Avatar Style="background-color: #1890ff;" Icon="ant-design" />
</AvatarGroup>
  • 第一组:4 个头像全部平铺展示;
  • 第二组:通过 MaxCount="2" 限制最多显示 2 个,超出部分自动折叠为一个 +2 头像,并通过 MaxStyle 为其定制背景色与文字颜色(color: #f56a00; background-color:#fde3cf)。

注意示例中的组合技巧:用 Tooltip + <Unbound> + RefBack="@context" 给单个头像附加悬浮提示;由于 AvatarGroup 通过 CascadingValue 向下传递 position 上下文(见 AvatarGroup.razor),组内所有头像(包括被折叠进气泡的)都能正确参与计数。

6.2 溢出折叠的底层原理

AvatarGroup 的折叠逻辑在 AvatarGroup.razor.cs 的 AddAvatar 中完成:

internal void AddAvatar(Avatar item)
{
    if (item.Position == null)
        return;

    var avatarList = item.Position == "shown" ? _shownAvatarList : _hiddenAvatarList;

    avatarList.Add(item);

    if (MaxCount > 0 && avatarList.Count > MaxCount)
    {
        _overflow = true;
        item.Overflow = true;
    }

    StateHasChanged();
}

配合 Avatar.razor 顶部的条件渲染:

@if (Position == null || (Position == "shown" && !Overflow) || (Position == "hidden" && Overflow))

整个机制是:AvatarGroup 用 CascadingValue 以 position 为名下发 "shown",并在溢出时将剩余头像放进 Popover 的 ContentTemplate 内、下发 "hidden"(见 AvatarGroup.razor)。每个 Avatar 在 OnInitialized 时注册进组(Group?.AddAvatar(this)),销毁时注销(Dispose 中调用 RemoveAvatar)。当 MaxCount > 0 且当前展示位头像数超过上限时,置位 _overflow,此时:

  • "shown" 位置且 Overflow == true 的头像不再渲染;
  • 溢出部分以 +{超出数量} 形式出现在 Popover 内,Popover 的 Trigger 为 Hover,悬浮即可查看全部剩余头像;
  • 溢出头像的样式由 MaxStyle 控制(<Avatar RefBack="@context" Style=@MaxStyle>@($"+{_shownAvatarList.Count - MaxCount}")</Avatar>),气泡的弹出位置由 MaxPopoverPlacement 决定。

七、图片加载失败与 fallback 机制

当 Src 指定的图片加载失败时,组件会进入 fallback 流程。触发入口是 ImgError:

private async Task ImgError(ErrorEventArgs args)
{
    await OnError.InvokeAsync(args);
    _hasSrc = false;
    _hasIcon = false;
    _hasText = false;
    if (!string.IsNullOrEmpty(Icon))
    {
        _hasIcon = true;
    }
    else if (!string.IsNullOrEmpty(_text))
    {
        _hasText = true;
    }

    _waitingCalcSize = true;
}

逻辑要点:

  1. 首先触发 OnError 事件回调(EventCallback<ErrorEventArgs>),供业务层监听与处理;
  2. 将图片开关 _hasSrc 置为 false,隐藏失效的 <img>;
  3. 依次检查 Icon 与字符内容作为兜底展示。

官方文档给出的 fallback 优先级为:Icon > ChildContent。即:设置了 Icon 就显示图标;否则若提供了 ChildContent(或 Text)则显示字符内容。文档原文注释位于 index.zh-CN.md,对应源码行为可在 Avatar.razor.cs 中验证——需要留意的是,源码实现中 Icon 优先于字符文本,ChildContent 与 Text 同属"字符形态",按官方文档所述可把二者都理解为图片加载失败时的 fallback 内容。

八、API 完整参考

8.1 Avatar Props

以下参数表完整继承自官方文档 index.zh-CN.md,并结合源码补充了取值细节:

参数 说明 类型 默认值 版本
Alt 图像无法显示时的替代文本 string -
Icon 设置头像的自定义图标 string -
OnError 图片加载失败的事件 EventCallback<ErrorEventArgs> -
Shape 指定头像的形状 string(枚举 AvatarShape:Circle / Square) Circle
Size 设置头像的大小 default | small | large,也支持 CSS 长度字符串 string(或枚举 AvatarSize) default
Src 图片类头像的资源地址或者图片元素 string -
SrcSet 设置图片类头像响应式资源地址 string -

Tip:你可以设置 Icon 或 ChildContent 作为图片加载失败的默认 fallback 行为,优先级为 Icon > ChildContent

需要补充说明的几点(来自源码):

  • Size 的复合类型:源码中类型为 OneOf<AvatarSize, string>(Avatar.razor.cs),文档表中写为 string 时指字符串尺寸写法;AvatarSize 枚举值为 Default / Large / Small(AvatarSize.cs)。
  • Shape 的默认值:源码中 Shape 为可空枚举,未设置时按 AvatarShape.Square 计算样式映射(Shape.GetValueOrDefault(AvatarShape.Square),见 Avatar.razor.cs),即默认渲染为方形;显式传 AvatarShape.Circle 则为圆形。
  • Text 与 ChildContent:文档表格未列出,但源码明确支持——Text 用于展示字符内容(典型场景是姓名首字母),ChildContent 优先级高于 Text(Avatar.razor.cs);渲染时 <span class="ant-avatar-string"> 内优先输出 ChildContent,否则输出 Text。

8.2 AvatarGroup Props

参数 说明 类型 默认值 版本
MaxCount 显示的最大头像个数 int -(源码中为 0,即不限制)
MaxPopoverPlacement 多余头像气泡弹出位置 top | bottom(枚举 Placement) top
MaxStyle 多余头像样式 string -

补充说明:

  • MaxPopoverPlacement 源码类型为 Placement 枚举,默认 Placement.Top(AvatarGroup.razor.cs);
  • 折叠触发条件为 MaxCount > 0 且当前展示头像数超过 MaxCount,溢出头像由 Popover(Trigger=Hover)承载,点击悬浮即可查看(AvatarGroup.razor.cs);
  • MaxStyle 会直接作用于"+N"溢出头像的 Style,可用于定制其文字颜色与背景色。

九、源码与样式索引

如需深入阅读或二次开发,可重点关注以下仓库文件:

十、总结

Avatar 组件以"图片、图标、字符"三种形态覆盖了绝大多数用户/事物展示需求:Src + SrcSet 负责图片类头像,Icon 负责图标类头像,Text / ChildContent 负责字符类头像,并内置了"图片优先、失败后 Icon > ChildContent 兜底"的完整 fallback 链路;Size 的 OneOf<AvatarSize, string> 设计让固定枚举与任意 CSS 尺寸无缝共存,字符自动缩放能力则通过 JS 测量 + transform: scale 实现无损适配。AvatarGroup 通过级联上下文与内部计数实现了溢出折叠,配合 MaxCount、MaxStyle、MaxPopoverPlacement 三个参数即可快速搭建成员列表、评论区头像墙等常见 UI。参考官方文档 index.zh-CN.md 与源码中的示例即可直接落地到你的 Blazor 项目中。

登录后查看全文
ant-design-blazor