定价

CircularChart 使用手册

v1.4.5 · @snowui-design-system/components

许可阅读:首次阅读组件文档、源码或 npm 使用流程,先读完整 LICENSE;同任务同版本去重。公开 API 配置与内部实现修改分别按许可处理;全部组件使用统一运行包,源码权益以许可为准。

组件介绍

用圆环或饼图展示数据占比,支持分段、圆角、环厚与悬停强调,适合构成分析和比例概览。

使用选择

用于展示占比、环形或饼图数据。目标完成度可按语义选择 GaugeChart 或 Progress;颜色与标签使用公开配置。

  • data 使用 name 与有限正 value;只显示前 maxItems 个有效项,占比分母为这些显示项之和。显式空数组展示空图。

  • 推荐用数字 size;字符串几何只取数值部分,不能依赖百分比或 CSS 变量完成自适应。中心内容用公开 center-label / segment-value / segment-name 角色。

  • 根默认可访问名称随 LocaleProvider 切换,使用 circularChart.name;显式 aria-label 优先。业务名称、数据值与数字格式保持调用方内容。

快速开始

以下示例展示推荐的基本组合。更多场景与组合限制见后文。

<script lang="ts">	import { Button, Frame, Icon, Text } from '@snowui-design-system/components';	import { DotCircle } from '@snowui-design-system/resource-svelte';	import { CircularChart } from '@snowui-design-system/components';	// Illustrative SnowUI site visits over the last 30 days; these are not actual statistics.	const channels = [	    { name: 'Search', value: 12840, color: 'var(--primary)' },	    { name: 'Direct', value: 8560, color: 'var(--secondary-purple)' },	    { name: 'GitHub', value: 5350, color: 'var(--secondary-cyan)' },	    { name: 'Figma', value: 4280, color: 'var(--secondary-mint)' },	    { name: 'Community', value: 3210, color: 'var(--secondary-green)' }	];	const total = channels.reduce((sum, item) => sum + item.value, 0);	let trafficChart: { replay: () => void; reverseAppearance: () => void } | undefined;</script> <div style="display: flex; flex-direction: column; align-items: center; width: var(--size-full); gap: var(--gap-4) var(--gap-3);">    <div style="display: flex; align-items: center; justify-content: center; flex-wrap: wrap; min-width: 0; max-width: var(--size-full); gap: var(--gap-4) var(--gap-7);">        <CircularChart bind:this={trafficChart} data={channels} ringThickness={48} appearOnView defaultAppearanceProgress={0} role="group" aria-label="SnowUI website visits by source, sample last 30 days" />        <div style="display: flex; flex-direction: column; gap: var(--gap-3);">            <div style="display: flex; flex-direction: column; gap: var(--gap-0);">                <Text style="font-size: var(--text-18); line-height: var(--leading-18); color: var(--black-100); font-weight: 600;">Website traffic</Text>                <Text style="font-size: var(--text-12); line-height: var(--leading-12); color: var(--black-40);">Sample · last 30 days · {total.toLocaleString('en-US')} visits</Text>            </div>            <div style="display: grid; grid-template-columns: auto auto; align-items: center; gap: var(--gap-2) var(--gap-6);">    {#each channels as item}        <Frame singleLine gap={0}><Icon as="leading" size={12} style={`color: ${item.color};`}><DotCircle weight="fill" /></Icon><Text lines={1} style="font-size: var(--text-14); line-height: var(--leading-14); color: var(--black-100);">{item.name}</Text></Frame>        <Text style="font-size: var(--text-14); line-height: var(--leading-14); color: var(--black-100); text-align: right; font-variant-numeric: tabular-nums;">{item.value.toLocaleString('en-US')}</Text>    {/each}</div>        </div>    </div>    <div style="display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--gap-4) var(--gap-3);">        <Button onclick={() => trafficChart?.replay()}>Replay animation</Button>        <Button onclick={() => trafficChart?.reverseAppearance()}>Reverse animation</Button>    </div></div>

API

