3D饼图
Pie3D 是一个基于 SVG 和 CSS3 变换构建的 3D 环形饼图组件。
与 Bar3D 类似,它不依赖庞大的 WebGL 引擎,而是创造性地直接调用了 Tui3DPanel 组件作为底层空间容器。它将平面的环形图放置于 Tui3DPanel 中进行 3D 倾斜,并通过动态计算的阴影层叠技术(Stacking Shadows)来模拟逼真的物理厚度和侧面光影。
核心特性
- 真 3D 姿态: 内部封装
Tui3DPanel,支持通过transform3D属性精确控制空间俯视角度。 - 物理厚度模拟: 利用 CSS 变量和阴影层自动计算扇区的侧面厚度颜色,呈现立体感。
- 高自由度造型: 支持调节内径(环形/饼形切换)、圆角 (
cornerRadius) 和扇区炸开间隙 (gapSize)。 - 丰富交互: 支持扇区悬停浮动动画 (
hoverOffset)、点击事件及图例交互。 - 中心仪表盘: 环形图中心自动聚合显示总数和标题,适合用作仪表盘。
基础用法
Pie3D 需要传入一个包含 label 和 value 的对象数组作为数据源。
html
<template>
<div style="height: 350px;">
<TuiPie3D
:data="pieData"
chartTitle="总销售额"
unit="万元"
/>
</div>
</template>
<script setup>
const pieData = [
{ label: '电子产品', value: 45 },
{ label: '服装', value: 30 },
{ label: '家居', value: 15 },
{ label: '其他', value: 10 }
]
</script>原理与进阶配置
3D 实现机制 (The 3D Trick)
核心原理:TuiPie3D = SVG + Tui3DPanel
TuiPie3D 组件内部直接调用了 Tui3DPanel。整个饼图本质上是一个 SVG 平面图形,被包裹在 Tui3DPanel 提供的 3D 空间容器中。
这意味着:
- 姿态控制: 您通过
transform3D属性传入的旋转参数(如俯视角度),实际上是直接作用于内部的Tui3DPanel上的。 - 配置透传: 您可以通过
t3DConfig属性,将阴影系数、厚度修正等底层参数透传给内部的Tui3DPanel。
厚度原理: 组件内部会为每个扇区生成一个对应的阴影层 (t3d-shadow-item)。侧面的颜色并不是贴图,而是通过计算基准色的变暗色值来实现的。
- 控制参数:
thicknessColorRatio(默认为 2)。数值越大,侧面(阴影面)颜色相对于顶面颜色越深,立体对比度越强。 - 代码逻辑:html
<path style="--tui-t3d-thickcolor: darken(slice.color, ratio);" ... />
造型控制
- 内径大小 (
innerRadiusPercent): 控制圆环的粗细。设为0时变为实心饼图。 - 扇区圆角 (
cornerRadius): 为扇区边缘添加圆角,使风格更柔和现代。 - 扇区炸开 (
gapSize): 设置扇区之间的物理间隙。不仅产生视觉间隔,还会让扇区在 3D 空间中产生轻微的向外位移,增强独立感。
中心内容 (Center Content)
当 innerRadiusPercent > 0(即环形图)且 showCenterText 为 true 时,组件中心会显示汇总信息。
- 自动汇总: 组件会自动计算
data中所有value的总和显示在中心。 - 标题与单位: 通过
chartTitle和unit定义。 - 偏移修正: 如果因 3D 透视导致视觉中心偏移,可使用
centerTextOffset进行微调。
3D 姿态与光影
可以通过 transform3D 精确控制图表的空间角度。
javascript
// 推荐配置:50度俯视角
const config = {
// 直接控制内部 Tui3DPanel 的旋转
transform3D: { x: 50, y: 0, z: 0 },
// 透传给内部 Tui3DPanel 的高级配置
t3DConfig: {
shadowCoeff: 0.1, // 阴影距离系数
thicknessCoeff: 0.15 // 厚度层叠系数
}
}API 参考
Props
数据与图例
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| data | Array | [] | 数据源。格式 [{ label, value, color? }, ...]。 |
| useDefaultColors | Boolean | true | 是否使用组件内置的色板。若数据项自带 color 则优先使用数据项颜色。 |
| legendShow | Boolean | true | 是否显示图例。 |
| legendPosition | String | 'bottom' | 图例位置:'bottom', 'top', 'left', 'right'。 |
| chartTitle | String | 'Total' | 中心显示的标题文本。 |
| unit | String | - | 中心显示的数值单位。 |
| showCenterText | Boolean | true | 是否显示中心汇总内容。 |
造型与外观
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| width | Number/String | - | 容器宽度。 |
| height | Number/String | - | 容器高度。 |
| innerRadiusPercent | Number | 50 | 内半径百分比 (0-95)。0 为实心饼图。 |
| cornerRadius | Number | 0 | 扇区圆角半径。 |
| gapSize | Number | 10 | 扇区之间的间隙大小。 |
| useGradient | Boolean | false | 是否开启扇区颜色的微渐变效果(增强质感)。 |
| gradientRatio | Number | 0.3 | 渐变强度系数。 |
| thicknessColorRatio | Number | 2 | 厚度暗色系数。控制侧面阴影的深浅。 |
3D 空间与交互
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| transform3D | Object | - | 3D 旋转角度。例如 { x: 50, y: 0, z: 0 }。作用于内部 Tui3DPanel。 |
| t3DConfig | Object | - | 透传给底层 Tui3DPanel 的配置对象(如阴影系数等)。 |
| pieOffset | Number | - | 饼图整体在容器中的 Y 轴偏移量。 |
| centerTextOffset | Number | - | 中心文字的 Y 轴微调偏移量。 |
| hoverOffset | Number | 5 | 鼠标悬停时扇区的浮动(炸开)距离。 |
| animate | Boolean | true | 是否开启入场动画。 |
| animationDuration | Number | 750 | 动画时长 (ms)。 |
| resizeObserver | String | 'global' | 尺寸监听策略:'self', 'global', 'none'。 |
Events
| 事件名 | 说明 |
|---|---|
| sliceClick | 点击扇区时触发。回调参数:(event, sliceData, index)。 |
| sliceHover | 鼠标移入扇区时触发。 |
| sliceLeave | 鼠标移出扇区时触发。 |
可能存在的问题
因为Pie3D内部包含了Tui3DPanel组件,所以可能在Pie3D外层如果嵌套了Tui3DPanel可能会导致无法意料的问题,因目前并未做详细测试,所以提醒用户,尽量避免Tui3DPanel的嵌套使用。