关键字 类型 默认值 描述
data CircularChartItem[] DEFAULT_DATA 比例数据数组;每项必填 name(名称)与 value(有限正数),可选 color、percentFormat。按输入顺序过滤非正数和非法值,再取前 maxItems 项;百分比分母是实际显示项之和。省略 data 时使用内置示例数据;显式空数组或全部无效时保留最终尺寸并渲染空图表。 默认行为:内置 5 项示例数据。
size number | string 240 图表正方形尺寸;推荐传正数,数字按 px 设计值转为 rem。字符串直接作为 CSS 长度,但 SVG 几何仅通过 parseFloat 取数,不进行单位换算,因此不支持可靠的百分比、calc() 或 CSS 变量自适应几何。
minWidth number | string `${SECTOR_CHART_MIN_WIDTH}px` 响应式最小显示宽度;数字与 size 使用相同的 px 设计值转 rem 规则,字符串直接作为 CSS 长度。默认固定 40 CSS px;设为与 size 相同可阻止自动缩小,设为更小值允许缩到该下限。仅 enableResponsive=true 时生效。
ringThickness number | string 32 环厚,推荐非负数字(px 设计值);内半径为 max(0, 外半径 − 环厚)。外半径为 size / 2 − hoverThicknessGrowth − 1,环厚达到它时形成实心饼图。字符串仅提取数值,不换算 CSS 单位。
cornerRadius number | string | "auto" "auto" 扇区端部圆角;非负数值或数字字符串表示 160×160 基准下的 px 设计值,按 size / 160 缩放;auto 使用基准值 4。最终圆角受环厚和扇区可容纳角度限制;0 为直角。
separatorWidth number | string | "auto" "auto" 扇区间透明隔断;非负数值或数字字符串表示 160×160 基准下的 px 设计值,按 size / 160 缩放;auto 使用基准值 2,0 关闭间隔。通过路径几何留空,透出真实背景。
colors (CircularChartColor | undefined)[] — 按过滤后显示索引覆盖颜色;每项支持语义色、CSS 颜色/变量、linear-gradient 字符串或 { type?, angle?, stops } 渐变对象。undefined 空位回退当前 colorMode;数据项 color 优先于调色板。不支持背景 utility 类名。
colorMode CircularChartColorMode "sequence" sequence 按 Primary 与 9 个 Secondary 色序循环;monochromeFade 使用同一主色从首项 100% 均匀降至末项 20%(单项为 100%);monochrome 所有项使用同一颜色。三种模式均允许数据项和调色板逐项覆盖。
color CircularChartColor — 同时覆盖 monochromeFade 与 monochrome 的回退主色,优先于 monochromeColor / mutedMonochromeColor;sequence 不使用它。支持与数据项 color 相同的纯色、语义色和渐变。
monochromeColor CircularChartColor "Primary" 仅在 monochromeFade 且未传 color 时使用的回退主色;支持纯色和渐变。透明度从首项 100% 降到末项 20%,数据项 color 与 colors 仍优先。
mutedMonochromeColor CircularChartColor "Black4" 仅在 monochrome 且未传 color 时使用的回退色;默认 Black4 是主题自适应的低对比色,扇区填充自身不再降低透明度。数据项 color 与 colors 仍优先。
hoverThicknessGrowth number | string — hover / focus 时向外增厚的非负 px 设计值;内半径与圆心不变。未传时依次读取旧别名 hoverScaleSize、回退 4;0 关闭几何增厚但保留数据提示。字符串仅提取数值。
startDirection StartDirection "top" 从 top、top-right、right、bottom-right、bottom、bottom-left、left、top-left 射线命中的扇区开始,按顺时针顺序播放;只选择首个播放扇区,不旋转数据排布。同一大扇区覆盖的多个方向可能产生相同顺序。
showBaseLayer boolean false 是否显示最终几何的同色 4% 透明度底层;默认不渲染。开启后底层不参与出现动效与命中,便于观察填充进度;不改变真实扇区和数据。
appearMotion boolean true 是否启用图形出现动效;false 时直接显示完整填充,并使 replay / reverseAppearance 不播放。此开关不关闭独立的 hover 增厚反馈。
appearOnView boolean true 非受控模式中,锚点到达指定视口位置时自动播放一次;同源 iframe 中按最外层同源页面的真实位置判断。false 可改用实例方法播放。appearanceProgress 优先;scrollAppearance 开启时由滚动驱动。
appearanceProgress number — 受控填充进度,数值限制到 0..1;提供后显示由调用方决定,自动播放和实例播放方法不改变受控画面。appearMotion=false 仍直接完整显示;外部进度变化不会触发 onAppearanceProgressChange。
defaultAppearanceProgress number 0 非受控模式首次初始化的进度,限制到 0..1,只读取一次;后续改变此属性不重置动画。有 appearanceProgress 时不决定画面;默认 0 为描边态。
appearanceDuration number — 实例播放与自动出现的总时长,单位 ms;未传时固定 1000,不随扇区数改变。非正数在下一动画帧直接到终点;不改变滚动或受控进度映射。
appearAnchorId string — 页面内触发锚点元素的 id;未传时使用图表根元素,传入不存在的 id 不回退根元素。仅用于自动出现或滚动时间轴,不改变图表位置。
appearAnchorPoint AnchorPoint "top" 选用锚点的 top(顶部)、center(垂直中心)或 bottom(底部)与视口触发线比较;不影响扇区绘制方向。
appearViewportPoint number | "top" | "center" | "bottom" 0.7 视口触发线:数字限制到 0..1,或使用 top=0、center=0.5、bottom=1。默认 0.7 为视口高度 70%;配合 appearAnchorPoint 决定触发/滚动起点。
scrollAppearance boolean | { distance?: number | string } false true 开启 window 滚动驱动的非受控时间轴;同源 iframe 同时响应外层页面滚动。对象可用 distance 覆盖滚动距离。锚点越过触发线后进度由距离决定,向回滚动会逆向恢复。不监听嵌套 ScrollArea;appearanceProgress / appearMotion=false 优先。
scrollAppearanceDistance number | string 320 滚动进度从 0 到 1 所需的 CSS px 距离;数字或数字字符串,最低按 1 处理。scrollAppearance.distance 优先;只在滚动时间轴开启时生效,不换算字符串单位。
onAppearanceProgressChange (progress: number) => void — 内部进度写入时接收 progress(0..1),包括初始化中的直接完成、自动播放、实例方法与滚动更新;可同步外部进度读数。默认值初始化本身不通知;不用于监听外部 appearanceProgress,返回值被忽略,不能取消更新。
hoverScaleSize number | string — 已废弃的增厚别名,单位和行为与 hoverThicknessGrowth 相同;仅后者未传时生效。新代码使用 hoverThicknessGrowth,不能把它理解为整体缩放比例。
maxItems number 10 过滤后保留的前 N 项数量,不排序、不自动合并 Other;取整并限制到 1..10,0 / NaN 回退 10。百分比只基于保留项,超过 10 类的业务应先聚合小类以保留总量;全无效时渲染空图表。
showCenterLabel boolean true 是否渲染中心内容区域;false 同时隐藏默认动态标签、segment-value / segment-name 模板与静态 center-label。隐藏中心不关闭显式启用的 HoverPanel。
hoverMode ChartHoverMode "cell" cell 按环带角度命中,跨过透明隔断仍保持所属扇区,排除中心空洞与图外;item 只响应扇区路径命中。两种模式均保留扇区键盘 focus 提示。
showHoverPanel boolean true 默认根据当前 hover / focus 扇区显示结构化面板,同时保留动态中心标签。false 关闭面板;但存在可见静态 center-label 时组件自动启用面板承载扇区信息。
hoverPanelVariant ChartHoverPanelVariant "light" 面板视觉:light 为默认浅色玻璃样式,dark 为深色样式,surface 为主题表面样式;仅改变面板外观,不改变数据和命中。
hoverPanelPlacement ChartHoverPanelPlacement "pointer" 面板位置:pointer 跟随指针;anchor-top / anchor-side 相对当前指针点定位(键盘焦点使用图心);pin-top-left / pin-top / pin-top-right / pin-right / pin-bottom-right / pin-bottom / pin-bottom-left / pin-left / pin-center 固定在图表对应位置,边缘保留 8px 并参与视口碰撞处理。
showHoverPanelLabel boolean false 是否在面板行数据上方额外显示当前扇区名称;false 只显示数据行。仅面板开启且存在当前项时有可见效果。
percentFormat NumberFormatOptions — 中心百分比、面板百分比与扇区 aria-label 的数字格式;支持 fractionDigits、locale 等 NumberFormatOptions。优先级为数据项 percentFormat → 本属性 → NumberFormatContext → 默认一位小数;labelFormatter 只覆盖中心文本。 默认行为:NumberFormats 百分比默认。
labelFormatter (item: CircularChartItem, percent: number) => string — hover / focus 时接收 item(当前有效数据项)与 percent(0..100 百分数),返回中心文字;以换行拆成数值行与名称行,最多使用两行。静态 center-label 或 showCenterLabel=false 时不调用;不改变面板和扇区 aria-label 的百分比。
loading boolean — 数据等待状态。保留 size 对应的最终占位和中心内容,将扇区固定在出现动效起点并暂停交互;变为 false 后按当前视口条件播放出现动效。图表不渲染 Skeleton,也会读取上层 Frame 的 loading 上下文;显式空 data={[]} 不回退默认演示数据。
children Snippet — 无参数 Snippet,渲染在 showCenterLabel=true 的中心区域。直系 Frame as="center-label" 提供常驻内容并自动启用面板,其内直系 Text as="segment-value" / "segment-name" 可复用默认中心排版且保留自定义文本;直系 Text as="segment-value" / "segment-name" 为动态标签样式模板,由组件写入两行文本。中心为展示区域,不用于交互工具栏。
class string "" 追加到图表根 Frame 的 class 字符串;不传时为空。仅表达调用方公开根样式,不穿透内部 SVG 和标签结构。
style string "" 追加到根 Frame 的 inline style 字符串,在组件注入的变量之后合并。可表达外部布局;图表几何优先使用 size、ringThickness 等公开 Props。
enableResponsive boolean true 默认在容器放不下时等比缩小图表本体,支持 flex 并排收缩,最小显示宽度由 minWidth 决定(默认 40px),与图表宽度相同时不收缩;HoverPanel 不缩放;false 保留声明尺寸。也透传至 Frame。
enableContext boolean true 透传 Frame 的上下文能力开关;当前组件自己的 size、颜色与出现进度仍由对应 Props 决定。
enableScaleObserver boolean false 透传 Frame 的旧版尺寸观察兼容能力,默认关闭;不等同于百分比图表尺寸,不建议新示例依赖此迁移期入口。
enableDefaultMotion boolean true 透传 Frame 默认外层动效能力;不接管图表内部出现时间轴和扇区 hover 增厚,后者分别由 appearMotion / appearanceProgress 与 hoverThicknessGrowth 控制。

未重新声明的继承能力请查所属基础组件文档;本表只列本组件源码具名公开属性。

使用边界与详细说明

HoverPanel 使用共享三列布局;圆点—名称优先 --gap-1,名称—数值优先 --gap-2,两处均至少保留 4 CSS px,并跟随 LTR / RTL 逻辑方向。默认 16px 根字号下仍为 4px / 8px,较大 Token 保留;面板纵向分区和图表中心注释不套用此下限。

设计原则

  • 专业图表组件:当前维护位置为 components/src/components/;该目录是迁移期技术位置。全部组件的运行包与原始源码均可免费获取;用途、项目、席位及生产使用权益按 LICENSE 执行,不按高级功能划分组件。

  • 最多 10 项:默认 maxItems=10。颜色只使用 primary 与 9 个 secondary-* token,10 项后颜色会重复且图表辨识度下降,因此组件默认截断到 10 项。

  • 颜色模式:默认 colorMode="sequence" 按 primary → secondary-purple → secondary-cyan → secondary-mint → secondary-green → secondary-indigo → secondary-blue → secondary-yellow → secondary-orange → secondary-red 循环;monochromeFade 使用 Primary 从 100% 均匀递减到最后一项 20%;monochrome 默认所有扇区使用 Black4。每个数据项可通过 color 单独定义扇区颜色;colors 可作为按 index 的调色板覆盖入口,留空项回退当前颜色模式。

  • 几何缩放:cornerRadius 与 separatorWidth 的数值都是 160x160 图表下的设计基准值,组件会按实际 size / 160 等比缩放。auto 使用默认基准值:圆角 4、间隔 2。

  • Hover 强调:hover / focus 当前项时,扇区不位移,仅外半径缓动增加 hoverThicknessGrowth,默认向外增厚 4px;中心标签上方显示百分比,下方显示当前项名称。


2.1 数据与形态

  • 支持圆环图与实心饼图:ringThickness 小于外半径时为圆环,ringThickness >= outerRadius 时内半径归零并形成实心饼图。

  • 支持最多 10 个扇区:maxItems 默认 10,内部上限固定为 10,超出项会被截断。

  • 自动过滤无效数据:value <= 0 或非数字项不参与渲染;显式空数组或全部无效时渲染空图表,只有省略 data 时使用内置示例数据。

  • 支持尺寸、环厚、圆角、隔断和 hover 外侧增厚调整:数字值按 px 语义写入组件私有 CSS 变量。

  • 支持 160x160 基准几何缩放:cornerRadius 与 separatorWidth 的传入数值都是设计基准值,实际渲染按 size / 160 等比放大或缩小。

2.2 扇区绘制

  • 扇区路径包含外圆弧、内圆弧和头尾切线圆角,圆角跟随真实扇区形状生成,不依赖后期裁切。

  • 扇区之间的透明间隔在 path 几何阶段生成:separatorWidth 会换算为 d3-shape 的 padAngle,并配合 padRadius 收缩内外圆弧。不绘制白色分隔线,也不使用后置 gap mask 挖空扇区。

  • 圆角仍由收缩后的扇区 path 生成,因此贯穿环厚的透明间隔与端部圆角可以同时成立。

  • showBaseLayer=true 时底层绘制一层同色 4% 透明度占位扇区,默认不绘制,不参与出现动效;真实填充层在其上方播放。

  • 最上层使用完整扇区 path 作为透明命中层,保证 hover / focus 的交互范围稳定。

2.3 颜色能力

  • 默认颜色顺序为 Primary、Purple、Cyan、Mint、Green、Indigo、Blue、Yellow、Orange、Red。

  • 每个扇区可通过 data[i].color 单独定义颜色;未定义颜色的扇区继续使用默认颜色序列。

  • colors 可作为整组调色板覆盖入口,并允许数组项为 undefined,空项会回退当前 colorMode 对应颜色。

  • 支持 Chart 通用三种颜色模式:sequence 默认色序、monochromeFade 单色渐浅、monochrome 单色。三种模式都支持 data[i].color 与 colors[i] 指定扇区自定义颜色。

  • color 支持普通颜色、CSS 变量、linear-gradient(...) 字符串和渐变对象。

  • 不直接支持 .bg-gradient-blue 这类背景工具类名;SVG 扇区使用 fill,背景类的 background / background-image 不会被 path 消费。

2.4 动效能力

  • 支持首次进入视口自动播放出现动效,可通过 appearOnView 关闭。

  • 支持 8 个出现起始方向:top / top-right / right / bottom-right / bottom / bottom-left / left / top-left。

  • 支持滚动条时间轴:scrollAppearance 开启后,滚动距离直接映射到 appearanceProgress。

  • 支持受控时间轴:外部传入 appearanceProgress 后,组件只根据该进度渲染,不自行播放。

  • 支持非受控方法:replay() 重新填充,resetAppearance() 重置,reverseAppearance() 反向回退。

  • 填充层与透明度层同时启动:填充完成后下一个扇区即可启动,透明度补齐独立继续,不阻塞后续扇区。

  • 支持反向时间轴:appearanceProgress 从 1 回到 0 时,填充宽度与透明度按同一公式回退。

2.5 交互与无障碍

  • hover / focus 当前扇区时,扇区外半径向外增厚,内半径不变,扇区不发生位移。

  • hover / focus 当前扇区时,中心标签显示当前项百分比和名称,默认百分比在上、名称在下。

  • labelFormatter 可自定义中心标签内容,并支持用 \n 拆成两行;第一行按数值样式渲染,第二行按名称样式渲染。

  • 可传入直接子元素 <Text as="segment-value" /> / <Text as="segment-name" /> 自定义中心标签样式模板;组件会自动写入当前扇区的真实百分比和名称,出现任一角色子元素时不渲染默认中心标签。

  • showCenterLabel={false} 可关闭中心标签,同时关闭外部写入的中心标签角色内容。

  • 根使用 role="group" 和 aria-label="圆形图表"(zh-CN 默认,随 locale 切换);SVG 不隐藏可聚焦扇区,每个扇区命中项以 role="button" 和包含名称、百分比的独立 aria-label 暴露给辅助技术。

  • 扇区命中层可获得键盘焦点,focus 行为与 hover 一致;中心标签使用 aria-live="polite"。

2.6 Frame 集成

  • 根层使用 Frame;loading 保留声明尺寸和中心内容,将扇区固定在出现动效起点并暂停交互。图表根层明确关闭 Skeleton,也会读取上层 Frame 的 loading 上下文。

  • 支持 enableResponsive、enableContext、enableScaleObserver、enableDefaultMotion 透传到 Frame。

  • class、style 和其余未声明属性会透传给根层 Frame。

  • 图表尺寸由 SVG 几何算法决定,作为外部布局子项时表现为 Hug。


3.1 Props

其余未声明属性会透传给根层 Frame。

3.2 组件方法

方法 描述
replay() 非受控出现动效从 0 重新播放到 1
resetAppearance() 非受控出现动效立即重置到 0
reverseAppearance() 非受控出现动效先进入完成态,再沿同一时间轴从 1 反向回退到 0

3.3 数据结构

interface CircularChartItem {  name: string;  value: number;  color?: CircularChartColor;  percentFormat?: NumberFormatOptions;}

百分比数字格式优先级:labelFormatter(中心标签)→ item.percentFormat → 组件 percentFormat → NumberFormatContext → NumberFormats 默认值。扇区命中层 aria-label 不使用 labelFormatter,但会消费 percentFormat。

value <= 0 或非数字项会被过滤;显式空数组或全部无效时渲染空图表,省略 data 才使用内置示例数据。

type CircularChartColor = string | CircularChartGradient; interface CircularChartGradient {  type?: "linear";  angle?: number;  stops: (string | { color: string; offset?: number | string; opacity?: number })[];}

颜色优先级:data[i].color → colors[i] → colorMode 对应回退色。未定义颜色的扇区不会受其它扇区自定义颜色影响,继续使用当前颜色模式。渐变字符串支持 linear-gradient(135deg, #111111 0%, #6BE6D3 100%) 形式;渐变对象支持用 angle 和 stops 显式声明。


布局模型

主布局模型:内禀原子布局。

  • 根层为 Frame,内部本体层统一承载 SVG 绘图区与中心标签,负责等比缩放;HoverPanel 与本体层并列,保持原有尺寸。

  • 图表尺寸由 size 与 SVG 几何算法决定;作为外部布局子项时表现为 Hug。

  • 不接入三槽位协议,不承担通用子元素排列。

详见 LayoutProtocol.md §12.3(源码参考:specs/maintainers/LayoutProtocol.md)。


动效

场景 实现 bridge 变量
首次登场 / 滚动出现 所有扇区先显示完整同色 0.5px 内描边;再从 startDirection 命中的扇区起始边界开始,按顺时针方向逐扇区执行。默认总时长固定为 1000ms,不随扇区数量变化;下一个扇区只在上一个扇区填充完成后启动,不等待上一个扇区透明度补齐完成;填充方向为扇区起点到终点;整张图表使用图表级缓出时间分配,前段时长接近,越靠后的扇区时长越长;单个扇区内部填充保持线性;滚动时间轴由 appearanceProgress 直接反推同一时间轴,天然可逆 组件内部确定性时间轴;appearanceProgress 控制总进度
扇区顺序与速度 第一个扇区立即启动;第 2 个扇区在第 1 个扇区填充完成后启动,第 3 个扇区在第 2 个扇区填充完成后启动,以此类推。CC-01 五扇区时前三段时长接近,后两段逐步变长,形成整张图表级别的缓出 组件内部时间轴
填充透明度 圆环扇区叠加透明度遮罩:启动时尾部透明度为 0%、中段为 62%、扫描头为 100%,并在 0.75s 内补齐。实心饼图直接绘制随进度增长的 revealPath,避免浏览器对动态嵌套 SVG mask 不重绘;两种形态都由同一进度时间轴驱动 appearanceProgress 直接渲染
底层占位扇区 showBaseLayer=true 时在真实填充层下方绘制一层同色 4% 透明度扇区,不参与出现动效;动效完成前也能看到完整图表结构 组件内部 base layer
扇区分隔线 间隔由 separatorWidth 调整;其数值表示 160x160 图表下的设计基准值,组件按 size / 160 等比缩放。间隔在 path 几何阶段通过 padAngle + padRadius 生成,让真实背景自然透出 separatorWidth
扇区 hover 强调 每个扇区仅保留当前动画;hover / focus 目标改变时立即取消旧帧,从当前外半径向最新目标过渡,不排队或补播;进入时增厚到 R + hoverThicknessGrowth,离开且没有焦点时回到 R,保持原有 300ms cubicOut;内半径不变,扇区不位移,减少动效时直接到达目标 组件内部 requestAnimationFrame + cubicOut 几何动画
扇区亮度反馈 filter: brightness(1.04) --snowui-frame-color-motion-*
中心标签进入 opacity + scale --snowui-frame-appear-motion-*(生命周期进入时序) / --snowui-frame-control-motion-*

6.1 出现动效起始方向

startDirection 支持 8 个方向:top / top-right / right / bottom-right / bottom / bottom-left / left / top-left。

判定规则:

  1. 从圆心向 startDirection 发出射线。

  2. 找到该射线命中的扇区。

  3. 不论射线落在该扇区的哪个位置,动效都从该扇区自身起始边界开始。

  4. 后续按顺时针方向逐扇区填充,直到所有扇区完成。

使用示例

<CircularChart  data={[    { name: "Search Engine", value: 1048 },    { name: "Direct", value: 735 },    { name: "Email", value: 580 },    { name: "Union Ads", value: 484 },    { name: "Video Ads", value: 300 }  ]}/>
<CircularChart  size={320}  ringThickness={88}  cornerRadius={16}  separatorWidth={4}  hoverThicknessGrowth={4}/>

上例中的 cornerRadius={16} 与 separatorWidth={4} 表示 160x160 图表下的设计基准值。实际尺寸为 320 时,最终呈现为 32px 圆角与 8px 间隔。

<CircularChart  size={220}  ringThickness={64}  data={[    {      name: "Primary Gradient",      value: 42,      color: "linear-gradient(135deg, var(--primary, #111111) 0%, var(--secondary-mint, #6BE6D3) 100%)"    },    { name: "Default Purple", value: 30 },    {      name: "Object Gradient",      value: 18,      color: {        angle: 45,        stops: [          "var(--secondary-purple, #B899EB) 0%",          "var(--secondary-cyan, #A0BCE8) 100%"        ]      }    },    { name: "Default Mint", value: 10 }  ]}/>
<CircularChart  data={[    { name: "Direct", value: 735 },    { name: "Email", value: 580 }  ]}>  <Text as="segment-value" class="text-18 font-bold text-black-100" />  <Text as="segment-name" class="text-14 text-black-40" /></CircularChart>
<CircularChart  bind:this={chart}  startDirection="left"  appearOnView={false}/> <Button onclick={() => chart.replay()}>重新填充</Button><Button onclick={() => chart.reverseAppearance()}>反向回退</Button>
 <CircularChart  size={220}  ringThickness={140}  cornerRadius={8}  separatorWidth={3}/>

CircularChart 样式覆盖

先阅读 完整 LICENSE;同任务、同版本、同范围去重。

优先用组件公开 Props 匹配合适样式,尽可能保留原有视觉。确需改写时按 样式选择与改写顺序 使用自己的 class(含项目已有 Tailwind)或实例 style。以下名称来自源码实际消费的公开 override;先核对目标作用域,不修改私有 DOM。采用 SnowUI Token 时选择正确类别,外部应用不被要求安装一方 utilities。

变量 用途与默认参考
--snowui-circular-chart-label-color-override 中心标签主色(默认 var(--black-100))
--snowui-circular-chart-label-font-size-override 中心标签数值字号(160 基准默认 14px,随图表缩放)
--snowui-circular-chart-label-font-weight-override 中心标签主行字重(默认 600)
--snowui-circular-chart-label-muted-color-override 中心标签次色(默认 var(--black-40))
--snowui-circular-chart-label-muted-font-weight-override 中心标签次行字重(默认 400)
--snowui-circular-chart-size-override 整体尺寸(默认 240px)

设计指南 · Token · 组合边界

CircularChart 类型与状态

必填属性:无具名必填属性。

可双向绑定:本组件未声明具名双向绑定属性;状态更新通过公开回调或所属宿主处理。

继承声明:无接口继承。继承能力以基类公开文档为准;Omit 中的字段已排除,不能按基类原样使用。

共享 Frame API · 返回 API

以下为公开属性实际引用的类型声明,来自源码;Svelte Snippet 表示内容片段,ComponentProps 表示对应组件的 Props。

CircularChartItem

来源:components/src/components/CircularChart.svelte

export interface CircularChartItem {        name: string;        value: number;        color?: CircularChartColor;        percentFormat?: NumberFormatOptions;    }

CircularChartColor

来源:components/src/components/CircularChart.svelte

export type CircularChartColor = ChartColor;

ChartColor

来源:components/src/lib/chart/colors.ts

export type ChartColor = SnowUIColor | string | ChartGradient;

SnowUIColor

来源:components/src/lib/color.ts

export type SnowUIColor = keyof typeof SNOWUI_COLOR_TOKENS;

ChartGradient

来源:components/src/lib/chart/colors.ts

export interface ChartGradient {    type?: "linear";    angle?: number;    stops: (string | ChartGradientStop)[];}

ChartGradientStop

来源:components/src/lib/chart/colors.ts

export interface ChartGradientStop {    color: SnowUIColor | string;    offset?: number | string;    opacity?: number;}

NumberFormatOptions

来源:components/src/lib/number-format.ts

export interface NumberFormatOptions {    fractionDigits?: number;    valueLabelFractionDigits?: number;    percentFractionDigits?: number;    preserveTrailingZeros?: boolean;    useGrouping?: boolean;    emptyValue?: string;    locale?: string;    notation?: NumberNotation;    compactThreshold?: number;    compactFractionDigits?: number;}

NumberNotation

来源:components/src/lib/number-format.ts

export type NumberNotation = "standard" | "compact" | "auto";

CircularChartColorMode

来源:components/src/components/CircularChart.svelte

export type CircularChartColorMode = ChartColorMode;

ChartColorMode

来源:components/src/lib/chart/colors.ts

export type ChartColorMode = "sequence" | "monochromeFade" | "monochrome";

StartDirection

来源:components/src/components/CircularChart.svelte

type StartDirection =        | "top"        | "top-right"        | "right"        | "bottom-right"        | "bottom"        | "bottom-left"        | "left"        | "top-left";

AnchorPoint

来源:components/src/components/CircularChart.svelte

type AnchorPoint = "top" | "center" | "bottom";

ChartHoverMode

来源:components/src/components/CircularChart.svelte

type ChartHoverMode = "item" | "cell";

ChartHoverPanelVariant

来源:components/src/lib/chart/hover-panel.ts

export type ChartHoverPanelVariant = "dark" | "light" | "surface";

ChartHoverPanelPlacement

来源:components/src/lib/chart/hover-panel.ts

export type ChartHoverPanelPlacement =    | "anchor-top"    | "anchor-side"    | "pointer"    | "pin-top-left"    | "pin-top"    | "pin-top-right"    | "pin-right"    | "pin-bottom-right"    | "pin-bottom"    | "pin-bottom-left"    | "pin-left"    | "pin-center";